帮忙看看I2C模块有啥问题,新手求指教!

2019-03-24 13:35发布

//所需头文件
#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;
        }
    }
} 此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
2条回答
Study_Stellaris
1楼-- · 2019-03-24 15:19
< 片手册上也没多说啊,都是按一个字节接收完毕就产生中断,哎。。。。看了很多例程,也分析了很长时间,是不是思路有问题,求解!!!还有就是如果我不要那个START的开始,
START 肯定是要的。
搞清楚是用哪种模式的,IIC 应该是没有问题的。
wq5551291
2楼-- · 2019-03-24 18:06
< :TI_MSP430_内容页_SA7 --> 多字节主机接收模式啊,但是按例程编的程序貌似不行啊。后来试了不用中断接收两个字节也不行,甚至接收一个字节也不行,哎,开始怀疑硬件了。。。

一周热门 更多>

相关问题

    相关文章