当前位置: 首页 > news >正文

【开源】基于STM32的智能骑行头盔设计

项目编号:STM32-T010

项目名称:基于STM32的智能骑行头盔设计

【摘要】

        本项目设计了一种基于STM32F103C8T6单片机的智能骑行头盔系统,集成多种传感器与智能控制功能,旨在提升骑行过程中的安全性与智能化体验。系统通过光敏电阻实时检测环境光照强度,当光照值低于设定阈值时自动开启LED照明灯,保障夜间骑行视野;心率检测模块实时监测佩戴者生理状态,若心率异常超过阈值,蜂鸣器立即报警。MPU6050陀螺仪模块用于识别头部转向动作,系统可智能点亮对应方向指示灯,提醒后方车辆注意。超声波模块用于检测后方来车距离,若小于设定阈值,OLED屏幕即时显示“后方来车”提示,增强后方预警功能。用户可通过按键设定光照、心率和距离等阈值,OLED模块同步显示当前环境数据和系统状态。该系统结构紧凑、功能全面,适用于日常骑行及长途骑行场景,具有良好的用户体验和广阔的市场应用前景。

【所用硬件】

1、STM32F103C8T6最小系统板

        STM32F103C8T6最小系统板是基于意法半导体(ST)Cortex-M3内核的微控制器开发板,核心芯片为STM32F103C8T6,主频72MHz,具有64KB Flash和20KB SRAM,满足中等复杂度的嵌入式应用需求。该板集成USB、USART、SPI、I2C等通信接口,支持多种外设扩展。最小系统板包含必要的外围电路,如8MHz晶振、复位电路、电源管理(3.3V稳压),并提供GPIO引脚引出,方便连接传感器、显示屏等模块。其低功耗、高性能特性使其广泛应用于智能硬件、工业控制等领域。在本设计中,它作为主控单元,负责数据采集、处理及外设控制,确保电子秤系统的稳定运行。

2、OLED显示模块

        OLED(有机发光二极管)显示屏模块是一种自发光显示器件,无需背光,具有高对比度、宽视角和快速响应的特点。本设计采用的OLED模块通常为0.96英寸或1.3英寸,分辨率为128×64像素,支持I2C或SPI通信协议,可直接与STM32等微控制器连接。其工作电压为3.3V~5V,功耗低,适合便携式设备。

3、轻触按键

        轻触按键(Tactile Switch)是一种瞬时接触式机械开关,通过按压触发导通,松开后自动复位。其结构简单、体积小巧,通常采用金属弹片或导电橡胶实现触点通断,具有手感清晰、寿命长(可达10万次以上操作)的特点。工作电压和电流范围宽(如12V/50mA),可直接与STM32等微控制器的GPIO引脚连接,需配合上拉/下拉电阻使用以避免信号浮动。

4、光敏电阻模块

        光敏电阻模块是一种基于光敏电阻传感器的检测模块,能够根据环境光强变化调整电阻值,从而实现光照强度的检测。模块通常集成电位器、电阻和比较器电路,可输出模拟信号或数字信号,便于与单片机连接。它响应速度快、使用简单,常用于自动照明、智能小车循迹、光控开关及光照监测等应用场景,是入门级传感器模块中常见且实用的一种。

5、照明LED灯

       LED灯模块是一种常用的光源驱动模块,内部集成了蓝色发光二极管及限流电阻,只需提供稳定的5V直流电源即可点亮,使用方便。该模块发出的蓝光亮度高、色彩纯净,常用于单片机实验、光控提示、装饰照明以及状态指示等场景。模块体积小巧,接口简单,既可单独作为指示灯使用,也能组合多颗实现丰富的视觉效果,具有寿命长、能耗低和响应速度快等优点,适合电子学习和小型智能系统应用。

6、MAX30102心率血氧检测模块

        MAX30102模块是一款集成脉搏血氧和心率监测功能的传感器模块,内部包含高效光学器件和低噪声信号处理电路,能够通过红光和红外光的透射或反射测量血氧饱和度及心率信号。其功耗低,体积小,适合便携式、可穿戴设备应用,常用于健康监测、运动追踪和医疗辅助系统中,具有检测精度高、响应速度快和通信接口简单等特点,便于与单片机、STM32等微控制器进行数据交互和二次开发。

7、蜂鸣器模块

        鸣器模块是一种常见的声音报警装置,广泛应用于电子设备中用于提示或报警功能。该模块通常由一个蜂鸣器和驱动电路组成,能发出高频的蜂鸣声。按照驱动方式可分为有源蜂鸣器和无源蜂鸣器两种类型。有源蜂鸣器只需提供直流电压即可发声,控制简单,适用于固定频率提示场景;无源蜂鸣器则需要外部提供特定频率的驱动信号才能工作,适用于需要调节音调或生成特定声音模式的场合。模块通常采用5V或3.3V供电,可通过三极管或专用驱动芯片控制启停,响应速度快,可靠性高,常用于智能设备、安防系统、工业仪表等场景中。

8、MPU6050陀螺仪模块

        MPU6050陀螺仪模块是一款常用的六轴传感器,内部集成了三轴加速度计和三轴陀螺仪,能够实时测量物体的加速度与角速度信息。该模块通过I2C接口与单片机或其他控制器进行通信,体积小巧、功耗低,适用于姿态检测、运动跟踪和机器人平衡控制等场景。由于其数据稳定、价格适中,MPU6050在智能车、无人机以及可穿戴设备中应用十分广泛。

9、超声波模块

超声波模块是一种利用超声波测距原理的传感器模块,常通过发射超声波并接收其反射信号来计算与目标物体的距离。该模块具有结构简单、成本低廉、精度较高和抗光线干扰能力强等优点,广泛应用于机器人避障、汽车倒车雷达、液位检测和智能家居等领域。其工作电压低,接口方式简单,易于与单片机、STM32等控制器结合使用,因而成为常见的测距与感知方案。

【系统框架图】

【软件流程图】

【核心代码展示】

#include "app_task.h"
#include "main.h"
#include "m5310a.h"
#include "delay.h"
#include "usart.h"
#include "timer.h"
#include "esp8266.h"
#include "io.h"
#include "led.h"
#include "oled.h"
#include "sim800l.h"
#include "rtc.h"
#include "Encoder.h"
#include "beep.h"
#include "mpu6050.h"
#include "inv_mpu.h"
#include "adc.h"
#include "key.h"
#include "dth11.h"
#include "ds18b20.h"
#include "PAJ7620.h"
#include "max30102.h"
#include "stm32f10x_adc.h"
#include "HCSR04.h"u8 str[100];
OLED oled;
USER user;TaskControlBlock TaskList[MAX_TASKS] = {0};
uint8_t RegisteredTasks = 0; // 已注册任务数
uint32_t SystemTick = 0;     // 系统时间基准// 任务注册函数
int8_t Task_Register(uint8_t id, uint32_t interval, void (*task_func)(void *), void *param)
{if (RegisteredTasks >= MAX_TASKS)return -1;TaskList[RegisteredTasks].TaskID = id;TaskList[RegisteredTasks].PollingInterval = interval;TaskList[RegisteredTasks].TimerCounter = 0;TaskList[RegisteredTasks].RunFlag = 0;TaskList[RegisteredTasks].EnableFlag = 1;TaskList[RegisteredTasks].TaskHook = task_func;TaskList[RegisteredTasks].TaskParam = param;TaskList[RegisteredTasks].Delay = 0;RegisteredTasks++;return 0;
}// 任务使能控制
void Task_Enable(uint8_t id, uint8_t enable)
{for (int i = 0; i < RegisteredTasks; i++){if (TaskList[i].TaskID == id){TaskList[i].EnableFlag = enable;break;}}
}/*** @brief LED闪烁任务** @param pt*/
void Led_Task(void *pt)
{LED1 = !LED1;}/*** @brief 按键任务** @param pt*/
void Key_Task(void *pt)
{switch (KEY_Scan(0)){case KEY1_PRICE:{if(oled.page == PAGE_1){OLED_Clear();oled.page = PAGE_2;Task_Enable(4,1);}else if(oled.page == PAGE_2){OLED_Clear();oled.page = PAGE_1;Task_Enable(4,0);}else if(oled.page == PAGE_SET1){if (oled.x < 4)oled.x++;if (oled.x == 4)oled.x = 1;}};break;case KEY2_PRICE:{if (oled.x == 1){if (user.max30102.dis_hr_value < 200)user.max30102.dis_hr_value++;}else if (oled.x == 2){if (user.light_value < 100)user.light_value++;}else if (oled.x == 3){if (user.distance_value < 100)user.distance_value++;}};break;case KEY3_PRICE:{if (oled.x == 1){if (user.max30102.dis_hr_value > 0)user.max30102.dis_hr_value--;}else if (oled.x == 2){if (user.light_value > 0)user.light_value--;}else if (oled.x == 3){if (user.distance_value > 0)user.distance_value--;}};break;case KEY4_PRICE:{if (oled.page == PAGE_1 || oled.page == PAGE_2){oled.page = PAGE_SET1;OLED_Clear();oled.x = 1;Task_Enable(4, 0);}else if (oled.page == PAGE_SET1){oled.page = PAGE_1;OLED_Clear();oled.x = 1;Task_Enable(4, 1);}};break;}
}/*** @brief OLED显示任务** @param pt*/
void OLED_Task(void *pt)
{if (oled.page == PAGE_1){/**智能骑行头盔 */OLED_ShowChinese(16, 0, 14, 16, 1);OLED_ShowChinese(32, 0, 15, 16, 1);OLED_ShowChinese(48, 0, 16, 16, 1);OLED_ShowChinese(64, 0, 17, 16, 1);OLED_ShowChinese(80, 0, 18, 16, 1);OLED_ShowChinese(96, 0, 19, 16, 1);/**光照: */OLED_ShowChinese(0, 16, 20, 16, 1);OLED_ShowChinese(16, 16, 21, 16, 1);OLED_ShowChinese(32, 16, 22, 16, 1);sprintf(str, "%d%%", user.light);OLED_ShowString(48, 16, str, 16, 1);/**距离:*/OLED_ShowChinese(0, 32, 23, 16, 1);OLED_ShowChinese(16, 32, 24, 16, 1);OLED_ShowChinese(32, 32, 25, 16, 1);sprintf(str, "%2.1lfcm", user.distance);OLED_ShowString(48, 32, str, 16, 1);}else if(oled.page == PAGE_2){/**智能骑行头盔 */OLED_ShowChinese(16, 0, 14, 16, 1);OLED_ShowChinese(32, 0, 15, 16, 1);OLED_ShowChinese(48, 0, 16, 16, 1);OLED_ShowChinese(64, 0, 17, 16, 1);OLED_ShowChinese(80, 0, 18, 16, 1);OLED_ShowChinese(96, 0, 19, 16, 1);/**心率: */OLED_ShowChinese(0, 16, 11, 16, 1);OLED_ShowChinese(16, 16, 12, 16, 1);OLED_ShowChinese(32, 16, 13, 16, 1);if (user.max30102.DataValid){sprintf(str, "%3d BPM", user.max30102.dis_hr);OLED_ShowString(48, 16, str, 16, 1);}else{OLED_ShowString(48, 16, "--        ", 16, 1);}}else if (oled.page == PAGE_SET1){/**阈值设置 */OLED_ShowChinese(32, 0, 31, 16, 1);OLED_ShowChinese(48, 0, 32, 16, 1);OLED_ShowChinese(64, 0, 33, 16, 1);OLED_ShowChinese(80, 0, 34, 16, 1);/**心率: */if (oled.x == 1){OLED_ShowChinese(0, 16, 11, 16, 0);OLED_ShowChinese(16, 16, 12, 16, 0);OLED_ShowChinese(32, 16, 13, 16, 0);sprintf(str, "%3d BPM", user.max30102.dis_hr_value);OLED_ShowString(48, 16, str, 16, 0);}else{OLED_ShowChinese(0, 16, 11, 16, 1);OLED_ShowChinese(16, 16, 12, 16, 1);OLED_ShowChinese(32, 16, 13, 16, 1);sprintf(str, "%3d BPM", user.max30102.dis_hr_value);OLED_ShowString(48, 16, str, 16, 1);}if (oled.x == 2){/**光照: */OLED_ShowChinese(0, 32, 20, 16, 0);OLED_ShowChinese(16, 32, 21, 16, 0);OLED_ShowChinese(32, 32, 22, 16, 0);sprintf(str, "%d%%", user.light_value);OLED_ShowString(48, 32, str, 16, 0);}else{/**光照: */OLED_ShowChinese(0, 32, 20, 16, 1);OLED_ShowChinese(16, 32, 21, 16, 1);OLED_ShowChinese(32, 32, 22, 16, 1);sprintf(str, "%d%%", user.light_value);OLED_ShowString(48, 32, str, 16, 1);}if (oled.x == 3){/**距离:*/OLED_ShowChinese(0, 48, 23, 16, 0);OLED_ShowChinese(16, 48, 24, 16, 0);OLED_ShowChinese(32, 48, 25, 16, 0);sprintf(str, "%2.1lfcm", user.distance_value);OLED_ShowString(48, 48, str, 16, 0);}else{/**距离:*/OLED_ShowChinese(0, 48, 23, 16, 1);OLED_ShowChinese(16, 48, 24, 16, 1);OLED_ShowChinese(32, 48, 25, 16, 1);sprintf(str, "%2.1lfcm", user.distance_value);OLED_ShowString(48, 48, str, 16, 1);}}else if (oled.page == PAGE_ALARM){/**后方来车! */OLED_ShowChinese(32, 32, 26, 16, 1);OLED_ShowChinese(48, 32, 27, 16, 1);OLED_ShowChinese(64, 32, 28, 16, 1);OLED_ShowChinese(80, 32, 29, 16, 1);OLED_ShowChinese(96, 32, 30, 16, 1);}OLED_Refresh();
}/*** @brief 心率血氧获取任务** @param pt*/
void MAX30102_Task(void *pt)
{Get_MAX30102(&user.max30102);
}/*** @brief 蜂鸣器报警任务** @param pt*/
void Alarm_Task(void *pt)
{if(oled.page == PAGE_1 || oled.page == PAGE_ALARM){if(user.distance < user.distance_value && user.distance_flag == 1){user.distance_flag=0;oled.page = PAGE_ALARM;OLED_Clear();BEEP = 0;}else if(user.distance >= user.distance_value && user.distance_flag == 0){user.distance_flag = 1;oled.page = PAGE_1;OLED_Clear();BEEP = 1;}}else if(oled.page == PAGE_2){if(user.max30102.dis_hr > user.max30102.dis_hr_value){BEEP = 0;}else{BEEP = 1;}}}/*** @brief 陀螺仪任务** @param pt*/
void MPU6050_Task(void *pt)
{mpu_dmp_get_data(&user.mpu6050.Pitch, &user.mpu6050.Roll, &user.mpu6050.Yaw); // 角度
}/*** @brief 灯光任务** @param pt*/
void Light_Task(void *pt)
{user.light = 100 - (Get_Adc(ADC_Channel_6) * 100 / 4095);if (user.light < user.light_value)LIGHT = 1;elseLIGHT = 0;
}/*** @brief 距离获取任务** @param pt*/
void Distance_Task(void *pt)
{user.distance = Getlength();
}/*** @brief * * @param pt */
void AngleControl_Task(void *pt)
{static MPU6050 last_angle;static u16 delay = 0;if (user.mpu6050.Yaw - last_angle.Yaw > 30){delay = 0;user.direction = LEFT;}else if (user.mpu6050.Yaw - last_angle.Yaw < -30){delay = 0;user.direction = RIGHT;}if (user.mpu6050.Roll - last_angle.Roll < -30){delay = 0;user.direction = STOP;}last_angle.Roll = user.mpu6050.Roll;last_angle.Yaw = user.mpu6050.Yaw;if (user.direction != RUN){if (delay++ > 6){delay = 0;user.direction = RUN;}}
}void Flicker_Task(void *pt)
{if(user.direction == LEFT) LED_LEFT = !LED_LEFT;else LED_LEFT = 1;if(user.direction == RIGHT) LED_RIGHT = !LED_RIGHT;else LED_RIGHT = 1;
}void Task_Init(void)
{Task_Register(1, 1000, Led_Task, NULL);Task_Register(2, 1, Key_Task, NULL);Task_Register(3, 200, OLED_Task, NULL);Task_Register(4, 1000, MAX30102_Task, NULL);Task_Register(5, 100, Alarm_Task, NULL);Task_Register(6, 500, MPU6050_Task, NULL);Task_Register(7, 200, Light_Task, NULL);Task_Register(8, 100, Distance_Task, NULL);Task_Register(9, 500, AngleControl_Task, NULL);Task_Register(10, 200, Flicker_Task, NULL);
}void Task_Run(void)
{for (int i = 0; i < RegisteredTasks; i++){if (TaskList[i].RunFlag && TaskList[i].EnableFlag){// 执行任务函数if (TaskList[i].TaskHook != NULL){TaskList[i].TaskHook(TaskList[i].TaskParam);}// 清除运行标志TaskList[i].RunFlag = 0;}}
}void TaskTime(void)
{static u32 tick_time = 0;tick_time++;// 遍历任务列表更新计数器for (int i = 0; i < RegisteredTasks; i++){if (TaskList[i].EnableFlag){TaskList[i].TimerCounter++;// 达到时间间隔时设置运行标志if (TaskList[i].TimerCounter >= TaskList[i].PollingInterval){TaskList[i].RunFlag = 1;TaskList[i].TimerCounter = 0;}}}
}

【原理图】

【硬件实物图】

【实物演示】

基于stm32的老人健康与跌倒监测系统

http://www.dtcms.com/a/453361.html

相关文章:

  • 【Python刷力扣hot100】49. Group Anagrams
  • 招聘网站大全专业的企业进销存软件定制
  • 绿色学校网站模板高明网站建设报价
  • Ubuntu 22.04 + Ryu/Mininet:跨越 Python 3.10 依赖“死亡三角”的完美配置指南
  • AI智能体(Agent)大模型入门【6】--编写fasteAPI后端请求接口实现页面聊天
  • 广西 南宁 微信微网站开发虚拟主机使用教程
  • 电子商务网站开发 当当网网站优化关键词怎么做
  • 学习日报 20251007|深度解析:基于 Guava LoadingCache 的优惠券模板缓存设计与实现
  • 什么是MOE?
  • 大模型-扩散模型(Diffusion Model)原理讲解(4
  • 【深度学习新浪潮】入门Flash Attention:从原理到Python手搓实现
  • 不做“KPI牛马“,回归真生活——双节沉思录
  • Java接口中实现多线程并行处理,大数据量查询实战,成倍提效、性能分析,笔记01
  • AI学习日记——参数的初始化
  • 数字信号处理 第七章(FIR数字滤波器设计)
  • 网站建设公司实力网站建设死人接单
  • 河南住房与建设厅网站杭州网站建设交易
  • 岳池建设局网站什么是网络设计的前提
  • GDB Stub定义及命名由来解析
  • 男人最爱上的做网站网页制作开版费
  • FreeRTOS_API模块综合应用篇(八)
  • tuchuang_myfilesshare文件列表_共享文件
  • GJOI 10.4/10.5 题解
  • C语言入门教程(第2讲):数据类型与变量详解与实战讲解
  • 哪些网站建设公司wordpress悬浮联系表
  • 5g互联如何取消网站备案中山seo代理商
  • 生成式人工智能对学习生态的重构:从“辅助工具”到“依赖风险”的平衡难题
  • 电商推广联盟大型网站技术架构演进与性能优化
  • short-term memory 和long-term memtory有什么区别
  • 公司网站建设与维护工作计划网站建设背景及意义