1 IIC进入主模式的步骤:
在主模式时,I 2 C接口启动数据传输并产生时钟信号。串行数据传输总是以起始条件开始并以停
止条件结束。当通过START位在总线上产生了起始条件,设备就进入了主模式。
以下是主模式所要求的操作顺序:
● 在I2C_CR2寄存器中设定该模块的输入时钟以产生正确的时序
● 配置时钟控制寄存器
● 配置上升时间寄存器
● 编程I2C_CR1寄存器启动外设
● 置I2C_CR1寄存器中的START位为1,产生起始条件
2 作为主机发送器时的传送时序图
主发送器发送流程及事件说明如下:
(1) 控制产生起始信号(S),当发生起始信号后,它产生事件“EV5”,并会对 SR1 寄存器的“SB”位置 1,表示起始信号已经发送;
EV5事件:
(2) 紧接着发送设备地址并等待应答信号,若有从机应答,则产生事件“EV6”及“EV8_1”,这时 SR1 寄存器的“ADDR”位及“TXE”位被置 1,ADDR 为 1 表示地址已经发送,TXE为 1 表示数据寄存器为空;
EV6事件:
EV8_1事件
(3) 以上步骤正常执行并对 ADDR 位清零后,我们往 I2C 的“数据寄存器 DR”写入要发送的数据,然后DR会将数据转移到移位寄存器,移位寄存器将数据通过SDA线一位一位的发送。一旦DR的数据转移到了移位寄存器,就会产生EV8事件:
EV8事件:EV8:TxE=1,移位寄存器非空,数据寄存器空,写入DR寄存器将清除该事件。值得注意的是,EV8事件必须在当前字节传输完成前清除,为什么?因为如果没有及时清除,就说明没有新的数据填入DR,此时会是发送完成的状态(即EV8_2),然后系统就会产生停止信号了。
如何消除EV8事件?
可以看到,EV8事件其实就是连续用于写入数据的。当发送数据时(DR已经转移到移位寄存器,且无新写入数据),EV8事件会一直持续,所以我们可以往DR再传入一个数据,来消除EV8事件。而其他的事件,会一直拉低SCL,不发送时钟信号,直到我们处理完对应的事件。
所以,当发送单个数据时,由于没有新的数据写入DR,会在这个单数据发送后BTF = 1,此时TXE = 1,产生EV8_2事件,然后继续发送停止信号。当连续发送时,不断的往DR写入数据,这会清除掉BTF标志,只有当最后一个数据时,才会产生EV8_2。
(4) 当我们发送数据完成后,控制 I2C 设备产生一个停止信号(P),这个时候会产生EV8_2 事件,SR1 的 TXE位及 BTF位都被置 1,表示通讯结束。
按照寄存器描述,BTF位实际上做的是如下工作:在移位寄存器将数据全部发送完成时判断DR是否有数据,如果没有,那就代表这已经是最后一个数据了,所以此时字节发送结束。
3 作为主机接收器时的传输时序
主接收器接收流程及事件说明如下:
(1) 同主发送流程,起始信号(S)是由主机端产生的,控制发生起始信号后,它产生事件“EV5”,并会对 SR1寄存器的“SB”位置 1,表示起始信号已经发送;
(2) 紧接着发送设备地址并等待应答信号,若有从机应答,则产生事件“EV6”这时SR1 寄存器的“ADDR”位被置 1,表示地址已经发送;
这里存在一些难以理解的地方,接下来是个人的理解,可能会有错误,欢迎指正。
首先是EV6_1事件:中文参考手册中说到,要清除响应和停止条件的产生位。清除响应很好理解(就是在接收到一个数据后不应答),此时发送器就不会再发送数据。但是为什么要清除停止条件的产生位?应该是要设置停止位才对啊
对于这个问题,最好的答案就是英文参考手册,其实中文参考手册在这里是错误的,真的无语了,以下是英文参考手册,如何设置说的非常清楚。
如果只接收一个字节的数据,在EV6事件后,马上设置关闭应答使能,以及产生停止条件,这些设置都必须在当前传输的ACK到达之前完成(如果没有,就容易出现数据错误),这也是硬件IIC的一个缺点吧,整个硬件IIC的详细分析就到此结束了。