STM32之UART(通用异步收发器)通信

一、UART通信概述

UART(Universal Asynchronous Receiver/Transmitter)是一种全双工异步串行通信协议,广泛应用于嵌入式系统中实现设备间的数据交互。其核心特点包括:

  1. 异步传输:无需时钟信号同步,通过起始位、数据位、校验位和停止位实现数据帧同步。
  2. 全双工模式:支持同时收发数据,典型应用场景如STM32与PC串口调试助手的通信。
  3. 灵活配置:支持多种波特率(如9600、115200)、数据位长度(8/9位)及校验方式(奇/偶/无校验)。

二、STM32的UART硬件特性

1. 硬件资源

  • USART与UART区别:USART支持同步/异步模式,UART仅支持异步模式;STM32F103系列提供5个串口(3个USART,2个UART)。
  • 关键引脚
    • TX(发送端):需配置为复用推挽输出(GPIO_Mode_AF_PP)
    • RX(接收端):需配置为浮空输入(GPIO_Mode_IN_FLOATING)。
  • 波特率计算:基于公式 波特率 = 串口时钟 / BRR寄存器值,例如72MHz时钟下115200波特率对应BRR=0x0271。

三、UART配置步骤(以STM32F103为例)

1. 硬件初始化

// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

// GPIO配置
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  // TX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);

2. 串口参数配置

USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);

3. 中断配置(可选)

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  // 使能接收中断
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

四、代码实现与实例

1. 查询方式收发数据

// 发送字符串
void USART_SendString(USART_TypeDef* USARTx, char* str) {
    while (*str) {
        USART_SendData(USARTx, *str++);
        while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
    }
}

// 接收单个字符
uint8_t USART_ReceiveChar(USART_TypeDef* USARTx) {
    while (USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == RESET);
    return USART_ReceiveData(USARTx);
}

2. 中断接收回显示例

void USART1_IRQHandler(void) {
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        uint8_t ch = USART_ReceiveData(USART1);
        USART_SendData(USART1, ch);  // 回传接收到的字符
    }
}

3. 重定向printf函数

int fputc(int ch, FILE *f) {
    USART_SendData(USART1, ch);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    return ch;
}
// 使用示例:printf("Hello STM32 UART!\r\n");

五、应用场景与调试技巧

1. 典型应用

  • 串口调试:通过printf输出调试信息至PC端。
  • 多设备通信:配置多个UART接口实现STM32与传感器、显示屏等外设的数据交互。
  • 工业控制:结合RS485协议实现长距离通信。

2. 常见问题

  • 波特率不匹配:确保收发双方波特率一致,误差需小于3%。
  • 数据丢失:使用DMA或FIFO缓冲区提升高波特率下的稳定性。
  • 电磁干扰:增加终端电阻或屏蔽线缆,降低误码率。

六、总结

UART作为嵌入式开发的基础通信接口,其配置灵活性和低成本特性使其在STM32项目中广泛应用。掌握波特率计算、中断处理及DMA优化等关键技术,可显著提升系统实时性和稳定性。建议结合具体项目需求,灵活选择查询、中断或DMA模式。

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐