ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

STM32智能家居语音控制系统:从原理图到仿真的完整开源实战

STM32智能家居语音控制系统:从原理图到仿真的完整开源实战 先交代一个背景我做嵌入式这几年拆过的“开源项目”没有一百也有八十真正称得上“拿回来能跑、照着能做、看完有收获”的其实不多。今天分享的这套STM32智能家居语音控制系统是少见的把原理图、代码、仿真三者都补齐而且难度正好卡在“学过单片机、想往实际项目走一步”的人能跟上的位置。它用STM32F103C8T6当主控配合离线语音识别模块识别“开灯”“关风扇”这类指令再通过继电器控制强电设备同时留了串口、定时器、传感器扩展接口Proteus仿真工程能让你在没有实物的情况下先把逻辑跑通。如果你正在准备嵌入式方向的毕业设计或者想从“点灯”进阶到“做一个真正能控制家电的小系统”这套玩法值得你花一个周末完整走一遍。下面我按“方案设计 - 原理图 - 代码 - 仿真 - 调试 - 复刻”的顺序把每个关键选择背后的“为什么”一起讲清楚。1. 项目整体设计与架构思路1.1 先想清楚这套系统到底做什么很多初学者拿到这类项目容易陷入一个误区一上来就惦记“智能家居是不是要做成物联网”“要不要接入App”。但实际上这套项目的核心目标非常聚焦用语音替代遥控器或物理开关让人说一句“打开客厅灯”灯就亮说一句“关闭风扇”风扇就停。整个系统可以拆成四个角色语音输入前端负责“听到”人的指令并转成文本或指令码。控制核心STM32F103C8T6负责接收指令、解析意图、驱动外设。执行单元继电器、PWM调速等负责真正控制电器。状态反馈与扩展OLED显示、温湿度传感器、状态指示灯等让系统不再是“黑盒”。这里要特别说清楚这套系统不是做“人工智能语音助手”而是做“指令识别 开关控制”的嵌入式控制中控。搞清楚这个边界后面的方案选型就会顺手很多。1.2 为什么主控选STM32F103C8T6很多人会问现在ESP32这么便宜还自带WiFi为什么不用Arduino写起来那么简单为什么不用我的回答是这套项目的核心目的是“学懂嵌入式控制系统的完整链路”而不是“快速做出一个WiFi盒子”。STM32F103C8T6的优势在于生态成熟、资料极多、价格便宜、外设丰富而且它几乎是国内嵌入式岗位面试题的标准素材。你做语音控制会用到串口做继电器会用到GPIO做PWM调速会用到定时器做传感器读取会用到单总线或I2C这些外设恰好是STM32最常被考察的部分。对比一下几个常见方案方案优点缺点适合场景STM32F103C8T6外设全面、资料多、岗位匹配度高开发门槛稍高没有无线学原理、做毕设、夯实基础ESP32自带WiFi/蓝牙性能强开发很多精力花在联网协议上想做物联网上云Arduino UNO上手极快性能弱离工程实践较远快速原型验证传统51单片机简单便宜外设太少性能拉胯纯入门教学结论很明确在“学习型开源项目”这个定位下STM32F103C8T6是最稳妥的答案。它能让你把UART、TIM、GPIO、中断这些基本功全部练一遍而这些技能迁移到任何其他MCU上都不过时。1.3 语音识别方案选型离线模块才是省心之选语音识别是这套系统最容易被卡住的环节。市面上常用方案有三类第一类是LD3320这类离线语音识别芯片。它的特点是“非特定人”识别不需要训练但实际用起来动态写入识别词条比较麻烦而且抗噪能力一般环境稍微吵一点识别率就往下掉。第二类是SU-03T这类离线语音识别模块。它通过配套的PC端工具预先配置好唤醒词和指令词运行时完全本地识别不需要联网识别结果通过串口直接输出一个自定义的字符串帧。对做嵌入式控制来说这就是最合适的语音前端你只需要解析串口来的几个字节不用管复杂的语音算法。第三类是ESP32加云端ASR方案。识别率确实高但延迟受网络影响还存在隐私和断网问题。对于一个以“手边可控”为主诉求的小系统来说有点杀鸡用牛刀。这套开源项目多数版本用的是SU-03T这类离线模块理由很直接离线、秒响应、串口帧输出稳定、开发成本低。你在配置工具里把“打开客厅灯”映射成指令帧led_on\r\n模块识别到后通过UART发给STM32主控收到这一段就执行对应动作。整个过程不需要写任何音频算法也不需要连服务器最省心。2. 原理图设计每一路信号都要算清楚2.1 电源树最容易翻车的地方很多新手画原理图喜欢把电源“随便接一接”但在这套系统里电源设计是否合理直接决定了继电器吸合时单片机会不会复位。系统采用外部5V适配器供电一路直接给继电器模块供电另一路经过AMS1117-3.3稳压到3.3V供给STM32、语音模块和传感器。这里的核心考量是继电器线圈是感性负载吸合瞬间会有比较大的电流冲击如果MCU和继电器共用一条电源轨且没有足够的滤波电容电压跌落就会导致单片机复位。我在实际测试中估算过整机功耗STM32核心板大约50mA语音模块约80mA单个5V继电器线圈大约70mA如果驱动4个继电器再算上传感器和指示灯总电流会到400mA以上。用USB口供电短时间没问题但长期运行建议用5V/1A以上的适配器并且在电源输入端放一个470uF电解电容和100nF陶瓷电容组合滤波。另外有一点需要特别注意AMS1117-3.3的输入输出压差不能太低5V输入转3.3V压差是1.7V这个没问题但不要试图用AMS1117给多个继电器模块供电压差乘以电流算出来的功耗足够让它发烫。2.2 继电器驱动GPIO不能直连中间必须加驱动级STM32的GPIO输出能力有限一般也就灌入/输出几个毫安级别的电流而5V继电器线圈的驱动电流通常要几十毫安。直接拿GPIO去推轻则继电器吸合无力重则把引脚烧掉。所以原理图里必须加一级三极管驱动。以常用的S8050三极管为例继电器线圈工作电流按70mA算三极管的放大倍数β大约100那么基极电流至少要0.7mA。为了保证三极管饱和导通我们一般取计算值的3到5倍也就是2到3.5mA。STM32GPIO输出高电平3.3V三极管基极-发射极压降约0.7V所以基极限流电阻可以算R (3.3V - 0.7V) / 2.5mA ≈ 1kΩ所以原理图里基极串联一个1kΩ电阻是合理的。再看续流二极管继电器线圈断电时会产生反向电动势这个尖峰如果不处理很容易击穿三极管或干扰单片机。正确做法是在线圈两端反向并联一个1N4148或1N4007注意二极管阴极接正电源阳极接三极管集电极。如果你买的是现成的“低电平触发继电器模块”模块上往往已经做好了光耦隔离和三极管驱动接线只要VCC、GND、IN三根线。但还是要提醒一句很多模块上的IN在低电平时才有效和“GPIO输出1就闭合”的逻辑正好相反写代码前一定要先看模块丝印说明否则你会被“为什么输出高电平灯反而关了”这种问题折磨一下午。2.3 语音模块与主控的通信接口电平匹配要留意SU-03T这类语音模块和STM32之间用的是UART串口通信。接线说简单也简单模块的TX接STM32的RX模块的RX接STM32的TXVCC接电源GND两端共地。但这里有一个容易被忽略的点语音模块默认供电电压可能是5V而STM32的IO口容忍电压虽然能接受5V但长期接不一定保险反过来STM32输出的3.3V电平去驱动某些5V逻辑的模块也可能达不到高电平门槛。稳妥的做法是加一组简单的电平匹配在语音模块TX到STM32RX之间串联一个1kΩ电阻如果模块是5V逻辑再对地加一个2kΩ电阻做分压把电平压到3.3V左右。STM32到模块的TX方向因为模块输入一般兼容3.3V问题不大。这个细节虽然小但在实际现场会避免很多“时通时不通”的诡异故障。2.4 外设扩展与传感器接口预留原理图里我还建议预留一组I2C接口和一组单总线接口方便接OLED显示屏和DHT11温湿度传感器。OLED屏幕能显示当前设备状态、温湿度数值让这套系统看起来更像一个完整的智能家居终端DHT11则能实现“温度超过30度自动开风扇”这种联动场景。在引脚分配上把USART1留给语音模块USART2预留扩展TIM2_CH1用作PWM输出剩余GPIO分配给继电器、按键、LED指示和传感器接口。这样做的价值在于当你以后想接入其他智能模块比如K210视觉模块做“手势识别开关灯”不需要改动整个工程直接在预留的串口上接就行改几行代码就能用。3. 代码实现状态机让“听指令”变成“做事情”3.1 工程结构模块化到文件粒度这套项目的代码工程采用标准模块化结构而不是把所有逻辑堆在main.c里。我建议按下面的方式组织main.c初始化外设、进入主循环。usart.c串口初始化、中断接收、发送函数。voice_ctrl.c语音指令解析与指令表维护。relay.c继电器开关控制接口。timer.cPWM输出配置。dht11.c温湿度读取。oled.c屏幕显示。这样分层的好处非常明显串口负责“搬运数据”语音解析负责“理解意图”继电器控制负责“真正干活”模块之间通过函数接口解耦。以后你想把语音模块换成蓝牙模块只需要在串口层改接收逻辑继电器和解析层完全不用动。3.2 串口接收别用阻塞查询用中断加状态机很多新手在收到语音模块的串口数据时第一反应是写一个while(USART_GetFlagStatus(...)RESET)等着收字节。这样做在小型Demo里能跑但这意味着主循环必须干等串口任何其他任务都做不了。语音控制这种场景有个特点模块吐数据是突发式的而且可能一次来好几个字节加上换行符。用查询方式极易丢失数据。正确做法是开启串口接收中断在中断里把字节放入缓冲区然后在主循环或解析任务里统一处理。这里我放一段精简的接收示例#define BUF_SIZE 64 volatile char rx_buf[BUF_SIZE]; volatile uint8_t rx_index 0; volatile uint8_t rx_complete 0; void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1, USART_IT_RXNE) ! RESET) { char ch USART_ReceiveData(USART1); if (ch \n || ch \r) { if (rx_index 0) { rx_buf[rx_index] \0; rx_complete 1; rx_index 0; } } else { if (rx_index BUF_SIZE - 1) rx_buf[rx_index] ch; } } }这段代码的思路是每次收到字节先判断是不是换行符是换行说明一帧指令收完了置rx_complete标志不是换行就放进缓冲区。主循环只需要轮询这个标志发现有完整的一帧数据就交给解析函数。这样串口中断只做“搬运工”所有耗时处理都放在主循环里既不会阻塞中断也不会丢数据。3.3 指令解析与动作执行解耦函数指针函数表是好东西语音模块识别到“打开客厅灯”之后输出到串口的是一个自定义字符串比如led_on\r\n。STM32收到这串字符后要找到对应的动作这就需要一个“指令表”。最直观的办法是写一堆if-else但指令一多代码就很丑。更优雅的做法是定义一张结构体表用函数指针关联字符串和动作typedef struct { const char *cmd; void (*handler)(void); } cmd_entry_t; void LED_On(void); void LED_Off(void); void FAN_On(void); void FAN_Off(void); const cmd_entry_t cmd_table[] { {led_on, LED_On}, {led_off, LED_Off}, {fan_on, FAN_On}, {fan_off, FAN_Off}, }; #define CMD_TABLE_SIZE (sizeof(cmd_table) / sizeof(cmd_table[0])) void Voice_Parse(char *cmd) { uint8_t i; for (i 0; i CMD_TABLE_SIZE; i) { if (strcmp(cmd, cmd_table[i].cmd) 0) { cmd_table[i].handler(); return; } } // 未匹配指令打印错误提示 printf(unknown cmd: %s\r\n, cmd); }这样做的好处是以后想增加一条“打开窗帘”指令只需要写一个Curtain_Open()函数然后在cmd_table里加一行字符串与函数的对应关系其他代码一概不用动。语音控制逻辑就从“一堆判断”变成了“一张表”可扩展性和可读性都上来了。实际使用时要留意一个问题语音模块输出的帧可能带\r\n也可能带其他前缀比如{event:led_on}这种JSON风格取决于模块固件。最稳妥的办法是先打印一帧原始数据根据实际格式编写解析函数别想当然认为一定是纯字符串。3.4 定时器与PWM调光调速的关键这套系统不只是做“开关”还应该支持“调”。比如控制风扇转速或者LED灯亮度就要用PWM。STM32的PWM功能是由定时器产生的以TIM2为例要把72MHz的定时器时钟配置成1kHz频率的PWM需要设置预分频和自动重载寄存器TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseStructure.TIM_Prescaler 72 - 1; TIM_TimeBaseStructure.TIM_Period 1000 - 1; TIM_TimeBaseStructure.TIM_ClockDivision 0; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse 500; TIM_OC1Init(TIM2, TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_Cmd(TIM2, ENABLE);计算逻辑是定时器输入时钟72MHz预分频72计数频率变成1MHz一个计数器周期是1us自动重载值1000一个PWM周期就是1000us也就是1kHz。TIM_Pulse设为500表示高电平占500个计数周期也就是50%占空比。把TIM_Pulse改到100亮度或转速就是10%。有一点必须讲清楚如果控制的是220V灯具或风扇不能直接把STM32的PWM输出接到可控硅上强电调光需要专门的过零检测和可控硅触发电路复杂度高很多也不安全。PWM调速只适用于直流设备比如5V风扇、LED灯带、直流电机。做这套系统时控制对象要么用继电器做开关要么用PWM做直流调速别混着来。3.5 printf重定向串口日志是嵌入式调试的眼睛嵌入式开发里串口打印日志是排查问题最直接的手段。STM32的USART要支持printf需要重定向fputc函数int fputc(int ch, FILE *f) { USART_SendData(USART1, (uint8_t)ch); while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) RESET); return ch; }之后代码里就能直接写printf(voice cmd: %s\r\n, cmd)来打印指令内容。我在调试语音波形时最常用的就是这套语音模块说话前先打一行waiting voice...收到一帧指令打一行recv: xxx执行动作后再打一行action done。三段日志一出来整个链路的哪个环节出了问题一眼就能定位。4. Proteus仿真没有硬件也能把逻辑跑通4.1 仿真工程搭建步骤这套开源项目里的Proteus仿真工程是我非常推荐先跑起来的东西。没有硬件时它能帮你验证指令解析逻辑和GPIO输出状态有硬件时它能帮你先排除软件逻辑错误避免反复烧录折腾。搭建仿真工程的思路很简单在Proteus元件库里找到STM32F103C8T6芯片拖到画布。晶振电路用8MHz晶体加两个20pF电容复位电路用10kΩ上拉电阻加一个100nF电容到地BOOT0接一个10kΩ下拉电阻。给USART1的TX、RX接一个Virtual Terminal这个虚拟终端用来模拟语音模块的串口输出。在GPIO输出引脚上接LED指示灯或逻辑探针模拟继电器和风扇。把Keil编译好的HEX文件加载进STM32芯片点运行。4.2 Keil如何生成HEX文件很多新手折腾半天发现Proteus里芯片“没程序”是因为Keil默认不输出HEX。需要在Keil里做两步操作点击Options for Target在Output标签页勾选Create HEX File。重新编译编译输出窗口会显示HEX文件生成的路径。然后回到Proteus双击STM32芯片在Program File一项选择刚生成的HEX点OK再运行。这里还要提一个细节如果你电脑上同时装着Keil的C51版和STM32版记得确认当前使用的编译器版本。老方法是在安装时让C51和MDK共存实际用的时候可能出现头文件路径串了的问题。后来我用的是“先装MDK再按官方Pack方式安装对应芯片支持包”的方式基本不会再出现器件选不到的情况。4.3 仿真能验证什么验证不了什么用Proteus跑这套项目能验证的逻辑包括串口能不能收到数据、指令解析能不能匹配、对应GPIO引脚能不能正确置高置低、PWM波形有没有输出、定时器能不能正常进入中断。这些都是嵌入式开发里最核心的软件逻辑能跑通说明代码主体没问题。但仿真验证不了的东西也要心里有数语音模块的实际串口帧格式和时序Proteus里没有这个模型只能靠虚拟终端手动输入模拟帧。继电器带载时的电源冲击、电磁干扰、触点抖动。STM32引脚在实际板子上的驱动能力和信号完整性。所以我的建议是仿真通过后只能代表“逻辑闭环了”不代表“硬件没问题”。真正调硬件时还要按下一章的方法一步一步来。5. 调试实录那些年让人卡住的问题清单5.1 又见“error: no stm32 target found!”很长一段时间这套项目群里的高频问题就是这个报错。完整提示一般是error: no stm32 target found! if your product embeds debug authentication, please check its configuration in the debug authentication pane.这句话本身是说调试器没找到芯片但实际原因五花八门我按排查顺序列一下现象常见原因解决方法设备管理器里ST-Link有黄色感叹号驱动没装好重装ST-Link驱动或用驱动工具修复设备管理器正常但Keil连不上SWDIO、SWCLK接反或接触不良核对杜邦线GND务必共地目标板没供电芯片没上电自然无法响应调试器确认VDD有3.3V电源指示灯亮BOOT0悬空或接高电平芯片进入ISP模式SWD可能异常把BOOT0下拉到地后重新上电接线正常但一直连接失败Keil里SW模式速度太高把Max Clock降到1MHz以下再试之前烧录过读保护程序芯片被锁定用STM32 ST-LINK Utility做Full Chip Erase这套排查顺序我每次都会按照“驱动 - 接线 - 供电 - BOOT - 速率 - 锁死”的顺序走。实际遇到最多的情况其实是前两种一是ST-Link插入后电脑报错“ST-Link驱动安装失败”二是SWDIO和SWCLK两根线接反了。每次出问题先别怀疑芯片烧了先拿万用表量一下VDD和GND再量一下SWDIO引脚有没有波形能省很多无用功。5.2 继电器吸合瞬间单片机当场复位这是我第一次搭这套系统时踩过最深的坑。现象是单独用串口助手发指令一切正常语音说“开灯”继电器“咔哒”一声吸合然后系统重启了。最后定位是电源问题。继电器线圈在通电瞬间会形成一个很大的冲击电流而我用的是USB供电电源本身能力弱5V电压瞬间被拉低AMS1117输出的3.3V也跟着跌落单片机直接欠压复位。解决方法是三管齐下换一个5V/2A的适配器供电在电源入口加大容量的电解电容同时对每个继电器线圈驱动电路做好续流保护。如果还不行就考虑把继电器模块独立供电用光耦把控制信号隔离不过这套系统的功率级别一般不用做到那么复杂。这里顺便说一个软件上的规避技巧如果系统同时控制多个继电器不要让它们在同一瞬间全部吸合可以在代码里给每个继电器的动作加一个30到50ms的延时。错峰启动能有效降低电源瞬时压力。代码很简单就是delay_ms(40)但效果很明显。5.3 串口中文乱码和语音识别率低语音模块的输出帧有时候不是纯英文而是中文编码字节。如果你在串口助手里看到一堆0xE5开头的字节那基本就是UTF-8编码的中文。解决办法是修改模块配置工具里的指令帧格式尽量用纯ASCII的指令比如led_on而不是“开灯”这两个字。这样STM32侧的解析更简单日志也好看。如果一定要用中文就需要在STM32里做字符串匹配注意编码一致性别混用UTF-8和GBK。语音识别率低的问题多半不是代码逻辑问题而是硬件位置问题语音模块离扬声器太近、麦克风孔被遮挡、供电不稳导致模块内部工作异常。SU-03T这类模块对环境噪声也比较敏感尽量把麦克风开孔朝上远离电机和继电器这类会产生噪声的器件。另外一个容易被忽略的点是唤醒词和指令词必须在模块配置工具里重新烧录后才会生效不要只改串口监视器里的内容那你改的只是自己前端看到的界面模块固件完全不知道你改过。5.4 ST-Link Utility与Keil怎么配合Keil的下载功能偶尔会出一些奇怪问题比如“Flash Download failed”。遇到这种情况不要死磕Keil可以拿STM32 ST-Link Utility来帮忙。它的用法很直接接好ST-Link和板子在Utility里连接目标芯片如果能读到芯片型号和Flash容量说明硬件链路OK然后执行Full Chip Erase把芯片恢复成出厂状态。之后再回到Keil重新下载绝大多数情况下问题就解决了。如果Utility里也连不上那就要回到上一张表格继续按“驱动 - 接线 - 供电”排查。Utility的好处是它能给出更底层的错误信息比Keil的提示更接近硬件真相。6. 开源资料怎么用从零复刻的完整路径6.1 拿到资料包先看什么这套项目开源包里的东西不少我建议不要一头扎进代码而是按下面顺序来先看README再看BOM物料清单然后打开原理图PDF最后才是代码。README里一般会写明所有资料的说明、版本号、和已知问题。BOM清单能告诉你要买哪些零件照着采购就行。原理图PDF要看懂电源走向、MCU引脚分配、每个外设的连接关系心里对整块板子的“地图”有数之后再去看代码会清晰很多。有一点要提醒开源包里的原理图可能是PDF、可能是原理图源文件也可能是图片不同作者习惯不一样。如果是PDF直接看网络标号和引脚名称如果是工程源文件需要对应的EDA软件才能打开别装一堆不必要的工具。6.2 焊接与验证顺序如果你打算自己焊板子强烈建议不要一次性把所有元器件全焊完再上电。正确的做法是“焊一块、测一块”先焊电源部分包括5V输入、AMS1117、滤波电容然后上电量3.3V是否正常。再焊STM32最小系统包括晶振、复位、BOOT电路用ST-Link连接确认能识别到芯片。接着焊串口和ST-Link调试接口下载一个点灯程序确认GPIO输出正常。然后焊继电器驱动电路用一个临时按键或串口指令控制继电器确认吸合释放。最后焊语音模块和传感器整机联调。这套顺序的本质是“先最低成本确认系统能跑起来再叠加复杂度”。如果一上来把所有东西焊满上电后发现3.3V异常你根本不知道是电源的问题还是某个外设短路排查难度会大很多。6.3 联调验证用串口助手代替语音模块做“假想敌”调试语音控制链路时不要一上来就用语音模块喷指令。先用USB转TTL串口模块接到STM32的USART1接口用电脑串口助手直接发送led_on这种指令串。这样做的好处是你能完全控制输入内容排除语音识别不准的干扰。等确认STM32能正确解析并执行动作后再把语音模块接上让模块替代串口助手来发数据。如果语音模块接到STM32上后串口助手能收到模块的数据但STM32不动作优先检查两边波特率是否一致。SU-03T在配置工具里可以设置串口波特率默认常见的是9600或115200而STM32初始化代码里写的波特率是否一致直接决定了解析能不能成功。遇到这类问题时打开串口助手的“HEX显示”把模块发送的原始字节拉出来看一眼立刻就能判断是波特率问题还是内容格式问题。6.4 扩展方向从开关控制到更完整的智能家居这套项目跑通后继续扩展的空间很大。从我个人经验看几条比较顺的路线是加一块OLED屏幕显示当前设备状态和温湿度数据。加DHT11传感器实现“温度超标自动启动风扇”的联动场景。把语音指令执行结果通过USART2发送给ESP8266或ESP32再由它们走WiFi上云积累点MQTT上报经验后面你可以直接去做“基于MQTT的智能家居监控平台”这类项目把设备状态推送到云端看板。利用预留串口接入K210等视觉模块实现“识别到某个手势就关灯”的图像联动。K210和STM32的通讯本质还是UART收发只要保证协议一致代码侧改一个串口入口就行。每次加一个功能都建议按“设计接口 - 跑通最小验证 - 再接入主工程”的节奏来走。这样既不会把已有功能搞坏也方便随时回退。最后说一点我自己的体会做这种开源项目最大的收获往往不是“系统能用了”这个结果而是你完整走了一遍“需求分析 - 方案选型 - 原理图 - 代码 - 仿真 - 真机调试”的闭环流程。这个过程里踩过的每个坑比如电平匹配、继电器反向电动势、串口解析粘帧、SWD连不上都是毕业设计和实际开发中更常见的问题。如果时间充裕我非常建议你亲手从原理图开始改一版哪怕只改一个引脚分配或者加一路继电器也能让你对这个系统的理解上一个大台阶。
返回列表