1.USART
USART 全称为 “Universal Synchronous/Asynchronous Receiver Transmitter”,即通用同步/异步收发器。它既支持异步通信(UART 模式),也可配置为同步通信(SPI 类似模式)。USART 是 STM32 系统中最常用的串口外设,用于点对点的数据收发、调试日志输出、模块通信等场景。
USART接口
TX(Transmit):传输线路,负责发送数据。连接到其他设备的接收端
RX(Receive):接收线路,负责接收数据。连接到其他设备的发送端
GND(Ground):地线,电路的公共参考点,确保信号的正常传输和电路的正常工作
VCC:提供电源
USART基本参数
波特率:串口通信的速率(如:规定每隔1ms发送1位等)每秒传送码元的个数。决定了每隔多久发送一位。
起始位:标志一个数据帧的开始,固定为低电平(空闲时为高电平)
数据位:数据帧的有效载荷,1为高电平,0为低电平,低位先行
校验位:用于数据验证,根据数据位计算得来
停止位:用于数据帧间隔,固定为高电平
2.特征
STM32 控制器中的 USART 外设具有以下主要特性:
①多种工作模式:支持异步 UART(8 位、9 位数据位,可选奇偶校验位)、同步模式(CLK 引脚)、单线半双工模式及 LIN、SmartCard、IrDA 子模式。
②可编程波特率:通过 BRR 寄存器精确配置波特率,支持与核心时钟及外部时钟源配合,多种分频方案可选。
③硬件流控:支持 RTS/CTS 硬件流控,避免数据丢失与阻塞。
④ DMA 联动:可与 DMA 配合,实现大数据量的非阻塞传输,释放 CPU 资源。
⑤多种中断与状态标志:接收完成、发送完成、传输半满、过载错误、帧错误、噪声检测等多种中断源及标志位,便于精细化管理。
⑥可配置字符格式:支持 1 或 2 停止位,8 或 9 位数据位,可选奇偶校验,满足多种通信协议需求。
3.结构:
1线路是USART接收数据的流程:数据从RX接收数据引脚进入→接收移位寄存器(该寄存器的作用是将数据一位一位的移到接收数据寄存器RDR中),利用USART_ReceiveData()函数可以直接读取出接收数据寄存器RDR的数据。
2线路是驱动接收移位寄存器工作:RE→接收控制器→接收移位寄存器
3线路是USART发送数据的流程:数据从发送数据寄存器TDR→发送移位寄存器→TX发送引脚
利用USART_SendData()函数可以将要发送的数据放在TDR发送寄存器中
4线路是驱动发送移位寄存器工作:TE→发送控制器→发送移位寄存器
5与6(TXEIE、RXNEIE)分别是使能发送中断使能、接收中断使能
7(TE、RE)分别是发送使能、接收使能
8与9(TXE、RXNE)分别是发送寄存器空、接收寄存器非空,这两个事件均可申请进入USART中断
发送寄存器空:表明发送寄存器空闲,可通知MCU向TDR写入数据
接收寄存器非空:表明已经接收到了数据,进入中断后可通知MCU读取RDR里的数据
注:发送数据寄存器TDR,接收数据寄存器RDR,这两个寄存器占用同一个地址,在程序上只表现为一个寄存器,就是数据寄存器DR。但实际硬件中是分成了两个寄存器
SW_RX IRDA_OUT IRDA_IN是只能卡与lrDA通信的引脚。
4.寄存器
USART_SR:状态寄存器,含 TXE(发送寄存器空)、TC(发送完成)、RXNE(接收寄存器非空)、PE(奇偶校验错误)、FE(帧错误)等位。
USART_DR:数据寄存器,读写此寄存器进行接收与发送。
USART_BRR:波特率寄存器,配置整数和小数分频系数,决定通信速率。
USART_CR1:控制寄存器1,含 UE(外设使能)、M(字长)、PCE(奇偶校验使能)、TE/RE(发送/接收使能)、RXNEIE/TXEIE(中断使能)等位。
USART_CR2:控制寄存器2,含 STOP(停止位长度)、CLKEN(同步模式时钟使能)、LINEN(LIN 模式)等位。
USART_CR3:控制寄存器3,含 CTSIE/RTSE(硬件流控与中断)、DMAR/DMAT(DMA 使能)等位。
5.相关函数介绍:
① void USART_DeInit(USART_TypeDef* USARTx);
复位指定 USART 外设寄存器。
② void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
根据 USART_InitStruct 中参数初始化波特率、字长、停止位、校验及模式。
③ void USART_StructInit(USART_InitTypeDef* USART_InitStruct);
将初始化结构体按缺省值填充。
④ void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
使能或禁止指定 USART 外设。
⑤ void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);
配置接收完成、发送寄存器空、中断错误等中断源。
⑥ void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState);
使能或禁止 TX/RX DMA 请求。
⑦ void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);
清除指定状态标志。
⑧ void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
写数据到 DR,启动发送。
⑨ uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
读取 DR 中已接收的数据。
6.代码
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中断控制器组选择 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置USART为中断源 */
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
/* 抢断优先级*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 子优先级 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中断 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置NVIC */
NVIC_Init(&NVIC_InitStructure);
}
void initUart()
{
GPIO_InitTypeDef PA; //定义io口结构体
USART_InitTypeDef usart; //定义串口口结构体
//打开时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
PA.GPIO_Pin = GPIO_Pin_9;
PA.GPIO_Mode = GPIO_Mode_AF_PP; //将io口复用为串口
PA.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&PA);
PA.GPIO_Pin = GPIO_Pin_10;
PA.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&PA);
usart.USART_BaudRate = 115200; //波特率,每秒传输二进制位
usart.USART_WordLength = USART_WordLength_8b;// 配置 帧数据字长
usart.USART_StopBits = USART_StopBits_1;// 配置停止位
usart.USART_Parity = USART_Parity_No;// 配置校验位
usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 配置硬件流控制,这里讲到的 “流”,指的是数据流;在数据通信中,流控制是管理两个节点之间数据传输速率的过程,以防止出现接收端的数据缓冲区已满,而发送端依然继续发送数据,所导致数据丢失当接收端的数据缓冲区已满,无法处理数据来时,就发出 “不再接收” 的信号,发送端则停止发送,直到发送端收到 “可以继续发送” 的信号再发送数据。
usart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;// 配置工作模式,收发一起
USART_Init(USART1,&usart);// 完成串口的初始化配置
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);// 使能串口接收中断
NVIC_Configuration();// 串口中断优先级配置
USART_Cmd(USART1, ENABLE);// 使能串口
}
/***************** 发送一个字符 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
/* 发送一个字节数据到USART */
USART_SendData(pUSARTx,ch);
/* 等待发送数据寄存器为空 */
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
/***************** 发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
unsigned int k=0;
do
{
Usart_SendByte( pUSARTx, *(str + k) );
k++;
} while(*(str + k)!='\0');
/* 等待发送完成 */
while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
{}
}
void USART1_IRQHandler(void)
{
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == SET)//注意串口中断还有一个寄存器,那个寄存器才是收发数据的第一个寄存器
{
utemp = USART_ReceiveData(USART1);
USART_SendData(USART1,utemp);
}
}
/*******************************************************************************
输出重定义
*******************************************************************************/
int fputc(int ch,FILE *f)
{
USART_SendData(USART1, (uint8_t)ch);
while(USART_GetFlagStatus (USART1,USART_FLAG_TXE) == RESET);
return (ch);
}
/*******************************************************************************
输入重定义
*******************************************************************************/
int fgetc (FILE *f)
{
while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(USART1);
}
USART 是 STM32 与外设、上位机交互的核心接口,配置灵活、多模式支持、DMA 与中断能力强,能满足从简单调试输出到大数据量高速通信的需求。
想要更深入了解 USART DMA 模式、高级流控及 LIN/IrDA 应用,请观看我的视频