51單片機交通燈的實物圖:
本proteus仿真文件是proteus7.4版本創建的,請用7.4版本或更高版本打開,較低版本可能出現無法打開的現象。
單片機源程序如下:
- /***************51單片機交通燈設計*******************/
- #include <reg52.h>
- #include <intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- uchar night_flag=0; //深夜標志位
- uchar time_cl=0; //定義時間控制標志位 取0
- uchar flag=0; //方向通行標志位
- uchar B_N_D_flag=1; //定義北南通燈行標志位
- uchar X_D_D_flag=1; //定義西東通燈行標志位
- uchar i,j; //定義變量i
- uchar t=3; //數碼管動態掃描延時時間基數
- uchar num=0; //時間基數初始化為0
- //uchar num_night=0; //深夜模式時間基數為0
- uchar time=30; //time初始化定為30秒
- int bei,nan,xi,dong; //定義 北 南 西 東
- uchar code Data[]={0x18,0x7B,0x89,0x49,0x6A,0x4C,0x0C,0x79,0x08,0x48,0xEF};
- //定義數組 數碼管 0 1 2 3 4 5 6 7 8 9 -
- /***************定義 紅黃綠燈**************/
- sbit B_R=P1^2; //北面 紅燈
- sbit B_Y=P1^1; //北面 黃燈
- sbit B_G=P1^0; //北面 綠燈
- sbit N_R=P2^0; //南面 紅燈
- sbit N_Y=P2^1; //南面 黃燈
- sbit N_G=P2^2; //南面 綠燈
- sbit X_R=P2^5;//西面 紅燈
- sbit X_Y=P2^6; //西面 黃燈
- sbit X_G=P2^7; //西面 綠燈
- sbit D_R=P3^7; //東面 紅燈
- sbit D_Y=P3^6; //東面 黃燈
- sbit D_G=P3^5; //東面 綠燈
- sbit s1=P3^4;//時間減
- sbit s2=P3^3;//時間加
- sbit s3=P3^1;//白天和夜間模式控制切換口
- sbit s4=P3^2;//進入時間可以設置狀態的切換口
- /***************定義 數碼管*****************/
- #define SMG_XS P0 //數碼管數據顯示
- #define SMG_KZ P2 //數碼管控制顯示
- sbit smg1=P2^4;//定義數碼管1控制口
- sbit smg2=P2^3;//定義數碼管2控制口
- void delay(uint time);// 定義延時程序
- void disp_init();//顯示初始化
- void disp(bei,nan,xi,dong);
- void Time0_init() //定時器0初始化函數
- {
- TMOD=0x01; //定時器0為方式1
- TL0=(65536-50000)%256;
- TH0=(65536-50000)/256; //12M晶振 定時時間50ms
- ET0=1; //開定時器0中斷
- EA=1; //開總中斷
- TR0=1; //啟動定時器0
- }
- void night_mode() //深夜模式
- {
- B_R=1;
- B_Y=~B_Y; //北 黃燈取反
- B_G=1;
- N_R=1;
- N_Y=~N_Y; //南 黃燈取反
- N_G=1;
- X_R=1;
- X_Y=~X_Y; //西 黃燈取反
- X_G=1;
- D_R=1;
- D_Y=~D_Y; //東 黃燈取反
- D_G=1;
- }
- void B_N_G() //北南通(綠燈) 西東(紅燈)
- {
- B_G=0; //北 綠燈亮
- N_G=0; //南 綠燈亮
- B_R=1;
- B_Y=1;
- N_R=1;
- N_Y=1;
- X_R=0; //西 紅燈亮
- D_R=0; //東 紅燈亮
- X_Y=1;
- X_G=1;
- D_Y=1;
- D_G=1;
- }
- void X_D_G() //西東通(綠燈) 北南(紅燈)
- {
- B_G=1;
- N_G=1;
- B_R=0; //北 紅燈亮
- B_Y=1;
- N_R=0; //南 紅燈亮
- N_Y=1;
- X_R=1;
- D_R=1;
- X_Y=1;
- X_G=0; //西 綠燈亮
- D_Y=1;
- D_G=0; //東 綠燈亮
- }
- void B_N_tong() //北南 通行
- {
- if(B_N_D_flag==1) //當北南通燈行標志位為1
- {
- B_N_G(); //北南通(綠燈) 西東(紅燈)
- B_N_D_flag=0; //北南通燈行標志位置0
- }
- while(num==20) //當1s時間到
- {
- num=0; //num清0
- bei--; //北時間 減1
- nan--; //南時間 減1
- xi--; //西時間 減1
- dong--; //東時間 減1
- if(bei<=6&&bei>=0||nan<=6&&nan>=0) //當北和南時間在0到6秒之間
- {
- if(bei<=6&&bei>3||nan<=6&&nan>3) //進一步判斷北和南時間是否在3到6秒之間
- {
- B_G=~B_G; //北 綠燈取反
- N_G=~N_G; //南 綠燈取反
- }
- if(bei<=3&&nan<=3) //進一步判斷北和南時間是否在3秒以內
- {
- B_G=1; //北 綠燈不亮
- N_G=1; //南 綠燈不亮
- B_Y=0; //北 黃燈亮
- N_Y=0; //南 黃燈亮
- }
- }
- else //否則(即北和南時間不在0到6秒之間)
- {
- B_G=0; //北 綠燈亮
- N_G=0; //南 綠燈亮
- B_Y=1; //北 黃燈不亮
- N_Y=1; //南 黃燈不亮
- }
- }
- }
- void X_D_tong() //西東 通行
- {
- if(X_D_D_flag==1) //當西東通燈行標志位為1
- {
- X_D_G(); //西東通(綠燈) 北南(紅燈)
- X_D_D_flag=0; //西東通燈行標志位置0
- }
- while(num==20) //當1s時間到
- {
- num=0; //num清0
- bei--; //北時間 減1
- nan--; //南時間 減1
- xi--; //西時間 減1
- dong--; //東時間 減1
- if(xi<=6&&xi>=0||dong<=6&&xi>=0) //當西和東時間在0到6秒之間
- {
- if(xi<=6&&xi>3||dong<=6&&dong>3) //進一步判斷西和東時間是否在3到6秒之間
- {
- X_G=~X_G; //西 綠燈取反
- D_G=~D_G; //東 綠燈取反
- }
- if(xi<=3&&dong<=3) //進一步判斷西和東時間是否在3秒以內
- {
- X_G=1; //西 綠燈不亮
- D_G=1; //東 綠燈不亮
- X_Y=0; //西 黃燈亮
- D_Y=0; //東 黃燈亮
- }
- }
- else //否則(即西和東時間不在0到6秒之間)
- {
- X_G=0; //西 綠燈亮
- D_G=0; //東 綠燈亮
- X_Y=1; //西 黃燈不亮
- D_Y=1;//東 黃燈不亮
- }
- }
- }
- void Time0() interrupt 1 //定時器0中斷服務函數
- {
- TH0=(65536-50000)/256; //重新載裝初值,設置50ms中斷一次
- TL0=(65536-50000)%256;
- num++; //時間基數加1
- }
-
- void main() //主函數入口
- {
- bei=nan=xi=dong=time; //把time值賦給北 南 西 東
- disp_init(); //顯示初始化
- Time0_init(); //定時器0初始化函數
- while(1) //無限循環
- {
- if(s4==0) //當P3.0按下(調整時間允許鍵)
- {
- delay(5); //延時去抖
- s4=1; //關閉數碼管顯示
- if(s4==0) //再次確定按鍵是否按下
- {
- time_cl=~time_cl;//時間控制標志位取反(開/關時間控制標志位)
- if(time_cl==0) //如果時間控制標志位為0
- {
- TL0=(65536-50000)%256;
- TH0=(65536-50000)/256; //12M晶振 定時時間50ms
- TR0=1; //開啟定時器0
- num=0; //num初始化為0
- }
- }
- while(s4==0); //等待按鍵松開
- }
-
- if(s3==0) //當P3.7按下(開/關 深夜模式)
- {
- delay(5); //延時去抖
- s3=1; //關閉數碼管顯示
- if(s3==0)
- {
- night_flag=~night_flag; //深夜標志位取反(開/關深夜模式),1表示開,0表示關
- if(night_flag==1) //如果深夜模式開
- {
- TR0=0; //關閉定時器0
- num=0; //時間基數清0
- TL0=(65536-50000)%256;
- TH0=(65536-50000)/256; //12M晶振 定時時間50ms
- TR0=1; //開啟定時器0
- SMG_KZ=0xff; //關閉數碼管顯示
- }
- else //否則night_flag=0表示深夜模式關(紅綠燈正常運行)
- {
- TR0=0; //關閉定時器0
- num=0; //時間基數清0
- TL0=(65536-50000)%256;
- TH0=(65536-50000)/256; //12M晶振 定時時間50ms
- TR0=1; //開啟定時器0
- B_N_D_flag=1; //定義北南通燈行標志位
- X_D_D_flag=1; //定義西東通燈行標志位
- if(bei<=3&&nan<=3) //判斷北和南時間是否在3秒以內
- {
- B_Y=1;
- N_Y=1;
- }
- if(xi<=3&&dong<=3) //判斷西和東時間是否在3秒以內
- {
- X_Y=1;
- D_Y=1;
- }
- }
- }
- while(s3==0);
- }
- if(night_flag==0) //如果深夜標志位為0,表示關閉深夜模式,紅綠燈正常運行
- {
- if(time_cl==0) //如果time_cl=0(不允許調整時間),即紅綠燈正常運行
- {
- if(flag==0) //flag=0表示北南通行允許
- {
- B_N_tong(); //北南 通行
- if(bei==0) //北南通行時間到
- {
- flag=~flag; //西東 通行允許
- B_N_D_flag=1; //北南通燈行標志位置1
- }
- }
- else //flag=1表示西東通行允許
- {
- X_D_tong(); //西東 通行
- if(xi==0) //西東通行時間到
- {
- flag=~flag; //北南 通行允許
- X_D_D_flag=1; //西東通燈行標志位置1
- }
- }
-
- disp(bei,nan,xi,dong); //顯示時間數據
- if(bei==0&&nan==0&&xi==0&&dong==0) //如果 北 南 西 東時間到(為0)
- {
- TR0=0; //關閉定時器0
- TL0=(65536-50000)%256;
- TH0=(65536-50000)/256; //12M晶振 定時時間50ms
- for(j=0;j<3;j++) //延時顯示閃爍3下
- {
- for(i=0;i<10;i++) //for語句延時
- {
- disp(bei,nan,xi,dong); //顯示函數
-
- }
- SMG_KZ=0xff; //關閉顯示
- delay(200); //延時一下
- }
- bei=time; //time值賦給北
- nan=time; //time值賦給南
- xi=time; //time值賦給西
- dong=time; //time值賦給東
- TR0=1; //開啟定時器0
- }
- else //否則
- {} //空操作
- }
- else //如果time_cl==1(允許時間調整)
- {
- TR0=0; //關閉定時器
- TL0=(65536-50000)%256;
- TH0=(65536-50000)/256; //12M晶振 定時時間50ms
- num=0; //時間基數清0
- bei=nan=xi=dong=time; //time值賦給 北 南 西 東
- disp(bei,nan,xi,dong); //顯示時間數據
- if(s2==0) //當P3.1按鍵按下(操作時間加1)
- {
- delay(5); //延時去抖
- if(s2==0) //再次確定按鍵是否按下
- {
- time++; //時間加1
- }
- while(s2==0); //等待按鍵松開
- }
- if(bei==100&&nan==100&&xi==100&&dong==100) //如果北 南 西 東 時間到100
- {
- time=1; //time等于1
- }
- if(s1==0) //當P3.6按鍵按下(操作時間減1)
- {
- delay(5); //延時去抖
- if(s1==0) //再次確定按鍵是否按下
- {
- time--; //time減1
- }
- while(s1==0); //等待按鍵松開
- }
- if(bei==0&&nan==0&&xi==0&&dong==0) //如果北 南 西 東 時間到0
- {
- time=99; //time等于99
- }
- }
- }
- else //否則深夜標志位為1,表示開啟深夜模式
- {
- if(num==20) //當1s時間到
- {
- num=0; //50ms時間基數清0
- night_mode(); //深夜模式
- }
- }
- // disp(69,69,69,69);
- }
-
- }
- void disp(bei,nan,xi,dong) //顯示(北 南 西 東)時間函數
- {
- SMG_XS=Data[bei/10]; //顯示北的十位
- smg1=0; //允許北十位顯示
- delay(t); //小延時一下,使數碼管顯示更清楚
- smg1=1; //關閉數碼管顯示(消隱)
- SMG_XS=Data[bei%10]; //顯示北的個位
- smg2=0; //允許北個位顯示
- delay(t); //小延時一下,使數碼管顯示更清楚
- smg2=1; //關閉數碼管顯示(消隱)
- SMG_XS=Data[nan/10]; //顯示南的十位
- //SMG_KZ=0xf7; //允許南十位顯示
- smg1=0;
- delay(t); //小延時一下,使數碼管顯示更清楚
- smg1=1;
- //SMG_KZ=0xff; //關閉數碼管顯示(消隱)
- SMG_XS=Data[nan%10]; //顯示南的個位
- //SMG_KZ=0xfb; //允許南個位顯示
- smg2=0;
- delay(t); //小延時一下,使數碼管顯示更清楚
- //SMG_KZ=0xff; //關閉數碼管顯示(消隱)
- smg2=1;
- SMG_XS=Data[xi/10]; //顯示西的十位
- // SMG_KZ=0xdf; //允許西十位顯示
- smg1=0;
- delay(t); //小延時一下,使數碼管顯示更清楚
- smg1=1;
- //SMG_KZ=0xff; //關閉數碼管顯示(消隱)
- SMG_XS=Data[xi%10]; //顯示西的個位
- smg2=0;
- //SMG_KZ=0xef; //允許西個位顯示
- delay(t); //小延時一下,使數碼管顯示更清楚
- smg2=1;
- //SMG_KZ=0xff; //關閉數碼管顯示(消隱)
- SMG_XS=Data[dong/10]; //顯示東的十位
- smg1=0;
- //SMG_KZ=0x7f; //允許東十位顯示
- delay(t); //小延時一下,使數碼管顯示更清楚
- smg1=1;
- //SMG_KZ=0xff; //關閉數碼管顯示(消隱)
- SMG_XS=Data[dong%10]; //顯示東的個位
- smg2=0;//
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
ID216 模塊相關資料 交通燈.zip
(794.82 KB, 下載次數: 90)
2017-6-5 19:52 上傳
點擊文件名下載附件
|