ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

STM32智能手环毕业设计:从原理图到代码的完整解析

STM32智能手环毕业设计:从原理图到代码的完整解析 简介基于STM32单片机的智能手环项目是一套完整的毕业设计资料涵盖硬件原理图、软件源码和详细设计文档适合电子信息、自动化、计算机等相关专业学生用于毕业设计、课程设计或项目练手。压缩包内共104个文件其中c和h源码负责心率测量、计步显示、血压提醒等功能逻辑与底层驱动bmp和png图片用于开机广告、菜单界面等屏幕显示pdf和docx文档介绍设计方案与使用方法db数据库可存储运行数据整套资料大小约17.74MB目录结构清晰便于对照学习。项目代码经过测试运行稳定支持二次开发或直接作为毕设课设成果。已有809人学习下载无论你是要完成毕业设计还是想入手嵌入式开发这套资料都能提供从原理到实现的全流程参考帮助你快速上手项目。1. STM32智能手环毕业设计拿到资料包先别急着烧录收到“基于STM32单片机的智能手环 源码原理图详细文档配套全部资料毕业设计.zip”这个压缩包很多人的第一反应是解压、打开 Keil 工程、编译下载。但 STM32 智能手环这类项目真正值钱的是“整条链路”而不是“能跑起来”。答辩老师最常问的是某一个引脚为什么这样接、计步阈值怎么定、I2C 总线上挂了三个设备为什么没冲突、掉电后 RTC 还走不走。这些答案都在原理图和源码里需要你顺着硬件、驱动、应用、文档一层层拆开看。所以第一步不是烧录而是把压缩包当学习样本按硬件到软件的顺序自己过一遍。2. 硬件原理图STM32最小系统到手环外设的接线2.1 先读 STM32F103C8T6 最小系统原理图别在电源和晶振上翻车看一张手环原理图我一般按电源、时钟、复位、启动模式、下载调试五步走。STM32F103C8T6 是 48 脚芯片常见于智能手环、鱼缸控制器这类小项目外设不多但 IO 够用。电源部分通常用 AMS1117-3.3 把 5V 降到 3.3V或者用锂电池供电时加一颗 TP4056 充电和升压/降压电路。注意 VDD 和 VDDA 上必须有 100nF 加 1μF 的去耦电容缺了这两颗电容ADC 采集电池电压时会跳得厉害。晶振这里是最容易出问题的地方。8MHz 主晶振要并联一个 1MΩ 电阻两个引脚各接一个 15pF 到 22pF 的负载电容到地电容值需要和晶振规格书匹配不是随便装一颗就能稳定起振。STM32F103C8T6 如果外接 HSE就必须把 OSC_IN/OSC_OUT 固定到 PD0/PD1 上如果是内部 HSI那么 PD0/PD1 可以复用为普通 IO。做手环一般还会加 32.768kHz 晶振给 RTC只能接 PC14/PC15同时这两个脚不能再配别的外设。BOOT0 引脚必须通过 10kΩ 下拉到 GND很多手环原理图会把 BOOT0 用一个 0Ω 电阻接地方便下载时改跳线。启动模式要保证上电从主 Flash 运行否则程序烧进去不跑。复位电路在 NRST 上接 10kΩ 上拉和 100nF 电容ST-Link 连接时也建议把 NRST 引到调试接口这样用 ST-Link Utility 擦除芯片时更稳定。调试接口建议用一个 4Pin 或者 5Pin 排针引出 SWDIO、SWCLK、GND、3.3V不需要带复位脚也可以。使用 ST-Link 的 SWD 模式只需要两根线比 JTAG 省脚。原理图核对到这里可以顺手检查 VREF 是否接 VDDF103C8T6 内部参考电压固定为 3.3V不需要额外电路。最小系统确认没问题后再去看传感器和显示部分。2.2 手环外设选型与模块接口I2C、SPI、UART 怎么分配智能手环的常见功能包括计步、心率、时间显示和蓝牙上报。基于这些功能外设一般选择 MPU6050 加速度计、MAX30102 心率传感器、SSD1306 OLED 屏和 HC-08 蓝牙透传模块。它们的接口如下表功能模块常见型号接口STM32F103C8T6 引脚建议加速度/陀螺仪MPU6050I2CPB8: SCLPB9: SDAOLED 显示屏SSD1306 0.96寸I2CPB8: SCLPB9: SDA心率传感器MAX30102I2CPB8: SCLPB9: SDAPB5: INT蓝牙透传HC-08 / ATK-HC05UARTPA9: TXPA10: RX按键轻触按键 x3GPIOPA0: 返回PA1: 确认PA2: 加一三个 I2C 设备可以挂在同一条总线上但必须保证从机地址不同。MPU6050 默认地址是 0x68AD0 接高电平时变成 0x69SSD1306 的 7 位地址一般是 0x3C这个地址硬件固定MAX30102 的默认地址是 0x57三者刚好错开。每个设备在 PCB 布局上都要加去耦电容I2C 的 SCL 和 SDA 还要分别接 4.7kΩ 上拉电阻到 3.3V上拉电阻不加上拉不起来通信会时好时坏。OLED 选 I2C 接口的版本比 SPI 版本少两根控制线布板更省位置。SSD1306 的复位引脚 RES 可以接 MCU 的 PB4也可以直接接 RC 复位电路为了稳定我一般用 MCU 控制 RES。按键接口要加上 10kΩ 下拉电阻PA0 本身支持 WakeUp待机模式下可以当唤醒源。心率传感器 MAX30102 的 INT 引脚最好接外部中断这样没有检测到脉搏时主控不用一直读 FIFO。为了后面写代码方便把整张原理图的引脚映射整理成头文件。这样原理图评审时也能对着引脚看少走回头路。下面是一段示意#define PIN_SCL GPIO_PIN_8 #define PIN_SDA GPIO_PIN_9 #define I2C_GPIO GPIOB #define HR_INT_PIN GPIO_PIN_5 #define HR_INT_PORT GPIOB #define BT_TX_PIN GPIO_PIN_9 #define BT_RX_PIN GPIO_PIN_10 #define BT_UART USART1这段定义把 I2C、心率中断、蓝牙串口的引脚和串口号固定下来。项目中所有驱动文件只引用这些宏不改裸引脚号。这样原理图和代码一一对应后面调试时查错也方便。如果中途换引脚只需改这一个头文件。2.3 用嘉立创EDA或Altium Designer检查原理图ERC、页码和BOM核对原理图绘制完成不是终点电气规则检查必须跑一遍。在嘉立创EDA中打开“设计规则检查”会看到悬空引脚、单端网络、重复页码等告警。比如有同学在画图时把多页原理图每页都设成 page number 1生成网表后就会出现“有 2 张或以上原理图页面page number 都设成了 1”的错误导出到 PCB 时网络连接全乱。遇到这种问题需要重新设置每一页的图纸编号保证唯一。Altium Designer 里可以执行 Project - Compile在 Messages 面板按错误级别筛选。最常见的 ERC 告警是“Unconnected Pin”和“Net has only one pin”前者说明某根线没连上后者说明网络标签漏了比如 SDA 引脚旁写了 SDA但传感器端的标签写成了 SDA0两个网络实际没连通。这种问题在原理图上不会红报但焊接完所有传感器都读不到。核对完电气规则后生成 BOM 表。逐项检查封装和供货0805 电容、0603 电阻、LQFP48 的 STM32 芯片、OLED 排针方向。嘉立创EDA可以直接联动立创商城看库存Altium 则需要去具体供应商核对。尤其注意晶振的负载电容指定 20pF 就不要换成 22pF否则频率偏差可能让串口乱码。BOM 对了再送去打样焊接回来才能顺利进入软件阶段。3. 源码工程从STM32CubeMX初始化到手环驱动框架3.1 用 STM32CubeMX 配置时钟、I2C、UART生成完整工程源码包里可能自带 Keil 工程但我建议用 STM32CubeMX 重新生成一遍因为初始化代码复用度更高也方便查参数。选择芯片型号 STM32F103C8TxRCC 打开 HSE使用外部晶振Debug 选择 Serial Wire也就是 SWD 模式。时钟树里把 HSE 8MHz 经 PLL 倍频到 72MHzAPB1 总线设置为 36MHzAPB2 设置为 72MHz。I2C1 配置为 Fast Mode速率 400kHz地址 7 位模式。注意 I2C 时钟源来自 APB1如果 APB1 是 36MHzI2C 外设时钟 36MHz400kHz 的分频系数是 90。STM32CubeMX 会自动计算但你要确认它没有报错。USART1 配置为异步模式波特率 115200数据位 8停止位 1无校验开启发送和接收中断。GPIO 配置 PA0-PA2 为输入下拉模式。PB5 配置为外部中断上升沿触发使能。配置完成后生成 MDK-ARM 工程在 Keil 里编译。这里有一个很常见的坑如果电脑里同时装了 Keil C51 和 Keil MDK打开工程时可能加载了错误的编译套装报“not a valid MDK project”或者找到不到头文件。这时需要在 Project - Manage - Project Items 里检查 Toolchain 是不是 ARM Compiler 5/6同时 Global 里确认 STM32F1xx_DFP 支持包已安装。3.2 手环核心驱动I2C 读 MPU6050 和写 OLED 的最小代码在 CubeMX 生成的main.c基础上把驱动单独放到 BSP 目录。MPU6050 初始化最关键是退出睡眠模式并配置采样率下面是精简版#include mpu6050.h #define MPU6050_ADDR 0x68 #define PWR_MGMT_1 0x6B #define SMPLRT_DIV 0x19 #define CONFIG 0x1A #define ACCEL_CONFIG 0x1C uint8_t mpu6050_init(I2C_HandleTypeDef *hi2c) { uint8_t tmp 0x00; // 写 0 到 PWR_MGMT_1退出 sleep并选择内部时钟源 tmp 0x00; HAL_I2C_Mem_Write(hi2c, MPU6050_ADDR 1, PWR_MGMT_1, I2C_MEMADD_SIZE_8BIT, tmp, 1, 100); // 采样率分频输出频率 1kHz / (SMPLRT_DIV 1) tmp 0x07; HAL_I2C_Mem_Write(hi2c, MPU6050_ADDR 1, SMPLRT_DIV, I2C_MEMADD_SIZE_8BIT, tmp, 1, 100); // 加速度量程 ±2g写入 0x00 tmp 0x00; HAL_I2C_Mem_Write(hi2c, MPU6050_ADDR 1, ACCEL_CONFIG, I2C_MEMADD_SIZE_8BIT, tmp, 1, 100); return 0; }所有 HAL 函数都带一个hi2c指针用来指定 I2C1 还是 I2C2。MPU6050 的地址在数据手册上是 7 位值 0x68HAL_I2C_Mem_Write要求传入 8 位地址所以要左移一位变成 0xD0。100 是超时毫秒数在调试时如果返回 HAL_TIMEOUT说明上拉电阻或接线有问题或者设备地址写错。OLED 驱动更简单。SSD1306 通过控制字节区分命令和数据0x00 表示后一个字节是命令0x40 表示后一个字节是数据。发送函数如下static void ssd1306_write(I2C_HandleTypeDef *hi2c, uint8_t type, uint8_t data) { uint8_t buf[2]; buf[0] type; // 0x00: 命令, 0x40: 数据 buf[1] data; HAL_I2C_Master_Transmit(hi2c, 0x3C 1, buf, 2, 50); }这里 I2C 从机地址是 0x3C发送两字节。控制字节的高位 Co 为 0 表示后面连续数据D/C# 位在最低位命令是 0x00数据是 0x40。把 OLED 的初始化命令序列封装成数组循环调用再填充显存屏幕就能亮了。3.3 源码工程怎么组织BSP、App 和文档目录分离源码工程如果只有main.c后期维护会非常痛苦。常见的做法是按 BSP板级支持包、App应用逻辑和 Doc 三层组织。目录结构如下Project/ ├─ Core/ # CubeMX 生成的 main.c、中断、系统时钟 │ ├─ Inc/ │ └─ Src/ ├─ Drivers/ # ST 官方 HAL 库与 CMSIS 内核文件 ├─ BSP/ # 板级驱动oled.c、mpu6050.c、max30102.c ├─ App/ # 应用逻辑menu.c、step_counter.c、power.c └─ Doc/ # 芯片手册、调试记录、通信协议说明BSP 层每个文件对应一个硬件外设对外只提供初始化函数和读写函数。App 层不直接操作 HAL只调用 BSP 提供的接口例如step_counter_update()。这样如果换了一颗加速度传感器只需要改 BSP 里的mpu6050.cApp 层计步逻辑完全不用动。源码里的头文件也要对应清晰mpu6050.h提供MPU_Init和MPU_Read_Acceloled.h提供OLED_ShowStringmenu.h提供状态机轮询。手环项目的源码包如果目录乱产物也难以核对。我会在Doc下放一份README.md写清楚编译工具链、烧录步骤和每个驱动文件的职责这份 README 对毕业设计文档编写也有直接帮助。4. 手环功能实现计步、心率、OLED显示与功耗控制4.1 计步算法从加速度数据到步数怎么算计步在 STM32 上不需要很复杂的神经网络一个阈值加消抖就能达到可演示效果。MPU6050 读出三轴原始加速度先转成单位 g再计算合量平方根。正常走路时加速度合量有周期性高峰峰值超过阈值就认为可能是一步。为了避免抖动要加上“最小步间隔”过滤。参考实现如下#define STEP_THRESHOLD 1.3f #define MIN_STEP_GAP 300u uint32_t step_count 0; static uint32_t last_step_ms 0; void step_detect(float x, float y, float z, uint32_t now_ms) { static float prev_norm 1.0f; float norm sqrtf(x * x y * y z * z); if (norm STEP_THRESHOLD norm prev_norm (now_ms - last_step_ms) MIN_STEP_GAP) { step_count; last_step_ms now_ms; } prev_norm norm; }STEP_THRESHOLD 选 1.3g 是因为正常走路垂直加速度峰值基本在 1.2g 到 1.5g。如果放在手上摆动幅度大可以提高到 1.5g放在口袋里可以降到 1.2g。MIN_STEP_GAP 设为 300ms对应最快每秒 3 步超过这个频率就忽略掉防止抖动和误触产生多个峰值。采样率保持 25Hz 足够过高的采样率只会增加计算量和功耗。4.2 心率采集MAX30102 的 INT 中断与 FIFO 读取心率模块 MAX30102 内部带一个 FIFO可以缓存采样数据。一般设置采样率为 100HzLED 电流根据肤色和佩戴松紧调节。代码里最关键的是中断回调。手指放在传感器上时INT 引脚会拉低或拉高进入下面回调void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin HR_INT_PIN) { hr_data_ready 1; } }主循环检测到hr_data_ready为 1 后通过 I2C 读取 MAX30102 的 FIFO 寄存器把红光和红外数据取出。因为 I2C 总线同时挂了 MPU6050 和 OLED主循环里读取时要注意不能长时间占用总线否则 OLED 刷新会卡顿。可以把心率采集放在定时器中断里触发用标志位通知主循环批量读取。实际测试中MAX30102 对佩戴位置非常敏感手指压紧或松动都会让数据失真。因此不能只看瞬时值需要做 10 个点的滑动平均再把波峰间隔换算成心率。这个算法放在 App 层与驱动分离。文档里要写明波峰检测的阈值是动态的通常取最近 1 秒数据最大值的 80%而不是固定值。4.3 OLED 显示与按键菜单用状态机管理多个页面手环界面一般包含时间、计步、心率、菜单四项。用状态机而不是多个 if 嵌套来维护代码清晰且好扩展。状态定义如下typedef enum { PAGE_MAIN, PAGE_STEP, PAGE_HEART_RATE, PAGE_SET_TIME } page_index_t;按键按下时切换page_index并调用对应的显示函数。长按和短按可以用同一个按键扫描函数区分PA0 短按返回上一级长按进入菜单。每次按键操作后点亮 OLED屏幕超时 10 秒自动熄灭。显示驱动要记得SSD1306 是显存型芯片写显存后要调用HAL_I2C_Mem_Write刷新否则屏幕内容不会变化。刷新频率控制在 20Hz 足够不要不断重绘。4.4 低功耗处理STOP 模式、RTC 唤醒和电池电压测量手环是电池供电整机电流最好控制在 30mA 以下。MCU 大部分时间应处于 STOP 模式用 RTC 闹钟周期性唤醒比如每 1 秒醒来一次刷新时间或者每 10 秒醒来一次采集传感器。进入 STOP 模式前要把 OLED 关掉、LED 灭掉并把 I2C 总线释放。F103 的 STOP 模式代码HAL_SuspendTick(); HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); HAL_ResumeTick(); SystemClock_Config();唤醒后第一件事必须重新调用SystemClock_Config()因为 STOP 模式会把 PLL 关掉如果不重新配置72MHz 主频会变回内部 8MHz串口波特率会乱。电池电压通过 PA1 接一个分压电阻到 3.3V用 ADC1 采集换算公式uint16_t adc HAL_ADC_GetValue(hadc1); float voltage adc * 3.3f / 4095.0f; float battery_v voltage * (100.0f 51.0f) / 51.0f;这里假设分压电阻是 100kΩ 和 51kΩ根据实际原理图调整系数。电池电压低于 3.5V 时要提示充电并在 OLED 上显示低电量图标。5. 配套文档原理图说明、源码注释与论文组织5.1 一个健壮的毕设资料包应该包含哪些文档压缩包名称里强调“详细文档配套全部资料”这说明毕业设计对资料的完整性要求很高。一个合格的手环资料包至少包含以下内容分类文件名称作用硬件资料原理图 PDF、PCB、BOM 表评审、打样、焊接软件资料Keil 工程源码、HEX 烧录文件复现和现场烧录说明文档README、接线说明、编译说明让别人快速上手设计文档开题报告、中期报告、毕业论文满足学校要求测试文档功能测试记录、调试截图、演示视频证明系统可用很多同学只在压缩包里放源码和原理图忽略了 BOM 和测试记录。实际上BOM 表在打样返工时特别重要测试记录则展示你从问题到解决的过程答辩老师非常喜欢看这一类内容。5.2 源码注释和文档对应的关键参数详细文档不是把代码抄一遍而是把“为什么这么设计”解释清楚。比如 I2C 速率为什么是 400kHz 而不是 100kHz因为手环需要快速刷新 OLED但 MPU6050 对 400kHz 也完全支持。MPU6050 采样率为什么设成 125Hz因为计步算法只用 25Hz降采样后可以省电。MAX30102 的 LED 电流为什么设成 6.4mA因为太大会穿透手指导致信号饱和。这些参数说明要写进“软件设计”部分和源码里的宏定义一一对应。建议在Doc目录下放一个parameter_settings.md把所有可调参数列成表格包含默认值、调整范围、对功耗和精度的影响。例如参数名默认值调整范围说明STEP_THRESHOLD1.3f1.1f - 1.6f峰值超过该值才计一步SAMPLE_RATE25Hz10Hz - 50Hz计步采样率OLED_REFRESH_MS50ms20ms - 100ms屏幕刷新周期越低越耗电5.3 毕业论文各章节怎样引用源码和原理图毕业论文写“硬件电路设计”时不要贴整张原理图而是拆成电源模块、STM32 最小系统、传感器模块、蓝牙模块四部分每部分用一张局部原理图或者引脚说明表格。写“软件设计”时把系统结构画成模块框图描述 BSP/App 分层关系然后针对计步和心率各写一个伪代码逻辑。测试章节则放实际测量数据待机电流、通信距离、计步误差。文档里所有图编号要和资料包里的原理图页对应老师按图索骥时能快速定位到原始文件。6. 验证与进阶让手环从“能跑”到“能答辩”6.1 拿到板子后的六步硬件联调第一步万用表测电源对地阻抗避免短路。第二步上电后用示波器或逻辑分析仪看 8MHz 晶振波形起振不正常直接查两个 20pF 电容和 1MΩ 电阻。第三步用 ST-Link 连接打开 ST-Link Utility如果提示 “Error: No STM32 Target Found”先查 SWDIO、SWCLK 是否接反、目标板是否供电、BOOT0 是否被拉高。第四步烧录一个最简单的 LED 闪烁程序确认内核能跑。第五步用 I2C 扫描程序确认总线上三个设备的地址。第六步逐个测试按键、OLED、蓝牙每项通过后再组合测试。扫描 I2C 设备地址的小函数可以写在一个独立工程里也可以临时放在主循环里for (uint8_t addr 1; addr 127; addr) { if (HAL_I2C_IsDeviceReady(hi2c1, addr 1, 1, 10) HAL_OK) { printf(Addr: 0x%02X\r\n, addr); } }这个循环会把总线上所有有响应的地址打印到串口和原理图上的地址一一对照。MPU6050 显示 0x68SSD1306 显示 0x3CMAX30102 显示 0x57这样硬件连接基本可信。串口如果打印乱码检查串口助手的波特率是不是 115200以及 STM32 虚拟串口驱动是否安装。6.2 进阶改造加入 FreeRTOS 和手机蓝牙如果学有余力可以在现有源码中引入 FreeRTOS用三个任务分别管理传感器采集、OLED 显示和按键处理。I2C 总线是共享资源每个设备访问时要加互斥锁否则 OLED 刷新和心率读取会互相打断。蓝牙模块已经在硬件预留了 UART1可以让手环定时把步数和心率打包成一行 JSON 数据发送到手机蓝牙调试助手用手机 APP 或微信小程序显示。最值得做的低功耗优化是把 MAX30102 和 OLED 的电源单独用 MOS 管控制待机时彻底断电这样整机待机电流能从 20mA 降到 1mA 以下。调试功耗时用万用表串联在电池正极分别测运行、睡眠、关机三挡电流记录到测试文档里。频率、电流、显示刷新率这几个数据证书齐全了答辩时无论是被问硬件还是软件都能拿出实际测量结果来印证。本文还有配套的精品资源点击获取
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表