@乔木 发表于 2017-8-24 19:41:33

【JESSE】STM32初学(寄存器版)——USART

接上篇:【JESSE】STM32初学(寄存器版)——位段操作
通用同步异步收发器(USART)在大部分STM32程序中都会用上,无论是功能需要,要求板子与外部设备通信,还是用于程序的调试,都离不开USART。 既然用的这么广,我们就先看看如何在寄存器模式下使用它。那首先就是要知道它的寄存器咯(有七个寄存器,分别是:状态寄存器(SR),数据寄存器(DR),波特率寄存器(BRR),控制寄存器1(CR1),控制寄存器2(CR2),控制寄存器3(CR3),还有一个保护时间和预分频寄存器(GTPR),它们的作用大家一看就知道了,最后一个寄存器可以暂时不用管,先看看它的控制寄存器USART1_CR1
位 15 OVER8:过采样模式 (Oversampling mode)
0: 16 倍过采样
1: 8 倍过采样
位 13 UE: USART 使能 (USART enable)
该位清零后, USART 预分频器和输出将停止,并会结束当前字节传输以降低功耗。此位由软
件置 1 和清零。
    0:禁止 USART 预分频器和输出
    1:使能 USART
位 12 M:字长 (Word length)
该位决定了字长。该位由软件置 1 或清零。
    0: 1 起始位,8 数据位, n 停止位
    1: 1 起始位,9 数据位, n 停止位
位 10 PCE:奇偶校验控制使能 (Parity control enable)
该位选择硬件奇偶校验控制(生成和检测)。使能奇偶校验控制时,计算出的奇偶校验位被
插入到 MSB 位置(如果 M=1,则为第9 位;如果 M=0,则为第8 位),并对接收到的数据
检查奇偶校验位。此位由软件置 1 和清零。一旦该位置1, PCE 在当前字节的后面处于活动
状态(在接收和发送时)。
    0:禁止奇偶校验控制
    1:使能奇偶校验控制
位 9 PS:奇偶校验选择 (Parity selection)
该位用于在使能奇偶校验生成/检测(PCE 位置 1)时选择奇校验或偶校验。该位由软件置1 和
清零。将在当前字节的后面选择奇偶校验。
    0:偶校验
    1:奇校验



位 3 TE:发送器使能 (Transmitter enable)
该位使能发送器。该位由软件置 1 和清零。
    0:禁止发送器
    1:使能发送器


位 2 RE:接收器使能 (Receiver enable)
该位使能接收器。该位由软件置 1 和清零。
    0:禁止接收器
    1:使能接收器并开始搜索起始位
USART_CR2
位 13:12 STOP:停止位 (STOPbit)
这些位用于编程停止位。
    00: 1 个停止位
    01: 0.5 个停止位
    10: 2 个停止位
    11: 1.5 个停止位
注意: 0.5 个停止位和 1.5 个停止位不适用于 UART4 和 UART5。
USART_CR3
位 11 ONEBIT:一个采样位方法使能 (Onesample bit method enable)
该位允许用户选择采样方法。选择一个采样位方法后,将禁止噪声检测标志 (NF)。
    0:三个采样位方法
    1:一个采样位方法
这里并没有列出它的中断使能位,中断放在下一篇进行探讨。 USART_SR
位 7 TXE:发送数据寄存器为空 (Transmit data register empty)
当 TDR 寄存器的内容已传输到移位寄存器时,该位由硬件置1。如果 USART_CR1 寄存器
中 TXEIE 位 = 1,则会生成中断。通过对USART_DR 寄存器执行写入操作将该位清零。
    0:数据未传输到移位寄存器
    1:数据传输到移位寄存器
注意: 单缓冲区发送期间使用该位
位 6 TC:发送完成 (Transmission complete)
如果已完成对包含数据的帧的发送并且 TXE 置 1,则该位由硬件置1。如果 USART_CR1 寄存
器中 TCIE = 1,则会生成中断。该位由软件序列清零(读取 USART_SR 寄存器,然后写入
USART_DR 寄存器)。 TC 位也可以通过向该位写入‘0’来清零。建议仅在多缓冲区通信
时使用此清零序列。
    0:传送未完成
    1:传送已完成
位 5 RXNE:读取数据寄存器不为空 (Readdata register not empty)
当 RDR 移 位 寄存 器 的 内 容 已 传 输 到 USART_DR 寄 存 器时,该 位 由 硬 件 置 1。如 果
USART_CR1寄存器中 RXNEIE = 1,则会生成中断。通过对 USART_DR 寄存器执行读入
操作将该位清零。 RXNE 标志也可以通过向该位写入零来清零。建议仅在多缓冲区通信时使
用此清零序列。
    0:未接收到数据
    1:已准备好读取接收到的数据
USART_DR 数据寄存器只有8位有效位,31-9都是保留位。数据寄存器包含两个寄存器,一个用于发送(TDR),一个用于接收(RDR),但是我们只能看到一个,就是(DR),因此它具有双重功能(读和写),DR具体代表哪一个寄存器取决于所执行的操作是“读取”还是“写入”。USART是通过GPIO与外部连接的,那对应的引脚就复用了特定的功能。我们从参考手册中可以找到相应的描述 说了这么多,我们来看看代码(我的板卡只引出了USART6)void usart_init(uint32_t brr)
{
    RCC->APB2ENR |= 0x01<<5;    //开启USART6的时钟
   
    USART6->CR1&= ~(0x01<<15|0x01<<13|0x01<<12|0x01<<10|0x01<<3|0x01<<2);
    USART6->CR1|= (0x01<<13|0x01<<3|0x01<<2);
    USART6->CR2&= ~(0x03<<12);
    USART6->CR3&= ~(0x01<<11);
    USART6->BRR   = 16000000/brr;
}

对应参考手册,我们知道这几行代码将USART6的控制寄存器进行了以下配置:16倍过采样使能USART1 起始位, 8 数据位,n 停止位禁止奇偶校验控制
使能发送器使能接收器并开始搜索起始位1 个停止位
三个采样位方法最后一个寄存器BRR配置的是USART6的波特率,形参brr就是波特率值,例如9600,115200等值。往BRR这个寄存器中写入的值是怎么算的呢,参考手册上有一个公式其中OVER8是过采样模式,我们采用的是16倍过采样(至于什么是16倍过采样,看参考手册吧),所以OVER8为0,fck是APB2总线时钟频率,简化之后便是:波特率 = fck/(16*USARTDIV)USARTDIV 是一个存放在 USART_BRR 寄存器中的无符号定点数(USARTDIV是个浮点数)。我们再看看波特率寄存器是什么样子的。参考手册上说,寄存器的低四位是用来存放USARTDIV的小数部分,15-4是用来存放USARTDIV的整数部分,好像有点懵逼,再说小数怎么存进去,不知道怎么做可以看看别人是怎么做的呀。正点原子是将小数部分乘以16(转16进制)再加上整数部分左移4位,之后写入BRR寄存器中的,这里好像可以发现点什么,整数左移4位不也相当于乘以16吗?小数乘以16后加上整数乘上16,再加上之前的波特率计算公式,不就相当于:波特率 = fck/写入BRR中的值将公式变换一下,就得到:写入BRR中的值 = fck/波特率这就尴尬了,绕了这么一圈。 这只是进行了USART6的相关配置,USART是通过GPIO与外部设备连接的,那肯定是要对相应的引脚进行配置了,从数据手册中我们找到了,能复用为USART6-RX和TX的引脚分别为PG9和PG14,接着便是初始化这段初始化程序和前面不同的地方在于,它配置了AFR寄存器AFR寄存器分为AFRL和AFRH(程序中的结构体将其封装为一个具有两个元素的数组),四个位控制一个引脚,共有16种复用功能。从上面的图2和图3了解到复用为USART6是AF8,所以程序便是将相应为上清零,并写入相应数值。 到这,我们只要写好发送和接收函数就可以进行简单的收发了 来张效果图
这篇帖子只是对USART进行简单的配置和应用,但是并没有将USART的问题讲述清楚,还有时钟、中断等问题,后续再更



springvirus 发表于 2018-2-1 10:57:50

写的很详细,好久没更新了。。。

@乔木 发表于 2018-2-3 11:43:40

springvirus 发表于 2018-2-1 10:57
写的很详细,好久没更新了。。。

不好意思不好意思,确实拖了很久:L。在学校做完毕设、答辩完就南下奔波了。年后找到工作稳定下来继续更,谢谢支持:)

springvirus 发表于 2018-2-5 08:27:47

@乔木 发表于 2018-2-3 11:43
不好意思不好意思,确实拖了很久。在学校做完毕设、答辩完就南下奔波了。年后找到工作稳定下来继续更, ...

辛苦了,毕业这阵子确实需要处理的事情很多

feixiang20 发表于 2018-9-5 23:55:00

谢谢分享                        
页: [1]
查看完整版本: 【JESSE】STM32初学(寄存器版)——USART