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

【开源】基于STM32的智能车尾灯

项目编号:STM32-T005

项目名称:基于STM32的智能车尾灯

【摘要】

        本项目设计了一种基于STM32F103单片机的智能车尾灯系统,旨在提升夜间骑行的安全性与个性化体验。系统融合MPU6050加速度与陀螺仪模块,实现对自行车运动状态的实时监测,如刹车、转弯及正常行驶;结合光敏电阻感知环境光照强度,智能判断是否需要启用尾灯照明。根据传感器采集的数据,STM32控制矩阵LED灯自动调整显示模式,包括闪烁频率和图案变化,从而有效提醒后方车辆并保障骑行者安全。同时,系统集成蓝牙模块,可与手机APP连接,实现闪烁频率、图案样式等个性化设置,增强用户交互体验。电源部分采用干电池供电,安装简便、功耗低。整体设计集成度高、功能实用,适用于智能出行、绿色交通等领域,具有较强的推广价值与市场前景。

【所用硬件】

1、STM32F103C8T6最小系统板

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

2、mpu6050陀螺仪模块

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

3、MAX7219点阵屏2*2*4模块

        MAX7219点阵屏224模块是一种基于MAX7219驱动芯片的LED点阵显示模块,由2行2列共4个点阵单元组合而成,通常采用8×8点阵屏拼接显示。模块通过SPI接口与单片机通信,仅需三根控制线即可驱动多个点阵级联,支持显示文字、数字、图形和动画。其特点是电路简洁、显示效果清晰、扩展方便,常用于电子钟、信息显示屏及创意电子项目中,适合学习和实际应用。

4、蓝牙模块

        HC-05蓝牙模块是一款常用的串口通信蓝牙模块,支持蓝牙2.0协议,采用主从一体设计,可通过AT指令自由配置工作模式。它通过UART接口与单片机或电脑连接,实现无线串口数据传输,使用方便、成本低廉、兼容性好。该模块传输稳定、距离可达10米左右,广泛应用于无线控制、小型物联网设备、智能小车和数据采集系统中,是嵌入式开发与蓝牙通信学习的常见选择。

5、光敏电阻模块

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

6、干电池

        4节干电池模块是一种常见的电源供电模块,一般由电池盒和导线组成,可串联放置四节1.5V干电池,输出电压为6V,适合作为单片机、传感器模块或小型电机等低功耗电路的供电电源。该模块体积小巧、安装方便,通常配有开关和电源接口,使用灵活,能够为实验项目、电子制作和便携设备提供稳定的直流电源。

【系统框架图】

【软件流程图】

【核心代码展示】

#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 "max7219.h"
#include "Preprocessdesign.h"u8 str[100];
PAGE page;
POINT point;CAR car;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;
}void MPU6050_Task(void *pt)
{mpu_dmp_get_data(&car.mpu.Pitch,&car.mpu.Roll,&car.mpu.Yaw);
}void MAX7219_Task(void *pt)
{u8 i, j;for (i = 1; i < 9; i++) // 点阵屏的第1行到第8行{MAX7219_CS = 0;if (car.modle == ONE){for (j = 0; j < 4; j++) // 因为有4个点阵屏,所以同一行需要发4次{switch (j) // 用switch只是为了方便看而已{case 0:MAX7219_Write_byte(i);if(car.direction == LEFT) MAX7219_Write_byte(_4x7Num[10][i - 1]);else MAX7219_Write_byte(_4x7Num[22][i - 1]);// 控制列的高低电平,行为低电平了,所以列为1时灯亮,如数据为// 0xF0 那么这一行就是4个亮4个灭break;case 1:MAX7219_Write_byte(i);if(car.direction == STOP) MAX7219_Write_byte(_4x7Num[12][i - 1]);else MAX7219_Write_byte(_4x7Num[22][i - 1]);break;case 2:MAX7219_Write_byte(i);if(car.direction == STOP) MAX7219_Write_byte(_4x7Num[13][i - 1]);else MAX7219_Write_byte(_4x7Num[22][i - 1]);break;case 3:MAX7219_Write_byte(i);if(car.direction == RIGHT) MAX7219_Write_byte(_4x7Num[11][i - 1]);else MAX7219_Write_byte(_4x7Num[22][i - 1]);break;}}}else if (car.modle == TWO){for (j = 0; j < 4; j++) // 因为有4个点阵屏,所以同一行需要发4次{switch (j) // 用switch只是为了方便看而已{case 0:MAX7219_Write_byte(i);if(car.direction == LEFT) MAX7219_Write_byte(_4x7Num[14][i - 1]);else MAX7219_Write_byte(_4x7Num[22][i - 1]);// 控制列的高低电平,行为低电平了,所以列为1时灯亮,如数据为// 0xF0 那么这一行就是4个亮4个灭break;case 1:MAX7219_Write_byte(i);if(car.direction == STOP) MAX7219_Write_byte(_4x7Num[16][i - 1]);else MAX7219_Write_byte(_4x7Num[22][i - 1]);break;case 2:MAX7219_Write_byte(i);if(car.direction == STOP) MAX7219_Write_byte(_4x7Num[17][i - 1]);else MAX7219_Write_byte(_4x7Num[22][i - 1]);break;case 3:MAX7219_Write_byte(i);if(car.direction == RIGHT) MAX7219_Write_byte(_4x7Num[15][i - 1]);else MAX7219_Write_byte(_4x7Num[22][i - 1]);break;}}}else if (car.modle == THREE){for (j = 0; j < 4; j++) // 因为有4个点阵屏,所以同一行需要发4次{switch (j) // 用switch只是为了方便看而已{case 0:MAX7219_Write_byte(i);if(car.direction == LEFT) MAX7219_Write_byte(_4x7Num[18][i - 1]);else MAX7219_Write_byte(_4x7Num[22][i - 1]);// 控制列的高低电平,行为低电平了,所以列为1时灯亮,如数据为// 0xF0 那么这一行就是4个亮4个灭break;case 1:MAX7219_Write_byte(i);if(car.direction == STOP) MAX7219_Write_byte(_4x7Num[20][i - 1]);else MAX7219_Write_byte(_4x7Num[22][i - 1]);break;case 2:MAX7219_Write_byte(i);if(car.direction == STOP) MAX7219_Write_byte(_4x7Num[21][i - 1]);else MAX7219_Write_byte(_4x7Num[22][i - 1]);break;case 3:MAX7219_Write_byte(i);if(car.direction == RIGHT) MAX7219_Write_byte(_4x7Num[19][i - 1]);else MAX7219_Write_byte(_4x7Num[22][i - 1]);break;}}}MAX7219_CS = 1;}
}void Light_Task(void *pt)
{u8 i;car.light = 15 - (Get_Adc_Average(ADC_Channel_6, 5) * 15 / 4095);MAX7219_CS = 0;for (i = 0; i < LEDCOUNT; i++){MAX7219_Write_Command(DECODEMODE, 0X00);/*译码寄存器:1使用BCD码   0不使用(数码管的话建议用BCD码)*/}MAX7219_CS = 1; // 这里发送4次后CS拉高,那么4个点阵屏都收到数据,然后加载到寄存器中MAX7219_CS = 0;for (i = 0; i < LEDCOUNT; i++){MAX7219_Write_Command(INTENSITY, car.light);/*亮度控制:0x00~0x0F  0是最暗  0xFs是最亮*/}MAX7219_CS = 1;MAX7219_CS = 0;for (i = 0; i < LEDCOUNT; i++){MAX7219_Write_Command(SCANLIMT, 0X07);/*点阵屏的行数  数码管的段位  0是1行,7是8行*/}MAX7219_CS = 1;MAX7219_CS = 0;for (i = 0; i < LEDCOUNT; i++){MAX7219_Write_Command(SHUTDOWN, 0X01);/*掉电模式:0掉电模式  1正常模式*/}MAX7219_CS = 1;MAX7219_CS = 0;for (i = 0; i < LEDCOUNT; i++){MAX7219_Write_Command(DISPLAYTEST, 0X00);/*显示寄存器:0普通模式   1测试模式*/}MAX7219_CS = 1;
}void Flicker_Task(void *pt)
{static u16 delay=0,flag=0;u8 i, j;if (delay++ == car.Freq){delay = 0;flag++;if(flag == 1)  Task_Enable(3,0);else{flag=0;Task_Enable(3,1);}for (i = 1; i < 9; i++) // 点阵屏的第1行到第8行{MAX7219_CS = 0;for (j = 0; j < 4; j++) // 因为有4个点阵屏,所以同一行需要发4次{switch (j) // 用switch只是为了方便看而已{case 0:MAX7219_Write_byte(i);MAX7219_Write_byte(_4x7Num[22][i - 1]);// 控制列的高低电平,行为低电平了,所以列为1时灯亮,如数据为// 0xF0 那么这一行就是4个亮4个灭break;case 1:MAX7219_Write_byte(i);MAX7219_Write_byte(_4x7Num[22][i - 1]);break;case 2:MAX7219_Write_byte(i);MAX7219_Write_byte(_4x7Num[22][i - 1]);break;case 3:MAX7219_Write_byte(i);MAX7219_Write_byte(_4x7Num[22][i - 1]);break;}}MAX7219_CS = 1;}}
}void AngleControl_Task(void *pt)
{static MPU6050 last_angle;static u16 delay=0;if(car.mpu.Yaw-last_angle.Yaw>15){delay=0;car.direction = LEFT;}else if(car.mpu.Yaw-last_angle.Yaw<-15){delay=0;car.direction = RIGHT;}if(car.mpu.Roll-last_angle.Roll<-15){delay=0;car.direction = STOP;}last_angle.Roll = car.mpu.Roll;last_angle.Yaw = car.mpu.Yaw;if(car.direction != RUN){if(delay++ > 15){delay=0;car.direction = RUN;}}
}void Task_Init(void)
{Task_Register(1, 1000, Led_Task, NULL);Task_Register(2, 1, MPU6050_Task, NULL);Task_Register(3, 100, MAX7219_Task, NULL);Task_Register(4, 1, Flicker_Task, NULL);Task_Register(5, 200, AngleControl_Task, NULL);Task_Register(6, 300, Light_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-T005-基于stm32智能车尾灯

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

相关文章:

  • 电子电气架构 --- 软件开发与产品系统集成流程(下)
  • Ubuntu系统目录架构是怎么样的
  • 自动驾驶仿真之“场景交互”技术研究
  • 《AI管家还是数字化身?—— 一种面向未来的个人智能架构构想》
  • AI提升工业生产制造安全,基于YOLOv9全系列【yolov9/t/s/m/c/e】参数模型开发构建工业生产制造加工场景下工业设备泄漏智能化检测识别预警系统
  • 深度学习(十一):深度神经网络和前向传播
  • js立即执行函数的几种写法
  • RecyclerView里更新列表数是不想让header也刷新,怎么处理
  • C#/.NET/.NET Core技术前沿周刊 | 第 55 期(2025年9.15-9.21)
  • 减少实验烦恼,革新实验效率——PFA塑料容量瓶降低实验成本与风险
  • 留给石头科技的赛道不多了
  • 基于卷积神经网络的人车识别技术:从原理突破到场景重构的深度探索
  • 信用免押租赁服务:重构消费信任体系的全球增长引擎
  • Redis数据迁移实战:从自建到云托管(阿里云/腾讯云)的平滑过渡
  • 从梵高到赛博格:我用4K模型重构艺术史的未来可能性-Seedream 4.0 实测
  • Mysql DBA学习笔记(Redo Log/Undo Log)
  • 买卖T平台如何以分红+排队免单重构零售生态?
  • 2025 年前端工具全景解析:从框架到 AI,重构开发效率的 N 种可能
  • 重构ruoyi前后端分离版
  • AI + 制造:AI 如何重构制造业的质检与排产流程
  • 卡尔曼滤波
  • Django安全完全指南:构建坚不可摧的Web应用
  • Mysql DBA学习笔记(MVCC)
  • 【论文阅读】GR-1:释放大规模视频生成式预训练用于视觉机器人操控
  • 分布式光伏阴影轨迹模拟
  • 【Java.数据结构】初识集合框架
  • 人工智能的推理方法实验-用归结原理解决机器人搬盒子问题
  • Flink中 Window解析
  • 医疗数据互操作性与联邦学习的python编程方向研究(下)
  • 摄像头视频云存储与回放系统架构