1. 硬件准备与连接指南第一次接触STM32串口通信时最让我头疼的就是硬件连接问题。记得当时因为TX和RX接反了调试了一整天都没发现。下面我就把STM32F103C8T6与CH340模块的正确连接方式详细说明一下。STM32F103C8T6这块蓝色小板子相信大家都很熟悉它内置了3个USART接口。我们这次主要使用USART1对应的引脚是PA9(TX)和PA10(RX)。CH340模块则是连接电脑USB和单片机的重要桥梁价格便宜而且稳定性不错。具体接线时要注意三个关键点交叉连接原则STM32的TX接CH340的RXSTM32的RX接CH340的TX共地连接一定要把两个模块的GND引脚连在一起电压匹配CH340模块上有3.3V和5V跳线记得选择3.3V与STM32匹配我推荐使用杜邦线连接时按颜色区分红色接VCC(3.3V)黑色接GND黄色接TX绿色接RX。这样既美观又不容易接错。连接完成后插上电脑USB口如果CH340的电源灯亮了说明硬件连接基本没问题。2. 驱动安装与串口识别很多新手都会卡在驱动安装这一步。我遇到过最典型的情况就是设备管理器里显示未知设备或者COM端口带黄色感叹号。Windows系统通常不会自动安装CH340驱动我们需要手动操作先去官网下载最新版CH340驱动打开设备管理器找到带感叹号的设备右键选择更新驱动程序手动指定驱动文件夹安装完成后应该能看到USB-SERIAL CH340设备如果安装后还是有问题可以试试这些排查方法换一个USB接口有些USB3.0接口兼容性不好检查CH340模块的晶振是否正常起振尝试在别的电脑上安装测试成功安装后记下分配的COM口号比如COM3后续串口调试工具会用到这个端口号。3. Keil工程配置详解现在我们来搭建软件开发环境。我使用的是Keil MDK-ARM这是最常用的STM32开发工具。首先新建工程时要注意选择正确的设备型号STM32F103C8T6添加标准外设库STM32F10x_StdPeriph_Lib设置正确的晶振频率根据实际硬件选择8MHz或12MHzUSART相关的关键配置包括系统时钟初始化时要正确配置APB2总线时钟GPIO模式设置PA9为复用推挽输出PA10为浮空输入开启USART1时钟RCC_APB2PeriphClockCmd()这里有个小技巧在Options for Target - Target选项卡中记得勾选Use MicroLIB这样后面使用printf函数时会方便很多。4. USART初始化代码解析下面这段代码是USART初始化的核心部分我加了详细注释USART_InitTypeDef USART_InitStructure; // 波特率设置9600这个值要和串口助手保持一致 USART_InitStructure.USART_BaudRate 9600; // 无硬件流控制 USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; // 同时启用发送和接收模式 USART_InitStructure.USART_Mode USART_Mode_Tx | USART_Mode_Rx; // 无校验位 USART_InitStructure.USART_Parity USART_Parity_No; // 1位停止位 USART_InitStructure.USART_StopBits USART_StopBits_1; // 8位数据长度 USART_InitStructure.USART_WordLength USART_WordLength_8b; // 应用配置 USART_Init(USART1, USART_InitStructure); // 使能USART1 USART_Cmd(USART1, ENABLE);实际项目中我建议把波特率设置为115200这样数据传输更快。但第一次调试时可以先使用9600稳定性更好。5. 数据收发实战代码5.1 基础发送函数先来看最简单的字节发送函数void USART_SendByte(USART_TypeDef* USARTx, uint8_t byte) { USART_SendData(USARTx, byte); // 等待发送完成 while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) RESET); }这个函数的工作原理是将数据写入TDR寄存器等待TXE标志位置1表示数据已转移到移位寄存器硬件会自动将数据通过TX引脚发出5.2 字符串发送函数基于字节发送我们可以实现字符串发送void USART_SendString(USART_TypeDef* USARTx, char *str) { while(*str ! \0){ USART_SendByte(USARTx, *str); } }使用时直接传入字符串指针即可USART_SendString(USART1, Hello STM32!\r\n);5.3 接收中断配置接收数据我更推荐使用中断方式效率更高// 开启接收中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // NVIC配置 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority 1; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure);对应的中断服务函数void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) SET){ uint8_t data USART_ReceiveData(USART1); // 这里可以添加数据处理逻辑 USART_SendByte(USART1, data); // 回传测试 } }6. 调试技巧与常见问题6.1 波特率不匹配表现接收到的全是乱码 解决方法检查STM32和串口助手的波特率是否一致确认APB时钟分频系数计算正确使用示波器测量实际波特率6.2 数据丢失问题表现长数据包接收不完整 可能原因发送速度太快接收方处理不过来缓冲区溢出 解决方案降低波特率使用DMA传输添加硬件流控制6.3 printf重定向方便调试的printf重定向方法#include stdio.h int fputc(int ch, FILE *f) { USART_SendByte(USART1, (uint8_t)ch); return ch; }使用时记得包含stdio.h头文件这样就可以直接使用printf了printf(系统启动完成当前温度%d℃\r\n, temperature);7. 数据包协议设计实际项目中我们通常需要定义自己的通信协议。这里介绍两种常用格式7.1 HEX数据包格式帧头(0xFF) 数据长度(1字节) 数据区 校验和(1字节) 帧尾(0xFE)校验和通常是所有数据字节的累加和取低8位。接收方通过校验和验证数据完整性。7.2 文本数据包格式$开头 命令字 参数1,参数2,... *校验和 \r\n结尾例如$SETTEMP,25*3A\r\n这种格式可读性好方便调试但解析效率较低。8. 进阶应用实例8.1 与上位机通信通过串口可以实现STM32与PC软件的通信。在C#中可以使用SerialPort控件serialPort1.PortName COM3; serialPort1.BaudRate 9600; serialPort1.DataReceived new SerialDataReceivedEventHandler(DataReceivedHandler); serialPort1.Open();8.2 无线模块连接将HC-05蓝牙模块连接到USART2就可以实现无线串口通信。接线方式与CH340类似但需要注意蓝牙模块需要进入AT模式进行配置通信双方波特率必须一致最好添加简单的加密机制8.3 多机通信USART支持多机通信模式通过地址匹配实现。关键配置USART_InitStructure.USART_Mode USART_Mode_Rx; USART_InitStructure.USART_WordLength USART_WordLength_9b; USART_InitStructure.USART_Parity USART_Parity_Even; USART_Init(USART1, USART_InitStructure); USART_SetAddress(USART1, 0x02); USART_ReceiverWakeUpCmd(USART1, ENABLE);主设备发送地址帧时第9位设置为1数据帧第9位设置为0。从设备只在地址匹配时才会唤醒。
从零到一:基于STM32F103C8T6与CH340的USART串口通信实战指南
发布时间:2026/5/31 14:34:53
1. 硬件准备与连接指南第一次接触STM32串口通信时最让我头疼的就是硬件连接问题。记得当时因为TX和RX接反了调试了一整天都没发现。下面我就把STM32F103C8T6与CH340模块的正确连接方式详细说明一下。STM32F103C8T6这块蓝色小板子相信大家都很熟悉它内置了3个USART接口。我们这次主要使用USART1对应的引脚是PA9(TX)和PA10(RX)。CH340模块则是连接电脑USB和单片机的重要桥梁价格便宜而且稳定性不错。具体接线时要注意三个关键点交叉连接原则STM32的TX接CH340的RXSTM32的RX接CH340的TX共地连接一定要把两个模块的GND引脚连在一起电压匹配CH340模块上有3.3V和5V跳线记得选择3.3V与STM32匹配我推荐使用杜邦线连接时按颜色区分红色接VCC(3.3V)黑色接GND黄色接TX绿色接RX。这样既美观又不容易接错。连接完成后插上电脑USB口如果CH340的电源灯亮了说明硬件连接基本没问题。2. 驱动安装与串口识别很多新手都会卡在驱动安装这一步。我遇到过最典型的情况就是设备管理器里显示未知设备或者COM端口带黄色感叹号。Windows系统通常不会自动安装CH340驱动我们需要手动操作先去官网下载最新版CH340驱动打开设备管理器找到带感叹号的设备右键选择更新驱动程序手动指定驱动文件夹安装完成后应该能看到USB-SERIAL CH340设备如果安装后还是有问题可以试试这些排查方法换一个USB接口有些USB3.0接口兼容性不好检查CH340模块的晶振是否正常起振尝试在别的电脑上安装测试成功安装后记下分配的COM口号比如COM3后续串口调试工具会用到这个端口号。3. Keil工程配置详解现在我们来搭建软件开发环境。我使用的是Keil MDK-ARM这是最常用的STM32开发工具。首先新建工程时要注意选择正确的设备型号STM32F103C8T6添加标准外设库STM32F10x_StdPeriph_Lib设置正确的晶振频率根据实际硬件选择8MHz或12MHzUSART相关的关键配置包括系统时钟初始化时要正确配置APB2总线时钟GPIO模式设置PA9为复用推挽输出PA10为浮空输入开启USART1时钟RCC_APB2PeriphClockCmd()这里有个小技巧在Options for Target - Target选项卡中记得勾选Use MicroLIB这样后面使用printf函数时会方便很多。4. USART初始化代码解析下面这段代码是USART初始化的核心部分我加了详细注释USART_InitTypeDef USART_InitStructure; // 波特率设置9600这个值要和串口助手保持一致 USART_InitStructure.USART_BaudRate 9600; // 无硬件流控制 USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; // 同时启用发送和接收模式 USART_InitStructure.USART_Mode USART_Mode_Tx | USART_Mode_Rx; // 无校验位 USART_InitStructure.USART_Parity USART_Parity_No; // 1位停止位 USART_InitStructure.USART_StopBits USART_StopBits_1; // 8位数据长度 USART_InitStructure.USART_WordLength USART_WordLength_8b; // 应用配置 USART_Init(USART1, USART_InitStructure); // 使能USART1 USART_Cmd(USART1, ENABLE);实际项目中我建议把波特率设置为115200这样数据传输更快。但第一次调试时可以先使用9600稳定性更好。5. 数据收发实战代码5.1 基础发送函数先来看最简单的字节发送函数void USART_SendByte(USART_TypeDef* USARTx, uint8_t byte) { USART_SendData(USARTx, byte); // 等待发送完成 while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) RESET); }这个函数的工作原理是将数据写入TDR寄存器等待TXE标志位置1表示数据已转移到移位寄存器硬件会自动将数据通过TX引脚发出5.2 字符串发送函数基于字节发送我们可以实现字符串发送void USART_SendString(USART_TypeDef* USARTx, char *str) { while(*str ! \0){ USART_SendByte(USARTx, *str); } }使用时直接传入字符串指针即可USART_SendString(USART1, Hello STM32!\r\n);5.3 接收中断配置接收数据我更推荐使用中断方式效率更高// 开启接收中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // NVIC配置 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority 1; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure);对应的中断服务函数void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) SET){ uint8_t data USART_ReceiveData(USART1); // 这里可以添加数据处理逻辑 USART_SendByte(USART1, data); // 回传测试 } }6. 调试技巧与常见问题6.1 波特率不匹配表现接收到的全是乱码 解决方法检查STM32和串口助手的波特率是否一致确认APB时钟分频系数计算正确使用示波器测量实际波特率6.2 数据丢失问题表现长数据包接收不完整 可能原因发送速度太快接收方处理不过来缓冲区溢出 解决方案降低波特率使用DMA传输添加硬件流控制6.3 printf重定向方便调试的printf重定向方法#include stdio.h int fputc(int ch, FILE *f) { USART_SendByte(USART1, (uint8_t)ch); return ch; }使用时记得包含stdio.h头文件这样就可以直接使用printf了printf(系统启动完成当前温度%d℃\r\n, temperature);7. 数据包协议设计实际项目中我们通常需要定义自己的通信协议。这里介绍两种常用格式7.1 HEX数据包格式帧头(0xFF) 数据长度(1字节) 数据区 校验和(1字节) 帧尾(0xFE)校验和通常是所有数据字节的累加和取低8位。接收方通过校验和验证数据完整性。7.2 文本数据包格式$开头 命令字 参数1,参数2,... *校验和 \r\n结尾例如$SETTEMP,25*3A\r\n这种格式可读性好方便调试但解析效率较低。8. 进阶应用实例8.1 与上位机通信通过串口可以实现STM32与PC软件的通信。在C#中可以使用SerialPort控件serialPort1.PortName COM3; serialPort1.BaudRate 9600; serialPort1.DataReceived new SerialDataReceivedEventHandler(DataReceivedHandler); serialPort1.Open();8.2 无线模块连接将HC-05蓝牙模块连接到USART2就可以实现无线串口通信。接线方式与CH340类似但需要注意蓝牙模块需要进入AT模式进行配置通信双方波特率必须一致最好添加简单的加密机制8.3 多机通信USART支持多机通信模式通过地址匹配实现。关键配置USART_InitStructure.USART_Mode USART_Mode_Rx; USART_InitStructure.USART_WordLength USART_WordLength_9b; USART_InitStructure.USART_Parity USART_Parity_Even; USART_Init(USART1, USART_InitStructure); USART_SetAddress(USART1, 0x02); USART_ReceiverWakeUpCmd(USART1, ENABLE);主设备发送地址帧时第9位设置为1数据帧第9位设置为0。从设备只在地址匹配时才会唤醒。