首页 > 其他分享 >基于STM32设计的自动刹车灯

基于STM32设计的自动刹车灯

时间:2023-08-26 13:32:22浏览次数:43  
标签:基于 TIM1 LED 刹车灯 STM32 TIM ADXL345 IIC GPIO

一、项目介绍

随着科技的发展,人们对低碳环保的认知和需求不断提高。骑自行车既能够低碳环保,又能够锻炼身体,成为了很多人出行的首选。然而,由于自行车本身没有带指示灯,比如刹车指示灯等,所以自行车的安全性并不是很好,如果人们在骑自行车时紧急刹车,后车无法及时判断前方自行车的行为,容易造成交通事故。因此,设计一款自动刹车灯系统具有十分重要的意义。

本项目实现了通过安装ADXL345陀螺仪和四枚LED灯还有STM32F103C8T6主控芯片来实现自行车自动刹车灯的功能。当自行车上安装了该设备后,ADXL345通过IIC通信协议将X,Y,Z三轴的加速度实时值发送给SMT32F103C8T6主控芯片,并结合STM32高级定时器的PWM功能,输出不同占空比的脉冲,控制不同的LED灯输出多种亮度等级,从而控制不同的LED的开关以及明暗,并且通过不同亮度的红光和绿光混合,能够得到黄色的LED灯光。这样,在自行车急刹或者加速时,实时地控制LED灯的亮度和颜色,让后方车辆能够更清楚地了解前方自行车的行为,从而做出快速的反应,保障骑行者以及后车的安全。同时,该系统也能够提高自行车的可见性,并且对于追求低碳环保的人群来说,让自行车既能低碳环保,又能够锻炼身体。

基于STM32设计的自动刹车灯_ADXL345

二、设计思路

2.1 项目目标

本项目通过安装ADXL345陀螺仪和四枚LED灯还有STM32F103C8T6主控芯片来实现自行车自动刹车灯的功能,使得自行车在急刹或者加速时,实时地控制LED灯的亮度和颜色,提高其可见性,降低交通事故的风险。同时,该系统还能够使自行车既能低碳环保,又能够锻炼身体。

2.2 项目硬件构成

(1)自行车:作为安装系统的物体,需要有一个固定的位置来安装ADXL345陀螺仪和四枚LED灯。

(2)ADXL345陀螺仪:通过IIC通信协议与STM32F103C8T6主控芯片通信,并将X、Y、Z三轴的加速度实时值发送给SMT32F103C8T6主控芯片。

(3)四枚LED灯:使用不同亮度的红光和绿光混合,能够得到黄色的LED灯光。通过控制其亮度和颜色来提高自行车的可见性。

(4)STM32F103C8T6主控芯片:根据接收到的ADXL345数据,结合STN32的高级定时器的PWM功能,输出不同占空比的脉冲,控制不同的LED灯输出多种亮度等级。

2.3 项目功能实现

(1)自行车加速度监测:ADXL345陀螺仪通过IIC通信协议与STM32F103C8T6主控芯片通信,实时地感知自行车的加速度变化。

(2)LED灯亮度和颜色控制:STM32F103C8T6主控芯片运用高级定时器的PWM功能,能够输出不同占空比的脉冲,并控制不同的LED灯输出多种亮度等级,通过不同亮度的红光和绿光混合,能够得到黄色的LED灯光,提高自行车的可见性。

(3)系统安装和调试:需要将ADXL345陀螺仪和四枚LED灯与STM32F103C8T6主控芯片连接起来,并进行系统测试和调试。

三、系统测试

3.1 功能样机安装与焊接

绘制好电路原理图之后,按照原理图将自动刹车灯系统的各个模块安装在事先购买好的洞洞板上,然后用导线将他们连接在一起,最后再焊接在一起,做成完整的自动刹车灯电路板。

基于STM32设计的自动刹车灯_ADXL345_02

3.2 ADXL345模块调试

当上电后,将自动刹车灯电路的串口2外设引脚连接至PC端,将加速度解算后的实际值发送至PC端,通过PC端串口调试助手显示出具体数值,再观察数值是否符合常理。

基于STM32设计的自动刹车灯_ADXL345_03

通过显示的数据信息,可以推测出ADXL345陀螺仪能够正常工作。

3.3 实物调试

最后阶段,将对自行车自动刹车灯进行实物调试,确定其基本功能能够正常实现。

当系统上电后,左右各一枚LED发出低亮黄色灯光,如下图。

基于STM32设计的自动刹车灯_ADXL345_04

静置30S后,所有LED均熄灭,如下图。

基于STM32设计的自动刹车灯_ADXL345_05

当检测到震动后,重新亮起两盏黄色LED灯,如下图。

基于STM32设计的自动刹车灯_ADXL345_06

当检测到刹车时,四枚LED灯均以高亮发出红色灯光,如下图。

基于STM32设计的自动刹车灯_ADXL345_07

结合自行车自动刹车灯的功能需求和实物调试结果,可以发现,调试结果完全符合自动刹车灯的预期功能。

四、代码设计

如果完整项目工程,可以去这里获取:

4.1 主函数

#include "stm32f10x.h"
#include "usart.h"
#include "led.h"
#include "RTC_Time.h" 
#include <stdio.h>
#include "delay.h"
#include "sys.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "adxl345.h"
int main(void)
{
      u32 flag=0;
      short x, y, z;
    float accelerated;
      LED_GPIO_Config();//初始化LED
    USART2_Config();
    delay_init(); //延时函数初始化
    PWM_LED_INIT();   //PWM   PA8-9
      LED_Init();    //PB7 LED-R
      PBout(7) = 1;     
      ADXL345_Init(); //PB 10,11
    ADXL345_Read_Average(&x, &y, &z, 20);
    ADXL345_AUTO_Adjust((char *)&x, (char *)&y, (char *)&z);
    TIM_SetCompare1(TIM1, 50); //设置TIMx捕获比较1寄存器(通道1)值(脉冲宽度)   占空比%20
    TIM_SetCompare2(TIM1, 50); //设置TIMx捕获比较2寄存器(通道2)值(脉冲宽度)   占空比%20
    while (1)
    {
        ADXL345_Read_Average(&x, &y, &z, 5);   //读加速度值
              accelerated=(x*3.9/1000*9.8);          //加速度实际值
            printf("X=%4.1f   Y=%4.1f  Z=%4.1f\r\n",accelerated,(y*3.9/1000*9.8),(z*3.9/1000*9.8));
            while(flag>425)
            {
                 TIM_SetCompare1(TIM1, 0);          //通道2 占空比%0                         
                 TIM_SetCompare2(TIM1, 0);          //通道2 占空比%0 
               ADXL345_Read_Average(&x, &y, &z, 5);
                 accelerated=(x*3.9/1000*9.8);
                if(accelerated<-5||accelerated>5) 
                {
                    break;
                }
            }
                flag++; 
          if(accelerated<-4)
                {
                    //四个LED低电平导通           
                    TIM_SetCompare1(TIM1, 0);            //GREEN不亮                          
                    TIM_SetCompare2(TIM1, 1000);         //RED高亮
                    PBout(7) = 0;   
                    flag=0;    
                }
                if(accelerated>0)
                {
                    PBout(7) = 1;
                    TIM_SetCompare1(TIM1, 50);           //RED低亮  
                    TIM_SetCompare2(TIM1, 50);           //GREEN低亮
         }
                if(accelerated>5)
                {
                flag=0; 
                }
    }   
}

4.2 LED灯控制

#include "led.h"
#include "delay.h"
void LED_GPIO_Config(void)
{   
    //定义一个GPIO_InitTypeDef 类型的结构体,名字叫GPIO_InitStructure 
    GPIO_InitTypeDef  GPIO_InitStructure;
    //使能GPIOC的外设时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
    //选择要用的GPIO引脚       
    GPIO_InitStructure.GPIO_Pin =GPIO_Pin_13;
    ///设置引脚模式为推免输出模式             
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         
    //设置引脚速度为50MHZ
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    //调用库函数,初始化GPIO
    GPIO_Init(GPIOC, &GPIO_InitStructure);
}
void TIME_INIT()
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure; //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
    //TIM1定时器初始化  10ms
    TIM_TimeBaseInitStructure.TIM_Period = 999; 
    TIM_TimeBaseInitStructure.TIM_Prescaler = 719;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure);
    //TIM1的PWM配置     
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_Pulse = 0;//设置初始PWM脉冲宽度为0
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //PWM输出使能
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//当定时器计数值小于CCR_Val时为低电平
      //通道的使能
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //通道1
    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); 
        TIM_OC2Init(TIM1, &TIM_OCInitStructure);  //通道2
    TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);   
        TIM_ARRPreloadConfig(TIM1, ENABLE);   //使能TIM1重载寄存器ARR
    TIM_Cmd(TIM1, ENABLE);                //使能
    TIM_CtrlPWMOutputs(TIM1, ENABLE);     //高级定时器必须加
}
void PWM_LED_INIT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);  //GPIOA8,9,10是TIM1的通道1,2,3
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 ;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    TIME_INIT();
}
void LED_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
  //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

4.3 adxl345.c

#include "adxl345.h"
#include "sys.h"
#include "delay.h"
#include "math.h"   
u8 ADXL345_Init(void)
{                 
    IIC_Init();                         //初始化IIC总线  
    if(ADXL345_RD_Reg(DEVICE_ID)==0XE5) //读取器件ID
    {  
        ADXL345_WR_Reg(0X31,0X2B);  //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程 
        ADXL345_WR_Reg(0X2C,0x0A);        //数据输出速度为100Hz
        ADXL345_WR_Reg(0X2D,0x28);    //链接使能,测量模式
        ADXL345_WR_Reg(0X2E,0x00);  //不使用中断      
        ADXL345_WR_Reg(0X1E,0x00);
        ADXL345_WR_Reg(0X1F,0x00);
        ADXL345_WR_Reg(0X20,0x00);  
        return 0;
    }           
    return 1;                                     
}   
//写ADXL345寄存器
//addr:寄存器地址
//val:要写入的值
//返回值:无
void ADXL345_WR_Reg(u8 addr,u8 val) 
{
    IIC_Start();                 
    IIC_Send_Byte(ADXL_WRITE);  //发送写器件指令    
    IIC_Wait_Ack();    
  IIC_Send_Byte(addr);              //发送寄存器地址
    IIC_Wait_Ack();                                                        
    IIC_Send_Byte(val);             //发送值                      
    IIC_Wait_Ack();                    
  IIC_Stop();                             //产生一个停止条件       
}
//读ADXL345寄存器
//addr:寄存器地址
//返回值:读到的值
u8 ADXL345_RD_Reg(u8 addr)      
{
    u8 temp=0;       
    IIC_Start();                 
    IIC_Send_Byte(ADXL_WRITE);  //发送写器件指令    
    temp=IIC_Wait_Ack();       
    IIC_Send_Byte(addr);        //发送寄存器地址
    temp=IIC_Wait_Ack();                                                       
    IIC_Start();                //重新启动
    IIC_Send_Byte(ADXL_READ);   //发送读器件指令    
    temp=IIC_Wait_Ack();       
    temp=IIC_Read_Byte(0);      //读取一个字节,不继续再读,发送NAK               
    IIC_Stop();                 //产生一个停止条件      
    return temp;                //返回读到的值
}  
//读取ADXL的平均值
//x,y,z:读取10次后取平均值
void ADXL345_RD_Avval(short *x,short *y,short *z)
{
    short tx=0,ty=0,tz=0;      
    u8 i;  
    for(i=0;i<10;i++)
    {
        ADXL345_RD_XYZ(x,y,z);
        delay_ms(10);
        tx+=(short)*x;
        ty+=(short)*y;
        tz+=(short)*z;     
    }
    *x=tx/10;
    *y=ty/10;
    *z=tz/10;
} 
//自动校准
//xval,yval,zval:x,y,z轴的校准值
void ADXL345_AUTO_Adjust(char *xval,char *yval,char *zval)
{
    short tx,ty,tz;
    u8 i;
    short offx=0,offy=0,offz=0;
    ADXL345_WR_Reg(POWER_CTL,0x00);     //先进入休眠模式.
    delay_ms(100);
    ADXL345_WR_Reg(DATA_FORMAT,0X2B);   //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程 
    ADXL345_WR_Reg(BW_RATE,0x0A);       //数据输出速度为100Hz
    ADXL345_WR_Reg(POWER_CTL,0x28);     //链接使能,测量模式
    ADXL345_WR_Reg(INT_ENABLE,0x00);    //不使用中断      
    ADXL345_WR_Reg(OFSX,0x00);
    ADXL345_WR_Reg(OFSY,0x00);
    ADXL345_WR_Reg(OFSZ,0x00);
    delay_ms(12);
    for(i=0;i<10;i++)
    {
        ADXL345_RD_Avval(&tx,&ty,&tz);
        offx+=tx;
        offy+=ty;
        offz+=tz;
    }           
    offx/=10;
    offy/=10;
    offz/=10;
    *xval=-offx/4;
    *yval=-offy/4;
    *zval=-(offz-256)/4;      
    ADXL345_WR_Reg(OFSX,*xval);
    ADXL345_WR_Reg(OFSY,*yval);
    ADXL345_WR_Reg(OFSZ,*zval); 
} 
//读取3个轴的数据
//x,y,z:读取到的数据
void ADXL345_RD_XYZ(short *x,short *y,short *z)
{
    u8 buf[6];
    u8 i;
    IIC_Start();                 
    IIC_Send_Byte(0X3A);    //发送写器件指令    
    IIC_Wait_Ack();    
  IIC_Send_Byte(0x32);          //发送寄存器地址(数据缓存的起始地址为0X32)
    IIC_Wait_Ack();             
    IIC_Start();                //重新启动
    IIC_Send_Byte(0X3B);    //发送读器件指令
    IIC_Wait_Ack();
    for(i=0;i<6;i++)
    {
        if(i==5)buf[i]=IIC_Read_Byte(0);//读取一个字节,不继续再读,发送NACK  
        else buf[i]=IIC_Read_Byte(1);   //读取一个字节,继续读,发送ACK 
        delay_us(15);
      IIC_Start();                  //重新启动
        IIC_Send_Byte(0X3A);    //发送写器件指令
            IIC_Wait_Ack(); 
        IIC_Send_Byte(0x33+i);          //发送寄存器地址(数据缓存的起始地址为0X32)
      IIC_Wait_Ack();           
      IIC_Start();                  //重新启动
      IIC_Send_Byte(0X3B);  //发送读器件指令
      IIC_Wait_Ack();
    }                  
    IIC_Stop();                 //产生一个停止条件
    *x=(short)(((u16)buf[1]<<8)+buf[0]);        
    *y=(short)(((u16)buf[3]<<8)+buf[2]);        
    *z=(short)(((u16)buf[5]<<8)+buf[4]);       
}
//读取ADXL345的数据times次,再取平均
//x,y,z:读到的数据
//times:读取多少次
void ADXL345_Read_Average(short *x,short *y,short *z,u8 times)
{
    u8 i;
    short tx,ty,tz;
    *x=0;
    *y=0;
    *z=0;
    if(times)//读取次数不为0
    {
        for(i=0;i<times;i++)//连续读取times次
        {
            ADXL345_RD_XYZ(&tx,&ty,&tz);
            *x+=tx;
            *y+=ty;
            *z+=tz;
            delay_ms(5);
        }
        *x/=times;
        *y/=times;
        *z/=times;
    }
}
//得到角度
//x,y,z:x,y,z方向的重力加速度分量(不需要单位,直接数值即可)
//dir:要获得的角度.0,与Z轴的角度;1,与X轴的角度;2,与Y轴的角度.
//返回值:角度值.单位0.1°.
short ADXL345_Get_Angle(float x,float y,float z,u8 dir)
{
    float temp;
    float res=0;
    switch(dir)
    {
        case 0://与自然Z轴的角度
            temp=sqrt((x*x+y*y))/z;
            res=atan(temp);
            break;
        case 1://与自然X轴的角度
            temp=x/sqrt((y*y+z*z));
            res=atan(temp);
            break;
        case 2://与自然Y轴的角度
            temp=y/sqrt((x*x+z*z));
            res=atan(temp);
            break;
    }
    return res*1800/3.14;
}


标签:基于,TIM1,LED,刹车灯,STM32,TIM,ADXL345,IIC,GPIO
From: https://blog.51cto.com/u_11822586/7243094

相关文章

  • 基于springboot编程训练系统设计与实现
    随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了编程训练系统的开发全过程。通过分析编程训练系统管理的不足,创建了一个计算机管理编程训练系统的方案。文章介绍了编程训练系统的系统分析部分,包括可行性分析等,系统设计部分主要介绍了......
  • 基于springboot框架的网上商城系统的设计与实现
    系统实现系统实现部分就是将系统分析,系统设计部分的内容通过编码进行功能实现,以一个实际应用系统的形式展示系统分析与系统设计的结果。前面提到的系统分析,系统设计最主要还是进行功能,系统操作逻辑的设计,也包括了存储数据的数据库方面的设计等内容,系统实现就是一个最终的实施阶段,将......
  • 基于springboot中药实验管理系统设计与实现
    随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了中药实验管理系统的开发全过程。通过分析中药实验管理系统管理的不足,创建了一个计算机管理中药实验管理系统的方案。文章介绍了中药实验管理系统的系统分析部分,包括可行性分析等,系统设......
  • 基于springboot汽车资讯网站
    随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了汽车资讯网站的开发全过程。通过分析汽车资讯网站管理的不足,创建了一个计算机管理汽车资讯网站的方案。文章介绍了汽车资讯网站的系统分析部分,包括可行性分析等,系统设计部分主要介绍了......
  • 基于PHP开发的拍卖直播系统源码分享
    东莞梦幻网络科技最新推出的拍卖直播系统源码,安卓端使用Java语言开发,苹果端则采用Objective-C开发,前端H5则采用了Vue.js开发,后台管理系统基于PHP的ThinkPHP框架开发。基础功能:创造竞价氛围直播拍卖:通过主播的话术,为拍品详细讲解产品特点,创造竞价氛围,不仅拉近了拍品与消费者之间的距......
  • 【STM32】4_1 通用定时器
    通用定时器概述定时器分类表如下图所示通用TIMx定时器具有以下特性:●16位(TIM3和TIM4)或32位(TIM2和TIM5)递增、递减和递增/递减自动重载计数器。●16位可编程预分频器,用于对计数器时钟频率进行分频(即运行时修改),分频系数介于1到65536之间。●多达4个独立......
  • 基于亚马逊云科技无服务器服务快速搭建电商平台——部署篇
    受疫情影响消费者习惯发生改变,刺激了全球电商行业的快速发展。除了依托第三方电商平台将产品销售给消费者之外,企业通过品牌官网或者自有电商平台销售商品也是近几年电商领域快速发展的商业模式。独立站电商模式可以进行多方面、全渠道的互联网市场拓展,推广所带来的流量、品牌印象......
  • m基于FPGA的多径信道模拟verilog实现,包含testbench,可配置SNR,频偏,多径增益和多径延
    1.算法仿真效果其中Vivado2019.2仿真结果如下:  2.算法涉及理论知识概要       瑞利分布是一个均值为0,方差为σ²的平稳窄带高斯过程,其包络的一维分布是瑞利分布。其表达式及概率密度如图所示。瑞利分布是最常见的用于描述平坦衰落信号接收包络或独立多径分量接受......
  • 知识付费系统源码基于PHP开源的网站内容付费源码,打开行业新机遇
    为什么说无论哪个行业,都值得考虑运用知识付费?让我重新为你解释这个逻辑,一旦你理解了它,你就将拥有极大地放大你现有生意机会的能力。 我们通常将知识付费课程视为一种产品,但它实际上还有另一种本质,那就是广告。或许你并未意识到,在创建知识付费课程时,你也在打造一种媒介,一种可以......
  • 【能量检测】基于认知无线电的能量检测算法的matlab仿真
    1.软件版本matlab2021a2.本算法理论知识随着无线通信的快速发展,用户对通信质量的要求越来越高,同时无线设备的大幅度增长,使得频谱资源显得更加重要。认知无线电(CognitiveRadio,CR)技术被当作解决频谱资源紧张、提高频谱利用率的强有力的技术,是下一代通信技术的重要组成成分......