汽车尾灯控制器的设计与实现

设计基于单片机开发的汽车尾灯控制器,要求实现以下功能:
(1)尾灯控制器由液晶屏、按键、蜂鸣器、LED灯、超声模块、光照传感器等组成;
(2)要求开机后先在液晶屏上显示课程名称、班级、学号、姓名等信息,要求显示时间为5秒;
(3)汽车车尾左右两侧各有四盏灯:黄灯、红灯、雾灯、倒车照明灯,前面有照明灯(远光、近光)、黄灯、雾灯;
(4)白天正常行驶时照明灯都不亮,夜间行驶时两个前照明灯都亮;
(5)左转弯时左侧黄灯闪亮(2Hz),右转弯时右侧黄灯闪亮;
(6)汽车刹车时,两个红灯都亮;
(7)能见度低或者夜间行驶时雾灯点亮;
(8)倒车时红灯、倒车照明灯亮。且通过超声传感器测量倒车过程中最近障碍物的距离,当安全距离小于5米、2米、1米和0.5米时分别以更为急促的蜂鸣器声音提示;
(9)所有的状态和测量参数均需在液晶屏上显示。

一、转向灯模块
转向灯模块很简单,就是AT89C51芯片引脚对应连接LED的引脚及按键,控制灯亮灯灭

#include <reg52.h>
#define unit unsigned int
#define uchar unsigned char
//按键接口
sbit k0=P1^0;//左转信号
sbit k1=P1^1;//右转信号
sbit k2=P1^2;//刹车信号
sbit k3=P1^3;//倒车信号
sbit k4=P1^4;//雾灯开关
//汽车前灯
sbit x0=P2^0;//
sbit x1=P2^1;//左转
sbit x2=P2^2;//
sbit x3=P2^3;//右转
sbit x4=P2^4;//
sbit x5=P2^5;//

sbit x6=P2^6;//光敏
//AOUT连接p口,DOUT连接流水灯

//汽车后灯
sbit y0=P3^0;//	右转
sbit y1=P3^1;//	刹车
sbit y2=P3^2;//	
sbit y3=P3^3;//	 倒车
sbit y4=P3^4;//倒车
sbit y5=P3^5;//
sbit y6=P3^6;//刹车
sbit y7=P3^7;//左转

bit flag=0 ;// 开始循环标志位
bit f1=0;
uchar num,miao;
void delay(unit ms)//ms级延时函数
{
	uchar j;
	for(ms;ms>0;ms--)
		for(j=110;j>0;j--);
}
void kong_zhi()//控制信号函数
{
	if(k2==0)//刹车信号
	{
		delay(10);//消抖
		if(k2==0)
		{
			y1=y6=0;//
		}
		while(!k2);//刹车松开检测
		 P2=0xff;
	   	P3=0xff;	//刹车松开所有灯同时灭
	}
	else if(k3==0)	//倒车信号
	{
		delay(10);//消抖
		while(!k3)//停止松开检测
		{
			   	y3=y4=0;//倒车灯亮
		}
		P2=0xff;
	   	P3=0xff;	//倒车松开所有同时灭
	}
	else if(k0==0)//左转
	{
		delay(10);
		TR0=1;//开启定时器
		num=0;
		miao=0;
		while(!k0)
		{
			if(k0==0)
			{
				x1=y7=1;
				while(!k0)
				{
					if(miao==0||miao==2) x1=y7=0;
					else if(miao==1||miao==3) x1=y7=1;
				}
			}
			if(miao==0||miao==2) x1=y7=0;
			else if(miao==1||miao==3) x1=y7=1;
		}
		P2=0xff;
	   	P3=0xff;
		TR0=0;//关闭定时器
	}
	else if(k1==0)//右转
	{
		delay(10);
		TR0=1;//开启定时器
		num=0;
		miao=0;
		while(!k1)
		{
			if(k1==0)
			{
				x4=y0=1;
				while(!k1)
				{
					if(miao==0||miao==2)x4=y0=0;
					else if(miao==1||miao==3) x4=y0=1;	
				}
			}
				if(miao==0||miao==2) x4=y0=0;
				else if(miao==1||miao==3) x4=y0=1;
		}
		P2=0xff;
	   	P3=0xff;
		TR0=0;//关闭定时器
	}
	else if(k4==0)	//倒车信号
	{
		delay(10);//消抖
		while(!k4)//停止松开检测
		{
		 x0=x5=y2=y5=f1;//雾灯亮    
		}
		f1=~f1;	
	}
}

void main()
{
	TH0=(65536-50000)/256;//设置初值
	TL0=(65536-50000)%256;
	TMOD=0x01;//设置定时器模式
	EA=1;//开启总中断
	ET0=1;//开启定时器中断
	TR0=0;//关闭定时器
	P2=0xff;
	P3=0xff;
	x6=0;
	while(1)
	{
		kong_zhi();//信号控制函数
	}
}
void T0_init() interrupt 1
{
	TH0=(65536-50000)/256;//设置初值
	TL0=(65536-50000)%256;
	num++;
	if(num==5)
	{
		num=0;
		miao++;
		if(miao==4)
		miao=0;
	}
}

二、显示屏模块
显示屏使用的是12864液晶显示屏,12864点阵最多可显示32个中文字符。ST7920控制器带中文字库,免除了编制字库的麻烦

/*******************************************************
程序功能:LCD12864液晶测试
*******************************************************/

#include "STC12C5A60S2.h"

sbit LCD12864_RS  =  P3^4;	 //RS控制引脚
sbit LCD12864_RW  =  P3^5;	 //RW控制引脚
sbit LCD12864_EN  =  P3^6;	 //EN控制引脚
sbit LCD12864_PSB  = P3^7;	  //CS1模式选择引脚,ST7920控制器,1为8位并行接口,0为串行接口

#define LCDPORT P1		//数据引脚

unsigned char code ucStr1[]  =  "汽车尾灯控制器";		//显示信息1
unsigned char code ucStr2[]  =  "  16计科一班";		//显示信息2
unsigned char code ucStr3[]  =  "      莫依     ";		//显示信息3
unsigned char code ucStr4[]  =  "   1111111111  ";		//显示信息4

void LCD12864_Init(void);		  //LCD12864初始化函数
void LCD12864_WriteInfomation(unsigned char ucData,bit bComOrData);	   //向LCD12864写入数据,bComOrData为1时写入的是数据,0时写入的是命令
void LCD12864_CheckBusy(void);		//忙检测函数
void LCD12864_DisplayOneLine(unsigned char ucPos,unsigned char *ucStr);	  //向LCD12864写入一行文字
void Delay(unsigned int uiCount);

/******************************************************************************
函数名称:main
函数功能:主函数
*******************************************************************************/
void main(void)
{
	LCD12864_Init();   //初始化液晶
	
	LCD12864_DisplayOneLine(0x80,ucStr1);	//显示信息1
	LCD12864_DisplayOneLine(0x90,ucStr2);	//显示信息2
	LCD12864_DisplayOneLine(0x88,ucStr3);	//显示信息3
	LCD12864_DisplayOneLine(0x98,ucStr4);	//显示信息4
	while(1);

}

/******************************************************************************
函数名称:LCD12864_WriteInfomation
函数功能:向LCD12864写入命令或者数据
入口参数:ucData-要写入液晶的数据或者命令的内容
		  bComOrData-命令或者数据的标志位选择,0或者1,其中
		  	1:写入的是数据
			0:写入的是命令
*******************************************************************************/
void LCD12864_WriteInfomation(unsigned char ucData,bit bComOrData)
{
	LCD12864_CheckBusy();	//忙检测
	LCD12864_RW = 0;	//拉低RW
	LCD12864_RS = bComOrData;	//根据标志位判断写入的是命令还是数据
	Delay(150);				  //延时,等待操作
	LCDPORT = ucData;		  //将数据送至数据端口
	LCD12864_EN = 1;		  //使能信号
	Delay(150);				  //延时
	LCD12864_EN = 0;		//按照时序来操作
	Delay(150);
}

/******************************************************************************
函数名称:LCD12864_Init
函数功能:LCD12864液晶初始化
入口参数:无
返回值:无
备注:无
*******************************************************************************/
void LCD12864_Init(void)
{
	Delay(400);//延时
	LCD12864_PSB = 1;	//8位并口工作模式
	Delay(150);//延时


	LCD12864_WriteInfomation(0x30,0); //基本指令集
	Delay(150);
	LCD12864_WriteInfomation(0x08,0);  //显示设置
	Delay(150);
	LCD12864_WriteInfomation(0x10,0);	//光标设置
	Delay(150);
	LCD12864_WriteInfomation(0x0c,0);	//游标设置
	Delay(150);
	LCD12864_WriteInfomation(0x01,0);  //清屏
	Delay(150);
	LCD12864_WriteInfomation(0x06,0);	//进入点设定
	Delay(150);
		
}

/******************************************************************************
函数名称:LCD12864_CheckBusy
函数功能:忙检测
入口参数:无
返回值:无
备注:使用变量i做计时,避免液晶在死循环处停滞。
*******************************************************************************/
void LCD12864_CheckBusy(void)
{
	unsigned char i = 250;	//局部变量

	LCD12864_RS = 0;	  //拉低
	LCD12864_RW = 1;	  //拉高

	LCD12864_EN = 1;	  //使能
	while((i > 0) && (P0 & 0x80))i--;  //判断忙标志位
	LCD12864_EN = 0;	  //释放
}

/******************************************************************************
函数名称:LCD12864_DisplayOneLine
函数功能:显示一行汉字(8个汉字或者16个英文字符)
入口参数:position-要显示的行的首地址,可选值0x80,0x88,0x90,0x98,其中:
			0x80:液晶的第一行;
			0x88:液晶的第三行;
			0x90:液晶的第二行;
			0x98:液晶的第四行。
		  p-要显示的内容的首地址。
*******************************************************************************/
void LCD12864_DisplayOneLine(unsigned char position,unsigned char *p)
{
	 unsigned char i;
	 LCD12864_WriteInfomation(position,0);//写入要显示文字的行的首地址
	 Delay(150);

	 for(i = 0;i<16;i++)		//依次执行写入操作
	 {
	 	 LCD12864_WriteInfomation(*p,1);
		 p++;
	 }
}

/******************************************************************************
函数名称:Delay
函数功能:延时函数
入口参数:uiCount-延时参数
*******************************************************************************/
void Delay(unsigned int uiCount)
{
	while(uiCount--);
}

三、超声波模块
使用的是HC_SR04超声波传感器
其工作原理如下:
1.给超声波模块接入电源和地。
2.给脉冲触发引脚(trig)输入一个长为20us的高电平方波
3.输入方波后,模块会自动发射8个40KHz的声波,与此同时回波引脚(echo)端的电平会由0变为1;(此时应该启动定时器计时)
4.当超声波返回被模块接收到时,回波引 脚端的电平会由1变为0;(此时应该停止定时器计数),定时器记下的这个时间即为超声波由发射到返回的总时长。
5.根据声音在空气中的速度为344米/秒,即可计算出所测的距离。

//超声波模块程序
//超声波模块程序
//Trig  = P2^0
//Echo  = P3^2
#include <reg51.h>    
#define uchar unsigned char
#define uint  unsigned int
sbit Trig  = P2^0;
sbit Echo  = P3^2;
sbit king=P1^1;
sbit test  = P1^2;
sbit succeed_flag  = P1^3;
uint time;
uint timeH;
uint timeL;
uint i;
//
void delay(uint z)
{
 uint x,y;
  for(x=z;x>0;x--)
  for(y=110;y>0;y--);
}
//
void delay_20us()
 { 
    uchar a ;
    for(a=0;a<100;a++);
 }
//***************************************************************
//显示数据转换程序
void display(uint temp) 
 { 
	if(temp<50)
		{
			king=0;
			delay(500);
			king=1;
			delay(500);
		}
 }
//***************************************************************
void main()  
{ 
    uint distance;

    test =0;
	king=1;
    Trig=0;       //首先拉低脉冲输入引脚
    EA=1;         //打开总中断0 
    TMOD=0x10;    //定时器1,16位工作方式 
    while(1)        
    {
        EA=0;           //关总中断
        Trig=1;         //超声波输入端
        delay_20us();   //延时20us
        Trig=0;         //产生一个20us的脉冲
		i=0;
        while(Echo==0) {//等待Echo回波引脚变高电平
			i++; 
			if(i==0xfffe) break;
		}
		if(i==0xffff) continue;
        succeed_flag=0; //清测量成功标志
        EA=1;  
        EX0=1;          //打开外部中断0
        TH1=0;          //定时器1清零
        TL1=0;          //定时器1清零
        TF1=0;          //计数溢出标志
        TR1=1;          //启动定时器1
        delay(20);      //等待测量的结果
        TR1=0;          //关闭定时器1
        EX0=0;          //关闭外部中断0
       if(succeed_flag==1)
       {   
          time=timeH*256+timeL;
          distance=time*0.172;  //厘米
          display(distance);
       }                         
      if(succeed_flag==0)
       {
          distance=0;                    //没有回波则清零
          test = !test;                  //测试灯变化
        }               
    }
}
//***************************************************************
//外部中断0,用做判断回波电平
void exter()  interrupt 0   // 外部中断0是0号
 {   
     timeH =TH1;    //取出定时器的值
     timeL =TL1;    //取出定时器的值
     succeed_flag=1;//至成功测量的标志
     EX0=0;         //关闭外部中断
 }
//****************************************************************
//定时器1中断,用做超声波测距计时
void timer1() interrupt 3  //
    {
         TH1=0;
         TL1=0;
     }

四、AD/DA模块
结合光照强度和输出的模拟电压之间的关系,可以得到某一光强度下的对应的模拟电压。将模拟电压通过AD转换器转换为数字电压,然后再将数字电压转换成光照度。其中写数据读数据使用IIC协议模拟信号。

#include "reg52.h"
#include "intrins.h" 
#define uint unsigned int
#define uchar unsigned char
#define PCF8591 0x90//PCF8591地址
/*********************************
*********************************/	
//-----------定义变量--------------
sbit scl = P1^1; //串行数据输入端 
sbit sda = P1^0; //串行时钟输入端
sbit DS_595 = P2^2;
sbit SHCP_595 = P2^1;
sbit STCP_595 = P2^0;			

uchar code du[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xFF};//段码	
uchar code we[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};	//位码

void send_595(uint j)
{
	uint num;
	//  	STCP_595 = 0;
	for( num = 0 ; num < 8 ; num++ )
	{
	 SHCP_595 = 0;
	 DS_595 = j&0x80;
	 j = j<<1;
	 SHCP_595 = 1;
	 _nop_();
	}
	_nop_();
	//   	STCP_595 = 1;
}


void Out_595()
{
	 STCP_595 = 0;
	 _nop_();
	 _nop_();
	 STCP_595 = 1;
 
}


//延时函数_1ms级别
void delay_1ms(uint z)
{
	uint x,y;
	for( x=z ; x>0 ; x-- )
		for( y=114 ; y>0 ; y-- );
}
//延时函数_us级别
void delay_nop(void)//延时4-5个微秒 
{
	_nop_();_nop_();_nop_();_nop_();_nop_();
}

//初始化函数
void IIC_Init(void)
{
	sda = 1;
    delay_nop();
	scl = 1;
	delay_nop();
}

//起始信号函数
void IIC_Start(void)
{
	sda = 1;
	delay_nop();
	scl = 1;
	delay_nop();
	sda = 0;
	delay_nop();
}

//停止信号函数
void IIC_Stop(void)
{
	sda = 0;
	delay_nop();
	scl = 1;
	delay_nop();
	sda = 1;
	delay_nop();
}

//应答函数
void Ack(void)
{
	uchar i;
	scl = 1;
	delay_nop();
	while( (sda==1)&&(i<220) ) 
	i++;
	scl = 0;
	delay_nop();
}

//非应答函数
void NoAck(void)
{
	sda = 1;
	delay_nop();
	scl = 1;
	delay_nop();
	scl = 0;
	delay_nop();
}

//写字节函数
void Write_byte(uchar dat)//单片机向里写
{
	uchar i;
	scl = 0;  
	for( i=0 ; i<8 ; i++ )
	{
		if( dat&0x80 )
		{
			sda = 1;
		}
		else
		{
			sda=0;
		}
		dat = dat<<1;
		delay_nop();
		scl = 1;//准备向里写数据
		delay_nop();
		scl = 0;
		delay_nop();//数据写完毕
	}
	sda = 1;//数据线释放,不再占用,便于判断应答位
	delay_nop();
}

//读字节函数
uchar Read_byte(void)
{
	uchar i,byte;
	scl = 0;
	delay_nop();
	sda = 1;
	delay_nop();
	for( i=0 ; i<8 ; i++ )
	{
	scl = 1;//准备读数据
	delay_nop();//稳定下来
	byte = (byte<<1)|sda;//先左移一位,再在最低位接受当前位 
	delay_nop();
	scl = 0;//读完
	delay_nop();
	}
	return byte;
}


//读数据函数
uchar Read_Data(uchar control)//任意一个地址读取字节函数
{
	uchar IIC_Data;
	IIC_Start();
	Write_byte(PCF8591);//选择从机
	Ack();//伪写
	Write_byte(control);
    Ack();
	IIC_Start(); 
	Write_byte(PCF8591+1);//读为1
	Ack();
	IIC_Data = Read_byte();
	NoAck();
	IIC_Stop();
	return IIC_Data;
}

void display(uchar bai,uchar shi,uchar ge) 
{ 
 	send_595(we[0]);
	send_595(du[bai]);
	Out_595();
	delay_1ms(10);

	send_595(we[1]);
	send_595(du[shi]);
	Out_595();
	delay_1ms(10);				   

	send_595(we[2]);
	send_595(du[ge]);
	Out_595();
	delay_1ms(10);
} 
//AD转换
void main() 
{ 
	uchar num,ge,shi,bai; 
    IIC_Init(); 
    while(1) 
    { 
		num = Read_Data(0x40);
		bai = num/100;
		shi = num%100/10;
		ge = num%10;
		display(bai,shi,ge);
    } 
} 

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值