I2C设计背景
与串口通信对比
串口从TX引脚向RX引脚发生数据流(以字节为单位),一条发送线,一条接收线,没有时钟线的异步全双工协议 设计一个通信协议,一个芯片的外设·是通过读写寄存器进行,芯片的所有寄存器被分配到一个线性的空间,如果想要==读写寄存器控制硬件电路==,至少需要两个字节数据,一个字节是要读写哪个寄存器(指定寄存器的地址),另一个字节这个地址下寄存器存储的内容(写入内容,控制电路,读出内容,获得电路状态),但是对于单片机来说可以直接通过内部的数据总线获得,用指针操作,不用自己操心。但是这个是外接芯片,不太现实。 如果用串口通信发送数据包,第一个表明写入操作,第二个表明寄存器地址,第三个表明写入的值。
要求
串口是需要两根数据线的全双工协议,整个过程可以同时进行接收和发送,但是这个要求是发送的时候不需要接受,接受时不需要发送,这样会导致一根数据线始终处于空闲状态,造成资源浪费(要求删除一根通信线,只能在同一根线上接进行发送和接收,即把全双工变成半双工) 串口没有应答机制,增加一个应答机制。 一根线上能同时接多个模块 串口是异步时序,发送方和接收方约定的传输速率非常严格,当某个时间进中断了,也不能暂停接收,这样导致传输数据出错,异步时序的缺点:非常依赖硬件外设支持,必须要有USART硬件电路支持才容易使用,如果没有这个电路,串口很难用软件模拟通信(异步时序对时间要求很严格,一般很少用软件来模拟)。将协议改成同步协议,加一个时钟线来指导对方读写,(好处)由于存在时钟线,对时间要求不高,单片机可以随时暂停传输(时钟线也暂停),可以过一段时间再来继续,这就是同步通信的好处。降低单片机对硬件电路的依赖,即使没有硬件电路,也可以用软件模拟的方式实现。(缺点:)多一个时钟线
I2C通信
基本要求:通过通信线,实现单片机读写外挂模块寄存器的功能(在指定的位置写寄存器,在指定的位置读寄存器)
-
I2C(Inter IC Bus)是由Philips公司开发的一种通用数据总线,一共为两根通信线SCL(Serial Clock)、SDA(Serial Data),
-
SCL满足有时钟线,SDA一根数据线,满足全双工到半双工转换,一根线兼具发送和接收
-
采用同步、半双工方式,
-
带数据应答,
-
支持总线挂载多设备(一主多从、多主多从)。
一主多从:单片机作为主机主导I2C总线的运行,挂载在I2C总线的所有外部模块都是从机,从机只有被主机点名之后才能控制I2c总线,不能在未经允许的情况下碰,防止冲突
多主多从:在总线上的任何一个模块都可以主动跳出来,成为主机,但是同一个时间只能有一个人说话,相当于发生了总线冲突,I2C协议会进行仲裁,成功一方获得控制权,失败一方自动变为从机,由于时钟线有主机控制,在多主机模型下,需要进行时钟同步
I2C硬件电路
-
所有I2C设备的SCL连在一起,SDA连在一起
-
设备的SCL和SDA均要配置成开漏输出模式。
-
SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右。
如果规定每个设备SCL和SDA的输入输出模式
SCL:
由于是一主多从,主机的SCL配置成推挽输出,从机的SCL配置成浮空输入或者上拉输入
SLC虽然在一主多从模式下使用推挽输出,但依旧是采用开漏加上拉输出模式
数据流向:主机发送,所有从机接收
SDA:
半双工协议,主机的SDA发送时是输出,接受时输入,从机也是如此。如果能协调好输入输出的切换时机也可以
如果没有协调好,极有可能出现两个引脚同时处于输出状态,恰好一个输出高电平,一个输出低电平,即电源短路状态,该状态要极力避免。
为了避免因没能协调好输入输出的切换时机,导致电源短路的问题
I2C的设计:禁止所有设备输出强上拉的高电平,采用外置弱上拉电阻加开漏输出的电路结构
从机默认输出高电平,且从机输出的高电平没有驱动能力,在开漏输出的模式下,从机电路处于高阻态,避免从机之间的相互干扰
左边是SCL的结构,
引脚进来都可以通过数据缓冲器或者施密特触发器进行输入,输入对电路无影响。任何设备在任何时候都可以输入
输出采用开漏输出(输出低电平,是强下拉,输出高电平 处于浮空状态),为了避免输出高电平导致引脚浮空,在外面SCL和SDA各外置一个上拉电阻,(通过一个电阻拉至高电平,弱上拉),
好处:
-
1.杜绝电源短路,保证电路安全;
-
2.避免引脚模式的频繁切换,开漏+弱上拉的模式,同时兼具输入和输出的功能(想输出 就拉杆子或者放手,操纵杆子变化,想输入,直接放手,观察杆子高低,因为开漏模式,输出高电平相当于断开引脚,)在输入之前可以直接输出高电平,不需要切换为输入模式
-
3.模式有“线与”的现象,只有有任意一个或者多个设备输出低电平,总线就处于低电平,只有所有设备输出高电平,总线才处于高电平(I2C,可利用该特征执行多主机模式下的时钟同步和总线仲裁)
右边是SDA的结构
引脚内部结构图
该图是一主多从模型,左边CPU就是单片机,
协议规定
作为总线的主机,(主机的权利,对SCL线的控制,任何时候都是主机完全掌控SCL线),在空闲状态下,主机可以主动发起对SDA的控制,只有在从机发送数据和从机应答时,主机才会转交SDA的控制权给从机。,被控IC就是挂载在I2C总线上的从机,(从机的权利小,对于SLC时钟线,在任何时候都只能被动的读取,从机不允许控制SCL线),对于SDA线,从机不允许主动发起对SDA的控制(只有在主机发送读取从机的命令或者从机应答时,从机才能短暂控制SDA控制权)
I2C基本时序单元
(1)起始条件和终止条件 (USART串口通信的起始位和停止位))
起始和终止都是由主机产生,从机不允许
①起始条件:SCL高电平期间,SDA从高电平切换到低电平。(左图)
②终止条件:SCL高电平期间,SDA从低电平切换到高电平。(右图)
空闲状态是SCL,SDA都处于高电平,(即没有任何一个设备去碰SCL和SDA,SCL和SDA由外挂的上拉电阻拉直高电平)
当主机需要进行数据收发,首先要打破总线的宁静,产生起始条件(SCL处于高电平,SDA拽下产生一个下降沿,)当从机捕获到SCL高电平,SDA下降沿信号时,就会进行自身复位,等待主机召唤
在SDA下降沿之后,主机要再把SCl拽下来
原因
-
占用总线
-
方便基本时序单元的拼接,保证除了起始和终止条件,每个单元的SCL都是以低电平开始,高电平结束
终止条件:SCL先放手,回弹置高电平,SDA再放手,回弹置高电平,产生一个上升沿。上升沿触发终止条件
(2)发送一个字节的时序单元
由于时序是发送整个字节,在该单元内SCL和SDA全都是由主机掌控,从机只能被动读取
发送一个字节:在SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节
起始条件之后,第一个字节(必须是主机发送的),SCL低电平期间,主机想发送,0就拉低SDA到低电平,想发送1,就放手,SDA回弹至高电平,。在SCL低电平期间,允许改变SDA的电平。当该位放好以后,主机松手时钟线,SCL回弹到高电平,在高电平期间从机读取SDA的时候。(SCL处于高电平之后,从机需尽快读取SDA,一般是在上升沿这个时刻,从机已经读取完成,因为时钟由主机控制,从机并不知道什么时刻就会产生下降沿),主机也需在SCL下降沿之后,尽快把数据放在SDA上,(由于主机有SCL的控制权,主机并不那么着急,在低电平时刻放上即可),放上以后,主机送开SCL,变成高电平,从机读取SDA.
由于有时钟线同步,如果主机一个字节发送一半,进中断,时序就会在中断位置不断拉长,SCL和SDA电平暂停变化
(3)接收一个字节
接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)释放SDA相当于切换为输入模式
所有设备包括主机都始终处于输入模式,当主机发送时,就可以主动去拉低SDA,而主机在被动接收时,必须先释放SDA,以免影响别人使用,因为线与的特征,任何一个设备拉低,总线就是低电平,如果主机被动接收时,还拽着SDA不放手,别人无论发送什么数据,SDA永远都是低电平
主机在接收之前,需要释放SDA,从机就取得SDA的控制权
从机发送0 就把SDA拉低 发送1 就放手 回弹至 SDA高电平
从机的数据变化基本是都是贴着SCL的下降沿进行(因为SCL始终由主机控制)
【实线部分主机控制的电平,虚线部分从机控制的电平】
(4)应答机制(时序和发送一个字节,接收一个字节的其中一位是相同的)
发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答
-
如果主机想要发送ACK(数据0),它会在下一个时钟周期内将SDA线拉低。
-
如果主机想要发送NACK(数据1),它会在下一个时钟周期内保持SDA线为高电平。
在接收一个字节之后,要紧跟着调用发送应答的时序,告诉从机,你是不是还有继续发,如果从机发送一个数据后,得到了主机的应答,从机就还会发送
接收应答:主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)
在调用发送一个字节之后,要紧跟着调用接收应答的时序,用来判断从机有没有收到刚才给它的数据,如果从机收到了数据,在主机释放SDA时,从机应该立刻将SDA拉下来,在SCL高电平期间,主机读取应答为,如果读取为0则表明是收到了
I2C完整时序
I2C是一主多从模型,如何发出指令来确定要访问的是哪个设备
首先,把每个从设备确定一个唯一的设备地址(相当于每个设备的名字) 主机在起始条件之后,要先发送一个字节叫一下从机的名字,(所有从机都会都会收到第一个字节,和自己的名字进行比较,如果不一样,说明主机没有叫我,之后的时序就不管了,如果一样,响应之后主机的读写操作) 在同一条I2C总线里,挂载的每个设备地址必须不一样。 从机设备地址 7位地址模式和10位地址模式 每个I2C设备出厂时,厂商会为其分配一个设备地址 MPU6050 是1101000 AT24C02 1010000 不同芯片的地址不同,相同芯片的地址相同 相同芯片挂载在一条I2C总线 -------用地址中的可变部分(最后几位可以在电路中改变) MPU6050地址的最后一位,就可以由AD0引脚确定 ,接高电平 地址1 AT24C02地址的最后三位 一般I2C的从机设备地址,高位由厂商确定,低位由引脚来灵活切换
(1)指定地址写
对于指定设备(Slave Address),在指定地址(Reg Address)下,写入指定数据(Data)
-
指定设备:通过从机地址确定
-
指定地址:某个设备内部的寄存器地址
-
指定数据:在寄存器中写入的数据、
①首先在SCL高电平期间主机拉低SDA,这就产生了起始条件。
②在起始条件后紧跟着的必须是发送一个字节的时序,字节的内容是从机地址(7位)(确定通信对象)+读写选择位(最后发送的1位,写操作为0)。
③主机发送一个字节的过程:SCL低电平期间SDA被主机写入一个数据位,接着主机释放SCL,SCL高电平期间从机读取SDA上的数据位,接着主机拉低SCL,往SDA写入下一个数据位,以此循环8次。
④发送了一个字节后,主机需要接收从机的应答位(RA),首先主机释放SDA,然后置SCL为高电平,在SCL为高电平时读取SDA的数据,如果为0,代表从机应答,主机可以继续下面的数据发送操作。
⑤主机收到从机应答后拉低SCL,从机也随之释放SDA,将SDA的控制权交回给主机,主机开始给从机发送第二个字节数据,一般第二个字节数据可以是寄存器地址或指令控制字等(第二个字节以及后面字节的用途由从机设备定义),下图所示的第二个字节数据内容为寄存器地址,代表主机要操作从机中地址为0x19的寄存器。
⑥主机发送完第二个字节数据,需要再一次接收从机的应答位,如果从机应答,主机发送第三个字节数据,流程和前面类似。
⑦如果主机完成了所有数据的发送,这时主机会拉低SDA,接着主机释放SCL,再释放SDA,SCL处于高电平期间SDA出现上升沿,这就产生了终止条件。
(2)当前地址读
对于指定设备(Slave Address),在当前地址指针指示的地址下,读取从机数据(Data)
在读的时序中,I2C协议规定:主机进行寻址时,一旦读写标志位给1,下一个字节就要立马转为读的时序
当前地址指针
在从机中,所有的寄存器被分配到了一个线性区域中,会有一个单独的指针变量,指针着其中一个寄存器,该指针上电默认是指向0地址,且每写入一个字节或者读出一个字节后,指针就会自动自增一次,移动到下一个位置。
在进行当前地址读的时序时,主机没有指定读哪个地址,从机就会返回当前指针指向的地址的值
①首先在SCL高电平期间主机拉低SDA,这就产生了起始条件。
②在起始条件后紧跟着的必须是发送一个字节的时序,字节的内容是从机地址(7位)+读写选择位(最后发送的1位,读操作为1)。
③主机发送一个字节的过程:SCL低电平期间SDA被主机写入一个数据位,接着主机释放SCL,SCL高电平期间从机读取SDA上的数据位,接着主机拉低SCL,往SDA写入下一个数据位,以此循环8次。
④发送了一个字节后,主机需要接收从机的应答位(RA),首先主机释放SDA,然后置SCL为高电平,在SCL为高电平时读取SDA的数据,如果为0,代表从机应答,主机可以开始下面的数据接收操作。
⑤主机释放SDA,将SDA的控制权移交给从机,SCL低电平期间SDA被从机写入一个数据位,接着主机释放SCL,SCL高电平期间主机读取SDA上的数据位,然后主机拉低SCL,从机往SDA写入下一个数据位,以此循环8次,主机接收从机的一个字节数据。
⑥主机每接收一个字节的数据,从机就需要接收一次主机的应答位(SA),主机会拉低SDA,接着释放SCL,这时从机读取SDA上的数据位为0,代表主机应答,从机开始下一个字节数据的发送。
⑦如果主机完成了所有数据的接收,主机会释放SDA,接着释放SCL,这时从机读取SDA上的数据位为1,代表主机非应答,从机暂停往SDA写数据。接着主机拉低SDA,再释放SCL,再释放SDA,SCL处于高电平期间SDA出现上升沿,这就产生了终止条件。
⑧“当前地址读”没有指定从机设备的内部地址,从机会将“当前地址指针”指向地址的字节数据发送给主机。主机对从机写操作时,比如主机指定往从机的0x19地址写数据,那么写一字节数据的操作结束后,“当前地址指针”会从0x19开始自增,指向地址0x1A,这时主机如果对从机进行读一字节数据的操作,那么从机会将0x1A地址中的值发送给主机,同时“当前地址指针”会自增为0x1B。(可见这个时序使用起来非常麻烦,在实际运用中并不会单独使用)
(3)指定地址读 (复合格式)
对于指定设备(Slave Address),在指定地址(Reg Address)下,读取从机数据(Data)
先起始再重复起始再停止
①首先在SCL高电平期间主机拉低SDA,这就产生了起始条件。
②在起始条件后紧跟着的必须是发送一个字节的时序,字节的内容是从机地址(7位)+读写选择位(“指定地址读”需要“指定地址写”的时序使“当前地址指针”指向指定的从机内部地址,所以该位为0)。
③主机发送一个字节的过程:SCL低电平期间SDA被主机写入一个数据位,接着主机释放SCL,SCL高电平期间从机读取SDA上的数据位,接着主机拉低SCL,往SDA写入下一个数据位,以此循环8次。
④起始条件后相当于发送了一个命令字节,接着主机需要接收从机的应答位(RA),首先主机释放SDA,然后置SCL为高电平,在SCL为高电平时读取SDA的数据,如果为0,代表从机应答,可以继续下面的数据发送操作。
⑤主机收到从机应答后拉低SCL,从机也随之释放SDA,将SDA的控制权交回给主机,主机开始给从机发送第二个字节数据,下图所示的第二个字节数据内容为寄存器地址0x19,该段时序会将“当前地址指针”指向指定的从机内部地址0x19。
⑥主机发送完第二个字节数据,需要再一次接收从机的应答位,首先主机释放SDA,然后置SCL为高电平,在SCL为高电平时读取SDA的数据,如果为0,代表从机应答,说明从机的“当前地址指针”成功被修改,这时可以马上接上“当前地址读”时序(从起始条件开始),主机读取从机中地址为0x19的寄存器。
Sr:重复起始条件:相当于另起一个时序,因为指定读写标志位只能跟着起始条件的第一个字节
指定地址写入多个字节,重复三遍发送一个字节和接收应答,第一个数据写到0x19,然后地址指针会自动+1
第二个数据会写入0x20。
如果只想读一个字节就停止,在读完一个字节后,一定要给从机发送发应答(SA)(该主机应答时,主机不把SDA拉低),从机读SDA为1,代表主机没有应答,,从机收到非应答,从机就会释放SDA还给主机;从机读SDA为0,则表面主机还要数据,则从机继续发送一个字节数据,此时主机如果想产生停止条件,SDA可能会应该被从机拽住,不能正常产生高电平
I2C外设简介
对于串口的异步时序 软件实现很麻烦,硬件实现简单 对于I2C的同步时序 软件实现简单灵活,硬件实现 不容易 麻烦 软件模拟情况多 但是硬件I2C 也有独特优势 1.执行效率高,节省软件资源 2.功能强大,可以实现完整的多主机通信模型 3.时序波形规整,通信速率快 总结:简单应用 软件I2c 性能指标要求高 硬件I2C
-
STM32内部集成了硬件I2C收发电路,可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能(即由硬件电路自动翻转电平,软件只需写入控制寄存器CR和数据寄存器DR,为了实时监控时序状态,软件还需读取状态寄存器SR),减轻CPU的负担、
USART外设 是串口通信的硬件收发器
-
支持多主机模型
-
支持7位/10位地址模式
-
支持不同的通讯速度,标准速度(高达100 kHz),快速(高达400 kHz)(协议规定的标准速度,如果某个设备支持快速I2C 那么它就支持最大400kHz的时钟频率)
-
支持DMA(多字节传输 提高传输效率 )
-
兼容SMBus协议(SMBus 系统管理总线 基于I2C改进 主用于电源管理系统中 )
-
STM32F103C8T6 硬件I2C资源:I2C1、I2C2
主机 拥有主动控制总线的权利 从机 只能在主机允许的情况下,才能够控制总线 多主机模型 固定多主机 有两个或更多个固定的主机(当这些主机 同时想说话时 就是总线冲突状态,需要进行总线仲裁 仲裁失败一方 让出总线控制权) 可变多主机 总线没有固定的主机,从机。任何一个设备都可以在总线空闲时跳出来指定其他任何设备进通信,当通信完成,这个跳出来的主机就要退回从机的位置(多个 同时跳出来 总线冲突) 7位/10位地址模式 7位地址模式 I2C起始条件以后 必须是 从机地址+读写位 即7位地址加读写位 只有128种可能 10位地址模式 I2C起始条件以后 前两个字节都作为寻址 第一个字节有7个空位,第二个字节有8个空位 加起来 有15位 但是I2C 只是10位地址寻址 剩下5位 当做标志位 在第一个字节写个特定的数据,作为10位寻址模式的标志位, 标志位 11110 如果你第二个字节也是寻址,那么你的第一个字节前5位 必须是 11110 第一个字节剩下的2位+第二个字节的8位 都作为寻址
I2C外设框图
外设模块引出来的引脚 (通信引脚) SDA SCL (SMBus)SMBALERT 一般都是借助GPIO口的复用模式与外界世界相连的。
复用在哪个引脚
STM32F103C8T6中I2C1_SCL复用在PB6上、I2C2_SDA复用在PB7上、I2C2_SCL复用在PB10上、I2C2_SDA复用在PB11上
如上图 SDA ---数据控制部分
核心:数据寄存器和数据移位寄存器
需要发送数据时,把一个字节数据写到数据寄存器(DATA REGISTER),数据寄存器会将字节数据写进数据移位寄存器并自动置状态寄存器的TxE位为1(发送寄存器为空),数据移位寄存器一位一位地将数据写到SDA上,在这个过程中用户可以把下一个字节数据写进数据寄存器,TxE位会自动被置为0,当数据移位寄存器完成上一个字节数据的发送后,数据寄存器就会把新写入的数据写进数据移位寄存器并自动置状态寄存器的TxE位为1,以此往复。
需要接收数据时,数据移位寄存器会将SDA传来的数据一位一位读入,当读满一个字节时 数据移位寄存器将字节数据一次性写入数据寄存器,同时置标志位RxNE为1(数据寄存器非空),用户可以读取数据寄存器的内容,,以此往复
什么时候数据发送,什么时候数据接收:需要写入控制寄存器的对应位进行操作(CR)(对于起始条件 等 会有电路自动完成)
比较器和地址寄存器 是 从机模式使用的
STM32是基于可变多主机模式设计的,STM32不进行通信时就是从机 (作为从机 它就可以被别人召唤 ,就需要一个从机地址 -----由 自身地址寄存器指定)
当STM32作为从机,在被寻址时,如果收到的寻址 通过 比较器判断,和自身地址相同 那STM32 就作为从机 响应 外部主机的召唤
STM32支持 同时响应两个从机地址
STM32设计的数据校验模块
当发送一个多字节的数据帧时,在PEC这儿 硬件可以自动执行CRC校验计算
SCL部分
时钟控制:用来控制SCL线
在时钟控制器(CCR)写对应的位,电路就会执行对应的功能
控制逻辑电路:
写入控制寄存器(CR1 CR2) 可以对整个电路进行控制
读取状态寄存器 可以得知电路的工作状态
I2C基本结构
I2C是高位先行,所以移位寄存器是向左移位,在发送数据是最高位先移出去 (一个SCl时钟移位一次 移位8次)
接收时 数据通过GPIO口 将数据移入,移8次
使用硬件I2C 这两个GPIO口 都要配置成复用开漏输出
复用:GPIO口状态交由片上外设来控制
开漏:I2C协议要求的端口配置
时钟控制器 通过GPIO口去控制时钟线SCL (上图是一主多从模型)
数据输入输出时 应该接在GPIO的哪里
硬件I2C操作流程
手册给了 主机发送 主机接收 从机发送 从机接收
主机发送
STM32想要执行指定地址写
7位地址的主发送 和 10位地址的主发送 区别 7位地址 起始条件后的1个字节是寻址 10位地址 起始条件后的2个字节是寻址 其中前一个字节内容 5位标志位 11110 + 2位地址 + 1位读写位 后一个字节 8位地址 11110 RW xxxxxxxx
7位主发送的时序流程
起始 从机地址 应答 数据1 应答 数据2 应答 等 最后 P 停止
I2C协议只规定了起始条件之后必须是寻址
后面数据的用途 没有明确规定,可以由各个芯片厂商来规定
MPU6050 规定 寻址之后 数据1 为 指定寄存器地址 数据2 指定寄存器地址下的数据 之后的数据N 就是从指定寄存器地址开始 依次往后写
初始化之后 总线默认空闲状态 STM32默认为从模式 为了产生起始条件(STM32 需要写入控制寄存器)
之后 STM32 由从模式转为主模式
起始条件之后会发生EV5事件(可以理解为标志位 手册这都是用EVn这个事件来代替标志位的)
为什么要设计事件 而不说产生什么标志位 因为 有的状态 会同时产生多个标志位 EV事件 就是组合了多个标志位的大标志位 库函数中有对应的 检查EV几事件是否发生的函数
EV5事件标志位含义
EV8_1事件:写入数据寄存器DR,因为移位寄存器也是空的 所以 DR会立刻转到移位寄存器 进行发送
EV8 事件 发数据状态
红线 这个位置 就是 写入了下一个数据 (即 数据2 在红线时刻已经被写入数据寄存器等待 接受应答位之后 数据2 转入移位寄存器进行发送)
一旦检测到EV8事件 就可以写入下一个数据
当我们想发送的数据写完之后,这时就没有新的数据写入DR,当移位寄存器,将当前数据移位完成时 此时就是 移位寄存器空,数据寄存器空的状态
该事件就是EV8_2
Txe = 1 数据寄存器空 BTF 字节发送结束标志位
当前移位寄存器已经移完了,该找DR要下一个数据,但是数据寄存器没有数据 说明主机不想发送了 这种情况代表 字节发送结束
置标志位 BTF =1
一旦检测到EV8_2事件 就可以产生终止条件
总结
写入控制寄存器(CR) 或数据寄存器(DR) 就可以控制时序单元发生,时序单元发生后,检查相应的EV事件(即检查 状态寄存器SR)来等待时序单元发送完成