STM32F1xx的IIC通信

用的是3.5版本的固件库

固件库中有些宏的名字起得并不好,这里主要做一些注释,方便以后查阅。而且还发现固件库做的各种检查实在是很繁琐,比如检查字节是否发送完毕,库函数不仅会检测字节是否发送完毕,还顺便同时检测5/6个比特位。如果对程序的速度需要优化的话,可以在库函数的基础上自己改改。

每次执行IIC操作后,都要检查操作的结果,检查所用的函数为I2C_CheckEvent(I2Cx, event),其中event为4B,高2B是I2C_SR2寄存器,低2B为I2C_SR1寄存器。

1、发送起始信号

I2C_GenerateSTART(I2C2,ENABLE);//起始信号
while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT));//等待起始信号完毕

其中I2C_EVENT_MASTER_MODE_SELECT宏代表SR2=b_0000_0011,SR1=b_0000_0001,也即SR共有3个bit置位,分别代表:IIC正在通信(忙标志)、当前为主机模式、起始信号已发送完毕。

PS:IIC的忙标志位SR2.1是由硬件自动置位和清除的,只要SCL或SDA中出现低电平,该bit就会被置1。

2、发送片选信号(写)

I2C_Send7bitAddress(I2C2, DB5883_CHIP_ADDR,I2C_Direction_Transmitter);//发送片选地址+写信号
while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//等待片选字节发送完毕,且等待从机的ack

其中I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED代表SR2=b_0000_0111,SR1=B_1000_0010,共5 bits置位,分别代表:数据已发送、正忙标志、是主机模式、数据寄存器已空、片选地址已发送(且已收到从机的ack)

3、发送片选信号(读)

I2C_Send7bitAddress(I2C2, DB5883_CHIP_ADDR,I2C_Direction_Receiver);//发送片选地址+读信号
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//等待片选地址发送完成,且等待从机ack

其中I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED代表SR2=b_0000_0011,SR1=B_0000_0010,共3 bits置位,分别代表:正忙标志、是主机模式、片选地址已发送(且已收到从机的ack)

4、发送一个字节的数据

I2C_SendData(I2C2,REG_Address);
while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED));//等待字节发送完毕,且等待从机ack

I2C_EVENT_MASTER_BYTE_TRANSMITTED代表SR2=b_0000_0111,SR1=B_1000_0100,共5 bits置位,分别代表:数据已发送、正忙标志、是主机模式、数据寄存器已空、收到了从机的ack。

5、设置主机接收到一个字节后要发送Ack还是NoAck

I2C_AcknowledgeConfig(I2C2, DISABLE);//不发送Ack(也即发送NoAck)

6、读取从机发来的字节

//等待读信号(选寄存器)信号发送完成
I2C_AcknowledgeConfig(I2C2, DISABLE);//设置为NoAck模式
while(!(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED)));//直到接收完从机发来的字节
REG_data=I2C_ReceiveData(I2C2);//读出寄存器数据
I2C_GenerateSTOP(I2C2,ENABLE);//停止信号

有些iic从机支持被主机连续读多个字节,一般这种设备在被连续读时,主机每收到从机的一个字节,主机都要向从机发送ACK,直到读完最后一个字节,主机向从机发送NoAck,这时从机会停止发送,从机会等待主机发起stop信号或从机自动超时等待新的start

猜你喜欢

转载自blog.csdn.net/qq_31073871/article/details/86593925