USART串口发送三大方案详解:从单字节到格式化输出 | 零基础入门STM32第三十四步
主题 | 内容 | 教学目的/扩展视频 |
---|---|---|
串口通信重点课程 |
什么是USART串口,电路原理,单片机内部寄存器,固件库说明。加载相关文件,驱动程序分析,printf的使用。什么是中断,中断的程序设计,还有哪些中断。 | 熟悉串口的使用,熟练使用printf函数。介绍printf函数的高级使用方法,介绍各中断。 |
师从洋桃电子,杜洋老师
📑文章目录
(图1:USART通信连接原理图)
▲ 回顾上期🔍USART串口通信详解:从电路原理到代码实现 | 零基础入门STM32第三十三步
一、USART发送模式全景解读
1. 三种发送方式对比
发送方式 | 实现原理 | 优点 | 缺点 | 适用场景 |
---|---|---|---|---|
USART_SendData单字节发送 | 直接操作数据寄存器 | 响应速度快 | 需手动管理发送状态 | 简单指令传输 |
中断标志位轮询发送 | 检测TC状态位 | 保证数据完整性 | 占用CPU资源 | 中低速可靠传输 |
printf格式化输出 | 重定向标准输出 | 支持复杂数据格式 | 需初始化库文件 | 调试信息输出 |
2. 数据格式核心概念
二、发送方案代码深度解析
1. 基础单字节发送方案
/* 发送方法1:寄存器级操作 */
USART_SendData(USART1, 0x55); // 写入发送寄存器
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); // 阻塞等待发送完成
关键点说明:
USART_FLAG_TC
:传输完成标志位(Transmission Complete)2. 中断状态管理方案
/* 发送方法2:状态机管理 */
#define BUFFER_SIZE 32
uint8_t tx_buffer[BUFFER_SIZE] = "Hello STM32!";
uint8_t *p_tx = tx_buffer;
while(*p_tx) {
USART_SendData(USART1, *p_tx++);
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE)); // 等待发送寄存器空
}
优化特性:
3. printf格式化输出方案
/* 发送方法3:格式化输出 */
#include "usart.h"
int main (void){//主程序
u8 a=7,b=8;
//初始化程序
RCC_Configuration(); //时钟设置
USART1_Init(115200); //串口初始化(参数是波特率)
//主循环
while(1){
/* 发送方法3.1 */
printf("STM32F103 "); //纯字符串发送数据到串口
/* 发送方法3.2 */
// printf("STM32 %d %d ",a,b); //纯字符串和变量发送数据到串口,a符号变量
/* 发送方法3.3 */
// USART1_printf("STM32 a=%d b=%d ",a,b);
delay_ms(1000); //延时
}
}
实现效果:
STM32F103 //发送方法3.1
STM32 7 8 //发送方法3.2
STM32 a=7 b=8 //发送方法3.3
▲ 完整工程代码示例⏬USART串口发送程序
三、数据格式转换秘籍
1. ASCII编码转换表
十六进制 | 字符 | 说明 |
---|---|---|
0x0A | \n | 换行符 |
0x0D | \r | 回车符 |
0x20 | 空格 | 数据分隔符 |
0x30-0x39 | 0-9 | 数字字符 |
▲ 🔍ASCII码表和转义字符
2. 转义字符应用实例
// 发送彩色终端控制指令
printf("\033[1;31m报警信息!\033[0m\n");
// 发送JSON格式数据
printf("{\"sensor\":\"DHT11\",\"temp\":%d}\r\n", temperature);
四、工程实践技巧
1. printf函数优化配置
// 在usart.h中添加以下宏定义
//函数声明
void USART1_Init(u32 bound);//串口1初始化并启动
void USART2_Init(u32 bound);//串口2初始化并启动
void USART3_Init(u32 bound);//串口3初始化并启动
void USART1_printf(char* fmt,...); //串口1的专用printf函数
void USART2_printf(char* fmt,...); //串口2的专用printf函数
void USART3_printf(char* fmt,...); //串口3的专用printf函数
2. 混合发送模式示例
void Send_MultiData(uint8_t cmd, float value) {
/* 协议帧格式:[头] [指令] [数据] [校验] */
USART_SendData(USART1, 0xAA); // 帧头
USART_SendData(USART1, cmd); // 指令码
printf("%.2f", value); // 浮点数据
USART_SendData(USART1, Calculate_Checksum()); // 校验位
}
五、串口助手调试技巧
1. 显示模式设置对比
模式类型 | 显示效果 | 应用场景 |
---|---|---|
十六进制 | 55 41 42 | 原始数据分析 |
文本模式 | UAB | 可读信息显示 |
混合模式 | 55(U) 41(A) 42(B) | 协议调试 |
2. 数据解析示例
当发送0x48 0x65 0x6C 0x6C 0x6F
时:
六、性能优化指南
1. 三种方案速度对比
发送方式 | 1KB数据耗时 | CPU占用率 |
---|---|---|
单字节轮询 | 120ms | 100% |
DMA传输 | 8ms | 0% |
中断批量发送 | 45ms | 30% |
2. 高级发送方案推荐
// DMA发送配置(需开启DMA时钟)
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)tx_buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = data_len;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel4, ENABLE);
七、常见问题排查
1. 典型故障分析表
现象 | 可能原因 | 解决方案 |
---|---|---|
数据首字节丢失 | 初始化时序错误 | 先配置USART再使能时钟 |
最后一个字符重复 | TC标志未及时清除 | 发送后读取DR寄存器 |
浮点数显示异常 | 未启用微库(MicroLIB) | 在IDE中勾选Use MicroLIB |
2. 调试检查清单
- 确认波特率误差小于2%
- 检查TX/RX线序是否交叉连接
- 验证printf重定向是否成功
- 测量信号电平是否达标(3.3V/5V)
- 查看芯片是否进入低功耗模式
实验建议:使用逻辑分析仪捕获发送时序,观察不同模式下的信号波形差异
八、相关资源
[1] 洋桃电子B站课程-STM32入门100步
[2] STM32F103xx官方数据手册
[3] STM32F103X8-B数据手册(中文)
[4] STM32F103固件函数库用户手册(中文)
[5] USART串口发送程序
[6] ASCII码表和转义字符
💬 技术讨论(请在评论区留言~)
📌 下期预告:下一期将探讨USART接收程序
重点课程
,欢迎持续关注!点击查阅🔍往期【STM32专栏】文章
版权声明:本文采用[CC BY-NC-SA 4.0]协议,转载请注明来源
实测开发版:洋桃1号开发版(基于STM32F103C8T6)
更新日志:v1.0 初始版本(2025-02-27)
作者:触角01010001