基于51单片机汽车智能灯光控制系统
(仿真+程序+原理图+PCB+设计报告)
功能介绍
具体功能:
1.光敏传感器测光线,低于设定值开启灯光;
2.使用超声波测距,低于设定距离开近光,高于设定距离转换成远光;
3.LCD1602实时显示监控到的光亮度和距离;
4.按键可以设置光亮和距离阈值;
5.可以切换成手动模式,手动控制灯光;
演示视频:
基于51单片机汽车智能灯光控制系统设计
#include <reg52.h>
#include "LCD1602.H"
#include "eeprom52.H"
#include "adc0832.H"
uint time=0;
int S=0; //测量距离
sbit echo=P2^3; //超声波接口定义
sbit trig=P2^4;
bit ir_ok=0; //定时测量标志位
sbit led1=P1^4;
sbit led2=P1^6; //手动自动LED指示灯灯接口定义
sbit LED_1=P2^0;
sbit LED_2=P2^1; //远近光灯接口定义
sbit key1=P3^2; //设置
sbit key2=P3^3; //增加
sbit key3=P3^4; //减小
sbit key4=P3^5; //手动/自动
sbit key5=P3^6; //远光 //近光
sbit key6=P3^7; //手动关灯
bit key1_flag=0;
bit key2_flag=0;
bit key3_flag=0;
bit key4_flag=0;
bit key5_flag=0;
bit key6_flag=0; //按键标志位
uchar sec1=0,sec2=0,ms=0; //sec1、sec2按键长按标志位,ms定时自加变量
uchar light_set=50,S_set=30,state; //光照设置值,距离设置值,设置变量
bit s0; //液晶闪烁效果标志位
bit memory_flag=0; //存储标志位
uchar light=0,ad_count; //光照值,滤波用累加变量
uint ad_dat=0; //ad数据
uchar beam;//0关闭 1近光 2远光
bit A_M=0;//0手动
uchar count; //中断累加变量
long int distance; //测量所得距离
void memory() //存储函数
{
SectorErase(0x2000); //清扇区
byte_write(0x2000,S_set/256);
byte_write(0x2001,S_set%256); //往扇区存设置距离
byte_write(0x2002,light_set); //往扇区存设置光强
}
void read_memory() //读存储函数
{
S_set=byte_read(0x2000)*256+byte_read(0x2001); //将存的数据读出来
light_set=byte_read(0x2002); //
if(S_set>400||light_set>100) //判断数据不正常,重新赋值
{
S_set=30;
light_set=50;
}
}
void trigger() //测量启动函数
{
trig=0;
_nop_(); //空语句,用来占用时间
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
trig=1;
}
void delayt(uint x) //延时函数
{
uchar j;
while(x-- > 0)
{
for(j = 0;j < 125;j++)
{
;
}
}
}
void init_measuring()
{
trig=1;
echo=1;
count=0;
}
void measuring() //启动测距信号
{
uchar l;
uint h,y;
TR0 = 1;
while(echo==1)
{
;
}
TR0 = 0;
l = TL0;
h = TH0;
y = (h << 8) + l;
y = y - 0xfc66;//us部分
distance = y + 1000 * count;//计算总时间,单位是微秒
TL0 = 0x66;
TH0 = 0xfc;
delayt(30);
S = 3453* distance / 200000;//原始为:(0.34毫米/us)*时间/2//
}
void interrupt_int() //定时器初始化
{
TMOD=0x11; //定时器0,定时器1都用模式1
TH0=0x00;
TL0=0x00; //定时器0赋初值0
ET0=1; //使能定时器0
TR0=0; //先不打开定时器0
TH1=0x3c;
TL1=0xb0; //定时器1赋值50ms
ET1=1;
TR1=1; //打开定时器1
EA=1; //打开总中断
}
void display() //显示函数
{
if(state==0) //如果是非设置状态
{
LCD1602_write(0,0x80); //第一行
LCD1602_writebyte("distance:"); //显示距离
if(S>99) LCD1602_write(1,0x30+S/100%10);
else LCD1602_writebyte(" ");
if(S>9) LCD1602_write(1,0x30+S/10%10);
else LCD1602_writebyte(" ");
LCD1602_write(1,0x30+S%10);
LCD1602_writebyte("cm ");
LCD1602_write(0,0xC0); //第二行
LCD1602_writebyte("light:"); //显示光照强度
if(light>99) LCD1602_write(1,0x30+light/100%10);
else LCD1602_writebyte(" ");
if(light>9) LCD1602_write(1,0x30+light/10%10);
else LCD1602_writebyte(" ");
LCD1602_write(1,0x30+light%10);
LCD1602_writebyte("% ");
}
else //设置状态
{
LCD1602_write(0,0x80); //第一行
LCD1602_writebyte("dis_set:"); //设置距离
if(state==1&&s0) LCD1602_writebyte(" "); //闪烁效果
else
{
if(S_set>99) LCD1602_write(1,0x30+S_set/100%10);
else LCD1602_writebyte(" ");
if(S_set>9) LCD1602_write(1,0x30+S_set/10%10);
else LCD1602_writebyte(" ");
LCD1602_write(1,0x30+S_set%10);
}
LCD1602_writebyte("cm ");
LCD1602_write(0,0xC0);
LCD1602_writebyte("lig_set:"); //设置光照
if(state==2&&s0) LCD1602_writebyte(" ");
else
{
if(light_set>99) LCD1602_write(1,0x30+light_set/100%10);
else LCD1602_writebyte(" ");
if(light_set>9) LCD1602_write(1,0x30+light_set/10%10);
else LCD1602_writebyte(" ");
LCD1602_write(1,0x30+light_set%10);
}
LCD1602_writebyte("% ");
}
}
void AD_dispose() //光照处理
{
if(ad_count<10) //读十次光照数据,取平均值,起到滤波的作用
{
ad_dat+=A_D(1);
ad_count++;
}
else
{
light=ad_dat/10;
light=(light*100)/255; //最大是255,所以这里扩大100倍除以255,可以得到百分比数据
ad_count=0;
ad_dat=0;
}
}
void key_scan() //按键扫描
{
if(!key1) //按键1按下
{
if(key1_flag) //如果标志位是1
{
key1_flag=0; //清0
state=(state+1)%3; //设置变量自加,%3限制了最大只能是2
}
}
else
{
key1_flag=1; //按键松开,才会给标志位置1,这样的话,按键按下只执行一次按键内容,起到了松手检测的作用
}
if(!key2)
{
if(key2_flag)
{
key2_flag=0;
if(state==1) //设置距离状态
{
if(S_set<400) S_set++; //小于400,就自加
}
else if(state==2)//设置光照状态
{
if(light_set<100) light_set++; //小于100就自加
}
}
if(sec2==0) //sec2==0,按键长按
{
if(state==1) //实现连加效果
{
if(S_set<400) S_set++;
}
else if(state==2)
{
if(light_set<100) light_set++;
}
}
memory_flag=1; //按键每次按下,存储标志位置1一次,这样只有设置的时候才会存储一次,一直执行存储函数会拖慢程序执行速度
}
else
{
key2_flag=1; sec2=2; //按键松开,按键标志位置1,按键长按变量赋0,当按键按下时,sec2不会再次赋值2,定时器有他的自减,当减到0,即为按键长按
}
if(!key3) //同上
{
if(key3_flag)
{
key3_flag=0;
if(state==1)
{
if(S_set>0) S_set--;
}
else if(state==2)
{
if(light_set>0) light_set--;
}
}
if(sec1==0)
{
if(state==1)
{
if(S_set>0) S_set--;
}
else if(state==2)
{
if(light_set>0) light_set--;
}
}
memory_flag=1;
}
else
{
key3_flag=1; sec1=2;
}
if(!key4)
{
if(key4_flag)
{
key4_flag=0;
A_M=!A_M; //手动自动切换
if(A_M==0) beam=0; //如果切换到手动,就把灯关了
}
}
else
{
key4_flag=1;
}
if(!key5)
{
if(key5_flag)
{
key5_flag=0;
if(A_M==0) //手动状态
{
if(beam==1) beam=2; //远近光灯切换
else beam=1;
}
}
}
else
{
key5_flag=1;
}
if(!key6)
{
if(key6_flag)
{
key6_flag=0;
if(A_M==0) //手动状态
{
beam=0; //可关闭远近光灯
}
}
}
else
{
key6_flag=1;
}
}
void police() //自动模式处理函数
{
if(light<light_set) //如果光照小于设置值,即天黑
{
if(S>S_set) beam=2; //如果距离大于设置距离,远光打开
else beam=1; //否则近光打开
}
else beam=0; //否则光照强,就关闭远近光灯
}
硬件设计
使用元器件:
单片机:STC89C51;
(注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)
10uF电解电容;30p瓷片电容;
5228光敏电阻;电源接口;
轻触按键;草帽LED;
3mm红色LED灯;超声波模块;
LCD1602液晶屏+16P排座;
4P排针;8位103排阻;
8550三极管;3K电阻;
10K电阻;1K电阻;
330欧电阻;自锁开关;
DIP40管座;12M晶振;
ADC0832芯片+DIP8底座;
导线:若干;
流程图:
设计资料
01 仿真图
本设计使用proteus7.8版本设计,资料里有安装包和安装视频教程,无需担心!具体如图!
02 原理图
本系统原理图采用Altium Designer19设计,具体如图!
03 程序
本设计使用软件keil4和keil5两个版本编程设计,无需担心!具体如图!
04 设计报告
六千字设计报告,具体如下!
05 设计资料
资料获取请关注同名公众号,全部资料包括仿真源文件 、程序(含注释)、AD原理图、pcb电路图、开题报告、参考论文、流程图、任务书、仿真视频等。具体内容如下,全网最全! !
资料获取请观看前面演示视频!
点赞分享一起学习成长。