当前位置: 首页 > ops >正文

嵌入式硬件篇---UART


文章目录

  • 前言
  • 1. UART协议基础
    • 1.1 物理层特性
      • 两根信号线
      • 无时钟信号
      • 电平标准
        • TTL UART
        • RS-232
    • 1.2 数据帧格式
    • 1.3 波特率计算
      • 波特率
  • 2. STM32F103RCT6的UART配置
    • 2.1 硬件连接
    • 2.2 CubeMX配置
      • 启用USART1
      • 引脚分配
      • 中断启用(可选)
  • 3. HAL库代码实现
    • 3.1 UART初始化
    • 3.2 发送数据(阻塞模式)
    • 3.3 接收数据(中断模式)
    • 3.4 DMA传输(高效大数据量)
  • 4. 自定义协议设计
    • 4.1 帧格式示例
    • 4.2 帧解析代码
  • 5. 常见问题与调试
    • 5.1 通信失败原因
      • 波特率不匹配
      • 电平不兼容
      • 接线错误
      • 中断为启用
    • 5.2 逻辑分析仪抓包
  • 6. 完整示例:与PC通信
    • STM32代码
    • PC端(Python脚本)
  • 7.总结
    • 基本配置
    • 通信模式
    • 协议设计
    • 调试工具


前言

UART(Universal Asynchronous Receiver/Transmitter)是一种异步串行通信协议,广泛应用于嵌入式设备与传感器、蓝牙模块、GPS等外设的通信。以下是UART协议的详细解析及在STM32F103RCT6上的完整代码实现。


1. UART协议基础

1.1 物理层特性

两根信号线

TX(Transmit):数据发送线(输出)。
RX(Receive):数据接收线(输入)。

无时钟信号

无时钟信号:依赖预定义的波特率(Baud Rate)同步。

电平标准

TTL UART

TTL UART:0V(逻辑0),3.3V/5V(逻辑1)。

RS-232

RS-232:±12V(需电平转换芯片如MAX232)。

1.2 数据帧格式

[起始位] [数据位(5-9位)] [校验位(可选)] [停止位(1-2位)]
起始位:1位低电平(逻辑0)。
数据位:通常8位(如ASCII字符)。
校验位(可选):
奇校验:数据位中1的个数为奇数时置1。
偶校验:数据位中1的个数为偶数时置1。
停止位:1或2位高电平(逻辑1)。

1.3 波特率计算

波特率

波特率(Baud Rate)表示每秒传输的符号数(1符号=1位)。
常见波特率:9600、115200等。
STM32的UART时钟源为APB2(默认72MHz),波特率计算公式:
波特率=APB2时钟USARTDIV
其中USARTDIV是一个16位寄存器值(整数部分 + 小数部分)。

2. STM32F103RCT6的UART配置

2.1 硬件连接

UART信号 STM32引脚 说明
USART1_TX PA9 发送数据
USART1_RX PA10 接收数据
GND 共地 确保电平参考一致

2.2 CubeMX配置

启用USART1

模式:Asynchronous(异步模式)。
波特率:115200。
数据位:8位。
校验位:None。
停止位:1位。

引脚分配

PA9 → USART1_TX
PA10 → USART1_RX

中断启用(可选)

接收中断(RXNE)。

3. HAL库代码实现

3.1 UART初始化

#include "stm32f1xx_hal.h"UART_HandleTypeDef huart1;void MX_USART1_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();}
}

3.2 发送数据(阻塞模式)

void UART_SendString(uint8_t *str) {HAL_UART_Transmit(&huart1, str, strlen((char *)str), 100); // 阻塞式发送
}// 示例:发送"Hello World!"
UART_SendString((uint8_t *)"Hello World!\r\n");

3.3 接收数据(中断模式)

uint8_t rx_data;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {if (huart == &huart1) {// 处理接收到的数据(如回显)HAL_UART_Transmit(&huart1, &rx_data, 1, 100);HAL_UART_Receive_IT(&huart1, &rx_data, 1); // 重新启用接收中断}
}// 主函数中启用接收中断
int main(void) {HAL_Init();MX_USART1_UART_Init();HAL_UART_Receive_IT(&huart1, &rx_data, 1); // 启动接收中断while (1) { /* 其他任务 */ }
}

3.4 DMA传输(高效大数据量)

uint8_t dma_tx_buffer[] = "DMA Transmission Test!\r\n";// 初始化DMA
void MX_DMA_Init(void) {__HAL_RCC_DMA1_CLK_ENABLE();
}// 通过DMA发送数据
HAL_UART_Transmit_DMA(&huart1, dma_tx_buffer, sizeof(dma_tx_buffer));

4. 自定义协议设计

4.1 帧格式示例

字段 长度 说明
帧头 2字节 0xAA 0x55
数据长度 1字节 后续数据长度(N)
数据 N字节 有效载荷
CRC校验 1字节 校验和(数据字节累加和)

4.2 帧解析代码

uint8_t rx_buffer[64];
uint8_t frame_state = 0;
uint8_t data_len = 0;
uint8_t crc = 0;void Process_UART_Byte(uint8_t byte) {static uint8_t idx = 0;switch (frame_state) {case 0: // 等待帧头1if (byte == 0xAA) frame_state = 1;break;case 1: // 等待帧头2if (byte == 0x55) frame_state = 2;else frame_state = 0;break;case 2: // 读取数据长度data_len = byte;idx = 0;crc = byte;frame_state = 3;break;case 3: // 读取数据rx_buffer[idx++] = byte;crc += byte;if (idx >= data_len) frame_state = 4;break;case 4: // 校验CRCif (crc == byte) {// 帧处理(如控制LED)if (rx_buffer[0] == 0x01) HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);}frame_state = 0;break;}
}// 在中断回调中调用
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {Process_UART_Byte(rx_data);HAL_UART_Receive_IT(&huart1, &rx_data, 1);
}

5. 常见问题与调试

5.1 通信失败原因

波特率不匹配

波特率不匹配:确保双方波特率一致(如115200)。

电平不兼容

电平不兼容:TTL UART不能直接接RS-232设备。

接线错误

接线错误:检查TX/RX是否交叉连接。

中断为启用

中断未启用:若使用中断接收,需调用HAL_UART_Receive_IT()。

5.2 逻辑分析仪抓包

使用工具(如Saleae Logic)观察:

  1. 起始位是否为低电平?
  2. 数据位是否符合预期?
  3. 停止位是否为高电平?

6. 完整示例:与PC通信

STM32代码

int main(void) {HAL_Init();MX_USART1_UART_Init();HAL_UART_Receive_IT(&huart1, &rx_data, 1); // 启用接收中断while (1) {// 每隔1秒发送数据UART_SendString((uint8_t *)"STM32 UART Test\r\n");HAL_Delay(1000);}
}

PC端(Python脚本)

import serial
ser = serial.Serial('COM3', 115200, timeout=1)  # 根据实际端口修改
while True:if ser.in_waiting:data = ser.readline().decode('utf-8').strip()print("Received:", data)

7.总结

基本配置

基本配置:波特率、数据位、停止位需匹配。

通信模式

通信模式:阻塞、中断、DMA按需选择

协议设计

协议设计:自定义帧格式提升可靠性

调试工具

调试工具:逻辑分析仪、串口助手是关键。
通过上述代码,STM32F103RCT6可实现稳定的UART通信,适用于传感器数据采集、无线模块控制等场景。


http://www.xdnf.cn/news/5282.html

相关文章:

  • 外网访问内网海康威视监控视频的方案:WebRTC + Coturn 搭建
  • Python OpenCV性能优化与部署实战指南
  • python 实现文件批量重命名
  • “frame stacking”---帮助强化学习稳定提升和收敛技巧
  • Nipype 简单使用教程
  • 5 从众效应
  • Spring Boot 集成 Flink CDC 实现 MySQL 到 Kafka 实时同步
  • RabbitMQ--进阶篇
  • React+Springboot项目部署ESC服务器
  • 三维空间中的组织行为映射:MATLAB 数据插值可视化技术
  • 【网络】:传输层协议 —— UDP、TCP协议
  • 兔子队列?RabbitMQ详解(1)
  • 数字化转型-4A架构之技术架构
  • Mac下Robotframework + Python3环境搭建
  • 《智能网联汽车 自动驾驶系统设计运行条件》 GB/T 45312-2025——解读
  • 无锁秒杀系统设计:基于Java的高效实现
  • 补补表面粗糙度的相关知识(一)
  • leetcode 15. 三数之和
  • Java 原生异步编程与Spring 异步编程 详解
  • 比亚迪全栈自研生态的底层逻辑
  • MySQL 索引(二)
  • 服务器mysql连接我碰到的错误
  • 高斯过程回归(GPR)原理的通俗解释
  • Spring循环依赖问题
  • 【DLF】基于语言的多模态情感分析
  • 邮件群发中如何确保图片加载速度
  • Qt开发经验 --- 避坑指南(12)
  • vue配置代理解决前端跨域的问题
  • python环境搭建和pycharm的安装配置以及使用face_recognition与cv2
  • 一键智能AI抠图,释放创意无限可能