I2C读数据
读取数据的流程
- 发送起始信号:主设备通过拉低SDA线(数据线),同时SCL线(时钟线)为高电平,来发送开始信号。
- 发送从设备地址:主设备发送从设备的7位地址,加上一个读/写位。在读操作的情况下,读/写位应为1。
- 等待应答:从设备接收到地址后,如果地址匹配,它会发送一个应答信号(ACK),通常是通过拉低SDA线来实现。
- 发送寄存器地址:主设备发送想要读取的寄存器地址。
- 再次确认应答:从设备接收到寄存器地址后,会再次发送ACK信号。
- 发送读取请求:主设备再次发送从设备的地址,这次读/写位仍为1,表示接下来是读取操作。
- 从设备发送数据:从设备接收到读取请求后,将指定寄存器的数据放在SDA线上,供主设备读取。
- 主设备确认应答:主设备在每次接收到数据后,都需要发送ACK信号,除了最后一次数据。最后一次数据接收后,主设备可以发送一个非应答信号(NACK)或不发送任何信号,表示不再接收数据。
- 发送结束信号:主设备在接收完所有需要的数据后,通过拉高SDA线,同时SCL线为高电平,来发送结束信号,结束通信。从设备接收到结束信号后,停止发送数据。
这个过程确保了数据的可靠传输,并且允许多个主设备和从设备在同一个I2C总线上进行通信。每个从设备都有一个唯一的地址,以避免地址冲突。
发送起始位
向START标志寄存器中写1,监控SB标志寄存器的状态,详细请看这里
//监控总线是否空闲
while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_BUSY) == SET){}
//发送起止位
I2C_GenerateSTART(I2C1,ENABLE);
//确定起止位是否发送完毕
while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_SB) == RESET){}
发送地址
首先要对AF标志位进行清零,将7位地址位和RW#写入发送数据寄存器,等待ACK回应
I2C_ClearFlag(I2Cx,I2C_FLAG_AF);//清除AF标志位
I2C_SendData(I2Cx,Addr | 0x01);//发送数据到发送数据寄存器
//等待ACK响应
while(1){
if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF) == SET){
I2C_GenerateSTOP(I2Cx,ENABLE);
return -1;
}
if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR) == SET){
break;
}
}
如何发送ACK和NAK
在从从机向主机发送数据时每个字节都会添加一个ACK,在最后一个字节后发送一个NA