UART通信协议详解

UART(Universal Asynchronous Receiver/Transmitter 通用异步收发器)是一种异步串行通信协议,广泛应用于嵌入式系统、工业控制、传感器通信等领域。以下从协议层物理层技术特点代码示例四个维度展开详细说明。


一、协议层

UART协议层定义了数据传输的帧格式时序规则错误检测机制,其核心是异步通信,无需共享时钟信号。

1. 数据帧结构

每帧数据由以下部分组成(以最常见的8N1格式为例):
在这里插入图片描述

  • 起始位(Start Bit)

    • 电平:低电平(逻辑0)
    • 作用:标志数据帧开始,接收端通过检测下降沿触发同步。
  • 数据位(Data Bits)

    • 位数:5/6/7/8位(常用8位)
    • 传输顺序:LSB(最低有效位)优先
    • 示例:发送字符A(ASCII 0x41 = 01000001),实际传输顺序为1 0 0 0 0 0 1 0(从右到左)。
  • 校验位(Parity Bit)(可选)

    校验类型规则特点
    无校验不添加校验位节省时间,无检错能力
    奇校验数据位+校验位中1的总数为奇数检测单比特错误
    偶校验数据位+校验位中1的总数为偶数检测单比特错误
    Mark固定为1作为第9位数据使用
    Space固定为0作为第9位数据使用
  • 停止位(Stop Bit)

    • 电平:高电平(逻辑1)
    • 位数:1位、1.5位(罕见)、2位
    • 作用:标志帧结束,并为下一帧提供缓冲时间。
2. 时序与波特率
  • 波特率(Baud Rate)

    • 定义:每秒传输的符号数(1符号=1位),常见值:9600、115200等。
    • 计算:
      位时间(秒)= 1 / 波特率  
      (例如:9600bps → 104μs/位)
      
    • 误差要求:通常需控制在±2%以内,否则可能采样错误。
  • 采样点

    • 接收端在每位中心点(如16倍过采样时,取第8、9、10次采样的多数值)进行采样。
    • 抗干扰机制:三次采样表决(提高噪声环境下的可靠性)。
3. 错误检测
  • 帧错误(Framing Error):停止位未检测到高电平。
  • 奇偶校验错误:数据与校验位不匹配。
  • 溢出错误(Overrun Error):接收缓冲区未及时读取,新数据覆盖旧数据。
4. 高级协议配置
  • 数据流控制(可选):
    • 硬件流控:使用RTS(请求发送)和CTS(清除发送)信号线。
    • 软件流控:通过XON/XOFF字符控制数据流。

二、物理层

UART的物理层定义了电气特性、接口标准和硬件连接方式。

1. 电平标准
  • TTL/CMOS电平

    • 逻辑0:0V(或接近0V,如<0.8V)
    • 逻辑1:3.3V或5V(如>2.4V为有效高电平)
    • 典型应用:单片机之间、芯片内部通信(传输距离<1米)。
  • RS232电平

    • 逻辑0:+3V ~ +15V
    • 逻辑1:-3V ~ -15V
    • 特点:抗干扰强,支持长距离(最长15米@20kbps)。
  • RS485电平(差分信号)

    • 通过A、B两线的电压差表示逻辑:
      • 逻辑1:B线电压 > A线电压
      • 逻辑0:A线电压 > B线电压
    • 特点:支持多点通信,最长1200米。
2. 接口定义
  • 基本引脚

    • TX(Transmit):数据发送线
    • RX(Receive):数据接收线
    • GND(Ground):共地参考
  • 扩展引脚(用于流控):

    • RTS(Request to Send):请求发送
    • CTS(Clear to Send):允许发送
    • DTR(Data Terminal Ready):设备就绪
    • DSR(Data Set Ready):数据就绪
3. 典型连接方式
  • 直接连接(TTL电平)
    设备A.TX → 设备B.RX  
    设备A.RX ← 设备B.TX  
    共地连接:GND ↔ GND  
    
  • RS232连接(使用DB9接口)
    TXD(Pin3) ↔ RXD(Pin2)  
    RXD(Pin2) ↔ TXD(Pin3)  
    GND(Pin5) ↔ GND(Pin5)  
    
    • 需交叉连接(DTE与DCE设备)。
4. 电平转换电路
  • TTL转RS232:使用MAX232芯片。
  • TTL转RS485:使用MAX485芯片(支持半双工)。

三、技术特点

1. 核心特性
  • 异步通信:无共享时钟,依赖预定义的波特率。
  • 全双工:可同时发送和接收数据(需独立TX/RX线路)。
  • 点对点:通常支持1对1通信,需扩展硬件支持多设备。
  • 配置灵活:可自定义数据位、停止位、校验方式、波特率。
2. 关键参数
参数典型值/选项影响
波特率9600, 19200, 115200 bps速度与抗干扰的平衡
数据位5/6/7/8位数据精度与效率
停止位1/1.5/2位帧间隔与同步稳定性
校验方式None/Even/Odd/Mark/Space检错能力与传输开销
3. 优势与局限

优势

  • 实现简单,仅需2根信号线(TX/RX)。
  • 成本低,几乎所有微控制器内置UART模块。
  • 支持全双工实时通信。

局限

  • 传输距离短(TTL电平<1米,RS232<15米)。
  • 无硬件寻址机制,难以直接支持多设备通信。
  • 依赖精确的波特率匹配,时钟误差敏感。
4. 典型应用场景
  1. 设备调试:通过UART输出调试信息(如STM32的printf重定向)。
  2. 模块通信:GPS模块、蓝牙模块(HC-05)、WiFi模块(ESP8266)。
  3. 工业控制:PLC与HMI(人机界面)的RS232通信。
  4. 芯片级通信:SoC与外围传感器(如温度传感器DS18B20)。

四、实际开发注意事项

  1. 波特率匹配:双方设备必须设置相同波特率(误差<3%)。
  2. 电平兼容:不同电平设备间需加转换芯片(如MAX232)。
  3. 抗干扰设计
    • 长距离通信使用RS485差分信号。
    • 添加终端电阻(120Ω)消除信号反射。
  4. 数据缓冲:使用FIFO缓冲区防止数据溢出。

五、代码示例

以下是一个基于 STM32 HAL库 的UART应用示例代码,包含 初始化配置数据发送接收中断printf重定向 的实现。

1、硬件配置要求
  1. MCU型号:以STM32F103C8T6为例(其他型号需调整引脚)
  2. UART接口:USART1(PA9-TX, PA10-RX)
  3. 波特率:115200, 8N1(8位数据,无校验,1停止位)
  4. 开发环境:STM32CubeIDE + HAL库

2、代码实现
1). UART初始化配置
// 在 main.c 中添加以下代码

UART_HandleTypeDef huart1;

void UART_Init(void) {
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  
  if (HAL_UART_Init(&huart1) != HAL_OK) {
    Error_Handler();
  }

  // 启用接收中断(可选)
  HAL_UART_Receive_IT(&huart1, &rx_buffer, 1); // rx_buffer为接收缓冲区
}
2). GPIO与时钟配置(CubeMX自动生成)
// 在 stm32f1xx_hal_msp.c 中添加:
void HAL_UART_MspInit(UART_HandleTypeDef* huart) {
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  
  if (huart->Instance == USART1) {
    __HAL_RCC_USART1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();

    // PA9-TX, PA10-RX
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // 启用USART1全局中断(若使用中断)
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
  }
}
3). 发送数据(阻塞模式)
// 发送字符串
void UART_SendString(char *str) {
  HAL_UART_Transmit(&huart1, (uint8_t*)str, strlen(str), HAL_MAX_DELAY);
}

// 发送字节数组
void UART_SendBytes(uint8_t *data, uint16_t len) {
  HAL_UART_Transmit(&huart1, data, len, 100);
}
4). 接收数据(中断模式)
// 定义接收缓冲区
uint8_t rx_buffer;

// 中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
  if (huart->Instance == USART1) {
    // 处理接收到的数据(示例:回显)
    HAL_UART_Transmit(&huart1, &rx_buffer, 1, 100);
    
    // 重新启用接收中断
    HAL_UART_Receive_IT(&huart1, &rx_buffer, 1);
  }
}
5). 重定向printf到UART
// 在 main.c 中添加以下代码
#include <stdio.h>

// 重写 _write 函数
int _write(int fd, char *ptr, int len) {
  HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, HAL_MAX_DELAY);
  return len;
}

// 使用示例
printf("System Clock: %ld Hz\r\n", HAL_RCC_GetHCLKFreq());

3、主函数调用
int main(void) {
  HAL_Init();
  SystemClock_Config();
  UART_Init();

  printf("UART Initialized\r\n");

  while (1) {
    // 主循环中可添加其他任务
    // 例如:每隔1秒发送数据
    HAL_Delay(1000);
    UART_SendString("Hello World!\r\n");
  }
}

4、关键功能说明
功能实现方式特点
初始化配置HAL_UART_Init + MSP配置自动生成引脚和时钟初始化代码
数据发送HAL_UART_Transmit阻塞式发送,简单可靠
中断接收HAL_UART_Receive_IT + 回调函数非阻塞接收,适合实时性要求高场景
printf重定向重写 _write 函数方便调试信息输出

5、常见问题解决
  1. 无输出/乱码

    • 检查波特率是否匹配(PC端串口工具与代码设置一致)
    • 验证TX/RX引脚是否交叉连接(MCU TX → USB-TTL RX,MCU RX → USB-TTL TX)
  2. 中断接收不触发

    • 确认已调用 HAL_UART_Receive_IT 并重新启用中断
    • 检查NVIC中断优先级配置
  3. printf无法使用

    • 确保工程设置中勾选 “Use MicroLIB”(Keil)或正确链接 syscalls.c

6、扩展功能
  1. DMA传输

    // 发送DMA
    HAL_UART_Transmit_DMA(&huart1, data, len);
    
    // 接收DMA
    HAL_UART_Receive_DMA(&huart1, rx_buf, len);
    
  2. RS485半双工控制

    // 发送前使能DE引脚(MAX485)
    HAL_GPIO_WritePin(DE_GPIO_Port, DE_Pin, GPIO_PIN_SET);
    HAL_UART_Transmit(...);
    HAL_GPIO_WritePin(DE_GPIO_Port, DE_Pin, GPIO_PIN_RESET);
    

通过上述代码,可实现STM32的UART基础通信功能。实际开发中建议使用 STM32CubeMX 生成初始化代码,确保配置正确性。


六、与其他协议的对比

特性UARTSPII²C
时钟异步同步(主控)同步(主控)
数据线数量2(TX/RX)3(SCK/MOSI/MISO)2(SDA/SCL)
最大速率1Mbps50Mbps3.4Mbps
寻址方式片选信号7/10位地址
拓扑结构点对点主从多主多从

七、总结

UART凭借其简单性、灵活性和广泛兼容性,成为嵌入式系统的“基础设施级”通信协议。尽管存在传输距离短和缺乏多设备支持的局限性,但通过电平转换芯片(如RS232/RS485)和协议扩展(如Modbus),仍可满足大多数中低速通信需求。在实际开发中,需重点关注电平匹配波特率精度抗干扰设计

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值