综合作业1:倒计时交通灯
用单片机模拟十字路口的交通灯,采用自动红绿黄交通灯控制,具有固定的红灯、绿灯转换时间间隔,自动切换,每个方向具有倒计时功能。
功能要求:
1)要求南北方向车道和东西方向车道2条交叉道路上的车辆自动交替运行,东西和南北方向各有一组红、绿、黄灯用于指挥交通;
2)红灯的持续时间为55s,绿灯持续时间为50s,闪烁时间为3s;
3)黄灯在绿灯转为红灯之前亮2s;
4)每一种灯亮的时间都用LED数码管进行倒计时显示;
5)如有紧急情况,系统可以禁止普通车辆通行,南北、东西方向都为红灯,时间持续20s,当紧急情况结束后,继续正常工作。
#include "reg52.h"
#include "math.h"
sbit QiTin = P3^0;//启停按键
sbit duan = P2^6;//数码段
sbit wei = P2^7;//数码位
sbit NanBeiHong = P1^0;
sbit NanBeiHuan = P1^1;
sbit NanBeiLu = P1^2;
sbit DongXiHong = P1^5;
sbit DongXiHuan = P1^6;
sbit DongXiLu = P1^7;
bit k=0, d=0;//中断标记//红绿灯倒换标记
unsigned char code ShuMaGuan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0X80};//0~9隐.小数点
unsigned char code WeiXuanBiao[] = { 0x00,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f };
unsigned char Js=0;//中断计时
unsigned char Hm=0;//毫秒
unsigned char Mo=0;//秒
unsigned char YanShi=0;延时
void ShuMaXianShi(unsigned char s,unsigned char w,unsigned char d)
{
YanShi=255;
P0=WeiXuanBiao[w];
wei=1;
wei=0;
P0=ShuMaGuan[s]|ShuMaGuan[d];//d显示小数点11,10关闭
duan=1;
while(YanShi--);
P0=ShuMaGuan[10];//消隐
duan=0;
}
void ZhongDuanSheZhi()
{
TH0+=0X4c;/*定时器赋初值,定时50ms触发中断,自动补偿方式*/
TL0+=0X00;
TMOD=0X01;
TR0=1;
ET0=1; //开启定时器
EA=1; //全局中断开关
}
void XianShi()
{
ShuMaXianShi((55-Mo)/10,1,10);
ShuMaXianShi((55-Mo)%10,2,11);//红绿灯转换秒数预设为55秒
// ShuMaXianShi(Hm,3,10);
ShuMaXianShi(10,4,10);
ShuMaXianShi(10,5,10);
ShuMaXianShi((55-Mo)/10,6,10);
ShuMaXianShi((55-Mo)%10,7,11);
// ShuMaXianShi(Hm,8,10);
}
void JiShi(/*时间计算*/)
{
if(!(Js%2))
if(!k&&++Hm>=10) Hm=0;
if(Js>=20)
{
if(++Mo>=60) Mo=0;
Js=0;
}
}
void main()
{
ZhongDuanSheZhi();
while(1)
{//南北红灯//东西绿灯//南北显示时间,东西显示时间雷同不重写了
if(Mo==0&&Mo<=50){NanBeiHong=DongXiLu=d;DongXiHong=NanBeiLu=!d;}
if(Mo>=50&&Mo<=53)//闪烁
{
if(Hm>=5)
{
NanBeiHong=DongXiLu=d;
DongXiHong=NanBeiLu=!d;
}
if(Hm==0)
{
NanBeiHong=DongXiLu=!d;
DongXiHong=NanBeiLu=d;
}
}
if(Mo>=53&&Mo<=55)
{
NanBeiHuan=DongXiHuan=0;//南北黄灯//东西黄灯
NanBeiHong=DongXiLu=DongXiHong=NanBeiLu=1;//南北红灯//东西绿灯
}
if(Mo>=55){Mo=Hm=Js=0;d=!d;NanBeiHuan=DongXiHuan=1;}//初始化各时间
JiShi();
XianShi();
if(!QiTin)
{
//XianShi(/*巧借8个数码显示消抖*/);
unsigned char Yan_Shi=Js;
if(TR0==0)TR0=k=1;//重启中断
while(Js==Yan_Shi)XianShi();//中断消抖
if(!QiTin)if(!k)TR0=k; else k=0;//关闭中断,消抖后清除标记
while(!QiTin) XianShi(/*按下期间显示*/);
}
}
}
void ZhongDuan() interrupt 1
{
++Js;
TH0+=0X4c;
TL0+=0X00;
}
以上代码在上一例秒表基础上修改,未经测试,只写了红绿灯的逻辑.只定义了一个数码显示用于东西或南北显示,另外一个数码显示雷同就不赘述了.中断按钮用于临时调度,如有特殊要求要另写逻辑.
添加一个紧急按键
添加一个处理紧急函数
把紧急处理函数添加到中断中调用
sbit JinJi = P3^1;//紧急按键
void JinJi()
{
Mo=35;
while(Mo<=55)
{
NanBeiHong=DongXiHong=0;//0表示点亮
NanBeiHuan=NanBeiLu=DongXiHuan=DongXiLu=1;
XianShi();
}
}
直解写未调试
2019-12-24 23:59:47。答提问:能够同时完成的道理很简单也很朴素却是编程最精华最佳最高理念和最精华最佳最高境界,即只有一个主循环体外不要停留在程序的任何地方,虽是单线程也能完成多任务的关键所在。这是一般教学,一般人无法到达的。这个程序还有停留的都可修改成非停留,即可达到无暇最精华最佳最高状态,修改的办法亦在这个程序中,亦在我写的无限嵌套和其他程序中使用的技巧,中华先贤名言:智者千虑必有一失,愚者千虑必有一得。人不怕思考就怕不思考,唯谦恭之人得之,非菲薄之辈可得。