实现的功能:
- 设计一个十字路口交通灯控制器,用LED发光二极管模拟东西南北方向交通灯,用LED点阵显示屏显示两个方向的剩余时间,用按键控制显示状态。时间用定时器准确控制。
- 单片机复位后,东西方向绿灯,从6秒倒计时;6秒过后,东西方向黄灯,从3秒倒计时;3秒过后,东西方向红灯,从9秒倒计时。单片机复位后,南北方向红灯,从9秒倒计时;9秒过后,南北方向绿灯,从6秒倒计时。此后按照以上方式循环显示。
- 单击K1键,恢复复位后的状态。单击K2键,停止,即LED发光二极管和LED点阵显示屏的状态保持不变。单片机停止后,再单击K3键,继续接着刚才的状态运行。
仿真图
效果图
完整代码(C语言)
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define f1(a) (65536-a)/256
#define f2(a) (65536-a)%256
uchar code table[]={
0xE7,0xEB,0xEF,0xEF,0xEF,0xEF,0xEF,0x83, /* */
0xC7,0xB7,0xBB,0xDF,0xEF,0xF7,0xFB,0x83, /* */
0xE3,0xDF,0xDF,0xE3,0xDF,0xDF,0xC3,0xFF, /* */
0xEF,0xE7,0xEB,0xED,0x81,0xEF,0xEF,0xEF, /* */
0xC3,0xFB,0xFB,0xFB,0xC3,0xDF,0xDF,0xC3, /* 红灯9秒 */
0xC3,0xFB,0xFB,0xFB,0xC3,0xDB,0xDB,0xC3, /* */
0xC3,0xDF,0xDF,0xDF,0xDF,0xDF,0xDF,0xDF, /* */
0xC1,0xDD,0xDD,0xC1,0xDD,0xDD,0xDD,0xC1, /* */
0xC1,0xDD,0xDD,0xC1,0xDF,0xDF,0xDD,0xC1, /* */
0xE7,0xEB,0xEF,0xEF,0xEF,0xEF,0xEF,0x83, /* */
0xC7,0xB7,0xBB,0xDF,0xEF,0xF7,0xFB,0x83, /* 黄灯3秒 */
0xE3,0xDF,0xDF,0xE3,0xDF,0xDF,0xC3,0xFF, /* */
0xE7,0xEB,0xEF,0xEF,0xEF,0xEF,0xEF,0x83, /* */
0xC7,0xB7,0xBB,0xDF,0xEF,0xF7,0xFB,0x83, /* */
0xE3,0xDF,0xDF,0xE3,0xDF,0xDF,0xC3,0xFF, /* */
0xEF,0xE7,0xEB,0xED,0x81,0xEF,0xEF,0xEF, /* 绿灯6秒 */
0xC3,0xFB,0xFB,0xFB,0xC3,0xDF,0xDF,0xC3, /* */
0xC3,0xFB,0xFB,0xFB,0xC3,0xDB,0xDB,0xC3, /* */
};
uchar sec=17;
sbit K1=P1^3; //将P1.3定义为K1
sbit K2=P1^4; //将P1.4定义为K2
sbit K3=P1^5; //将P1.5定义为K3
void delay(uint t);
void Init();
void LatticDisplay(uchar num);
void Light(uchar num);
void keyscan();
void delay(uint t) //延时函数
{
uchar i;
while(t--)
{
for(i=0;i<120;i++);
}
}
void Init() //初始化函数
{
TMOD=0x01; //只是用定时器T0,使用计数功能
TH0=f1(1000); //高8位初始化
TL0=f2(1000); //地8位初始化
//1ms进入一次中断函数
EA=1; //中断总开关开启
ET0=1; //T0定时器中断开关开启
TR0=1; //允许T0定时器工作标志位打开
}
void LatticDisplay(uchar num)//点阵屏显示数字函数
{
uchar i,j;
for(i=0;i<8;i++)
{
P1=i|0xf8; //将P1口的高5位置1
P0=table[8*num+i]; //显示P0接的点阵屏第i行的亮点情况
if(8*(num-9)+i<0)//求出P2接口点阵屏亮的条件
j=8*(num+9)+i;
else
j=8*(num-9)+i;
P2=table[j]; //显示P2接的点阵屏幕第i行的亮点情况
delay(4); //延迟4ms,4*8=32ms<50ms 满足视觉余辉效应
P0=0xff; //避免出现点阵有残影
P2=0xff;
}
}
void Light(uchar num)//交通灯亮的函数
{
uchar state_E_W,state_S_N;
if(num>=12&&num<=17)//
state_E_W=0x04; //
if(num>=9&&num<=11) // 东西方向交通灯根据时间亮不同的颜色
state_E_W=0x02; //
if(num>=0&&num<=8) //
state_E_W=0x01; //
if(num>=9&&num<=17) //
state_S_N=0x08; //
if(num>=0&&num<=2) // 南北方向交通灯根据时间亮不同的颜色
state_S_N=0x10; //
if(num>=3&&num<=8) //
state_S_N=0x20; //
P3=state_E_W|state_S_N; //东西方向和南北方向交通灯情况互不干扰地写入P3,由P3输出
}
void keyscan()//键盘检测函数
{
if(K2==0)//判断K2按键是否被按下
{
delay(20);//适当延迟,起到消抖作用
if(K2==0)//再次判断K2是否被按下,这是如果检测到被按下那就是真的被按下了
{
TR0=0;//允许T0定时器工作标志位关闭
}
}
if(K3==0&&TR0==0)//判断K3是否被按下且允许T0定时器工作标志位关闭
{
delay(20);
if(K3==0&&TR0==0)
{
TR0=!TR0;//允许T0定时器工作标志位打开
}
}
if(K1==0)//判断K1按键是否被按下
{
delay(20);
if(K1==0)
{
Init();//单片机设置初始化
sec=17;//单片机设置初始化
}
}
}
void main()
{
Init();
while(1)
{
LatticDisplay(sec);
Light(sec);
keyscan();
}
}
void timer0(void) interrupt 1 //定时器T0的中断函数,接口是1
{
uint k;
TH0=f1(1000); //高8位初始化
TL0=f2(1000); //低8位初始化
//1ms进入一次中断函数
k++;
if(k==1000) //判断是否进入中断函数1000次
{ //进入中断函数1000次需要1s
k=0; //将记录进入中断函数的变量置0
sec--; //秒数-1
if(sec==-1)//判断秒数是否为-1
{
sec=17; //将秒数复位,即17~0为一个周期
}
}
}
通过网盘分享的文件:TrafficLight.7z
链接: https://pan.baidu.com/s/17Ny31dXfK0MWUPQNIDBPKg?pwd=zzzz
提取码: zzzz
拿走的记得自觉点赞就行, 谢谢大家