嵌入式硬件篇---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)观察:
- 起始位是否为低电平?
- 数据位是否符合预期?
- 停止位是否为高电平?
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通信,适用于传感器数据采集、无线模块控制等场景。