STM32芯片具有多个USART外设用于串口通讯,USART(通用同步异步收发器)能够灵活地与外部设备进行全双工通讯。USART的全称“通用同步异步收发器”,也就是说他可以同步通信也可以异步通信。但是我们实现串口打印调试信息到电脑,其实只用到了他的异步通信的功能。
USART除了有串口功能,它满足外部设备对工业标准NRZ 异步串行数据格式的要求,并且使用了小数波特率发生器提供了多种波特率,使得它的应用更加广泛。它还支持同步单向通信和半双工单线通信;还支持 LIN(局域互连网络)、智能卡协议与 IrDA(红外线数据协会) SIR ENDEC 规范,以及调制解调器操作 (CTS/RTS)。而且,它还支持多处理器通信。所以说USART还是很强悍的,我们不可能一一讲解这些功能,其他功能还有待大家一起去研究。具体这些功能的详细介绍可查看《STM32F4xx中文参考手册》26章通用同步异步收发器(USART)。
此图我们可以分为四部分讲解分为引脚讲解、波特率发生器、USART控制单元、数据交换相关寄存器。
Tx:发送数据输出引脚
Rx:接收数据输入引脚
SW_Rx:数据接收引脚,只用于单线和智能卡模式,属于内部引脚,没有具体外部引脚。
nRST:请求以发送(Request To Send), n 表示低电平有效。如果使能 RTS 流控制,当USART 接收器准备好接收新数据时就会将 nRTS 变成低电平;当接收寄存器已满时,nRTS 将被设置为高电平。该引脚只适用于硬件流控制。
nCTS:清除以发送(Clear To Send), n 表示低电平有效。如果使能 CTS 流控制,发送器在发送下一帧数据之前会检测 nCTS 引脚,如果为低电平,表示可以发送数据,如果为高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。
SCLK:发送器时钟输出引脚。这个引脚仅适用于同步模式。
STM32F411CCU6一共有3个USART,USART1和USART6时钟来源与APB2总线时钟,其最大频率为100MHz, USART2来源于APB1总线时钟,其最大频率为50MHz。也就意味着他们的最大通讯速率也是不同的。
看USART内部框图2部分,USART的发送器速率控制与接收器速率控制共用一个波特率寄存器(USART_BRR),波特率寄存器里存放的是时钟分频值它一共16位,分为整数部分DIV_Mantissa[16:5]和小数部分DIV_Fraction[4:0]两部分。 USART通信所需波特率是对相应总线时钟分频然后一系列计算所得到的。USART波特率计算公式如下:
fck:系统总线时钟。USART1和USART6在APB2总线下,USART2在APB1总线下
0VER8:是由USART_CR1的第15位设置。O:16倍过采样;1:8倍过采样
USARTDIV:波特率分频系数,USART_BRR配置得到。USARTDIV的计算公式
USARTDIV = DIV_Mantissa + (DIV_Fraction/8 * (2-OVER8))
以下例题:
1.知USARTDIV(10进制)算出USART_BRR(16进制)的值
例如:如果OVER8=0, USARTDIV=25.62,求USART_BRR?
DIV_Fraction = 16*0.62 = 9.92 约等于10 = 0xA;
DIV_Mantissa = 25 = 0x19;
则USART_BRR = 0x19A;
2.知USART_BRR(16进制)算出USARTDIV(10进制)的值
例如:如果OVER8=0, USART_BRR=0x1BC,求USARTDIV?
DIV_Mantissa = 0x1B = 27;
DIV_Fraction = 12/16 = 0.75;
则USARTDIV = 27.75;
例如:USART1通信的波特率位115200,0VER8=0,fck = 100Mhz,求USARTDIV?
解得USARTDIV = 54.253472,可根据上面公式算出DIV_Mantissa = 0x36, DIV_Fraction = 0x4,那么USART_BRR = 0x364
在计算 DIV_Fraction 时经常出现小数情况,经过我们取舍得到整数,这样会导致最终输出的波特率较目标值略有偏差。下面我们从 USART_BRR 的值为 0x364 开始计算得出实际输出的波特率大小。
由 USART_BRR 的值为 0x364,可得 DIV_Fraction=4, DIV_Mantissa=54,所以USARTDIV=54+4/16 =54.25,所以实际波特率为: 115207;这个值跟我们的目标波特率误差为 0.03%,这么小的误差在正常通信的允许范围内。
0VER8=1时,8 倍过采样时计算情况原理是一样的。此部分内容不必全部搞懂,波特率具体计算在库函数中都已完成,不用我们一一计算。
看USART内部框图3部分,是整个USART外设的控制单元,包括发送控制器、唤醒单元、接收控制器,我们通过配置寄存器相应位来设置这些控制器的工作模式,USART的配置寄存器一共有三个我们在这里不一一讲解,我们看这个框图只需理解USART的大致工作过程即可,具体寄存器的配置我们直接调用库函数即可配置,无需我们一位一位的手动配置,如想仔细了解各寄存器的位详细意义,可参考《STM32f4xx中文参考手册》和《RM0383_STM32F411CCU6_Reference manual》。
发送控制器:工作在发送模式,它将按照程序设置的波特率、帧格式将CPU的数据或者DMA总线上的数据一位一位送到Tx引脚。
接收控制器:工作在接收模式,它将按照程序设置的波特率、帧格式将数据从Rx引脚一位一位的接收外部发来的数据并上传给CPU或者DMA。
看USART内部框图4部分,此部分是USART外设外部与内部总线和DMA联系的接口,4部分一共四个寄存器,发送模式用的“发送数据寄存器(TDR)”和“发送移位寄存器”,接收模式用的“接收数据寄存器(RDR)”和“接收移位寄存器”。其实TDR和RDR都属于数据寄存器(USART_DR)具体寄存机介绍看《STM32F4xx中文参考手册》。我们用的时候可以当成两个用。
内部总线有数据需要发送时,
Rx引脚有数据输入时,
首先要使能接收即USART_CR1的RE位置1;
然后Rx引脚移入数据的最低有效位,到“接收移位寄存器”;
当“接收移位寄存器”8位满时,将数据一次性写入“接收数据寄存器(RDR)”;(该操作将RXNE置1既接收数据寄存器非空,总线可读取)
总线发现RXNE=1时立即读取数据并将RXNE置零(注意接收期间每接收一个字节RXNE都置1)
循环执行上面操作,直到Rx引脚将最后一字节数据传送入“接收数据寄存器(RDR)”后,等待总线读取完成。