厦门免费建立企业网站,苏州有什么好玩的地方适合小朋友,0453牡丹江信息网息网,通州做网站公司1.I2C外设简介 STM32内部集成了硬件I2C收发电路#xff0c;可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能#xff0c;减轻CPU的负担支持多主机模型#xff08;可变多主机#xff09;支持7位/10位地址模式#xff08;11110......)支持不同的通…1.I2C外设简介 STM32内部集成了硬件I2C收发电路可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能减轻CPU的负担支持多主机模型可变多主机支持7位/10位地址模式11110......)支持不同的通讯速度标准速度(高达100 kHz)快速(高达400 kHz)支持DMA多字节读写兼容SMBus协议SMBus(System Management Bus)是系统管理总线SMBus是基于I2C总线改进而来的主要用于电源管理系统中SMBus和I2C非常像STM32F103C8T6 硬件I2C资源I2C1、I2C2
硬件12C也有很多独有的优势执行效率比较高可以节省软件资源功能比较强大可以实现完整的多主机通信模型时序波形规整通信速率快等等
如果你只是简单应用可以选择比较灵活的软件I2C如果你对性能指标要求比较高就可以考虑一下硬件I2C
2.I2C框图 左边是这个外设的通信引脚SDA和SCL这就是12C通信的两个引脚这个SMBALERT是SMBus用的12C用不到不用管的那像这种外设模块引出来的引脚般都是借用GPIO口的复用模式与外部世界相连的
首先上面这一块是SDA也就是数据控制部分这里数据收发的核心部分是这里的数据寄存器和数据移位寄存器当我们需要发送数据时可以把一个字节数据写到数据寄存器DR当移位寄存器没有数据移位时这个数据寄存器的值就会进一步转到移位寄存器里我们就可以直接把下一个数据放到数据寄存器里等着了一旦前一个数据移位完成下一个数据就可以无缝衔接继续发送当数据由数据寄存器转到移位寄存器时就会置状态寄存器的TXE位为1表示发送奇存器为空这就是发送的流程 那在接收时也是这路输入的数据一位一位地从引脚移入到移位寄存器里当一个字节的数据收齐之后数据就整体从移位寄存器转到数据寄存器同时置标志位RXNE表示接收寄存器非空这时我们就可以把数据从数据寄存器读出来了
至于什么时候收什么时候发需要我们写入控制寄存器的对应位进行操作对于起始条件、终止条件、应管位什么的这里也都有控制电路可以完成
下面这里还有两个功能个是比较器和自身地址寄存器、双地址寄存器另一个是帧错误校验计算和帧错误校验寄存器
比较器和地址寄存器这是从机模式使用的刚才说了STM32的I2C是基于可变多主机模型设计的STM32不进行通信的时候就是从机既然作为从机它就应该可以被别人召唤想被别人召唤它就应该有从机地址吧就可以由这个自身地址寄存器指定我们可以自定一个从机地址写到这个寄存器当STM32作为从机在被寻址时如果收到的寻址通过比较器判断和自身地址相同那STM32就作为从机响应外部主机的召唤并且这个STM32支持同时响应两个从机地址所以就有自身地址寄存器和双地址寄存器这一块我们需要在多主机的模型下来理解右边这部分这是STM32设计的一个数据校验模块当我们发送一个多字节的数据帧时在这里硬件可以自动执行CRC校验计算CRC是一种很常见的数据校验算法它会根据前面这些数据进行各种数据运算然后会得到一个字节的校验位附加在这个数据的后面在接收到这一帧数据后STM32的硬件也可以自动执行校验的判定如果数据在传输的过程中出错了CRC校验算法就通不过硬件就会置校验错误标志位告诉你数据错了使用的时候注意点这个校验过程就跟串口的奇偶校验差不多也是用于进行数据有效性验证的 下面SCL的这部分时钟控制是用来控制SCL线的在这个时钟控制寄存器写对应的位电路就会执行对应的功能然后控制逻辑电路也是黑盒子写入控制寄存器可以对整个电路进行控制读取状态寄存器可以得知电路的工作状态之后是中断当内部有一些标志位置1之后可能事件比较紧急就可以申请中断如果我们开启了这个中断那当这个事件发生后程序就可以跳到中断函数来处理这个事件了
最后是DMA请求与响应在进行很多字节的收发时可以配合DMA来提高效率
3.I2C基本结构 首先移位寄存器和数据寄存器DR的配合是通信的核心部分这里因为l2C是高位先行所以这个移位寄存器是向左移位在发送的时候最高位先移出去然后是次高位等等一个SCL时钟移位一次移位8次这样就能把一个字节由高位到低位依次放到SDA线上了
那在接收的时候呢数据通过GPIO口从右边依次移进来最终移8次一个字节就接收完成了
之后GPI0口这里使用硬件I2C的时候这两个对应的GPIO口都要配置成复用开漏输出的模式复用就是GPIO的状态是交由片上外设来控制的开漏输出这是12C协议要求的端口配置
然后SCL这里时钟控制器通过GPIO去控制时钟线这里我简化成一主多从的模型了所以时钟这里只画了输出的方向实际上前面这里如果是多主机的模型时钟线也是会进行输入的
然后继续SDA的部分输出数据通过GPIO输出到端口输入数据也是通过GPIO输入到移位寄存器那这两个箭头连接在GPIO的哪个位置呢 4.主机发送 当STM32想要执行指定地址写的时候就要按照这个主发送器传送序列图来进行这里有7位地址的主发送和10位地址的主发送他们的区别就是7位地址起始条件后的一个字节是寻址10位地址起始条件后的两个字节都是寻址其中前一个字节这里写的是帧头内容是5位的标志位111102位地址1位读写位然后后一个字节内容就是纯粹的8位地址了两个字节加一起构成10位的寻址这是10位地址的寻址方式
7位主发送这个时序呢流程是起始从机地址应答后面是数据1应答数据2应答等等最后是P停止因为12C协议只规定了起始之后必须是寻址至于后面数据的用途并没有明确的规定这些数据可以由各个芯片厂商自己来规定比如MPU6050规定就是寻址之后数据1为指定寄存器地址数据2为指定寄存器地址下的数据之后的数据N就是从指定寄存器地址开始依次往后写这就是一个典型的指定地址写的时序流程
然后我们从头来看一下首先初始化之后总线默认空闲状态STM32默认是从模式为了产生一个起始条件STM32需要写入控制寄存器手册中在这个控制寄存器CR1中有个STAKT位在这一位写1就可以产生起始条件了当起始条件发出后这一位可以由硬件清除所以只要在这一位写1STM32就自动产生起始条件了
之后STM32由从模式转为主模式也就是多主机模型下STM32有数据要发就要跳出来这个意思然后控制完硬件电路之后就要检查标志位来看看硬件有没有达到我们想要的状态在这里起始条件之后会发生EV5事件这个EV5事件你就可以把它当成是标志位这个手册这里都是用EV(Event)几这个事件来代替标志位的为什么要设计这个EV几EV几事件而不直接说产生什么标志位呢这是因为有的状态会同时产生多个标志位所以这个EV几事件就是组合了多个标志位的一个大标志位在库函数中也会有对应的检查EV几事件是否发生的函数所以就当成是一个大标志位来理解就行了 当我们检测起始条件已发送时EV5就可以发送一个字节的从机地址了从机地址需要写到数据寄存器DR中写入DR之后硬件电路就会自动把这一个字节转到移位寄存器里再把这一个字节发送到12C总线上之后硬件会自动接收应答并判断如果没有应答硬件会置应答失败的标志位然后这个标志位可以申请中断来提醒我们当寻址完成之后会发生EV6事件地址发送结束EV6事件结束后是EV8_1事件EV8_1事件就是TxE标志位1移位寄存器空数据寄存器空这时需要我们写入数据寄存器DR进行数据发送了一旦写入DR之后因为移位寄存器也是空所以DR会立刻转到移位寄存器进行发送这时就是EV8事件移位寄存器韭空数据寄存器空这时就是移位寄存器正在发数据的状态所以流程这里数据1的时序就产生了
在EV8后面没有了写入DR密存器将清除该事件所以按理说这个位置应该是写入了下一个数据也就是后面这个数据2在这个时刻就被写入到数据寄存器里等着了然后接收应答位之后数据2就转入移位寄存器进行发送此时的状态是移位寄存器非空数据寄存器空所以这时这个EV8事件就又发生了之后这个位置数据2还正在移位发送但此时下一个数据已经被写到数据寄存器等着了所以这个时候EV8事件消失按照这个流程来一旦我们检测到EV8事件就可以写入下一个数据了
最后当我们想要发送的数据写完之后这时就没有新的数据可以写入到数据寄存器了当移位寄存器当前的数据移位完成时此时就是移位寄存器空数据寄存器也空的状态这个事件就是这里的EV8_2下面解释EV8_2是TxE1也就是数据寄存器空BTF (Bvte Transfer Finished)这个是字节发送结束标志位所以在这里当检测到EV8_2时就可以产生终止条件了显然应该在控制寄存器里有相应的位可以控制
5.主机接收 主机接收的流程这里有7位主接收和10位主接收从这个7位主接收的时序看这里时序的流程是起始从机地址读接收应答然后就是接收数据发送应答接收数据发送应答最后一个数据给非应答之后终止可以看出这个时序应该是当前地址读的时序
下面10位地址的当前地址读就复杂一些这里是起始发送帧头这个帧头里的读写位应该还是写的因为后面还要跟着发送第二个字节的地址之后继续发送第二个字节的8位地址这样才能进行寻址然后要想转入读的时序必须再发送重复起始条件发送帧头这次帧头的读写位就是读的了因为发送读的指令之后必须要立刻转入读的时序所以这第二个字节的地址就没有了直接转入接收数据的时序这是10位地址的操作流程
7位首先写入控制寄存器的START位产生其实条件然后等待EV5事件EV5事件就代表起始条件已发送之后是寻址接收应答结束后产生EV6事件EV6事件代表寻址已完成之后数据1这块代表数据正在通过移位寄存器进行输入EV6_1事件下面解释是没有对应的事件标志只适于接收1个字节的情况这个EV6_1可以看到数据1其实还正在移位还没收到呢所以这个事件就没有标志位之后当这个时序单元完成时硬件会自动根据我们的配置把应答位发送出去
如何配置是否要给应答呢也是看手册:控制寄存器CR1里这里有一位ACK:应答使能如果写1在接收到一个学节后就返回一个应答写0就是不给应答当这个时序单元结束后就说明移位寄存器就已经成功移入一个字节的数据1了这时移入的一个字节就整体转移到数据奇存器同时置RXNE标志位表示数据寄存器非空也就是收到了一个字节的数据这个状态就是EV7事件RXNE1数据寄存器非空读DR寄存器清除该事件也就是收到数据了当我们把数据读走之后这个事件就没有了上面这里EV7事件没有了说明此时数据1被读走当然数据1还没读走的时候数据2就可以直接移入移位寄存器了之后数据2移位完成收到数据2产生EV7事件读走数据2EV7事件没有了最后当我们不需要继续接收时需要在最后一个时序单元发生时提前把刚才说的应答位控制寄存器ACK置0并且设置终止条件请求这就是EV7-1事件和EV7一样后面加了一句设置ACK0和STOP请求也就是我们想要结束了之后在这个时序完成后由于设置了ACK0所以这里就会给出非应答最后由于设置STOP位所以产生终止条件这样接收一个字节的时序就完成了
6.软件/硬件波形对比