用STM32F103C8T6+JDY-32蓝牙做个智能药箱,附完整电路图与代码(避坑DS1302和OLED)

张开发
2026/4/17 21:39:32 15 分钟阅读

分享文章

用STM32F103C8T6+JDY-32蓝牙做个智能药箱,附完整电路图与代码(避坑DS1302和OLED)
基于STM32F103C8T6与JDY-32蓝牙的智能药箱实战指南记得去年帮家里老人整理药箱时发现过期药品和混乱的用药时间让我意识到传统药箱的不足。作为电子爱好者我决定用STM32打造一个能定时提醒、自动记录用药情况的智能药箱。经过三个版本迭代最终方案选择了STM32F103C8T6作为主控搭配JDY-32蓝牙模块实现手机联动。本文将分享从电路设计到代码调试的全过程特别是如何避开DS1302时钟模块和OLED显示的那些坑。1. 硬件选型与核心模块解析1.1 为什么选择STM32F103C8T6这颗72MHz主频的Cortex-M3内核单片机堪称性价比之王尤其适合需要丰富外设的中小型项目资源充足64KB Flash 20KB RAM足够运行RTOS和蓝牙协议栈开发友好Arduino兼容的硬件生态支持PlatformIO开发环境成本优势国产替代型号价格已降至10元以内扩展性强内置12位ADC、多个定时器和USART接口实际使用中发现其GPIO驱动能力较强直接驱动OLED无需额外电平转换电路。1.2 蓝牙模块选型对比测试过HC-05、JDY-31和JDY-32三种模块后最终选择JDY-32的关键因素模块型号传输距离功耗AT指令价格稳定性HC-0510米较高复杂25元一般JDY-3120米中等简单18元较好JDY-3230米低极简15元优秀JDY-32的另一个优势是支持透传模式无需复杂协议开发即可与手机APP通信。2. 电路设计关键点2.1 主控电路设计要点STM32最小系统需要特别注意以下三点复位电路10K上拉电阻100nF电容组合确保稳定复位晶振电路8MHz主晶振匹配22pF负载电容外壳接地减少干扰电源滤波每个VDD引脚搭配100nF去耦电容靠近芯片放置提示使用0603封装的电容电阻可以大幅缩小PCB面积2.2 传感器接口设计光电开关用于检测药品取出动作电路设计需注意// 光电开关接口配置 void Sensor_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU; // 上拉输入 GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); }实际测试中发现添加10KΩ上拉电阻后信号稳定性提升明显。3. 软件架构与核心代码3.1 主程序框架设计采用时间片轮询架构平衡实时性和开发复杂度void main(void) { Hardware_Init(); // 硬件初始化 Timer_Init(1); // 1ms定时中断 while(1) { if(flag_1ms) { flag_1ms 0; Task_1ms(); // 高速任务按键扫描等 } if(flag_10ms) { flag_10ms 0; Task_10ms(); // 中速任务传感器处理 } Task_Idle(); // 低速任务显示更新等 } }3.2 蓝牙通信协议设计定义简洁的JSON格式数据传输协议{ type: remind, drug: A, time: 08:00, qty: 2 }在STM32端使用轻量级的JSMN解析器处理JSON数据void Bluetooth_Parse(char *json) { jsmn_parser p; jsmntok_t t[32]; jsmn_init(p); int r jsmn_parse(p, json, strlen(json), t, sizeof(t)/sizeof(t[0])); if(r 0 t[0].type JSMN_OBJECT) { for(int i1; ir; i) { if(jsoneq(json, t[i], type) 0) { // 处理type字段 } } } }4. 常见问题解决方案4.1 DS1302时钟模块的坑这个看似简单的时钟芯片有几个隐藏陷阱时序问题必须严格遵循数据手册的时序要求特别是上升沿采样备用电池CR2032电池需要并联100μF电容防止断电时数据丢失初始化问题首次上电必须写入有效时间否则读取值为0xFF改进后的初始化代码void DS1302_Init(void) { // 检查时钟是否已设置 if(DS1302_Read(0x81) 0xFF) { DS1302_Write_Time(2023, 1, 1, 12, 0, 0); // 设置默认时间 } // 启用写保护前需要先关闭保护 DS1302_Write(0x8E, 0x00); DS1302_Write(0x80, 0x00); // 关闭写保护 }4.2 OLED显示优化技巧使用SSD1306驱动的OLED时这些技巧可以提升显示效果双缓冲机制减少屏幕闪烁局部刷新只更新变化区域降低功耗字体优化使用自定义字体节省存储空间实测显示优化前后的对比优化项刷新速度功耗代码量全屏刷新120ms8mA小局部刷新30ms3mA中双缓冲局部15ms2mA大5. 整机测试与性能优化经过两周的连续测试发现几个需要改进的细节蓝牙模块天线位置影响信号强度最终调整到PCB边缘光电开关灵敏度需要软件去抖添加20ms延时判断低功耗模式下DS1302的电流仍有0.5mA改用软件RTC硬件唤醒最终的待机电流控制在1.2mA左右使用2000mAh电池可续航约60天。在多次药物提醒测试中时间误差控制在±3秒/天完全满足用药提醒的精度要求。

更多文章