一、CubeMX 参数配置详解
在 CubeMX 的 USART1 配置页中,核心参数如下:
| 参数 | 值 | 含义 |
|---|---|---|
| Baud Rate | 115200 | 波特率 |
| Word Length | 8 Bits (including Parity) | 8 数据位 |
| Parity | None | 无校验 |
| Stop Bits | 1 | 1 停止位 |
| Data Direction | Receive and Transmit | 收发双向 |
| Over Sampling | 16 samples | 16 倍过采样 |
逐项原理说明:
- Baud Rate(波特率):每秒传输的比特数。115200 是嵌入式最常用速率,由 BRR 寄存器分频得到:
BRR = f_PCLK / 波特率(USART1 挂 APB2 = 72MHz,72000000/115200 = 625,无误差)。 - Word Length(字长):一个数据帧的数据位长度。注意 HAL 的 8B 是"含校验位"的——若开启奇偶校验,实际有效数据只有 7 位;无校验时才是完整 8 位。
- Parity(校验):None / Even(偶校验)/ Odd(奇校验)。无校验最常用;开启后校验位占用数据帧一位。
- Stop Bits(停止位):帧尾电平保持时间,1 位最常用(0.5/1/1.5/2 可选)。
- Data Direction(模式):TX_RX 同时使能发送与接收(对应 CR1 寄存器的 TE、RE 位)。
- Over Sampling(过采样):16 倍过采样对每位采样 16 次取多数,抗干扰强,是默认推荐;8 倍过采样可支撑更高波特率但容错差。
一帧完整格式:起始位(1) + 数据位(8) + 校验位(0) + 停止位(1),即 115200-8-N-1。
二、CubeMX 生成的初始化代码
usart.c 中的核心结构体与初始化函数:
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;
HAL_UART_Init(&huart1);
}
结构体字段与硬件的对应关系:
| 字段 | 写入的寄存器/位 | 作用 |
|---|---|---|
| Instance | — | 指向 USART1 外设基地址 |
| BaudRate | BRR | 波特率分频值 |
| WordLength | CR1.M | 数据位长度 |
| StopBits | CR2.STOP | 停止位 |
| Parity | CR1.PCE / PS | 校验使能与类型 |
| Mode | CR1.TE / RE | 发送/接收使能 |
| HwFlowCtl | CR3.RTSE / CTSE | 硬件流控(RTS/CTS) |
| OverSampling | CR1.OVER8 | 8/16 倍过采样 |
HAL_UART_Init() 内部依次完成:参数校验 → 调用 HAL_UART_MspInit()(CubeMX 生成在 usart.c 底部:使能 USART1 与 GPIOA 时钟、配置 PA9/PA10 复用推挽)→ 按 Init 结构体写入 CR1/CR2/CR3/BRR → 使能外设。
为什么代码里看不到 RCC 和 GPIO 配置? 因为 CubeMX 把"芯片级初始化"(时钟使能、引脚复用)拆进了 HAL_UART_MspInit(),与"协议参数配置"(MX_USART1_UART_Init())分离——前者管硬件资源,后者管通信格式,各司其职。
三、HAL_UART_Transmit 发送函数
HAL_StatusTypeDef HAL_UART_Transmit(
UART_HandleTypeDef *huart, // 串口句柄
uint8_t *pData, // 数据指针
uint16_t Size, // 数据长度
uint32_t Timeout // 超时(ms)
);
工作流程(阻塞式发送):
- 逐字节把数据写入 DR(数据寄存器)
- 等待 TXE(发送数据寄存器空)标志,再写下一字节
- 全部写完后等待 TC(发送完成)标志
- 期间用 Timeout 计数,超时则放弃并返回
HAL_TIMEOUT
返回值:
| 返回值 | 含义 |
|---|---|
| HAL_OK | 发送成功 |
| HAL_ERROR | 参数错误 |
| HAL_BUSY | 串口被占用(如上次发送未完成) |
| HAL_TIMEOUT | 超时放弃 |
使用示例:
uint8_t msg[] = "Hello USART1\r\n";
HAL_UART_Transmit(&huart1, msg, sizeof(msg) - 1, 100); // 100ms 超时
要点:
- 阻塞式发送——CPU 停在函数里等硬件搬完,期间不能干别的;大数据量场景应改用中断(
HAL_UART_Transmit_IT)或 DMA 版本。 sizeof(msg) - 1减掉字符串末尾的\0,串口不需要发它。- 发送速率由波特率决定:115200bps 下每字节约 87μs,发 100 字节约 8.7ms。