写在前面
记录STM32串口USART的学习笔记,包括 理论部分和 代码部分,理论部分讲解USART工作原理,涉及寄存器的控制,代码部分完全由库函数编写完成。
一.工作原理
1.USART功能框图
关于USART,首先要了解有关串口的基本知识,比如:同步、异步,单工、双工、半双工,串行、并行等基本概念,在51单片机中也有串口,叫做UART,和stm32单片机的串口相比少了一个S,stm32单片机的串口USART,中的S代表着同步的意思,表示其能使用同步通讯方式,使用异步通信方式的串口只需要TX和RX两根数据线即可,而同步通信方式还需要一根时钟线。stm32f10x系列芯片中包含5个串口,三个USART和两个UART,而USART1的时钟来源是APB2总线,时钟频率能达到72Mhz,其他串口最大时钟频率为32Mhz,这篇笔记以USART1为例。
首先要讲解的是USART的功能框图,图片来源野火开发板资料,如下:
1.1 引脚
关于引脚在此关注一下:TX、RX、nRTS、nCTS、SCLK。
TX & RX:发送引脚 和 接收引脚
两个硬件流控制引脚:
nRTS:请求以发送引脚,n表示低电平有效,USART准备接收新数据时候,nRTS变为低电平,接收完成变为高电平。
nCTS:清除一发送引脚,n表示低电平有效,发送器在发送下一帧数据时候检测nCTS,如果为低电平,则可以发送数据,否则在发送完前一帧数据后停止发送。
SCLK:发送器时钟输出引脚,仅用于同步模式。
1.2 数据寄存器USART_DR
USART外设包含这几个主要寄存器:
- USART_DR:数据寄存器
- USART_SR:状态寄存器
- USART_BRR:波特率寄存器
- USART_CR1:控制寄存器1
其中上图中的2表示的是数据寄存器USART_DR,USART_DR只有9位有效,并且第九位是否有效取决于USART控制器寄存器USART_CR1的M位设置,M=0,则为8位数据字长,M=1,则为9位数据字长,一般使用8位数据字长。
USART_DR包含两个寄存器 TDR和 RDR,前者是专门用于 发送 的 可写寄存器,后者是专门用于 接收 的 可读 寄存器。
串口通信是一个位一个位的传输,发送数据时候总线把数据为TDR寄存器,TDR寄存器数据转移到发送移位寄存器,然后把数据发送出去,接收数据时候把接收到的数据一位一位顺序保存到接收移位寄存器,再转移到RDR寄存器,再传给总线,配合上图2部分理解。
1.3 控制器
USART有专门控制发送的发送器和专门控制接收的接收器,还有唤醒单元,中断控制等,控制器分为发送器控制和接收器控制,使用USART之前向USART_CR1寄存器的UE位置1,使能USART.
1.3.1 发送器控制及字符帧组成
将USART_CR1寄存器发送使能位 TE 置1,启动数据发送,发送移位寄存器在TX引脚输出,低位在前,高位在后。发送的数据为字符帧,一个字符帧由三个部分组成,起始位、数据帧、停止位。
起始位是一个位周期的低电平,位周期是每一位数据占用的时间。
数据帧表示要发送的数据,8位或者9位,从低位开始传输。
停止位是一定时间周期的高电平,这个一定时间可以是0.5、1、1.5、2个周期,默认使用一个周期的停止位。通过USART_CR2的stop[1:0]控制。
发送数据的流程:发送使能位TE置1,发送器先发送一个空闲帧(一个数据帧长度的高电平),接着往USART_DR寄存器的 发送数据寄存器TDR写入数据,发送寄存器 把数据全部转到 移位寄存器 后,UDART_SR的TXE位置1,表示 发送寄存器 为空,发送移位寄存器 发送最后一个数据之后,USART_SR的TC位置1,表示数据传输完成。如果USART_CR1寄存器的TCIE位置1,可产生中断。
1.3.2 接收器控制
接收数据流程:USART_CR1寄存器的RE置1,使能USART接收,接收器在RX线上开始搜索起始位,确定起始位之后,根据RX电平状态,把数据放在 接收移位寄存器 中,接收完成后,把数据移到 接收数据寄存器RDR 内,并把USART_SR寄存器的RXNE位置1。如果USART_CR1的RXNEIE置1,可产生中断。
1.4 波特率
波特率表示数据传输的速率,波特率越大,速率越快,USART发送器和接收器使用相同的波特率,波特率计算公式如下:
波特率=$$\frac{f_{ck}}{16*USARTDIV}$$
fck表示时钟频率。
USARTDIV是一个存放在波特率寄存器USART_BRR中的无符号定点数。DIV_Mantissa[15:4]定义整数部分,DIV_Fraction[3:0]表示小数部分。
例1DIV_Mantissa=24(0x18),DIV_Fraction=10(0x0A),则USART_BRR的值为0x18A。那么USARTDIV的小数部分为 10/16=0.625,则USARTDIV等于24.625。
例2以USART1为例子,为了得到115200的波特率,则USARTDIV该取多少?
由波特率公式一个算的UDARTDIV等于39.0625,可以知道DIV_Fraction=16 * 0.0625=1=0x01(取最近似值),DIV_Mantissa=39=0x27,故USART_BRR等于0x271。
1.5 校验控制
使用奇偶校验则串口传输长度是8位数据帧加上1位校验位共9位,此时USART_CR1的M位置1,。USART_CR1寄存器的PCE位置1,可以启动奇偶位校验控制位。
奇偶校验由硬件自动完成,发送数据帧自动加校验位,接收时自动验证。此时的一个字符帧为:
起始位+数据帧+校验位+停止位
1.6 中断控制
USART有多个中断请求事件,其中有TXE、TC、RXNE中断时间比较常用,如下表格
中断事件 | 事件标志 | 使能控制位 |
---|---|---|
发送数据寄存器位空 | TXE | TXEIE |
CTS标志 | CTS | CTSIE |
发送完成 | TC | TCIE |
准备好读取接收到的数据 | RXNE | RXNEIE |
检测到上溢错误 | ORE | RXNEIE |
检测到空闲线路 | IDLE | IDLEIE |
奇偶校验错误 | PE | PEIE |
断路标志 | LBD | LBDIE |
多缓冲通信中噪声、上溢、帧错误 | NF/ORE/FE | EIE |
二.代码
标准库函数对每一个外设都建立了一个初始哈结构体,USART的初始化结构体就是USART_InitTypDef,结构体成员用于设置外设工作参数,并由外设初始化函数调用,如USART_Init(),初始化结构体设定的参数将会通过设置外设相应的寄存器,完成配置外设的工作。初始化结构体和初始化库函数配合使用是标准库的精髓所在。
USART的初始化结构体:
1 | typedef struct{ |
USART时钟初始化结构体
1 | typedef struct{ |
在使用同步模式的时候需要配置时钟初始化结构体。
USART串口实验,代码编写
- 使能TX和RX引脚的GPIO时钟和USART时钟。
- 初始化GPIO,并将GPIO复用到USART。
- 配置USART参数。
- 配置中断控制器,并使能USART接受中断。
- 使能USART。
- 在USART接受中断服务函数实现中断功能。
1 | static void USART_Config(void) |
通过以上代码块完成USART的初始化配置,后续需要完成USART串口发送函数的编写。
字符发送函数
1 | /************************发送一个字符************************/ |