引言
在嵌入式开发中,串口通信(UART)是最基础且重要的通信方式之一。本文记录了我基于STM32F103系列芯片(标准库)学习串口通信的全过程,涵盖硬件配置、代码实现及调试经验,适合初学者参考。
硬件准备
- 开发板:STM32F103ZET6(其他F1系列芯片类似)
- 串口模块:USB转TTL模块(CH340/CP2102等)
- 接线:
- PA9(USART1_TX) → TTL模块RX
- PA10(USART1_RX) → TTL模块TX
- GND共地
开发步骤详解
1. 时钟使能
所有外设使用前需开启对应时钟:
// 开启USART1和GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
2. GPIO配置
根据参考手册,USART1的TX(PA9)需设置为复用推挽输出,RX(PA10)为浮空输入:
GPIO_InitTypeDef GPIO_InitStruct;
// 配置TX引脚(PA9)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置RX引脚(PA10)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
GPIO_Init(GPIOA, &GPIO_InitStruct);
3. USART参数初始化
设置波特率、数据位、停止位等关键参数(以115200bps为例):
USART_InitTypeDef USART_InitStruct;
USART_InitStruct.USART_BaudRate = 115200; // 波特率
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 8位数据位
USART_InitStruct.USART_StopBits = USART_StopBits_1; // 1位停止位
USART_InitStruct.USART_Parity = USART_Parity_No; // 无校验
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无流控
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 启用发送和接收
USART_Init(USART1, &USART_InitStruct);
USART_Cmd(USART1, ENABLE); // 使能USART1
4. 中断配置(可选)
如需接收数据,需配置接收中断:
// 使能接收中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
// 配置NVIC
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
5. 中断服务函数
在stm32f10x_it.c
中编写中断处理逻辑:
void USART1_IRQHandler(void) {
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
uint8_t ch = USART_ReceiveData(USART1); // 读取接收到的字节
USART_SendData(USART1, ch); // 回传数据(回显测试)
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); // 等待发送完成
}
}
功能验证
发送测试
在main
函数中循环发送字符串:
while (1) {
char msg[] = "Hello CSDN!\r\n";
for (int i = 0; i < strlen(msg); i++) {
USART_SendData(USART1, msg[i]);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); // 等待发送完成
}
delay_ms(1000); // 延时1秒
}
接收测试
使用串口助手(如XCOM、SSCOM):
- 设置波特率115200,8N1格式。
- 发送任意字符,观察是否回显。
常见问题及解决
-
无数据输出
- 检查TX/RX接线是否反接
- 确认串口助手波特率设置正确
-
接收乱码
- 检查系统时钟配置(如HSE_VALUE是否与实际晶振匹配)
- 重新计算波特率:
USART_Baud = fPCLK2 / (16 * BaudRate)
-
中断无法触发
- 确认NVIC配置正确,中断服务函数名无拼写错误
- 检查是否在初始化时使能了接收中断
总结
通过本次学习,掌握了以下技能:
- 使用标准库配置USART外设
- 实现阻塞式发送与中断接收
- 通过串口助手验证通信功能
参考资料:
- 《STM32F10x中文参考手册》
- 野火/正点原子STM32开发教程