stm32/comm/usart3-rs232.md
RS232 串口(USART3,HAL)
RS232 串口(USART3,HAL)
洋桃1号开发板 RS232 通信测试,PB10/PB11,回环测试验证通过。
#一、元信息
| 字段 | 值 |
|---|---|
| 芯片/平台 | STM32F103C8T6(HAL) |
| 接口类型 | UART(USART3,RS232 电平经板上 MAX3232/SP3232) |
| 验证状态 | ✅ 已验证 |
| 验证环境 | RS232_test 工程 / Keil MDK-ARM(AC5)/ ST-Link(OpenOCD) 烧录 / 2026-09-07 |
| 驱动方式 | HAL(查询方式收发,无中断) |
#二、接线表
| 信号 | MCU 引脚 | 模块引脚 | 备注 |
|---|---|---|---|
| USART3_TX | PB10 | DB9-3(经 MAX3232) | 复用推挽输出(AF_PP) |
| USART3_RX | PB11 | DB9-2(经 MAX3232) | 浮空输入(IN_FLOATING) |
| 回环测试 | PB10 ↔ PB11 | 杜邦线直接短接 | 板上 DB9 不接时自测用 |
- 波特率 115200-8-N-1;F103 的 USART3 挂在 APB1(36MHz)
- 官方例程(标准库)同样用 USART3 115200:
1-2-25-RS232通信测试程序
#三、踩坑清单
- CubeMX 工程默认没启用 UART 模块:
stm32f1xx_hal_conf.h里/#define HAL_UART_MODULE_ENABLED/是注释状态(CubeMX 只在勾选 USART 时才解开)。手写 USART 驱动必须先解开这行,否则HAL_UART_Init直接 assert 失败。 - Keil 工程要手动加
stm32f1xx_hal_uart.c:CubeMX 生成的工程 Drivers 组里没有 UART 源文件,HAL_UART_Transmit/Init 会链接失败(L6218E)。加到 Drivers/STM32F1xx_HAL_Driver 组。 - 查询接收要处理 ORE(溢出)标志:长时间不读 RXNE 再收到新数据会置 ORE,之后 RXNE 不再置位(收不到新数据)。
DataAvailable()里先清 ORE 再查 RXNE。 - 回环短接即可自测:PB10-PB11 杜邦线短接,发送字符立即从 RX 收回;OLED 同时显示 TX/RX 两个值,一眼验证收发链路。
- GB2312 编码源码文件别用 UTF-8 文本编辑器改:老工程(官方/标准库移植的 .c/.h)是 GB2312 编码,用按 UTF-8 读写工具修改后中文注释会变成乱码(U+FFFD)不可恢复。本工程全部源文件已重写为 ASCII/UTF-8。改 GB2312 文件务必用保持原编码的工具(如 PowerShell + GBK 编解码)。
- USART3_ReadByte 只在 DataAvailable() 为真后再调用,内部自带等待循环,别在无条件路径调用(否则死等)。
#四、驱动代码
#4.1 usart3.h
c#ifndef __USART3_H
#define __USART3_H
#include "main.h"
extern UART_HandleTypeDef huart3;
void USART3_Init(uint32_t baudrate);
void USART3_SendByte(uint8_t byte);
uint8_t USART3_DataAvailable(void);
uint8_t USART3_ReadByte(void);
#endif
#4.2 usart3.c
c#include "usart3.h"
UART_HandleTypeDef huart3;
void USART3_Init(uint32_t baudrate)
{
huart3.Instance = USART3;
huart3.Init.BaudRate = baudrate;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler();
}
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef gpio = {0};
if (uartHandle->Instance == USART3)
{
__HAL_RCC_USART3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
gpio.Pin = GPIO_PIN_10;
gpio.Mode = GPIO_MODE_AF_PP;
gpio.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &gpio);
gpio.Pin = GPIO_PIN_11;
gpio.Mode = GPIO_MODE_INPUT;
gpio.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &gpio);
}
}
void USART3_SendByte(uint8_t byte)
{
HAL_UART_Transmit(&huart3, &byte, 1, 100);
}
uint8_t USART3_DataAvailable(void)
{
if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_ORE))
{
__HAL_UART_CLEAR_OREFLAG(&huart3);
}
return (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE) != RESET) ? 1 : 0;
}
uint8_t USART3_ReadByte(void)
{
while (!USART3_DataAvailable())
{
}
return (uint8_t)(huart3.Instance->DR & 0xFF);
}
#五、调用示例
c/* 初始化顺序(USER CODE BEGIN 2) */
OLED_Init();
OLED_Clear();
TOUCH_KEY_Init(); /* 触摸按键 PA0-PA3 上拉输入 */
USART3_Init(115200); /* PB10=TX, PB11=RX */
/* 主循环:按键发送 + 查询接收(回环测试) */
uint8_t prev_keys = 0;
uint8_t rx_shown = '-';
while (1)
{
/* 按键任意电平翻转触发(适配 TTP223 自锁模式,见 ttp223 档案) */
uint8_t cur_keys = TOUCH_KEY_Scan();
uint8_t toggled = cur_keys ^ prev_keys;
prev_keys = cur_keys;
uint8_t key = 0;
if (toggled & TOUCH_KEY_A) key = 'A';
else if (toggled & TOUCH_KEY_B) key = 'B';
else if (toggled & TOUCH_KEY_C) key = 'C';
else if (toggled & TOUCH_KEY_D) key = 'D';
if (key != 0)
{
USART3_SendByte(key); /* 发送 */
OLED_WriteChar8x16(6, 32, key); /* TX 显示 */
}
if (USART3_DataAvailable()) /* 回环接收 */
{
uint8_t rx = USART3_ReadByte();
if (rx != rx_shown)
{
OLED_WriteChar8x16(6, 96, rx); /* RX 显示 */
rx_shown = rx;
}
}
}
#六、参考库/链接
- 洋桃1号官方 RS232 例程(标准库):
D:\学习资料\【用户资料】洋桃1号开发板(2)\B5-教学视频示例程序\1-2-25-RS232通信测试程序\ - 本工程:
D:\stm32_demo\YoungTalk\RS232_test\(HAL 版,触摸按键发送 + 回环显示) - 板上电平转换芯片:SP3232(RS232)数据手册见 A5 外设手册目录
#七、更新日志
📝共 1 条记录
| 日期 | 类型 | 更新内容 |
|---|---|---|
| 2026-09-08 | 新增 | 首次建档(RS232_test 工程验证:PB10/PB11 回环测试通过) |