【STM32】USART串口和I2C通信

2024-08-09 13:15:45 浏览数 (2)

一、串口

1、简介

串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单、可实现两个设备的互相通信

单片机的串口可以使单片机与单片机、单片机与电脑、单片机与其他模块互相通信

2、电路要求

简单双向串口通信有两根通讯线:发送端TX和接收端RX,以及两根供电线:VCC和GND,TX和RX是单端信号,它们的高低电平都是相对于GND的,所以GND也可以看做是通讯线

TX和RX要交叉连接,一个设备的输出代表着另一个设备的输入,如果只需要单向的数据传输时,可以只接一根通信线

3、参数及时序

串口通信的速率就是波特率,单位为波特,在二进制下,波特率相当于比特率

串口通信先后由起始位1位、数据位8位、(校验位1位)、停止位1位四个位一帧共10(11)位组成,一般启用校验就是11位,不启用校验就是10位

起始位标志一个数据帧的开始,固定为低电平 停止位标志一个数据帧的结束,固定为高电平

在空闲时也就是不通讯的时候,默认为高电平也就是1,在开始写入时,起始位置为0,为低电平,给出一个开始通信的信号,然后依序写入数据位8位,写入数据位时低位先行,也就是最后一个二进制数放到第一个数据位上,然后写入校验位,然后来到停止位置为1,为高电平,恢复默认状态 在需要串口通信时,按照波特率的要求,定时翻转引脚电平就可以了

校验位是用于数据验证的,共三种校验方式:奇校验、偶校验、无校验 如果设定为奇校验位,那么它会统计数据位中1的个数,如果为奇数个那么就为1,为偶数个就为0,如果设定为偶校验位,则反之,如果无校验方式,那么这一位直接无 这样的检验方式可以保证在传输过程中如果有一位数据丢失了可以被检测出来,可是它只能检测一位数据的丢失,如果两位数据都丢失了它是检测不出来的,鸡肋

1位起始位、8位数据位、(1位校验位)、1位停止位共10(11)位打包成一帧通过TX发送到RX中,RX一位一位的读取,这样就实现了串口通信

二、USART外设

USART,通用同步/异步收发器,是STM32内部集成的硬件外设,可以根据数据寄存器的一个字节数据自动生成数据帧时序,从TX引脚打包发送出去,也可以自动接收RX引脚的数据帧时序,拼接为一个字节数据,存放在数据寄存器里

自带波特率发生器,最高为4.5Mbit/s

可以配置是否有校验位,并且可以选择无校验、奇校验还是偶校验,可以配置停止位的长度为0.5/1/1.5/2,因为停止位的长度决定了帧的间隔

1、USART结构

可以看到TX和RX两个引脚,它们连接到IrDA SIR编解码模块,负责通过引脚进入数据的解码和通过引脚离开数据的编码,TX引脚连接到发送移位寄存器,RX引脚连接到接收移位寄存器,发送移位寄存器的作用是一位一位地移出去,接收移位寄存器的作用是一位一位地写进来

接收和发送寄存器RDR、TDR,在程序中只能操纵一个寄存器DR,实际上在硬件中分为了两个,RDR是只读寄存器,TDR是只写寄存器

当有数据写入TDR中时,硬件电路自动检查发送移位寄存器是否有数据正在移位,如果没有,这个数据就会立刻移动到发送移位寄存器中准备发送,发送时向右移位,将数据一位一位地输出到TX引脚,当数据从TDR移动到发送移位寄存器时,会置一个标志位,叫做TXE(TX Empty),用于判定发送数据寄存器TDR是否为空,如果TXE为1,就可以在TDR中写入下一个数据

通过RX引脚将数据写入接收移位寄存器,硬件电路自动检查接收数据寄存器是否有数据正在移位,如果没有,这个数据就会立刻移动到接收移位寄存器中准备接收,接收时向右移位,将数据一位一位地写进数据寄存器,当数据从读取移位寄存器移动到接收数据寄存器RDR时,会置一个标志位,叫做RXNE(RX Nonempty),用于判定接受数据寄存器RDR是否不为空,如果RXNE为1,RDR就可以继续读取RX引脚的数据

硬件数据流控可以避免接收或发送数据过多过快导致的数据覆盖的问题,有两个引脚:nRTS(Request To Send)用于发送,nCTS(Clear To Send)用于接收,一个设备的RTS连接另一个设备的CTS,当一个设备可接收时,RTS置低电平,请求对方发送,当这个设备忙,不想接收时,RTS置高电平,对方CTS接收到后就会暂时停止发送

这就是USART的基本功能了,其他的不多介绍

2、波特率发生器

发送器和接收器的波特率由波特率寄存器BRR里的DIV确定

波特率 = 时钟频率/(16*DIV)

波特率是很重要的,它决定了设备读取高低电平的间隔,也就是说,设备能否正确读取到正确的信息,都取决于波特率的匹配

三、数据包

1、HEX数据包

在HEX数据包里,数据都是以原始的字节数据本身呈现的 HEX数据包分为两种,一种是固定的包长,也就是每次打包的数据长度相同,然后由包头和包尾将它包起来,另一种是不固定包长,也就是每次打包的数据长度可以不同,也是由包头和包尾包起来

包头包尾的作用是标志位,包头标志数据开始,包尾标志数据结束

由于包头包尾也是数据,当我们需要包起来的数据和包头包尾重复了,我们可以尽量选择固定包长的方式打包数据,再一个就是尽量传输与包头包尾不同的数据,还有就是增加包头包尾的数据个数,比如说两个数据做包头,两个数据做包尾

HEX数据包接收

置一个标志位,开始值为0,在检测到包头时置为1,然后开始接收数据,如果是固定包长数据包,那么就接收相应固定个数个数据后将标志位置为2,等待包尾,检测到包尾后打包,置标志位为0,如果是不固定包长数据包,就是在接收数据的同时检测包尾,出现包尾标志位就置为0

2、文本数据包

文本数据包的本质也是字节数据,不过经过编码和译码最终成了字符形式,这个数据包也是通过包头和包尾包起来的,这样的包头包尾与需要打包的数据出现重复的可能性会大大降低

文本数据包接收

跟HEX数据包接收差不多,也是置一个标志位,开始值为0,在检测到包头时置为1,然后开始接收数据,如果是固定包长数据包,那么就接收相应固定个数个数据后将标志位置为2,等待包尾,检测到包尾后打包,置标志位为0,如果是不固定包长数据包,就是在接收数据的同时检测包尾,出现包尾标志位就置为0,不过这个包头和包尾变成了字符,且一般包尾是‘n’换行

I2C通信

一、简介

I2C(Inter IC BUS),读作I方C,2是平方的意思,它有两根通信线:SCL(Serial Clock)、SDA(Serial Data),是同步(主机通过时钟线SCL发送时钟信号,控制数据传输的节奏,确保发送和接收双方的数据同步,也就是二者时钟相同),半双工通信(通过一根数据线SDA实现数据的双向传输,但在同一时刻只能有一个设备发送数据,另一个设备接收数据,通过切换数据传输方向)

在一个设备与另一个设备通信时,接收到数据的一方在接收完毕后会有数据应答,即告诉发送数据的设备一声已经接收到了,且一个主机可以通过I2C通信挂载多个设备

二、通信协议

1、硬件电路

所有I2C设备的SCL连在一起,SDA连在一起

设备的SCL和SDA要配置成开漏输出模式

SCL和SDA各添加一个上拉电阻

IC是被控机,也就是从机,从机接到I2C总线上,CPU对SCL线有绝对的控制权,任何从机不允许控制SCL线,CPU对SDA稍微放松,在CPU发送数据的时候,从机只能被动的读取,在需要从机向主机写入时,CPU同意后,从机才能获得暂时的SDA控制权

上图是SCL和SDA的输入输出的模式,为开漏输出,我们之前提到过,开漏输出只有一个MOS管,接GND,在MOS管开通时为低电平,在MOS管关闭时为浮空输出,此时在外接一个如上上图的上拉电阻,起到一个弱上拉的作用,就可以在MOS管关闭时为高电平,且这种弱上拉的高电平不会对电路造成损害

2、I2C时序基本单元

一个完整的数据帧由起始条件开始,终止条件结束

起始条件:SCL高电平期间,SDA从高电平切换到低电平 终止条件:SCL高电平期间,SDA从低电平切换到高电平 这里的起始终止条件跟串口通信的起始位终止位是一样的,并且起始和终止的信号只能由主机控制

发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节 接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节,主机在接收之前需要释放SDA(因为释放SDA后才能切换为输入模式,也就是高电平)

发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答 接收应答:主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答,主机在接收之前需要释放SDA

如果从机发送一个数据后主机有应答,从机就继续发送数据 如果从机发送一个数据主机无应答,从机就将SDA的控制权交出

三、I2C外设

1、简介

STM32内部集成了硬件I2C收发电路,可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能

支持多主机模型,是可变多主机模型,就是有很多从机,在需要收发信号时有一个从机跳出来做主机,当活动结束后,又变回从机

2、基本结构

数据移位寄存器(高位先行,向左移位)与数据寄存器DR(DATA REGISTER)相互配合,实现逻辑与上面的USART串口实现逻辑基本相同,只是上方的USART串口为全双工通信,拥有独立的写入寄存器和读取寄存器,而I2C通信是一种半双工通信,写入和读取都是用一套寄存器

输入数据通过SDA进入到数据移位寄存器,然后写进数据寄存器DR,输出数据通过数据寄存器DR写入到数据移位寄存器,再将数据向左移位一位一位移出

这里还有PEC功能,这个相当于前面所说的串口通信中的校验位,用于校验数据的传输是否正确

还有比较器和地址寄存器,在多主机模型下,所有设备都是从机,所以这里需要一个存放一个自身地址的寄存器,以及主机寻址判断是否与自身地址相同的比较器

时钟控制寄存器用来控制时钟控制电路,时钟控制电路控制SCL线,控制寄存器可以对电路进行控制,读取状态寄存器可以读取当前电路状态,然后再内部请求中断时可以进行中断程序,以及请求DMA的协助

3、主机发送

我们碰到的从机一般都是7位地址的,也有10位地址的,入门先了解7位地址的

Start后,会发生EV5事件,置SB为1,当SB为1时,代表起始条件已发送,读SR1然后将地址写入DR寄存器将清除该事件,也就是无需我们手动清除

EV5事件后,在数据寄存器DR接收到开始条件后,开始写入从机地址,然后数据从数据寄存器DR转移到移位寄存器中,将这一个字节发送到I2C总线上,之后硬件会自动接收应答并判断,也就是上边所说的比较器和地址寄存器的作用

发送地址结束后,会发生EV6事件,将ADDR置为1,标志着主机发送地址完成,读SR1后读SR2将清除该事件说明也不需要我们手动清除

EV6事件结束后,会发生EB8_1事件,置TxE(数据寄存器为空)为1,此时移位寄存器和数据寄存器DR都为空,写入数据寄存器DR,写入后会立刻转移到移位寄存器中,发生EV8事件,移位寄存器非空,数据寄存器为空,之后就是直接发送

在数据1的在应答之前,我们发现EV8事件已经消失,说明此时数据寄存器DR已经被写入,也就是数据2被写入到数据寄存器DR中,应答结束后发生EV8事件,继续发送数据,如此循环往复就可以将N个数据发送

当我们发送完所有我们想要发送的数据,并且移位寄存器和数据寄存器DR都为空时,发生EV8_2事件,置TxE为1,BTF为1(字节发送结束标志位),就会触发Stop停止条件,在停止寄存器里写1,终止发送

4、主机接收

前面的部分一直到EV6事件与上方效果相同,不再赘述

EV6事件结束后发生EV6_1事件,在数据1进行移位的过程中发生,所以没有对应的时间标志,作用是清除相应和停止条件的产生位,然后给一个应答,在应答结束后说明移位寄存器已经成功移入一个字节的数据1了,此时整个字节同时转移到数据寄存器DR,同时置RxNE标志位为1(数据寄存器DR非空),也就是EV7事件

按照上述流程,一直到最后一个数据接收前提前将应答位控制寄存器ACK置0,设置STOP终止条件请求,也就是EV7_1事件,此时数据寄存器DR非空,还在接收,之后置非应答位NA,最后置STOP位

0 人点赞