4.1USART简介
通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。USART利用分数波特率发生器提供宽范围的波特率选择。 它支持同步单向通信和半双工单线通信,也支持LIN(局部互连网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。 使用多缓冲器配置的DMA方式,可以实现高速数据通信。以分层的方式来理解,可以把它分为物理层和协议层。
1、功能引脚
TX:发送数据输出引脚。
RX:接收数据输入引脚。
SW_RX:数据接收引脚,属于内部引脚。
nRTS:请求以发送,n表示低电平有效。如果使能 RTS 流控制,当USART接收器准备好接收新数据时就会将nRTS变成低电平;当接收寄存器已满时,nRTS将被设置为高电平。该引脚只适用于硬件流控制。
nCTS:清除以发送(Clear To Send),n表示低电平有效。如果使能 CTS流控制,发送器在发送下一帧数据之前会检测 nCTS 引脚,如果为低电平,表示可以发送数据,如果为高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。
SCLK:发送器时钟输出引脚。这个引脚仅适用于同步模式。
2.数据寄存器(写操作和读操作)
USART_DR有两个,里面包含了已发送的数据或者接收到的数据。一个用于发送的可写 TDR,一个用于接收的可读 RDR。发送操作时,往 USART_DR写入数据会自动存储在 TDR内;读取操作时,向 USART_DR读取数据会自动提取 RDR 数据。
串行通信是一个位一个位传输的,发送时把 TDR 内容转移到发送移位寄存器,然后把移位寄存器数据每一位发送出去,接时把接收到的每一位顺序保存在接收移位寄存器内然后才转移到 RDR。
USART 支持 DMA 传输,可以实现高速数据传输。
3.控制发送的发送器、控制接收的接收器,唤醒单元、中断控制等
使用USART之前需要向USART_CR1寄存器的UE位置1使能USART,UE位用来开启供给给串口的时钟。发送或者接收数据字长可选8位或9位,由USART_CR1的M位控制。
4.波特率发生器
4.2USART的物理层
串口通讯的物理层的主要标准是RS-232标准。
4.3USART的协议层
串口通信时,一个控制器的发送口TXD与另一个控制器的接收口RXD相连,一个控制器的接收口RXD与另一个控制器的发送口TXD相连,这样才能一个发一个收。协议层中,规定了数据包的内容,它由起始位、主体数据、校验位以及停止位组成。
4.3.1起始位
串口通信的一个数据包从起始信号开始。数据包的起始信号由一个逻辑0的数据位表示。
4.3.2数据位
在数据包的起始位之后紧接着的就是要传输的主体数据内容,也称为有效数据,有效数据的长度常被约定为 5、6、7 或 8 位长。数据位的具体位数可以通过寄存器调节。
4.3.3校验位
在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验 (odd)、偶校验 (even)、0 校验 (space)、1 校验 (mark) 以及无校验 (noparity)。
4.3.4停止位
数据包的最后停止位,数据包的起始信号由一个逻辑0的数据位表示,停止位信号可由0.5、1、1.5、2个逻辑1的数据位表示。STM32停止信号的设置通过串口初始化结构体来实现。
4.4USART应用
usart.c
#include "usart.h"
//PA9 复用推挽输出
//PA10 浮空输入
void usartInit (void)
{
//IO口初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启IO口的时钟
GPIO_InitTypeDef GPIO_InitStructure = {0}; //定义结构体
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //选择引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //选择速率
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //调用函数
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //选择引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //调用函数
//外设初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //开启外设的时钟
USART_InitTypeDef USART_InitStructure={0}; //定义结构体函数
USART_InitStructure.USART_BaudRate = 115200; // 设置波特率 常用的有4800 9600 15500
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //传输数据的长度
USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位长度
USART_InitStructure.USART_Parity = USART_Parity_No; //奇偶检验失能
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE); //串口使能或失能函数
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //使能或者失能指定的 USART 中断
NVIC_InitTypeDef NVIC_InitStructure={0};
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
接收函数
uint8_t Usart_Rx(void) //串口接收
{
uint8_t data =0;
while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==0); //检查指定的 USART 标志位设置与否 USART_FLAG_RXNE接收数据寄存器非空标志位
data=USART_ReceiveData(USART1); //data承接串口接收的数据
return data;
}
发送函数
void Usart_Tx(uint8_t data) //串口发送
{
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==0); //USART_FLAG_TC 发送完成标志位
USART_SendData(USART1,data);
}