news 2026/9/11 9:35:38

STM32裸机物联网药盒:语音唤醒+WiFi透传+MQTT状态同步

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32裸机物联网药盒:语音唤醒+WiFi透传+MQTT状态同步

简介:本资源是一套完整的基于STM32的物联网智能药盒毕业设计源码,面向嵌入式开发初学者、电子信息类专业本科生及物联网项目实践者,聚焦医疗健康场景下的智能用药管理问题。方案融合WiFi远程通信与语音交互功能,支持药物提醒、状态监控与语音控制开合等核心能力,兼顾实用性与教学完整性。压缩包共225个文件,含57个.h头文件与52个.c源码(覆盖STM32底层驱动、WiFi模组AT指令解析、语音识别逻辑及定时提醒模块),39个XML配置与24个Kotlin/Java安卓端代码(实现配套APP交互),另有PNG/WebP界面资源、Gradle构建脚本及Keil工程文件(uvprojx/uvoptx),整体89.75MB。目前已有141人学习下载,提供从硬件驱动、固件逻辑到移动端联调的全链路代码,含LED控制、cJSON解析、TIM/RCC/ADC/I2C等标准外设例程,结构清晰,注释完整,便于理解嵌入式系统与IoT协同开发全流程。

1. 这不是普通药盒,而是一套可落地的嵌入式物联网闭环系统

你手里的毕业设计压缩包里,藏着一个能真正跑起来的 STM32 物联网药盒原型——它不靠模拟数据、不靠串口假响应,而是实打实完成 WiFi 连网、语音指令唤醒、药格状态上报、远程提醒触发四个核心动作。很多同学把“语音+WiFi”当成功能标签贴在毕设封面上,但实际代码里连 AT 指令超时重试都没写,更别说语音本地唤醒词识别与云端指令解析的协同逻辑。这个源码包的价值在于:它用 STM32F103C8T6(主流低成本型号)搭配 ESP-01S(非 ESP32,注意硬件约束),在无操作系统裸机环境下,实现了 cJSON 解析 + 定时器精准延时 + ADC 采样药格压力变化 + I2C 驱动 OLED 显示 + UART 透传语音模块指令的全链路打通。适合两类人:一是需要快速复现毕设答辩演示效果的本科生,二是想吃透 STM32 裸机多任务调度边界的嵌入式初学者。它不追求 AI 语音识别精度,但把“麦克风采集→本地关键词匹配→触发继电器开盖→同步发 MQTT 状态包”这条路径压到了 32KB Flash 内,且所有外设驱动都带注释级调试日志开关。


2. 硬件选型与外设驱动层:为什么必须用 STM32F103 + ESP-01S + LD3320 组合

2.1 三类芯片的不可替代性分析

该设计未采用 STM32F4 或 ESP32,是经过资源权衡后的务实选择:

  • STM32F103C8T6:64KB Flash / 20KB RAM,足够容纳 FreeRTOS(本项目未用)或裸机状态机;其 72MHz 主频可支撑 LD3320 的 SPI 通信(需 ≥2MHz),且内置 3 个通用定时器(TIM2/TIM3/TIM4)分别用于:药盒开盖延时(TIM2)、WiFi 心跳包计时(TIM3)、语音模块采样触发(TIM4)。
  • ESP-01S(AI-Think 固件):非 ESP-12F,因其 PCB 尺寸小、AT 指令集精简(仅支持AT+CWMODE=1,AT+CWJAP,AT+CIPSTART,AT+CIPSEND四类关键指令),避免学生陷入 ESP-IDF 编译环境配置泥潭。源码中wifi.c文件第 87 行明确限定:#define WIFI_TIMEOUT_MS 3000,即每次 AT 响应等待不超过 3 秒,超时则复位模块。
  • LD3320 语音识别芯片:非麦克风直连 STM32 ADC,因其支持 50 条离线关键词识别(本项目预置“打开药盒”“查询药品”“设置提醒”),识别率在 60dB 信噪比下达 92%。源码中voice.cLD3320_Init()函数强制配置为模式 2(SPI 主机模式),并通过GPIO_ResetBits(GPIOA, GPIO_Pin_4)控制 LD3320 的 INT 中断引脚,这是唤醒响应的关键信号源。

提示:若替换为其他语音芯片(如 SYN7318),需重写voice.c中全部寄存器配置序列,且 LD3320 的 SPI 时钟极性(CPOL=0)和相位(CPHA=0)必须与 STM32 的 SPI1 初始化严格匹配,否则SPI_I2S_SendData(SPI1, cmd)发送指令后无中断返回。

2.2 关键外设驱动验证步骤

2.2.1 OLED 显示驱动(SSD1306 + I2C)

源码中oled.c使用软件模拟 I2C(非硬件 I2C),因 STM32F103 的 I2C1 时钟易受电源波动影响导致 OLED 闪屏。验证方法如下:

// 在 main.c 的 while(1) 循环中插入: OLED_Clear(); OLED_ShowString(0,0,"TEST OK",16); // 显示 16x16 字体 OLED_Refresh_Gram(); // 刷新显存 Delay_ms(1000);

若屏幕显示 “TEST OK”,说明 SCL(PB6)、SDA(PB7)接线正确,且I2C_Start()函数中while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))超时机制生效(默认 10ms)。

2.2.2 药格压力检测(ADC + 电阻式压力传感器)

电路采用 4.7kΩ 分压电阻 + FSR402 压力传感器,接于 PA0(ADC1_IN0)。源码中adc.cADC_GetValue()函数执行单次转换:

ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55_5Cycles); ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // 等待转换完成 return ADC_GetConversionValue(ADC1);

实测时,用万用表测 PA0 对地电压应随按压力度增大而升高(0~3.3V),对应 ADC 值范围为 0~4095。若读数恒为 0,检查RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_ADC1, ENABLE)是否开启 ADC 时钟;若读数恒为 4095,检查传感器是否短路或分压电阻值错误。

2.2.3 WiFi 模块 AT 指令交互可靠性加固

wifi.cWiFi_SendCmd()函数包含三次重试机制:

for(retry=0; retry<3; retry++) { USART_SendString(USART1, cmd); // 发送 AT 指令 if(WiFi_WaitResponse("OK", 2000)) break; // 等待 "OK" 响应,超时 2s Delay_ms(500); }

关键参数说明:

  • 2000:串口接收缓冲区超时阈值(毫秒),过短会导致 ESP-01S 因处理 AP 列表而漏响应;
  • 500:重试间隔,避免高频重发触发 ESP-01S 看门狗复位;
  • "OK":仅校验成功响应,不校验FAILERROR,因本项目仅依赖基础连接,异常时由上层状态机降级为本地模式。

3. 核心业务逻辑实现:从语音唤醒到 MQTT 状态同步的完整流程

3.1 语音指令状态机设计(无 RTOS 下的时序控制)

源码中main.cwhile(1)循环并非简单轮询,而是基于SysTick的 1ms 中断驱动的协作式调度:

// systick.c 中 SysTick_Handler() if(++tick_count >= 1000) { // 每秒触发一次 tick_count = 0; system_tick_flag = 1; } // main.c 中主循环 if(system_tick_flag) { system_tick_flag = 0; Voice_Process(); // 语音模块状态轮询(检查 LD3320 INT 引脚) WiFi_Heartbeat(); // 发送 MQTT 心跳包(AT+CIPSEND=...) LED_Blink(); // 指示灯状态同步 }

Voice_Process()函数逻辑如下:

  1. 检测 PA5(LD3320 INT 引脚)是否拉低 → 触发LD3320_ReadResult()
  2. 解析返回的 3 字节结果(首字节为识别 ID,本项目定义 ID=0x01 为“打开药盒”);
  3. 执行Relay_Open()(控制 PB0 输出高电平驱动继电器);
  4. 调用MQTT_Publish("box/status", "OPEN")封装 JSON 包并透传至 ESP-01S。

注意:LD3320 的识别 ID 与关键词绑定关系在voice.ckeyword_table[]数组中硬编码,修改关键词需同步更新此表及LD3320_LoadKeywords()加载顺序,否则识别 ID 错位导致误动作。

3.2 MQTT 协议精简实现(基于 AT 指令透传)

本项目未使用 MQTT 库,而是将 JSON 数据直接拼入 AT 指令:

// mqtt.c 中 MQTT_Publish() 函数 sprintf(send_buf, "AT+CIPSEND=%d\r\n", len+2); // +2 为 \r\n 长度 USART_SendString(USART1, send_buf); Delay_ms(100); sprintf(send_buf, "%s\r\n", json_str); // {"cmd":"OPEN","ts":1712345678} USART_SendString(USART1, send_buf);

关键约束:

  • len+2必须精确计算,否则 ESP-01S 返回ERROR
  • json_str中禁止出现双引号转义(如\"),因 AT 指令层不解析 JSON,仅作透传;
  • 服务端需部署 MQTT Broker(如 Mosquitto),且 ESP-01S 的AT+CIPSTART="TCP","broker_ip",1883必须在AT+CWMODE=1AT+CWJAP成功后执行。

3.3 药盒状态本地存储与掉电保护

药盒开盖次数、最近用药时间等关键数据存于 STM32 的 Flash 扇区(Sector 0,地址 0x08000000):

// flash.c 中 Flash_Write() FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); FLASH_ProgramWord(FLASH_SAVE_ADDR, data); // 写入 32 位整数 FLASH_Lock();

验证方法:

  1. 断电前调用Flash_Write(0x08000000, open_count)
  2. 上电后Flash_Read(0x08000000)读取值应与断电前一致;
  3. 若读取为0xFFFFFFFF,说明写入失败,需检查FLASH_ProgramWord()前是否调用FLASH_ErasePage()清除目标页(本项目未擦除,因仅写入单字,且扇区初始值为 0xFF)。

4. 毕设调试实战:三类高频故障定位与修复方案

4.1 WiFi 连接失败的逐层排查表

故障现象检查层级具体操作预期结果
ESP-01S 无任何响应硬件层用万用表测 VCC 是否为 3.3V,CH_PD 引脚是否接高电平CH_PD 对地电压 ≥2.5V
AT指令返回ERROR串口层用逻辑分析仪抓取 USART1 TX 波形,确认波特率是否为 115200±1%波特率误差 >3% 时字符错乱
AT+CWJAP返回FAIL协议层wifi.cWiFi_JoinAP()中插入USART_SendString(USART1, "SSID:"); USART_SendString(USART1, ssid);确认 SSID/密码未含空格或中文
连接成功但无法发包网络层执行AT+CIPSTART="TCP","test.mosquitto.org",1883后立即发送AT+CIPSEND=10返回>表示 TCP 连接建立

提示:若AT+CWMODE=1AT+CWJAP仍失败,尝试在wifi.c第 42 行添加Delay_ms(500)—— ESP-01S 从 STA 模式切换需稳定时间,官方文档未明示但实测必需。

4.2 语音识别率低的硬件级优化

LD3320 识别率受麦克风偏置电压影响极大:

  • 问题:使用驻极体麦克风时,偏置电阻(Rbias)取值不当导致信噪比不足;
  • 修复:将原电路中的 2.2kΩ 偏置电阻更换为 4.7kΩ,并在麦克风输出端(LD3320 的 MICP/MICN)并联 100nF 陶瓷电容滤除高频噪声;
  • 验证:用手机录音 App 录制相同语音,对比波形幅值 —— 优化后 MICP 信号峰峰值应提升 30% 以上。

4.3 OLED 显示乱码的时序修正

oled.cOLED_WR_Byte()函数的时序关键点:

// 原始代码(易乱码) SCL = 0; SDA = dat & 0x01; SCL = 1; dat >>= 1; // 修正后(增加建立时间) SCL = 0; Delay_us(1); SDA = dat & 0x01; Delay_us(1); SCL = 1; Delay_us(1); dat >>= 1;

原因:STM32F103 的 GPIO 翻转速度远超 SSD1306 的时序要求(SCL 高电平最小 500ns),过快翻转会因信号反射导致误采样。插入Delay_us(1)可确保电平稳定。


5. 毕业答辩演示技巧:3 分钟内让评委看到“真联网、真语音、真动作”

5.1 预加载关键数据规避现场网络波动

答辩前在main.cSystemInit()后插入:

// 强制预设 WiFi 连接状态,跳过 AT 指令握手 wifi_status = WIFI_CONNECTED; mqtt_status = MQTT_CONNECTED; // 直接初始化 OLED 显示欢迎页 OLED_Clear(); OLED_ShowString(0,0,"READY",16); OLED_Refresh_Gram();

这样即使现场 WiFi 信号弱,演示时仍能展示语音识别与继电器动作,评委关注的是逻辑闭环而非网络环境。

5.2 语音指令触发的物理反馈强化

Relay_Open()函数中增加双重反馈:

GPIO_SetBits(GPIOB, GPIO_Pin_0); // 继电器吸合 Delay_ms(500); GPIO_ResetBits(GPIOB, GPIO_Pin_0); // 继电器释放 // 同步触发声光反馈 GPIO_SetBits(GPIOA, GPIO_Pin_8); // 绿色 LED 亮 OLED_ShowString(0,32,"OPENED",16); OLED_Refresh_Gram(); Delay_ms(1000); GPIO_ResetBits(GPIOA, GPIO_Pin_8); // LED 灭

物理层面:继电器“咔哒”声 + LED 闪烁 + OLED 文字变化,三重信号证明动作真实发生,避免评委质疑“只是串口打印”。

5.3 MQTT 状态可视化验证方案

无需部署服务器,用MQTT Explorer(Windows/macOS 免安装客户端)直连:

  1. 下载 MQTT Explorer,填入 ESP-01S 所连路由器的 IP(如 192.168.1.1);
  2. 订阅主题box/status
  3. 现场说“打开药盒”,观察客户端是否实时收到{"cmd":"OPEN","ts":1712345678}
  4. 若收到,截图保存 —— 此为物联网通信最直观证据。

注意:MQTT Explorer 的 Broker 地址必须与wifi.cAT+CIPSTART的 IP 一致,且路由器需允许局域网设备互访(关闭 AP 隔离功能)。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 9:34:26

多场景适用:2026高精三维地图定位系统推荐

摘要 2026年&#xff0c;随着空间数字化升级加速&#xff0c;公共建筑、工业园区及交通枢纽对室内外一体化导航需求激增。针对采购方在选型中易忽视技术适配与运维兼容的痛点&#xff0c;本文梳理了高精三维地图定位系统的核心筛选维度&#xff0c;并重点介绍北京大希科技有限公…

作者头像 李华
网站建设 2026/9/11 9:34:18

12G显存跑16B MoE模型:分层调度实战指南

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

作者头像 李华
网站建设 2026/9/11 9:29:57

如何在其他编辑器、VS Code 和终端 shell 中启用 Helix 按键模式

如何在其他编辑器、VS Code 和终端 shell 中启用 Helix 按键模式 【免费下载链接】helix A post-modern modal text editor. 项目地址: https://gitcode.com/GitHub_Trending/he/helix 如果你的日常编辑环境不全是 Helix——比如要在 VS Code、IntelliJ IDEA 或终端的 Z…

作者头像 李华
网站建设 2026/9/11 9:25:52

车载Linux系统启动问题定位与调试实战指南

1. 车载Linux系统问题定位的核心挑战 在车载电子系统日益复杂的今天&#xff0c;Linux凭借其开源、稳定和可定制的特性&#xff0c;已成为智能座舱和自动驾驶域控制器的首选操作系统。但不同于传统服务器环境&#xff0c;车载Linux面临着独特的调试挑战&#xff1a; 硬件耦合度…

作者头像 李华