要求使用protues仿真软件,来模仿实际十字路口的红绿的显示变化,同时数码管进行时间倒计时的显示。百度了下实际情况的交通灯规则如下图。
整个交通灯的运行流程如下图所示,这个应该和实际工作流程是非常接近的。
根据这些资料开始绘制protues的仿真图,一开始是完全按照实际情况来设置的,画出来的是这样的。。
写了个测试小程序一跑,懵逼了。。出现了Simulation is not running in real time due to excessive CPU load 这条警告。当时百度了很久都没有查询到问题,所以就放弃这个电路了。(现在知道解决办法了,在我的另一篇博文中有介绍)当时没办法,只好又画了个简单点的电路,同时把这些乱七八糟的线全部变成net标号了。最终如下图所示,这个电路是不改LED属性也能跑的,当然现在我已经全改了,因为我们只需要LED有亮灭两种状态就可以了。
下面贴个测试的工程,适用于第二个电路(其实差不多,就是数码管这边有写不同吧。)
#include<reg51.h> // 数据类型定义 #define u8 unsigned char #define u16 unsigned int // 数码管段选数组 u8 code NUM[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; u8 time_cnt=0; u8 turn_yellow=0; u8 ex =1; u8 turnflag=0; u8 left_time; u8 for_time; // 管脚定义 sbit left_red = P3^0; sbit left_yellow = P3^1; sbit left_green = P3^2; sbit for_red = P3^3; sbit for_yellow = P3^4; sbit for_green = P3^5; sbit leftc=P2^7; sbit forc = P2^6; // 延时函数 void delay_us(u16 t) { while(t--); } // 定时器 50ms void Timer_Init() { EA=1; ET0=1; TMOD=0x01; TH0=15536/256; TL0=15536%256; TR0=1; } //前方向 黄灯亮 void foryellow() { forc=0; leftc=1; for_red=0; for_yellow=1; for_green=1; left_red = 1; left_yellow = 0; left_green = 1; leftc=0; forc=1; for_red=1; for_yellow=1; for_green=0; left_red = 0; left_yellow = 1; left_green = 1; forc=0; } // 左右方向 黄灯亮 void leftyellow() { forc=0; leftc=1; for_red=1; for_yellow=1; for_green=0; left_red = 0; left_yellow = 1; left_green = 1; leftc=0; forc=1; for_red=0; for_yellow=1; for_green=1; left_red = 1; left_yellow = 0; left_green = 1; forc=0; } //前方向转向 void forturn() { forc=0; leftc=1; for_red=1; for_yellow=1; for_green=0; left_red = 0; left_yellow = 1; left_green = 1; leftc=0; forc=1; for_red=0; for_yellow=1; for_green=1; left_red = 0; left_yellow = 1; left_green = 1; forc=0; } //左右方向转向 void leftturn() { forc=0; leftc=1; for_red=0; for_yellow=1; for_green=1; left_red = 0; left_yellow = 1; left_green = 1; leftc=0; forc=1; for_red=1; for_yellow=1; for_green=0; left_red = 0; left_yellow = 1; left_green = 1; forc=0; } //前进绿灯 void forgo() { forc=0; leftc=1; for_red=0; for_yellow=1; for_green=1; left_red = 1; left_yellow = 1; left_green = 0; leftc=0; forc=1; for_red=0; for_yellow=1; for_green=1; left_red = 0; left_yellow = 1; left_green = 1; forc=0; } //前进红灯 void forstop() { forc=0; leftc=1; for_red=0; for_yellow=1; for_green=1; left_red = 0; left_yellow = 1; left_green = 1; leftc=0; forc=1; for_red=0; for_yellow=1; for_green=1; left_red = 1; left_yellow = 1; left_green = 0; forc=0; } //前进方向数码管显示 void dispfor(u8 num) { P2|=0x0f; P0=0xff; P2=(P2&0xc0)|0x01; P0=NUM[num/10]; delay_us(100); P0=0xff; P2|=0x0f; P0=0xff; P2=(P2&0xc0)|0x02; P0=NUM[num%10]; delay_us(100); P0=0xff; } //左右方向数码管显示 void displeft(u8 num) { P2|=0x0f; P0=0xff; P2=(P2&0xc0)|0x04; P0=NUM[num/10]; delay_us(100); P0=0xff; P2|=0x0f; P0=0xff; P2=(P2&0xc0)|0x08; P0=NUM[num%10]; delay_us(100); P0=0xff; } //主函数 void main() { for_time=17; left_time=30; Timer_Init(); //初始时间 forgo(); while(1) { dispfor(for_time); displeft(left_time);//显示 } } //定时器中断 void Timer0() interrupt 1 { TR0=0; time_cnt++; if(time_cnt>19) { time_cnt=0; for_time--; left_time--; if(for_time==0&&ex) //时间为0 { if(turn_yellow) //是否变过黄灯 { if(turnflag==0) //是否转向 { for_time=10; forturn(); turnflag=1; } else { for_time=30; left_time=17; forstop(); ex=0; turnflag=0; turn_yellow=0; } } else { for_time=3; foryellow(); turn_yellow=1; } } if(left_time==0&&ex==0) { if(turn_yellow) //是否变过黄灯 { if(turnflag==0) //是否转向 { left_time=10; leftturn(); turnflag=1; } else { for_time=17; left_time=30; forgo(); ex=0; turnflag=0; } } else { left_time=3; leftyellow(); turn_yellow=1; } } } TH0=15536/256; TL0=15536%256; TR0=1; }
近期在整理自己以前做的一些小工程,算是给自己留记录,同时也分享给需要的人。仿真文件大家可以按照上面的自己画,也可以在我的个人公众号“硬件君”私聊我获取。