STM32 I2C 源代码,应用STM32的标准库,非中断方式,已测试,通信稳定,给初学STM32 I2C的朋友

2019-12-11 18:39发布

最近刚买了块金牛的开发板,用的STM32F107VC的MPU,在网上搜了半天找了些资料,但测试过程中发现通信不太稳定,在自己的板子上调试了几天,修改了几个地方,现在通过i2c读写,24CL02正常,且稳定。
下面整理些在开发中需要注意的问题,供初学者参考,并附上软件包。供大家研究。 代码是参照网上一位朋友的,在细节部分做了修改,在此表示感谢。

STM32 I2C开发注意问题,非中断方式
1.GPIO端口配置阶段,需要首先使能I2C时钟,然后再配置端口工作方式,否则无效,配置SDA、SCL端口为开漏输出模式,注意与ARM不同的是即使使能IO的特殊功能,仍然需要手动设置GPIO的工作方式;
2.对于I2C器件的读写,由于时序的原因,有的时候读写状态寄存器时会有问题,不像51那样可以自己控制时序与数据,操作起来比较方便,在查询和清除状态寄存器时同样要注意时序问题,否则可能不能正确捕捉到。比如在查询i2c总线是否被占用时,发送完地址数据需要延时一点时间,否则不能捕捉到ADDR置位信号。具体参看程序代码;
3.模拟I2C读写时,如果一次读取多个字节,总是传输不稳定,经过反复测试,将多字节操作全部由单字节操作实现,经实践发现通信比较稳定;
4.STM的数据手册写得确实不怎么样,对于在i2c通信过程中,产生的状态信息说明很不清楚,不要按照数据手册上的去研究通信过程中各个状态寄存器的单个或组合值,直接看它提供的库文件,它已经把各个状态时的状态寄存器组合值定义好了,拿过来直接用吧。
5.切记,在通信过程中,不是每一个状态仅置位一个状态位,而是多个状态位,否则你怎么搞都搞不通的。

以上是我在开发过程中的一点心得,希望对大家有帮助,也希望有心的人可以对驱动加以改进,大家共同研究。

另外说明:
代码中除了i2c,还有lcd的代码,lcd的代码是开发板带的,如果不用直接注释掉就可以了。
用stm32f107最好用mdk3.8以上的版本,另外如果要用到这个芯片的一些外围接口,最好安装RL-ARM库,因为现在对stm32的支持比较少,开发板上的例程很多都是用的stm的RL-ARM中的库文件。
STM32 的I2C应用-非中断方式ourdev_491300.rar(文件大小:398K) (原文件名:I2C.rar)
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
59条回答
yangwc
2019-12-15 05:03
移到24C64上:

/************************************************************************************
**函 数 名: unsigned char I2C_ReadOneByte(I2C_TypeDef *I2Cx,unsigned char I2C_Addr,unsigned char addr)
**功    能: 通过指定I2C接口读取一个字节数据
**入口参数: I2C_TypeDef *I2Cx,STM32 的I2C 寄存器基址,从器件地址,addr 预读取字节存储位置
**         
**出口参数: 读取到的数值
************************************************************************************/
static unsigned char I2C_ReadOneByte(I2C_TypeDef *I2Cx,unsigned char I2C_Addr,unsigned short int addr)
{
        unsigned char res=0;
        I2C_AcknowledgePolling(I2Cx,I2C_Addr);
       
        I2C_GenerateSTART(I2Cx, ENABLE);       
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_MODE_SELECT));
       
        I2C_Send7bitAddress(I2Cx,I2C_Addr,I2C_Direction_Transmitter);
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

        I2C_SendData(I2Cx,(unsigned char)((addr & 0x1F00) >> 8));  //设置高起始地址
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_BYTE_TRANSMITTED));

        I2C_SendData(I2Cx,(unsigned char)(addr & 0x00FF));         //设置低起始地址
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_BYTE_TRANSMITTED));

        I2C_GenerateSTART(I2Cx,ENABLE);
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_MODE_SELECT));
       
        I2C_Send7bitAddress(I2Cx,I2C_Addr,I2C_Direction_Receiver);
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
       
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_BYTE_RECEIVED));
        res=I2Cx->DR;

        I2C_GenerateSTOP(I2Cx,ENABLE);
        return res;
               
}

/************************************************************************************
**函 数 名: static unsigned char I2C_WriteOneByte(I2C_TypeDef *I2Cx,unsigned char I2C_Addr,unsigned char addr,unsigned char value)
**功    能: 通过指定I2C接口写入一个字节数据
**入口参数: I2C_TypeDef *I2Cx,STM32 的I2C 寄存器基址,从器件地址,addr 预写入字节地址,value 写入数据
**         
**出口参数: 成功返回0
************************************************************************************/
static unsigned char I2C_WriteOneByte(I2C_TypeDef *I2Cx,unsigned char I2C_Addr,unsigned short int addr,unsigned char value)
{
       
        I2C_AcknowledgePolling(I2Cx,I2C_Addr);
       
        I2C_GenerateSTART(I2Cx, ENABLE);       
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_MODE_SELECT));
       
        I2C_Send7bitAddress(I2Cx,I2C_Addr,I2C_Direction_Transmitter);
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

        I2C_SendData(I2Cx,(unsigned char)((addr & 0x1F00) >> 8));         //设置高起始地址
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_BYTE_TRANSMITTED));

        I2C_SendData(I2Cx,(unsigned char)(addr & 0x00FF));                         //设置低起始地址
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
       
        I2C_SendData(I2Cx,value);
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_BYTE_TRANSMITTED));       
       
        I2C_GenerateSTOP(I2Cx,ENABLE);
        return 0;
}

一周热门 更多>