简介:
给大家分享一个用lcd1602显示的交通灯,下面是仿真原理图:
单片机源程序(部分预览):
#include<reg51.h>
#include"lcd.h"
#define NORMAL_MODE 0 //正常运行模式
#define NIGHT_MODE 3 //夜间模式
#define URGENCY_MODE 6 //紧急模式
#define NORMAL_MODE_STEP1 0
#define NORMAL_MODE_STEP2 1
#define NORMAL_MODE_STEP3 2
#define NORMAL_MODE_STEP4 3
sbit BUT1=P1^0;
sbit BUT2=P1^1;
sbit BUT3=P1^3;
sbit LED_EW_RED = P2^0; //东西红灯
sbit LED_EW_GREEN = P2^2; //东西绿灯
sbit LED_EW_YELLOW = P2^1; //东西黄灯
sbit LED_SN_RED = P2^3; //南北红灯
sbit LED_SN_GREEN = P2^5; //南北绿灯
sbit LED_SN_YELLOW = P2^4; //南北黄灯
unsigned char WorkMode = 0;
unsigned char DisplayTime = 0;
unsigned char DisplayTime1 = 4; //黄灯显示时间
unsigned char SD_DisplayTime = 0; //红绿灯显示时间
unsigned char NormalModeStep = 0;
unsigned char fag=0,k=0;
unsigned char djs1[]="Daojishi:";
unsigned char djs2[]="SN-Daojishi:";
int a=0;
void Delay1ms(uint y);
void InitTimer0(void);
void LcdDisplay1(int a);
void Work_Night_Mode();
void Work_NORMAL_Mode();
void Work_Urgency_Mode();
void SetBtn_Check_Work(void);
void delay10ms(unsigned char num);
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main(void)
{
unsigned char i;
LcdInit();
for(i=0;i<9;i++)
{
LcdWriteData(djs1[i]);
}
InitTimer0();
SD_DisplayTime = 15;
DisplayTime = SD_DisplayTime;
WorkMode = NORMAL_MODE;
NormalModeStep=NORMAL_MODE_STEP1;
while(1)
{
switch(WorkMode) //工作模式判断
{
case NORMAL_MODE: //正常模式
Work_NORMAL_Mode();
break;
case NIGHT_MODE: //夜间模式
Work_Night_Mode();
break;
case URGENCY_MODE: //紧急模式
Work_Urgency_Mode();
break;
}
SetBtn_Check_Work();
LcdDisplay1(DisplayTime);
}
}
void Work_NORMAL_Mode() //正常工作模式
{
switch(NormalModeStep) //工作步段判断
{
case NORMAL_MODE_STEP1: //步段1, 南北绿灯,东西红灯
LED_SN_RED = 0; //南北红灯灭
LED_SN_GREEN = 1; //南北绿灯亮
LED_SN_YELLOW = 0; //南北黄灯灭
LED_EW_RED = 1; //东西红灯亮
LED_EW_GREEN = 0; //东西绿灯灭
LED_EW_YELLOW = 0; //东西黄灯灭
if(DisplayTime ==0 ) //如果通行时间走完,即等于0
{
NormalModeStep = NORMAL_MODE_STEP2; //设置工作步段为步段2,南北黄灯,东西红灯
DisplayTime = DisplayTime1; //南北增减s黄灯时间
}
break;
case NORMAL_MODE_STEP2: //步段2, 南北黄灯,东西红灯
LED_SN_RED = 0; //南北红灯灭
LED_SN_GREEN = 0; //南北绿灯灭
LED_SN_YELLOW = 1; //南北黄灯亮
LED_EW_RED = 1; //东西红灯亮
LED_EW_GREEN = 0; //东西绿灯灭
LED_EW_YELLOW = 0; //东西黄灯灭
if(DisplayTime == 0) //如果通行时间走完,即等于0
{
NormalModeStep = NORMAL_MODE_STEP3; //设置工作步段为步段3,南北红灯,东西绿灯
DisplayTime = SD_DisplayTime; //南北加5s黄灯时间
}
break;
case NORMAL_MODE_STEP3: //步段3, 南北红灯,东西绿灯
LED_SN_RED = 1; //南北红灯亮
LED_SN_GREEN = 0; //南北绿灯灭
LED_SN_YELLOW = 0; //南北黄灯灭
LED_EW_RED = 0; //东西红灯灭
LED_EW_GREEN = 1; //东西绿灯亮
LED_EW_YELLOW = 0; //东西黄灯灭
if(DisplayTime == 0) //如果通行时间走完,即等于0
{
NormalModeStep = NORMAL_MODE_STEP4; //设置工作步段为步段4,南北红灯,东西黄灯
DisplayTime = DisplayTime1; //东西增减若干s黄灯时间
}
break;
case NORMAL_MODE_STEP4: //步段4, 南北红灯,东西黄灯
LED_SN_RED = 1; //南北红灯亮
LED_SN_GREEN = 0; //南北绿灯灭
LED_SN_YELLOW = 0; //南北黄灯灭
LED_EW_RED = 0; //东西红灯灭
LED_EW_GREEN = 0; //东西绿灯灭
LED_EW_YELLOW = 1; //东西黄灯亮
if(DisplayTime == 0) //如果通行时间走完,即等于0
{
NormalModeStep = NORMAL_MODE_STEP1; //设置工作步段为步段1,南北绿灯,东西红灯
DisplayTime = SD_DisplayTime; //南北同行时间重赋值
}
break;
}
}
void Work_Urgency_Mode() //紧急模式
{
LED_SN_RED = 1; //南北红灯亮
LED_SN_GREEN = 0; //南北绿灯灭
LED_SN_YELLOW = 0; //南北黄灯灭
LED_EW_RED = 1; //东西红灯亮
LED_EW_GREEN = 0; //东西绿灯灭
LED_EW_YELLOW = 0; //东西黄灯灭
DisplayTime =SD_DisplayTime; //南北显示时间为0xff,在显示函数里判断时间为0xff时不做显示,会显示“-”
}
void Work_Night_Mode() //夜间模式
{
LED_SN_RED = 0; //南北红灯灭
LED_SN_GREEN = 0; //南北绿灯灭
LED_SN_YELLOW = 1; //南北黄灯亮
LED_EW_RED = 0; //东西红灯灭
LED_EW_GREEN = 0; //东西绿灯灭
LED_EW_YELLOW = 1; //东西黄灯亮
DisplayTime = DisplayTime1; //南北显示时间为0xff,在显示函数里判断时间为0xff时不做显示,会显示“-”
}
void SetBtn_Check_Work(void) //设置按键检测函数
{
if(BUT1 == 0) //设置键按下 ,夜间模式 ,紧急模式 ,恢复正常模式
{
delay10ms(5); //50ms去抖
fag=0;
while(fag==0)
{ while(BUT1==0)
{ fag=1;
}
k++;
}
if(k%3 == 1)
{
TR0 = 0; //计时器停止
WorkMode = NIGHT_MODE; //夜间模式
DisplayTime=DisplayTime1;
}
else if(k%3==2)
{
TR0 = 0; //计时器停止
WorkMode = URGENCY_MODE; //紧急模式
DisplayTime = SD_DisplayTime;
}
else
{ TR0 = 1;
DisplayTime = SD_DisplayTime;
WorkMode = NORMAL_MODE;
}
}
else if(BUT2 == 0) //设置键按下 ,灯的时间加一 控制
{
delay10ms(10); //50ms去抖
if(BUT2 == 0)
{
TR0 = 0;
if(k%3==2) //红灯时间加一
{ SD_DisplayTime = SD_DisplayTime+1;
DisplayTime = SD_DisplayTime;
delay10ms(10);
//WorkMode = URGENCY_MODE;
}
else if(k%3==1) //黄灯时间加一
{
DisplayTime1=DisplayTime1+1;
DisplayTime=DisplayTime1;
delay10ms(10);
// WorkMode = NIGHT_MODE;
}
}
}
else if(BUT3 == 0) //设置键按下, 灯的时间减控制
{
delay10ms(5); //50ms去抖
if(BUT3 == 0)
{
TR0 = 0;
if(k%3==2)
{SD_DisplayTime = SD_DisplayTime-1; //按键使红灯时间减一
DisplayTime = SD_DisplayTime;
WorkMode = URGENCY_MODE;
}
else if(k%3==1)
{
DisplayTime1=DisplayTime1-1; //按键使黄灯时间减一
DisplayTime=DisplayTime1;
WorkMode = NIGHT_MODE;
}
}
}
}
void LcdDisplay1(int a) //lcd显示
{
LcdWriteCom(0x8A);
LcdWriteData('0'+a/10);
LcdWriteCom(0x8B);
LcdWriteData('0'+a%10);
}
void InitTimer0(void) //初始化定时器0
{
TMOD = 0x01; //模式1
TH0 = 0x3C; //定时器装载值
TL0 = 0xB0;
EA = 1; //使能总中断
ET0 = 1; //使能定时器0中断
TR0 = 1; //启动定时器0
}
void Timer0Interrupt(void) interrupt 1 //定时器0中断处理函数
{
static unsigned char TimeOutNum = 0;
TH0 = 0x3C; //重新装载值
TL0 = 0xB0;
TimeOutNum++; //中断次数++, 即50ms的次数
if(TimeOutNum>=20) //达到50ms * 20 = 1s条件
{
TimeOutNum = 0; //中断次数清0
DisplayTime--; //南北显示时间-1
}
}
void Delay1ms(uint y)
{
uint x;
for( ; y>0; y--)
{
for(x=110; x>0; x--);
}
}
void delay10ms(unsigned char num) //误差 0us
{
unsigned char i,a,b,c;
for(i=0;i<num;i++)
for(c=5;c>0;c--)
for(b=4;b>0;b--)
for(a=248;a>0;a--);
}