之前博文介绍了串口协议,本文接下来就介绍STM32的USART外设的基础内容。
1. USART英文全称是Universal Synchronous/Asynchronous Receiver/Transmitter,直译就是通用同步/异步收发器,里面S就是同步的意思。另外还有一个经常用到的串口,叫UART,少了个S,就是异步收发器。一般串口很少使用同步功能,所以USART和UART使用起来也没有什么区别。其实STM32的USART同步模式只是多了个时钟输出而已,USART同步模式只支持时钟输出,不支持时钟输入。所以USART同步模式更多的是为了兼容别的协议或者特殊用途而设计的,并不支持两个USART之间进行同步通信。所以对串口的学习,主要还是异步通信。
2. USART是STM32内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧时序,从TX引脚发送出去,也可自动接收RX引脚的数据帧时序,拼接为一个字节数据,存放在数据寄存器里。上文通信协议中讲,串口主要就是靠收发约定好的电压波形来进行通信的。USART外设就是串口通信的硬件支持电路,USART大致可以分为发送和接收两部分,发送部分就是将数据寄存器的一个字节数据自动转换为协议规定的波形,从TX引脚发送出去。接收部分就是,自动接收RX引脚的波形,按照协议规定解码为一个字节数据,存放在数据寄存器里。这就是USART电路的功能,当配置好USART电路,直接读写数据寄存器,就能自动发送和接收数据了。
3. 自带波特率发生器,最高达4.5Mbits/s。波特率发生器就是用来配置波特率的,它其实就是一个分频器,比如APB2总线给个72MHz的频率,然后波特率发生器进行一个分频,可以得到需要的波特率时钟,最后在这个时钟下进行收发,就是指定的通信波特率。
4. 可配置数据位长度(8/9)、停止位长度(0.5/1/1.5/2)这些就是STM32 USART支持配置的参数了。数据位长度就是发送一帧数据的长度,有8位和9位,是包含奇偶校验位的长度。一般不需要校验位就选8位,需要校验就选9位。停止位长度支持0.5、1、1.5、2这么多种停止位。在进行连续发送时,停止位长度决定了帧的间隔。最常用的就是1位停止位,其他的很少使用。
5. 可选校验位(无校验/奇校验/偶校验),最常用的是无校验。
波特率、数据长度和校验位都是可以通过配置寄存器来完成的。使用库函数配置的话直接给结构体赋值就行。串口参数最常用的配置就是:波特率9600或者115200,数据位8位,停止位1位,无校验。
6. 支持同步模式、硬件流控制、DMA、智能卡、IrDA、LIN。
7.STM32F103C8T6 芯片的USART资源有 USART1、 USART2、 USART3,总共3个的USART外设,可以挂载很多串口设备。其中USART1是APB2总线上的设备,USART2和USART3是APB1总线的设备,开启时钟时需注意。
框图中把各个寄存器和寄存器每一位控制的地方都画出来了,显得框图比较复杂。在看框图的时候可以忽略这些寄存器,先看主体结构。
TX发送引脚,RX接收引脚。SW_RX、IRDA_OUT/IN这些是智能卡和IrDA通信的引脚,本文不重点介绍。
发送或接收的字节数据就存在串口数据寄存器里。
下方是两个移位寄存器,一个用于发送数据,一个用于接收数据。
数据发送端的发送数据寄存器TDR和发送移位寄存器的工作逻辑这里举例来说明,比如在某时刻给TDR寄存器写入了0x55这个数据,在寄存器里就是二进制存储 0101 0101,那么此时硬件检测到你写入数据了,就会检查当前发送移位寄存器是不是有数据位正在移位,如果没有移位,数据0101 0101就会立刻全部移动到发送移位寄存器,准备发送。
当数据从TDR寄存器移动到移位寄存器时,会置一个标志位,叫做TEX(TX Empty)发送寄存器空。检查TEX标志位,如果置1了,就可以在TDR寄存器写入下一个数据了。注意一下,当TXE标志位置1时,数据其实还没有发送出去。只要数据从TDR寄存器转移到发送移位寄存器了,TXE就会置1,就可以写入新的数据了。发送移位寄存器就会在发送器控制的驱动下向右移位,然后一位一位地把数据输出到TX引脚。因为是向右移位,所以正好和串口协议规定的低位先行是一致的。
当数据移位完成后,新的数据就会再次自动地从TDR寄存器转移到发送移位寄存器里来。如果当前移位寄存器移位还没有完成,TDR寄存器的数据就会进行等待,一旦移位完成,就会立刻转移过来。有了TDR寄存器和发送移位寄存器的双重缓存,可以保证连续发送数据的时候,数据帧之间不会有空闲,提高了工作效率。简单来说,就是数据一但从TDR寄存器转移到了发送移位寄存器了,不管移位有没有完成,就立刻把下一个数据放在TDR寄存器等着。一但数据移完了,新的数据就会立刻跟上。这样效率就会比较高。
数据接收端这里也是和发送端类似的,数据从RX引脚通向接收移位寄存器,在接收器控制的驱动下,一位一位的读取RX电平,先放在最高位,然后向右移,移位8次之后,就能接收一个字节了。同样,因为串口协议规定是低位先行,所以接收移位寄存器是从高位往低位这个方向移动的,之后当一个字节移位完成之后,这一个字节的数据就会整体的一下子转移到接收数据寄存器RDR里来。在转移过程中也会置一个标志位,RSNE(RX Not Empty)接收数据寄存器非空。当检测到RXNE置1之后,就可以把数据读走了。同样,这里也是两个寄存器进行缓存,当数据从接收移位寄存器转移到RDR时,就可以直接移位接收下一帧数据了。这就是USART外设整个的工作流程。
以上内容对USART外设的主要功能就讲述的差不多了,大体上就是数据寄存器和移位寄存器。发送移位寄存器往TX引脚移位,接收移位寄存器从RX引脚移位。当然发送还需要加上帧头帧尾,接收还需要剔除帧头帧尾,这些操作在USART内部有电路会自动执行,只需要知道有硬件做了这些工作就可。接着继续分析一下控制部分和其他的增强功能。
发送器控制,是用来控制发送移位寄存器的工作的。
接收器控制,是用来控制接收移位寄存器的工作的。
硬件数据流控,也就是硬件流控制简称流控,如果发送设备发的太快,接收设备来不及处理,就会出现丢弃或覆盖数据的现象。那有了流控就可以避免这个问题了。流控有两个引脚,一个是nRTS,一个是nCTS。前面加个n意思是低电平有效。
这两个引脚的工作逻辑:首先得找另一个支持流控的其它设备的串口,其它设备的TX接到本设备的RX。然后本设备的RTS要输出一个能不能接收数据的反馈信号,接到对方的CTS。当本设备能接收的时候,RTS就置低电平,请求对方发送。对方的CTS接收到之后,就可以一直发。当本设备处理不过来时,比如接收数据寄存器本设备一直没有读,又有新的数据过来了,现在就代表本设备没有及时处理,那RTS就会置高电平,对方CTS接收到之后,就会暂停发送。直到接收数据寄存器被读走,RTS置低电平,新的数据才会继续发送。那反过来,当本设备的TX给对方发送数据时,本设备CTS就要接收到对方的RTS,用于判断对方,能不能接收。TX和CTS是一对的,RX和RTS是一对的。CTS和RTS也要交叉连接。这就是流控的工作模式,流控一般不常使用,了解即可。
SCLK控制和SCLK引脚这部分电路用于产生同步的时钟信号,是配合发送移位寄存器输出的,发送寄存器每移位一次,同步时钟电平就跳变一个周期。时钟告诉对方,本设备已移出去一位数据了,接收方看看要不要让本设备的时钟信号来指导接收方接收一下。当然这个时钟只支持输出,不支持输入,所以两个USART之间,不能实现同步的串口通信。那这个时钟信号有什么用呢?第一个用途是,兼容别的协议,比如串口加上时钟之后,就跟SPI协议特别像,所以有了时钟输出的串口,就可以兼容SPI。另外这个时钟也可以做自适应比特率,比如接收设备不确定发送设备给的什么波特率,那就可以测量一下这个时钟的周期,然后再计算得到波特率,不过这就需要另外写程序来实现这个功能了。这个时钟功能不常用,了解即可。
图中USART中断控制这部分是中断输出控制,中断申请位就是SR状态寄存器这里的各种标志位。SR状态寄存器这里有两个标志位比较重要,一个是TXE发送寄存器空,另一个是RXNE接收寄存器非空。这两个是判断发送状态和接收状态的必要标志位,剩下的标志位了解一下就行。
中断输出控制就是配置中断是不是能通向NVIC。
波特率发生器其实就是分频器,APB时钟进行分频,得到发送和接收移位的时钟。这里时钟输入是fPCLKx(x=1或2),USART1挂载在APB2,所以就是PCLK2的时钟,一般是72M;其他的USART都挂载在APB1,所以是PCLK1的时钟,一般是36M。之后这个时钟进行一个分频,除一个USARTDIV的分频系数。USARTDIV里面就是图中指向USARTDIV的虚线框中的样子,USARTDIV是一个数值。并且分为了整数部分和小数部分,因为有些波特率用72除一个整数的话,可能除不尽,会有误差。所以这里分频系数是支持小数点后4位的,分频就更加精准。分频完之后,还要再除个16,得到发送器时钟和接收器时钟,通向控制器部分。然后在虚线框USARTDIV内部里:
以上对串口的主体结构就介绍完了。还有一些寄存器中每一位的指示可以看看STM32手册里的寄存器描述。
引脚定义表中复用功能这一栏,就给出了每个USART的各个引脚都是复用在了哪个GPIO上的。
这些引脚都必须按照引脚定义里的规定来,若引脚使用冲突可以查看重映射部分,也就是表中重定义这一列。
时钟来源是PCLK2或1.
波特率发生器,用于产生约定的通信速率。
经过波特率发生器分频后产生的时钟通向发送控制器和接收控制器。
发送部分:
由发送数据寄存器和发送移位寄存器这两个寄存器的配合,将数据一位一位地移出去,通过GPIO的复用输出,输出到TX引脚,产生串口协议规定的波形。
图中发送移位寄存器标记的右移的符号>>就是代表发送移位寄存器是往右移的,是低位先行。
当数据由数据寄存器转移到移位寄存器时,会置一个TXE的标志位,判断这个TXE标志位就可以知道是不是可以写下一个数据了。
接收部分:
接受部分也是类似的,RX引脚的波形,通过GPIO口输入,在接收控制器的控制下,一位一位地移入接收移位寄存器。
图中接收移位寄存器标记的右移的符号>>就是代表接收移位寄存器也是往右移的,是低位先行。所以图中数据传输的箭头指向是从接收移位寄存器的左边开始移进来,移完一帧数据后,数据就会统一转运到接收数据寄存器。
在数据转移的同时,置一个RXNE标志位,检查这个RXNE标志位就可以知道是不是收到数据了,同时这个标志位也可以去申请中断,这样就可以在收到数据时,直接进入中断函数,然后快速地读取和保存数据。
图右边虽然有4个寄存器,但在软件层面,只有一个DR寄存器可以读写。写入DR时,数据走上面发送部分的两个寄存器,进行数据发送;读取DR时,数据走下面接收部分的两个寄存器,进行数据接收。
以上就是USART进行串口数据收发的过程,图中右下角还有一个开关控制,就是配置完成之后,用Cmd函数开启一下外设。
上图是在程序中配置8位字长和9位字长的波形对比,这里的字长就是数据位长度。图中的字长是包含校验位的数据帧格式。
图上半部分9位字长的波形:
1.数据帧波形
第一条时序,很明显就是TX发送或者TX接收的数据帧格式。空闲高电平,接着起始位置0。然后根据写入的数据,置1或0,依次发送位0到位8,加起来就是9位。最后停止位置1,数据帧结束。
在这里位8,也就是第9个位置,是一个可能的奇偶校验位,通过配置寄存器就可以配置成奇校验、偶校验或者无校验。
这里可以选择配置成8位有效载荷加1位校验位,也可以选择9位全都是有效载荷。只不过既然选择了9位字长,那一般都是要加上校验位的,因为8位有效载荷,正好对应一个字节。
2.时钟波形
时钟的这一条波形就是之前说的同步时钟输出的功能,可以看到,在每个数据位的中间,都有一个时钟上升沿。时钟的频率和数据速率也是一样的,接收端可以在时钟上升沿进行采样,这样就可以精准定位每一位数据。
这个时钟的最后一位可以通过LBCL位控制输出还是不输出,另外这个时钟的极性、相位等也可以通过配置寄存器来配置。
3.空闲帧和断开帧波形
空闲帧就是从头到尾都是1.
断开帧就是从头到尾都是0.
空闲帧和断开帧是局域网协议用的,串口用不到。
图下半部分8位字长的波形:
8位字长的数据位是从位0一直到位7,总共是8位,比图中上方的9位字长少了一个位8。同样这个8位字长的最后一位位7,也是一个可能的奇偶校验位。但是既然选择了8位字长,那这里就是最好选择无校验,不然校验位占1位,有效载荷就只剩7位了,一个字节都发不了了。
总的来说,一共有四种选择:
其中最好选择9位字长有校验或8位字长无校验这两种,这两种的每一帧有效载荷都是1字节。
8位字长的时钟、空闲帧、断开帧和9位字长的类似。
看一下数据帧里不同停止位的波形变化,STM32的串口可以配置停止位长度为0.5、1、1.5、2这四种。这四种参数的区别就是停止位的时长不一样。
对应波形:
以上可以理解,就是控制停止位时长的,一般选择1位停止位就行了,其他的参数不太常用。
来看一些细节问题,对于串口来说,输出的TX应该是比输入的RX简单很多。
输出就定时翻转TX引脚高低电平就行了。
但是输入就复杂一些。不仅要保证输入的采样频率和波特率一致,还要保证每次输入采样的位置要正好处于每一位的正中间,只有在每一位的正中间采样时高低电平读进来才是最可靠的。如果采样点过于靠前或靠后,那有可能高低电平还正在翻转,电平还不稳定,或者稍有误差,数据就采样错了。
另外输入最好还要对噪声有一定的判断能力,如果是噪声,最好能置个标志位提醒一下。
以上就是输入数据所面临的问题。下面来看一下STM32设计的输入电路USART输入数据的一些策略。
起始位侦测图,展示的是USART的起始位侦测。
当输入电路侦测到一个数据帧的起始位后,就会以波特率的频率连续采样一帧数据。同时,从起始位开始,采样位置就要对齐到位的正中间,只要第一位对齐了,后面就肯定都是对齐的。
为了实现这些功能,首先输入的这部分电路对采样时钟进行了细分,它会以波特率的16倍频率进行采样,也就是在一位的时间里可以进行16次采样。
它的策略是,最开始空闲状态高电平,那采样就一直是1,在某个位置突然采到一个0,那么就说明在这两次采样之间出现了下降沿。
如果没有任何噪声,那之后就应该是起始位了。在起始位会进行连续16次采样,没有噪声的话,这16次采样肯定就都是0,这没问题。
但是实际电路还是会存在一些噪声的,所以这里即使出现下降沿了,后续也要再采样几次,以防万一。
根据STM32的手册里描述,接收电路还会在下降沿之后的理想的采样时钟那一行的第3次、5次、7次进行一批采样,在第8次、9次、10次再进行一批采样,且这两批采样都要求每3位里面至少应有2个0.
这就是STM32的串口在接受过程中对噪声的处理,如果通过了这个起始位侦测,那接收状态就由空闲变为接收起始位,同时理想的采样时钟那一行的第8、9、10次采样的位置就正好是起始位的正中间。之后接收数据位时,就都在第8、9、10次,进行采样,这样就能保证采样位置在位的正中间了。这就是起始位侦测和采样位置对齐的策略。
采样时钟从1到16是一个数据位的时间长度。在一个数据位有16个采样时钟,由于起始位侦测已经对齐了采样时钟,所以就直接在采样时钟第8、9、10次采样数据位。为了保证数据的可靠性,这里是连续采样3次。没有噪声的理想情况下,这3次肯定会全为1或者全为0.
如果有噪声导致3次采样不是全为1或者全为0,那就按照2:1的规则来:
在这种情况下,噪声标志位NE也会置1.就是提醒一下,数据是收到了,但是有噪声,用的时候注意。
以上就是检测噪声的数据采样,可见STM32对这个电路的设计考虑还是很充分的。
波特率发生器就是分频器。
发送器和接收器的波特率由波特率寄存器BRR里的DIV确定。
图中就是BRR寄存器,里面就是分频系数DIV。DIV分为整数部分和小数部分,可以实现更细腻的分频。
波特率和分频系数的关系可以由以下公式进行计算:
公式里需要除16倍的DIV的原因是它内部还有一个16倍波特率的采样时钟,可从检测噪声的数据采样图中看到。
举例:
比如要配置USART1为9600的波特率,那如何配置BRR寄存器呢?
代入公式:9600 = 72M /(16*DIV) 解得:DIV = 72M/9600/16 = 468.75
注:USART1的时钟是72M
最终解得DIV是一个带小数的分频系数,最终写到寄存器还需要装换成二进制。
由进制装换器计算468.75转换为二进制为11101 0100.11,写到波特率寄存器就是:
以上就是根据波特率写BRR波特率寄存器的方法,可以了解一下。实际用库函数的配置方法非常方便,需要多少波特率可直接写,库函数会自动帮忙算好。
HEX模式,有的地方也称做十六进制模式或者二进制模式,这些称呼都是一个意思,它表示的是以原始数据的形式显示。收到什么数据就把这个数据本身显示出来。在这种模式下只能显示一个个的十六进制数。
此表就是ASCII码字符集的大概分布。
在表的前面这里,还有一些不可见字符,比如退格、换行、换页等等,这些字符可以用于控制文本的打印。
字符集的第一个字符,原始数据是0x00,对应字符是空字符,也就是保留位,不映射任何字符。一般这个0x00经常用作为字符串的结束标志位,字符串遇到数据0x00之后,就代表字符串结束了。
在做数据和字符串的相互转换时,需要查一下这个表。ASCII码是一种最简单且最常用的字符集。如果想显示和存储汉字的话,也得制定汉字的字符集,那由于汉字比较多,就需要多个字节才能编码一个汉字。常用的汉字字符集有GB2312、GBK、GB18030等等。
对应外国也有相应的字符集,随着计算机的发展,全球互相通信,为了防止不同国家编码的不兼容现象,可以把所有国家的字符全部收录到一个统一的字符集,于是就有了Unicode字符集,Unicode最常用的传输形式是UTF8。如果编码不匹配就会出现乱码现象。
这个图描述的是字符和数据,在发送和接收的转换关系。
图上方发送0x41数据,发送到线路传输就是0x41.接收方如果以原始数据形式显示,就是0x41;如果以字符显示,就是走下方这一路,通过字符集译码。这个译码的字符集就是ASCII码、GBK、UTF8等等。通过字符集译码,找到字符,然后显示字符A。
在发送方也可以直接发送字符,比如发送字符A,这时它就会先从字符集找到A的数据,进行编码,发现A对应的数据是0x41,最终在线路中传输的必须是十六进制数0x41,然后接收方可以选择查看原始数据0x41,也可进行译码,得到字符A。这就是字符和数据在发送接受过程中经历的变化。
以上就是今天要讲的内容,本文仅仅简单介绍了STM32的USART外设的基础内容。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- azee.cn 版权所有 赣ICP备2024042794号-5
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务