发布时间:2026/9/4 22:47:41
STM32F103通过USART串口指令实现多LED状态控制 1. 项目背景与硬件准备最近在做一个智能家居控制项目需要STM32通过串口接收指令控制多个LED灯的状态。手头正好有块正点原子的精英版STM32F103ZET6开发板板载4个LED和CH340G串口芯片特别适合做这个实验。先说说硬件连接开发板USART1的PA9(TX)和PA10(RX)已通过CH340G与电脑连接LED1~LED4分别连接在PB5、PB0、PB1、PC13引脚使用USB转串口模块时记得把开发板的BOOT0跳线帽接到1下载模式实测中发现个坑如果直接用杜邦线连接USB转TTL模块必须共地GND接GND否则会出现乱码。有次调试两小时才发现是地线没接气得我差点把开发板扔出窗外。2. USART串口初始化配置先上干货初始化代码要配置三个部分// 1. GPIO初始化 void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; // 开启GPIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE); // 配置USART1的TX(PA9)为复用推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); // 配置USART1的RX(PA10)为浮空输入 GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStructure); // 配置LED引脚(PB5,PB0,PB1,PC13)为推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_5 | GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_Init(GPIOB, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_13; GPIO_Init(GPIOC, GPIO_InitStructure); } // 2. USART初始化 void USART1_Config(void) { USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); USART_InitStructure.USART_BaudRate 115200; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; USART_Init(USART1, USART_InitStructure); USART_Cmd(USART1, ENABLE); }波特率计算有个小技巧当系统时钟72MHz时115200波特率对应的USARTDIV39.0625。配置时直接填整数部分39小数部分0.0625×161所以BRR寄存器应设置为0x271。3. 指令集设计与状态控制3.1 指令格式定义为了控制多个LED我设计了这样的指令格式单灯控制LEDx_ON / LEDx_OFF x1~4群组控制ALL_ON / ALL_OFF特殊效果ALL_BLINK闪烁3次查询状态STATUS?例如发送LED1_ON点亮PB5的LED发送ALL_BLINK让所有LED闪烁发送STATUS?返回当前LED状态3.2 状态机实现用状态机处理指令更可靠下面是核心逻辑typedef enum { CMD_LED1_ON, CMD_LED1_OFF, CMD_LED2_ON, // ...其他指令枚举 CMD_UNKNOWN } CommandType; CommandType parse_command(char* cmd) { if(strstr(cmd, LED1_ON)) return CMD_LED1_ON; if(strstr(cmd, LED1_OFF)) return CMD_LED1_OFF; // ...其他条件判断 return CMD_UNKNOWN; } void execute_command(CommandType cmd) { switch(cmd) { case CMD_LED1_ON: GPIO_ResetBits(GPIOB, GPIO_Pin_5); USART_SendString(USART1, LED1 is ON\r\n); break; case CMD_LED1_OFF: GPIO_SetBits(GPIOB, GPIO_Pin_5); USART_SendString(USART1, LED1 is OFF\r\n); break; // ...其他case } }4. 字符串解析与中断处理4.1 接收缓冲区管理#define MAX_CMD_LEN 32 char rx_buffer[MAX_CMD_LEN]; uint8_t rx_index 0; void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) ! RESET) { char ch USART_ReceiveData(USART1); if(ch \n || rx_index MAX_CMD_LEN-1) { rx_buffer[rx_index] \0; process_command(rx_buffer); rx_index 0; } else { rx_buffer[rx_index] ch; } } }4.2 实用字符串处理技巧在嵌入式环境处理字符串要特别注意效率我总结了几个技巧用strncmp代替strstr做前缀匹配更高效环形缓冲区比线性缓冲区更适合高频数据使用查表法解析指令比if-else更快const CmdEntry cmd_table[] { {LED1_ON, CMD_LED1_ON}, {LED1_OFF, CMD_LED1_OFF}, // ...其他指令 }; CommandType fast_parse(char* cmd) { for(int i0; isizeof(cmd_table)/sizeof(CmdEntry); i) { if(strncmp(cmd, cmd_table[i].name, strlen(cmd_table[i].name)) 0) return cmd_table[i].cmd; } return CMD_UNKNOWN; }5. 系统整合与调试5.1 主程序逻辑int main(void) { SystemInit(); GPIO_Config(); USART1_Config(); // 使能接收中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); NVIC_EnableIRQ(USART1_IRQn); // 发送欢迎信息 USART_SendString(USART1, LED Control System Ready\r\n); while(1) { // 主循环可以添加其他任务 __WFI(); // 进入低功耗模式 } }5.2 调试经验分享调试时踩过几个坑波特率不匹配电脑端和STM32的波特率必须完全一致中断优先级如果系统有其他中断要合理设置USART中断优先级缓冲区溢出一定要做长度检查我有次就因为没检查导致系统崩溃电气干扰长距离传输时建议加120Ω终端电阻推荐使用SecureCRT或Putty作为串口调试工具比普通的串口助手更稳定。调试时可以添加这样的调试信息#define DEBUG(fmt, ...) \ do { \ char dbg_buf[64]; \ sprintf(dbg_buf, [DEBUG] fmt \r\n, ##__VA_ARGS__); \ USART_SendString(USART1, dbg_buf); \ } while(0)6. 功能扩展与优化6.1 增加指令校验为防止误操作可以增加简单的校验机制指令格式#CMD?问号是校验和校验和计算所有字符异或bool verify_command(char* cmd) { if(cmd[0] ! # || strlen(cmd) 3) return false; char checksum 0; for(int i1; istrlen(cmd)-1; i) { checksum ^ cmd[i]; } return (checksum cmd[strlen(cmd)-1]); }6.2 使用DMA提高效率当需要控制大量LED或高频通信时可以用DMAvoid DMA_Config(void) { DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA1_Channel4); DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)USART1-DR; DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)tx_buffer; DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize 0; DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode DMA_Mode_Normal; DMA_InitStructure.DMA_Priority DMA_Priority_High; DMA_InitStructure.DMA_M2M DMA_M2M_Disable; DMA_Init(DMA1_Channel4, DMA_InitStructure); USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); }7. 最终效果演示烧录程序后打开串口助手测试发送LED1_ON→ PB5 LED点亮发送ALL_BLINK→ 所有LED闪烁三次发送STATUS?→ 返回LED1:ON,LED2:OFF,...为了更直观可以用Python写个测试脚本import serial import time ser serial.Serial(COM3, 115200, timeout1) def send_cmd(cmd): ser.write((cmd \n).encode()) print(ser.readline().decode().strip()) send_cmd(LED1_ON) time.sleep(1) send_cmd(ALL_BLINK) time.sleep(2) send_cmd(STATUS?)这个项目最让我自豪的是指令系统的可扩展性——新增LED或功能只需修改指令表和状态机核心逻辑不用动。后来客户要求增加PWM调光功能我只用了半小时就实现了。

相关新闻

2026/8/31 12:04:17

08-LCD1602驱动实战:从时序解析到自定义字符显示

1. LCD1602基础认知与硬件解析第一次接触LCD1602时,我盯着这个巴掌大的屏幕想了半天——这玩意儿怎么就能显示两行字符呢?后来拆开看才发现,它内部藏着个精密的点阵世界。LCD1602本质上是个16列2行的字符型液晶显示器,每个字符位置…

2026/9/2 7:56:53

从赛题到实战:剖析三端口DC-DC变换器的双模式能量管理策略

1. 三端口DC-DC变换器的设计挑战与工程价值在新能源和智能硬件快速发展的今天,高效能量管理成为技术突破的关键。2021年全国大学生电子设计竞赛的C题——三端口DC-DC变换器,正是对这一技术痛点的精准捕捉。这个看似专业的赛题,实际上解决的是…

2026/8/31 23:07:34

QQ截图独立版:5个隐藏功能让你的Windows截图效率提升300%

QQ截图独立版:5个隐藏功能让你的Windows截图效率提升300% 【免费下载链接】QQScreenShot 电脑QQ截图工具提取版,支持文字提取、图片识别、截长图、qq录屏。默认截图文件名为ScreenShot日期 项目地址: https://gitcode.com/gh_mirrors/qq/QQScreenShot 还在为…

2026/9/5 8:35:22

开源磁盘清理工具选型与安全使用指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/5 8:35:22

从交通灯到LCVCO:射频振荡器设计核心逻辑与相位噪声实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/5 8:35:22

Automation License Manager Service 无法启动

前言:Automation License Manager Service 这个服务项目,一直无法在电脑里启动,在找到这个启动服务项目以后,发现这个项目属性里的“启动”“停止”“暂停”“恢复”所有选项全是灰色,无法选择,另外我还按照…

2026/9/5 8:30:22

Grok Build v1.0.17 MCP多步输入支持:让AI工具调用不再断链

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/5 2:46:54

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/9/5 2:46:52

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/9/5 2:44:34

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/9/5 0:04:47

流式背压机制:避免前端渲染卡死与内存暴涨的滑动窗口限流

流式背压机制:避免前端渲染卡死与内存暴涨的滑动窗口限流在大模型流式输出(Streaming)与智能体实时推流的架构中,生产环境中经常出现一种“上下游生产消费速率严重失衡”的极端情况: 生产端极速产出:大模型…

2026/9/5 2:45:13

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/5 2:30:42

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/5 2:46:50

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…