通讯的起始与停止位
当时钟线是高电平时,数据线从高电平切换为低电平时,表示通讯开始(S信号)。
当时钟线时高电平时,数据线从低电平切换为高电平时,表示通讯停止(P信号)。
S和P信号都有主机产生。
数据的有效性
SDA在SCL的每个时钟周期传输一位数据,且SCL在周期内的高电平时SDA有效,SCL低电平时,SDA一般用于切换电平,为下一次SCL高电平时读取数据做准备;传输的数据单位为字节,每次传输的字节数不受限制。
地址及数据方向
I2C总线上每个设备都有独立的地址,一般用7位表示,后面紧跟一位表示数据传输方向(0为写,1为读)。写的时候主机控制数据线,读的时候从机控制数据线。
响应
当设备接收了一个字节数据或地址之后,若要继续接受,就会向发送方返回一个ACK信号,发送方才会继续发送;否则,返回NACK信号,发送端结束发送。
时钟控制
SCL是由I2C的时钟控制寄存器控制,控制的参数主要是时钟频率(100Kbits/s和400Kbits/s),该寄存器还有一个配置因子CRR,它与I2C外设的时钟输入源共同作用,产生SCL时钟(由于I2C挂载在APB1上APB1的时钟源为PLCK1);
上面说过,SCl低电平SDA数据,SCL高电平读取SDA数据,时钟线的低电平/高电平的时钟占空比=2或16/9。
数据控制逻辑
SDA信号主要连接在移位寄存器上,当向外发送数据时数据会从数据寄存器通过移位寄存器一位一位发送出去(因为之前我们说过串行通信传输数据一般都是用移位寄存器),接受时移位寄存器会将接受到的数据一位一位的存储到数据寄存器。
整体逻辑控制
本质就是写寄存器相应位参数来得到工作模式,读寄存器相应位得到工作状态。(本人的这句总结还不错)
主机发送
- SB位置1表示起始信号已经发送。
- ADDR置1表示地址已经发送,TXE置1表示数据寄存器为空。
- 2步骤执行完后ADDR会清零;【往数据寄存器写入数据之后,TXE会清零表示数据寄存器非空,数据通过SDA一位一位发送出去之后,又会产生EV8事件(也即TXE置1)】;重复【】内的内容就可以发送多个字节了。
- 当数据发送完成之后,主设备产生一个P信号,产生EV8_2事件,TXE和BTF都会置1表示通讯结束。
5. 假如我们使能了I2C 中断,以上所有事件产生时,都会产生I2C 中断信号,进入同一
个中断服务函数,到I2C 中断服务程序后,再通过检查寄存器位来判断是哪一个事件。
主机接收
- 同主发送流程,起始信号(S)是由主机端产生的,控制发生起始信号后,它产生事件“EV5”,并会对SR1 寄存器的“SB”位置1,表示起始信号已经发送;
- 紧接着发送设备地址并等待应答信号,若有从机应答,则产生事件“EV6 ”这时SR1 寄存器的“ADDR”位被置1,表示地址已经发送。
- 从机端接收到地址后,开始向主机端发送数据。当主机接收到这些数据后,会产生“EV7”事件,SR1 寄存器的RXNE 被置1,表示接收数据寄存器非空,我们读取该寄存器后,可对数据寄存器清空,以便接收下一次数据。此时我们可以控制I2C发送应答信号(ACK)或非应答信号(NACK),若应答,则重复以上步骤接收数据,若非应答,则停止传输;
- 发送非应答信号后,产生停止信号(P),结束传输。在发送和接收过程中,有的事件不只是标志了我们上面提到的状态位,还可能同时标 志主机状态之类的状态位,而且读了之后还需要清除标志位,比较复杂。我们可使用 STM32 标准库函数来直接检测这些事件的复合标志,降低编程难度。
总结
具体分析就到这里了,源码及注释前面就贴过(IIC读写EEPROM)。