//所需头文件
#include "includes.h" // 封装的头文件、宏定义、变量、函数声明
/*************************全局变量定义及初始化*********************************/
u8 I2C0_sla=0x28; // I2C0初始化为气压传感器的地址(本身为移位后地址)
u8 I2C1_sla=0x27; // I2C1初始化为湿度传感器1的地址(本身为移位后地址)
u8 I2C0_num=4; // I2C0开始要读取的数据个数(字节数)
u8 I2C1_num=2; // I2C1开始要读取的数据个数(字节数)
u8 I2C0_state = STATE_READ_FIRST; // I2C0初始化为读取多字节开始态
u8 I2C1_state = STATE_READ_FIRST; // I2C1初始化为读取多字节开始态
u8 *I2C0_buf,*I2C1_buf; // 定义I2C数据缓存
int i=0; // For循环循环次数
/**************************函数声明,中断函数在启动文件里已注册过**************/
static void SystemInit(void);
static void SC_Init(void);
static void GPIO_Init(void);
static void I2C_Init(void);
/****************************************************************************
*****Function name: main
***** input parameters: 无
***** output parameters: 无
***** Returned value: 无
****************************************************************************/
int main(void)
{
SystemInit(); // 系统初始化
// 控制I2C主从模块的状态:主机地址,发给主机的命令(多字节突发读操作启动)------------------------只有加了这句话才能进入中断,是这样吗????
I2CMasterControl(I2C0_MASTER_BASE,I2C_MASTER_CMD_BURST_RECEIVE_START);
for(;;)
{
}
}
void SystemInit(void)
{
SC_Init(); // 初始化系统时钟
GPIO_Init(); // 初始化GPIO
I2C_Init(); // 初始化I2C
}
/*************************************************************************************
***** Function name: SC_Init
***** Descriptions: 系统时钟初始化
***** input parameters: none
***** output parameters: none
***** Returned value: none
*************************************************************************************/
void SC_Init(void)
{
//采用主振荡器作为系统时钟源,外接16MHz晶振,不分频,禁止内部振荡器---------------用获得函数看过,16MHz还算稳定^-^
SysCtlClockSet(SYSCTL_USE_OSC|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ|SYSCTL_SYSDIV_1);
}
/*************************************************************************************
***** Function name: GPIO_Init
***** Descriptions: GPIO初始化
***** input parameters: none
***** output parameters: none
***** Returned value: none
*************************************************************************************/
void GPIO_Init(void)
{
这块有关I2C的都在调试的时候看过了,主机使能了,中断使能了,引脚也配置了,所以略过!
}
/*************************************************************************************
***** Function name: I2C_Init
***** Descriptions: I2C初始化,总线速度100Kbps
***** input parameters: none
***** output parameters: none
***** Returned value: none
*************************************************************************************/
void I2C_Init(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); //使能I2C1所在的GPIOA模块
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); //使能I2C0所在的GPIOB模块
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0); //使能I2C0模块
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1); //使能I2C1模块
GPIOPinTypeI2C(GPIO_PORTA_BASE,(GPIO_PIN_0|GPIO_PIN_1));// 配置I2C1所在的GPIOA引脚
GPIOPinTypeI2C(GPIO_PORTB_BASE,(GPIO_PIN_2|GPIO_PIN_3));// 配置I2C0所在的GPIOB引脚
GPIOPinConfigure(GPIO_PA0_I2C1SCL);
GPIOPinConfigure(GPIO_PA1_I2C1SDA);
GPIOPinConfigure(GPIO_PB2_I2C0SCL);
GPIOPinConfigure(GPIO_PB3_I2C0SDA);
GPIOPadConfigSet(GPIO_PORTA_BASE,(GPIO_PIN_0|GPIO_PIN_1),GPIO_STRENGTH_4MA,GPIO_PIN_TYPE_OD);// I2C1SCL和I2C1SDA配置为4mA驱动的开漏管脚
GPIOPadConfigSet(GPIO_PORTB_BASE,(GPIO_PIN_2|GPIO_PIN_3),GPIO_STRENGTH_4MA,GPIO_PIN_TYPE_OD);// I2C0SCL和I2C0SDA配置为4mA驱动的开漏管脚
//I2C1和I2C0均配置为低速100Kbps,系统时钟频率16MHz
I2CMasterInitExpClk(I2C1_MASTER_BASE,SysCtlClockGet(),false);
I2CMasterInitExpClk(I2C0_MASTER_BASE,SysCtlClockGet(),false);
// 设置I2C主机将放置到总线上的地址:主机地址,从机地址(7位),主从机通信类型
I2CMasterSlaveAddrSet(I2C0_MASTER_BASE,I2C0_sla,true); // 主机读操作
I2CMasterSlaveAddrSet(I2C1_MASTER_BASE,I2C1_sla,true); // 主机读操作
//设定I2C0和I2C1的中断优先级
IntPrioritySet(INT_I2C1,2 << 5);
IntPrioritySet(INT_I2C0,1 << 5);
//I2C中断开关
IntMasterEnable(); // 使能处理器中断
I2CMasterDisable(I2C1_MASTER_BASE); // I2C1主机禁能
I2CMasterEnable(I2C0_MASTER_BASE); // I2C0主机使能
IntDisable(INT_I2C1); // 初始化时先关闭I2C1中断
IntEnable(INT_I2C0); // 初始化时先开启I2C0中断
I2CMasterIntDisable(I2C1_MASTER_BASE); // 初始化时先关闭I2C1主机中断
I2CMasterIntEnable(I2C0_MASTER_BASE); // 初始化时先开启I2C0主机中断
}
/********************************************************************************
** 函数名称 :I2C0_ISR()
** 函数功能 :I2C0中断读数据---------------------------------------------------------在这个中断里,只能接收到第一个字节0x38,第二个字节的时候就死机了,还是单
步运行的;若全速运行,采到的数据全为零,我把采到的数都放到数组里实时监测了,顺便说一下传感器的数据都是14位,器件地址就是用的手册上给的(貌似听人说这就是那个
有效的7位地址,移位后的,不需要移位(明天打电话问问霍尼韦尔的技术支持),有一个明显的现象是MCU和传感器同时上电复位,单步运行能采到4个字节数据,但是再从头运行
几遍就不行了,要么采一个字节死,要么一个字节都采不到,不管怎么样全速运行显示的都是零。问过同事,说可能是时序没合拍,也就是可能是时序问题,但是我看LM3S2793芯
片手册上也没多说啊,都是按一个字节接收完毕就产生中断,哎。。。。看了很多例程,也分析了很长时间,是不是思路有问题,求解!!!还有就是如果我不要那个START的开始
命令就根本不会进入中断,是这样吗?谢谢啊!
** 入口参数 :无
** 出口参数 :无
********************************************************************************/
void I2C0_ISR (void)
{
I2CMasterIntClear(I2C0_MASTER_BASE); // 清除I2C0中断标志
switch(I2C0_state)
{
case STATE_IDLE: // 空闲状态
{
break;
}
case STATE_READ_FIRST: // 读取4个字节开始
{
// 设置I2C0主机将放置到总线上的地址:主机地址,从机地址(7位),主从机通信类型
I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, I2C0_sla, true); // 主机读操作
// 控制I2C主从模块的状态:主机地址,发给主机的命令(多字节突发读操作启动)
I2CMasterControl(I2C0_MASTER_BASE,I2C_MASTER_CMD_BURST_RECEIVE_START);
I2C0_state = STATE_READ_NEXT;
break; // 跳出
}
case STATE_READ_NEXT: // 读取下一个字节
{
// 把上个读取的数据放入对应的缓冲区里
*I2C0_buf++ = I2CMasterDataGet(I2C0_MASTER_BASE);
I2C0_num--; // 需读取的字节数自减1
I2CMasterControl(I2C0_MASTER_BASE, // 继续读取
I2C_MASTER_CMD_BURST_RECEIVE_CONT);
if(I2C0_num == 2)
{
// 切换为湿度传感器2的地址(与湿度传感器1的地址相同)
I2C0_sla=0x27;
Delay_Ms(5); // 延时5ms
I2C0_state = STATE_READ_FINAL; // 显示读取最后一个字节状态
}
else
// 若本次不是倒数第二个数据,继续显示读取下一个字节状态
I2C0_state = STATE_READ_NEXT;
break; // 跳出
}
case STATE_READ_FINAL: // 读取最后一个字节
{
// 存湿度传感器2低字节数据到对应的缓冲区里
*I2C0_buf++ = I2CMasterDataGet(I2C0_MASTER_BASE);
I2C0_num--; // 此后I2C0_num==1
I2CMasterControl(I2C0_MASTER_BASE,I2C_MASTER_CMD_BURST_RECEIVE_CONT);
I2C0_state= STATE_READ_WAIT; // 显示读字节等待状态
break; // 跳出
}
case STATE_READ_WAIT: // 等待读取一个字节
{
// 存湿度传感器2高字节数据到对应的缓冲区里
*I2C0_buf++ = I2CMasterDataGet(I2C0_MASTER_BASE);
I2C0_num--; // 此后I2C0_num==0,此次读数完毕
I2CMasterControl(I2C0_MASTER_BASE,I2C_MASTER_CMD_BURST_RECEIVE_FINISH); //接收完成
I2C0_state= STATE_IDLE; // 显示总线空闲态
I2C0_num=4; // 重新装入I2C0传输字节数
IntDisable(INT_I2C0); // 关闭I2C0中断
I2CMasterIntDisable(I2C0_MASTER_BASE); // 关闭I2C0主机中断
I2CMasterDisable(I2C0_MASTER_BASE); // I2C0主机禁能
I2CMasterEnable(I2C1_MASTER_BASE); // I2C1主机使能
IntEnable(INT_I2C1); // 使能I2C1中断
I2CMasterIntEnable(I2C1_MASTER_BASE); // 使能I2C1主机中断
// 控制I2C主从模块的状态:主机地址,发给主机的命令(多字节突发读操作启动)------------------------只有加了这句话才能进入中断,是这样吗????
I2CMasterControl(I2C0_MASTER_BASE,I2C_MASTER_CMD_BURST_RECEIVE_START);
break;
}
}
}
/********************************************************************************
** 函数名称 :I2C1_ISR()
** 函数功能 :I2C1中断读数据
** 入口参数 :无
** 出口参数 :无
********************************************************************************/
void I2C1_ISR (void)
{
I2CMasterIntClear(I2C1_MASTER_BASE); // 清除I2C1中断标志
switch(I2C1_state)
{
case STATE_IDLE: // 空闲状态
{
break;
}
case STATE_READ_FIRST: // 读取2个字节开始
{
// 设置I2C1主机将放置到总线上的地址:主机地址,从机地址(7位),主从机通信类型
I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, I2C1_sla, true); // 主机读操作
// 控制I2C主从模块的状态:主机地址,发给主机的命令(多字节突发读操作启动)
I2CMasterControl(I2C1_MASTER_BASE,I2C_MASTER_CMD_BURST_RECEIVE_START);
I2C1_state = STATE_READ_FINAL; // 显示读取最后一个字节状态
break; // 跳出
}
case STATE_READ_FINAL: // 读取最后一个字节
{
// 存湿度传感器1低字节数据到对应的缓冲区里
*I2C1_buf++ = I2CMasterDataGet(I2C1_MASTER_BASE);
I2C1_num--; // 此后I2C1_num==1
I2CMasterControl(I2C0_MASTER_BASE,I2C_MASTER_CMD_BURST_RECEIVE_CONT); //继续读取第二个字节
I2C1_state= STATE_READ_WAIT; // 显示读字节等待状态
break; // 跳出
}
case STATE_READ_WAIT: // 等待读取一个字节
{
// 存湿度传感器1高字节数据到对应的缓冲区里
*I2C1_buf++ = I2CMasterDataGet(I2C1_MASTER_BASE);
I2C1_num--; // 此后I2C1_num==0,此次读数完毕
I2CMasterControl(I2C1_MASTER_BASE,I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
I2C1_state= STATE_IDLE; // 显示总线空闲态
I2C1_num=2; // 重新装入I2C1传输字节数
IntDisable(INT_I2C1); // 关闭I2C1中断
I2CMasterIntDisable(I2C1_MASTER_BASE); // 关闭I2C1主机中断
I2CMasterDisable(I2C1_MASTER_BASE); // I2C1主机禁能
break;
}
}
}
此帖出自
小平头技术问答
一周热门 更多>