• 方案介紹
    • 一、項目介紹
    • 二、設(shè)計思路
    • 三、系統(tǒng)測試
    • 四、代碼設(shè)計
  • 附件下載
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

基于STM32設(shè)計的自動剎車燈

04/19 08:31
775
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

更多詳細資料請聯(lián)系.docx

共1個文件

一、項目介紹

隨著科技的發(fā)展,人們對低碳環(huán)保的認知和需求不斷提高。騎自行車既能夠低碳環(huán)保,又能夠鍛煉身體,成為了很多人出行的首選。然而,由于自行車本身沒有帶指示燈,比如剎車指示燈等,所以自行車的安全性并不是很好,如果人們在騎自行車時緊急剎車,后車無法及時判斷前方自行車的行為,容易造成交通事故。因此,設(shè)計一款自動剎車燈系統(tǒng)具有十分重要的意義。

本項目實現(xiàn)了通過安裝ADXL345陀螺儀和四枚LED燈還有STM32F103C8T6主控芯片來實現(xiàn)自行車自動剎車燈的功能。

當自行車上安裝了該設(shè)備后,ADXL345通過IIC通信協(xié)議將X,Y,Z三軸的加速度實時值發(fā)送給SMT32F103C8T6主控芯片,并結(jié)合STM32高級定時器PWM功能,輸出不同占空比的脈沖,控制不同的LED燈輸出多種亮度等級,從而控制不同的LED的開關(guān)以及明暗,并且通過不同亮度的紅光和綠光混合,能夠得到黃色的LED燈光。

這樣,在自行車急剎或者加速時,實時地控制LED燈的亮度和顏色,讓后方車輛能夠更清楚地了解前方自行車的行為,從而做出快速的反應(yīng),保障騎行者以及后車的安全。

同時,該系統(tǒng)也能夠提高自行車的可見性,并且對于追求低碳環(huán)保的人群來說,讓自行車既能低碳環(huán)保,又能夠鍛煉身體。

image-20230618184936424

二、設(shè)計思路

如果需要下載項目工程,可以去這里:
https://blog.csdn.net/xiaolong1126626497/category_10192120.html

2.1 項目目標

本項目通過安裝ADXL345陀螺儀和四枚LED燈還有STM32F103C8T6主控芯片來實現(xiàn)自行車自動剎車燈的功能,使得自行車在急剎或者加速時,實時地控制LED燈的亮度和顏色,提高其可見性,降低交通事故的風險。同時,該系統(tǒng)還能夠使自行車既能低碳環(huán)保,又能夠鍛煉身體。

2.2 項目硬件構(gòu)成

(1)自行車:作為安裝系統(tǒng)的物體,需要有一個固定的位置來安裝ADXL345陀螺儀和四枚LED燈。

(2)ADXL345陀螺儀:通過IIC通信協(xié)議與STM32F103C8T6主控芯片通信,并將X、Y、Z三軸的加速度實時值發(fā)送給SMT32F103C8T6主控芯片。

(3)四枚LED燈:使用不同亮度的紅光和綠光混合,能夠得到黃色的LED燈光。通過控制其亮度和顏色來提高自行車的可見性。

(4)STM32F103C8T6主控芯片:根據(jù)接收到的ADXL345數(shù)據(jù),結(jié)合STN32的高級定時器的PWM功能,輸出不同占空比的脈沖,控制不同的LED燈輸出多種亮度等級。

2.3 項目功能實現(xiàn)

(1)自行車加速度監(jiān)測:ADXL345陀螺儀通過IIC通信協(xié)議與STM32F103C8T6主控芯片通信,實時地感知自行車的加速度變化。

(2)LED燈亮度和顏色控制:STM32F103C8T6主控芯片運用高級定時器的PWM功能,能夠輸出不同占空比的脈沖,并控制不同的LED燈輸出多種亮度等級,通過不同亮度的紅光和綠光混合,能夠得到黃色的LED燈光,提高自行車的可見性。

(3)系統(tǒng)安裝和調(diào)試:需要將ADXL345陀螺儀和四枚LED燈與STM32F103C8T6主控芯片連接起來,并進行系統(tǒng)測試和調(diào)試。

三、系統(tǒng)測試

3.1 功能樣機安裝與焊接

繪制好電路原理圖之后,按照原理圖將自動剎車燈系統(tǒng)的各個模塊安裝在事先購買好的洞洞板上,然后用導(dǎo)線將他們連接在一起,最后再焊接在一起,做成完整的自動剎車燈電路板。

image-20230618184608787

3.2 ADXL345模塊調(diào)試

當上電后,將自動剎車燈電路的串口2外設(shè)引腳連接至PC端,將加速度解算后的實際值發(fā)送至PC端,通過PC端串口調(diào)試助手顯示出具體數(shù)值,再觀察數(shù)值是否符合常理。

image-20230618184700297

通過顯示的數(shù)據(jù)信息,可以推測出ADXL345陀螺儀能夠正常工作。

3.3 實物調(diào)試

最后階段,將對自行車自動剎車燈進行實物調(diào)試,確定其基本功能能夠正常實現(xiàn)。

當系統(tǒng)上電后,左右各一枚LED發(fā)出低亮黃色燈光,如下圖。

image-20230618184801135

靜置30S后,所有LED均熄滅,如下圖。

image-20230618184825767

當檢測到震動后,重新亮起兩盞黃色LED燈,如下圖。

image-20230618184849795

當檢測到剎車時,四枚LED燈均以高亮發(fā)出紅色燈光,如下圖。

image-20230618184910210

結(jié)合自行車自動剎車燈的功能需求和實物調(diào)試結(jié)果,可以發(fā)現(xiàn),調(diào)試結(jié)果完全符合自動剎車燈的預(yù)期功能。

四、代碼設(shè)計

4.1 主函數(shù)

#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(); //延時函數(shù)初始化
  	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); //設(shè)置TIMx捕獲比較1寄存器(通道1)值(脈沖寬度)   占空比%20
    TIM_SetCompare2(TIM1, 50); //設(shè)置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.1frn",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低電平導(dǎo)通		   
					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 類型的結(jié)構(gòu)體,名字叫GPIO_InitStructure 
	GPIO_InitTypeDef  GPIO_InitStructure;
	//使能GPIOC的外設(shè)時鐘
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	//選擇要用的GPIO引腳		
	GPIO_InitStructure.GPIO_Pin =GPIO_Pin_13;
	///設(shè)置引腳模式為推免輸出模式			 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 
	//設(shè)置引腳速度為50MHZ
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	//調(diào)用庫函數(shù),初始化GPIO
	GPIO_Init(GPIOC, &GPIO_InitStructure);
}
void TIME_INIT()
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure; //根據(jù)TIM_OCInitStruct中指定的參數(shù)初始化外設(shè)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;//設(shè)置初始PWM脈沖寬度為0
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //PWM輸出使能
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//當定時器計數(shù)值小于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; //復(fù)用推挽輸出
    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位全分辨率,輸出數(shù)據(jù)右對齊,16g量程 
		ADXL345_WR_Reg(0X2C,0x0A);		  //數(shù)據(jù)輸出速度為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);  //發(fā)送寫器件指令	 
	IIC_Wait_Ack();	   
  IIC_Send_Byte(addr);   			//發(fā)送寄存器地址
	IIC_Wait_Ack(); 	 										  		   
	IIC_Send_Byte(val);     		//發(fā)送值					   
	IIC_Wait_Ack();  		    	   
  IIC_Stop();						      //產(chǎn)生一個停止條件 	   
}
//讀ADXL345寄存器
//addr:寄存器地址
//返回值:讀到的值
u8 ADXL345_RD_Reg(u8 addr) 		
{
	u8 temp=0;		 
	IIC_Start();  				 
	IIC_Send_Byte(ADXL_WRITE);	//發(fā)送寫器件指令	 
	temp=IIC_Wait_Ack();	   
    IIC_Send_Byte(addr);   		//發(fā)送寄存器地址
	temp=IIC_Wait_Ack(); 	 										  		   
	IIC_Start();  	 	   		//重新啟動
	IIC_Send_Byte(ADXL_READ);	//發(fā)送讀器件指令	 
	temp=IIC_Wait_Ack();	   
    temp=IIC_Read_Byte(0);		//讀取一個字節(jié),不繼續(xù)再讀,發(fā)送NAK 	    	   
    IIC_Stop();					//產(chǎn)生一個停止條件 	    
	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位全分辨率,輸出數(shù)據(jù)右對齊,16g量程 
	ADXL345_WR_Reg(BW_RATE,0x0A);		//數(shù)據(jù)輸出速度為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個軸的數(shù)據(jù)
//x,y,z:讀取到的數(shù)據(jù)
void ADXL345_RD_XYZ(short *x,short *y,short *z)
{
	u8 buf[6];
	u8 i;
	IIC_Start();  				 
	IIC_Send_Byte(0X3A);	//發(fā)送寫器件指令	 
	IIC_Wait_Ack();	   
  IIC_Send_Byte(0x32);   		//發(fā)送寄存器地址(數(shù)據(jù)緩存的起始地址為0X32)
	IIC_Wait_Ack(); 	 		
 	IIC_Start();  	 	   		//重新啟動
	IIC_Send_Byte(0X3B);	//發(fā)送讀器件指令
	IIC_Wait_Ack();
	for(i=0;i<6;i++)
	{
		if(i==5)buf[i]=IIC_Read_Byte(0);//讀取一個字節(jié),不繼續(xù)再讀,發(fā)送NACK  
		else buf[i]=IIC_Read_Byte(1);	//讀取一個字節(jié),繼續(xù)讀,發(fā)送ACK 
		delay_us(15);
	  IIC_Start();  	 	   		//重新啟動
		IIC_Send_Byte(0X3A);	//發(fā)送寫器件指令
			IIC_Wait_Ack();	
		IIC_Send_Byte(0x33+i);   		//發(fā)送寄存器地址(數(shù)據(jù)緩存的起始地址為0X32)
	  IIC_Wait_Ack(); 	 		
	  IIC_Start();  	 	   		//重新啟動
	  IIC_Send_Byte(0X3B);	//發(fā)送讀器件指令
	  IIC_Wait_Ack();
 	}	        	   
    IIC_Stop();					//產(chǎn)生一個停止條件
	*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的數(shù)據(jù)times次,再取平均
//x,y,z:讀到的數(shù)據(jù)
//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)//讀取次數(shù)不為0
	{
		for(i=0;i<times;i++)//連續(xù)讀取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方向的重力加速度分量(不需要單位,直接數(shù)值即可)
//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;
}
  • 更多詳細資料請聯(lián)系.docx
    下載
意法半導(dǎo)體

意法半導(dǎo)體

意法半導(dǎo)體(ST)集團于1987年6月成立,是由意大利的SGS微電子公司和法國Thomson半導(dǎo)體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱改為意法半導(dǎo)體有限公司。意法半導(dǎo)體是世界最大的半導(dǎo)體公司之一,公司銷售收入在半導(dǎo)體工業(yè)五大高速增長市場之間分布均衡(五大市場占2007年銷售收入的百分比):通信(35%),消費(17%),計算機(16%),汽車(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計數(shù)據(jù),意法半導(dǎo)體是全球第五大半導(dǎo)體廠商,在很多市場居世界領(lǐng)先水平。例如,意法半導(dǎo)體是世界第一大專用模擬芯片和電源轉(zhuǎn)換芯片制造商,世界第一大工業(yè)半導(dǎo)體和機頂盒芯片供應(yīng)商,而且在分立器件、手機相機模塊和車用集成電路領(lǐng)域居世界前列.

意法半導(dǎo)體(ST)集團于1987年6月成立,是由意大利的SGS微電子公司和法國Thomson半導(dǎo)體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱改為意法半導(dǎo)體有限公司。意法半導(dǎo)體是世界最大的半導(dǎo)體公司之一,公司銷售收入在半導(dǎo)體工業(yè)五大高速增長市場之間分布均衡(五大市場占2007年銷售收入的百分比):通信(35%),消費(17%),計算機(16%),汽車(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計數(shù)據(jù),意法半導(dǎo)體是全球第五大半導(dǎo)體廠商,在很多市場居世界領(lǐng)先水平。例如,意法半導(dǎo)體是世界第一大專用模擬芯片和電源轉(zhuǎn)換芯片制造商,世界第一大工業(yè)半導(dǎo)體和機頂盒芯片供應(yīng)商,而且在分立器件、手機相機模塊和車用集成電路領(lǐng)域居世界前列.收起

查看更多

相關(guān)推薦