串口其实就是一种通信协议。
什么是通信协议?
通信双方在数据交流的过程中需要遵守的规则。
1.1 补充(常用通信协议分类及其特征介绍)
1. 同步、异步
同步:通信双方在同一个时钟脉冲下进行通信
异步:通信双方的时钟脉冲由各自提供
2. 单工、半双工、全双工
单工:在一个通信系统中,发送数据的一方叫发送发,接受数据的一方叫接受方,一旦角色确定下来后,永远不会改变。(遥控器)
半双工:在一个通信系统中,一个设备既可以作为发送方发送数据,也可以作为接收方接受数据,但是同一时刻只能拥有一种身份。----可以切换方向的单工 (对讲机)
全双工:在一个通信系统中,同一个设备同一时刻既是发送方,也是接收方,同时收发数据。(电话,手机)
3. 串行、并行
串行:只有一根数据线,数据一位一位地传输
并行:有多跟数据线,数据多位传输
4. 现场总线、板级总线
现场总线:没有固定在PCB板上的总线。( can )
板级总线:固定在PCB班上的总线。(串口、IIC、SPI)
UART原理示意图:
UART数据帧格式
启动位:
一个bit的低电平时间,一帧的数据的开始
数据位:
传输的有效数据,可以是5-8位
奇偶校验位:
当开启了奇偶校验功能时,数据位的最高位就作为奇偶校验位;如果不开启奇偶校验功能时,就不奇偶校验位。用于验证数据传输过程中是否有数据丢失。
奇偶校验精度只有50%。
CRC校验精度高达99.7%。
停止位:
1个位的高电平时间。(可设置成0.5、1、1.5、2bit)
一取数据位为8,不开奇偶校验,停止位为1。
UART四要素
- 数据位
- 奇偶校验位
- 停止位
- 波特率(bps):bit per second,每秒传输多少位数据。
通信双方必须在同一个波特率下进行通信
2. STM32的UART
异步串行全双工
universal synchronous asynchronous receiver transmitter
通用同步异步收发器 (USART) 能够灵活地与外部设备进行全双工数据交换,满足外部设备对工业标准 NRZ 异步串行数据格式的要求。 USART 通过小数波特率发生器提供了多种波特率。
它支持同步单向通信和半双工单线通信;还支持 LIN(局域互连网络)、智能卡协议与 IrDA(红外线数据协会) SIR ENDEC 规范,以及调制解调器操作 (CTS/RTS)。而且,它还支持多处理器通信。通过配置多个缓冲区使用 DMA 可实现高速数据通信。
STM32的UART特征(节选)
● 全双工异步通信
● NRZ 标准格式(标记/空格)
● 可配置为 16 倍过采样或 8 倍过采样,因而为速度容差与时钟容差的灵活配置提供了可能
● 小数波特率发生器系统
— 通用可编程收发波特率(有关最大 APB 频率时的波特率值,请参见数据手册)。
● 数据字长度可编程(8 位或 9 位)
● 停止位可配置 - 支持 1 或 2 个停止位
● 传输检测标志:
— 接收缓冲区已满
— 发送缓冲区为空
— 传输结束标志
STM32的UART框架
框架分析
将框架划分成4个部分:
-
外部接口部分
TX:数据发送管脚
RX:数据接收管脚
SW_RX:不属于标准串口
nRTS:问对方忙不忙(不属于标准串口)
nCTS:告诉对方你忙不忙(不属于标准串口)
SCLK:在同步模式下发送同步信号的(不属于标准串口) -
数据收发传输部分
数据寄存器(DR)其实在内部分成两个寄存器,一个是用于发送的TDR寄存器,另一个是用于接收的RDR寄存器。我们对DR寄存器进行写操作时,实际上实在操作TDR寄存器,对DR寄存器进行读操作时,实际上是在操作RDR寄存器。
串口接受数据:数据从RX管脚一位一位地传输到接受移位寄存器里面,当接受移位寄存器接受满了后,就会自动送上接受数据寄存器(RDR),硬件就会使接受满标志位置1,我们直接读取DR寄存器就可以读取到串口接收到的数据。
串口发送数据:当发送缓冲区为空时,我们把要发送的数据直接写入到DR寄存器中,发送数据寄存器(TDR)就会将此数据传输到发送移位寄存器中,然后一位一位输出到TX端。 -
控制器部分
通过配置发送控制器和接受控制器来控制数据收发传输过程。主要是配置CR1控制寄存器。 -
小数波特率部分
-
以USART1为例:
fck=84Mhz.OVER8=0(过采样模式),波特率的值为bond.这些都是已知量。从此可以求出USARTDIV的值,将这个值写入到USART_BRR寄存器里面。
float USARTDIV;u32 DIV_Man;u32 DIV_Fra;
USARTDIV=84000000.0/(16*bond);
DIV_Man=USARTDIV;
DIV_Fra=(USARTDIV-DIV_Man)*16+0.5;
USART_BRR = DIV_Man<<4 | DIV_Fra;
注意:USART_BRR是寄存器,看手册
位 31:16 保留,必须保持复位值
位 15:4 DIV_Mantissa[11:0]:USARTDIV 的尾数
这 12 个位用于定义 USART 除数 (USARTDIV) 的尾数
位 3:0 DIV_Fraction[3:0]:USARTDIV 的小数
这 4 个位用于定义 USART 除数 (USARTDIV) 的小数。当 OVER8 = 1 时,不考虑 DIV_Fraction3
位,且必须将该位保持清零。
3.4 STM32的UART寄存器
3.4.1 状态寄存器 (USART_SR)
位 7 TXE:发送数据寄存器为空 (Transmit data register empty)
当 TDR 寄存器的内容已传输到移位寄存器时,该位由硬件置 1。如果 USART_CR1 寄存器
中 TXEIE 位 = 1,则会生成中断。通过对 USART_DR 寄存器执行写入操作将该位清零。
0:数据未传输到移位寄存器
1:数据传输到移位寄存器
注意: 单缓冲区发送期间使用该位。
位 5 RXNE:读取数据寄存器不为空 (Read data register not empty)
当 RDR 移 位 寄 存 器 的 内 容 已 传 输 到 USART_DR 寄 存 器 时,该 位 由 硬 件 置 1。如 果
USART_CR1 寄存器中 RXNEIE = 1,则会生成中断。通过对 USART_DR 寄存器执行读入
操作将该位清零。 RXNE 标志也可以通过向该位写入零来清零。建议仅在多缓冲区通信时使
用此清零序列。
0:未接收到数据
1:已准备好读取接收到的数据
3.4.2 数据寄存器 (USART_DR)
位 8:0 DR[8:0]:数据值
3.4.3 波特率寄存器 (USART_BRR)
3.4.4 控制寄存器 1 (USART_CR1)
位 15 OVER8:过采样模式 (Oversampling mode)
0: 16 倍过采样
1: 8 倍过采样
注意: 8 倍过采样在智能卡、 IrDA 和 LIN 模式下不可用:当 SCEN=1、 IREN=1 或 LINEN=1 时,
OVER8 由硬件强制清零。
位 13 UE: USART 使能 (USART enable)
该位清零后, USART 预分频器和输出将停止,并会结束当前字节传输以降低功耗。此位由软
件置 1 和清零。
0:禁止 USART 预分频器和输出
1:使能 USART
位 12 M:字长 (Word length)
该位决定了字长。该位由软件置 1 或清零。
0: 1 起始位, 8 数据位, n 停止位
1: 1 起始位, 9 数据位, n 停止位
注意: 在数据传输(发送和接收)期间不得更改 M 位
位 10 PCE:奇偶校验控制使能 (Parity control enable)
该位选择硬件奇偶校验控制(生成和检测)。使能奇偶校验控制时,计算出的奇偶校验位被
插入到 MSB 位置(如果 M=1,则为第 9 位;如果 M=0,则为第 8 位),并对接收到的数据
检查奇偶校验位。此位由软件置 1 和清零。一旦该位置 1, PCE 在当前字节的后面处于活动
状态(在接收和发送时)。
0:禁止奇偶校验控制
1:使能奇偶校验控制
位 3 TE:发送器使能 (Transmitter enable)
该位使能发送器。该位由软件置 1 和清零。
0:禁止发送器
1:使能发送器
注意: 1:除了在智能卡模式下以外,传送期间 TE 位上的“0”脉冲(“0”后紧跟的是“1”)
会在当前字的后面发送一个报头(空闲线路)。
2:当 TE 置 1 时,在发送开始前存在 1 位的时间延迟。
位 2 RE:接收器使能 (Receiver enable)
该位使能接收器。该位由软件置 1 和清零。
0:禁止接收器
1:使能接收器并开始搜索起始位
3.4.5 控制寄存器 2 (USART_CR2)
位 13:12 STOP:停止位 (STOP bit)
这些位用于编程停止位。
00: 1 个停止位
01: 0.5 个停止位
10: 2 个停止位
11: 1.5 个停止位
3.5 STM32的UART实验
PC通过串口发送数据给开发板,然后开发板通过串口接收到数据后回发给PC。
利用串口助手把数据从PC端发送到开发板
程序改进:
在demo1中,下载链接:https://download.csdn.net/download/qq_40860986/10962073
使用查询方式,查询接收缓冲区是否为空,不为空表示接收到数据完毕,将数据从数据寄存器保存到自己定义的char data;接收到马上发送出去。
demo2,使用串口中断,在中断完成收发,提高效率。但是有个问题,使用串口中断后并不知道串口接收在什么时候接收完成,需要在串口调试助手添加特殊结束符作为发送结束标志,当单片机接收到结束符,表示接收完成。下载链接:
u8 rev_buf[100];//接收缓冲区
u8 addr=0; //地址偏移量
u8 revice_ok=0;//接收完成标志
//串口1中断服务函数
/*
注意:
1.接收过程发生多次中断,并不是一次就接收完,PC端是一个字节一个字节的发送
单片机一个字节一个字节的接收,当发送完再读出一个完整的字符串。读取过程与
查询方式一样。
2.串口助手发送时,要以#做结尾,同时取消发送新行模式。
*/
void USART1_IRQHandler(void)
{
u8 data;
data=USART1->DR;//读取同时会清除标志
if(data=='#')//接收完成
{
rev_buf[addr]='\0';
addr=0;
revice_ok=1;
}
else//正常接收
{
rev_buf[addr++]=data;
}
}
demo3,使用串口中断,在中断完成收发,提高效率。取消用特殊标识符作为接收完成的标志。使用超时判断。(一个字节一个字节接收,每次接收计数值清零,当停止接收后,计数值不再清零,超过预设值就代表接收完成)
下载链接:
中断服务函数:
u8 rev_buf[100];//接收缓冲区
u8 addr=0; //地址偏移量
u8 revice_ok=0;//接收完成标志
u8 revice_start=0;//开始接收受标志
u32 time_out=0;//超时计数值
//串口1中断服务函数
void USART1_IRQHandler(void)
{
u8 data;
data=USART1->DR;//读取同时会清除标志
rev_buf[addr++]=data;
revice_start=1;//开始接收
time_out=0;//超级计数值清零
}
主函数判断:
if(revice_start)//开始接收
{
Main_delay();
time_out++;
if(time_out>=50)//超时就
{
revice_ok=1;
rev_buf[addr]='\0';
addr=0;
time_out=0;
revice_start=0;
}
}