51单片机——交通灯
生活随笔
收集整理的這篇文章主要介紹了
51单片机——交通灯
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原理圖
功能描述
??1、基本功能就是如同紅綠燈一般,不做贅述。
??2、紅燈時長和綠燈時長可通過按鍵設置,即按鍵列中的上面4個,當這4個按鍵有一個按下后便進入時長設置功能,設置完成后按最下面兩個按鍵(緊急控制按鈕)任意一個便可退出該功能。
??3、有緊急控制功能,按下緊急控制按鈕后,便進入該功能,保持紅燈或綠燈常亮,且關閉數碼管,當按下時長控制按鈕即最上面的4個按鈕便可退出該功能。
效果展示
代碼
#include <reg52.h>//數碼管選擇位 sbit EW_1=P1^0; sbit EW_2=P1^1; sbit NS_1=P1^2; sbit NS_2=P1^3;sbit add_red_time=P1^4; //加紅燈時間按鈕 sbit add_green_time=P1^5; //加綠燈時間按鈕 sbit reduce_red_time=P1^6; //減紅燈時間按鈕 sbit reduce_green_time=P1^7; //減綠燈時間按鈕 sbit NS_led=P2^6; //南北向燈緊急控制按鈕 sbit EW_led=P2^7; //東西向燈緊急控制按鈕sbit EW_red=P2^0; //東西向紅燈 sbit EW_green=P2^1; //東西向綠燈 sbit EW_yellow=P2^2; //東西向黃燈 sbit NS_red=P2^3; //南北向紅燈 sbit NS_green=P2^4; //南北向綠燈 sbit NS_yellow=P2^5; //南北向黃燈char count=0; //計數,count=20表示1s char red_time=30; //紅燈停留時間 char green_time=25; //綠燈停留時間 char yellow_time=0; //黃燈停留時間 char NS_second=0; //南北紅綠燈秒計時 char EW_second=0; //東西紅綠燈秒計時 char code smgduan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //共陽數碼管段碼表,仿真中用的是共陰數碼管,所以使用時需對段碼取反 char display_data[4]={0}; //show_data[0]顯示南北計時十位,show_data[1]顯示南北計時個位,show_data[2]顯示東西計時十位,show_data[3]顯示東西計時個位 char temp_data[4]={0};char NS_R_G_mode=0; //南北紅綠燈亮模式 0 紅燈 1 綠燈 2 黃燈 char EW_R_G_mode=1; //東西紅綠燈亮模式 0 紅燈 1 綠燈 2 黃燈bit NS_R_G_flag=0; //南北紅綠燈標識位 0 紅燈 1 綠燈 bit EW_R_G_flag=0; //東西紅綠燈標識位 0 紅燈 1 綠燈 void delay(unsigned int i) //簡單延時 {while(i--); }void Timer_init() //定時器初始化 {//定時50msTMOD = 0x01; //定時器方式1TH0 = 0x3C; //定時器賦初值TL0 = 0xB0;EA = 1; //開啟總中斷ET0 = 1; //開啟定時器中斷TR0 = 1; //開啟定時器 }void Init() //系統初始化 {P0=0x00;P2=0x00;EW_1=1; EW_2=1;NS_1=1;NS_2=1;NS_led=1;EW_led=1;NS_second=red_time; //默認初始時南北向燈亮紅燈,并賦紅燈時長EW_second=green_time; //默認初始時東西向燈亮綠燈,并賦綠燈時長yellow_time=red_time-green_time;//黃燈時間為紅燈時間與綠燈時間差Timer_init(); }void NS_SMG_drive(char *buff) //南北向數碼管驅動 {//顯示十位NS_1=0;NS_2=1;P0=~smgduan[buff[0]]; //段碼取反delay(5); //間隔一段時間掃描 P0=0x00; //消隱//顯示個位NS_1=1;NS_2=0;P0=~smgduan[buff[1]];delay(5); P0=0x00;//關閉南北向數碼管NS_1=1;NS_2=1; }void EW_SMG_drive(char *buff) //東西向數碼管驅動 {//顯示十位EW_1=0;EW_2=1;P0=~smgduan[buff[2]]; //段碼取反delay(5); //間隔一段時間掃描 P0=0x00; //消隱//顯示個位EW_1=1;EW_2=0;P0=~smgduan[buff[3]];delay(5); P0=0x00;//關閉東西向數碼管EW_1=1; EW_2=1; }void data_del(char *buff,char data1,char data2) //數據處理 {buff[0]=data1/10; //取data1的十位buff[1]=data1%10; //取data1的個位buff[2]=data2/10; //取data2的十位buff[3]=data2%10; //取data2的個位 }void Time_del() //計時處理 {if(count>=20) //判斷是否滿1s{NS_second--; //南北向燈計時自減EW_second--; //東北向燈計時自減switch(NS_R_G_mode) //南北向燈{case 0: //紅燈{if(NS_second<0){NS_second=green_time; //開始綠燈倒計時NS_R_G_mode=1; //紅燈亮完綠燈亮} }break;case 1: //綠燈{if(NS_second<0){NS_second=yellow_time; //開始黃燈倒計時NS_R_G_mode=2; //綠燈亮完黃燈亮 } }break;case 2: //黃燈{if(NS_second<0){NS_second=red_time; //開始紅燈到計時NS_R_G_mode=0; //黃燈亮完紅燈亮 } }break;default:break;}switch(EW_R_G_mode) //東西向燈{case 0: //紅燈{if(EW_second<0){EW_second=green_time; //開始綠燈倒計時EW_R_G_mode=1; //紅燈亮完綠燈亮} }break;case 1: //綠燈{if(EW_second<0){EW_second=yellow_time; //開始黃燈倒計時EW_R_G_mode=2; //綠燈亮完黃燈亮 } }break;case 2: //黃燈{if(EW_second<0){EW_second=red_time; //開始紅燈倒計時EW_R_G_mode=0; //黃燈亮完紅燈亮 } }break;default:break;}count=0; //計數值清零} }void R_G_Y_led() //紅綠燈驅動 {switch(NS_R_G_mode) //南北向{case 0: //紅燈{NS_yellow=0; //黃燈滅NS_red=1; //紅燈亮}break;case 1: //綠燈{NS_red=0; //紅燈滅NS_green=1; //綠燈亮}break;case 2: //黃燈{NS_green=0; //綠燈滅if(count<10) //黃燈以1hz頻率閃爍NS_yellow=1;elseNS_yellow=0; }break;default:break; }switch(EW_R_G_mode) //東西向{case 0: //紅燈{EW_yellow=0; //黃燈滅EW_red=1; //紅燈亮}break;case 1: //綠燈{EW_red=0; //紅燈滅EW_green=1; //綠燈亮}break;case 2: //黃燈{EW_green=0; //綠燈滅if(count<10) //黃燈以1hz頻率閃爍EW_yellow=1;elseEW_yellow=0; }break;default:break; } }void Set_time() //設置紅綠燈亮的時長 {if((add_red_time==0)||(add_green_time==0)||(reduce_red_time==0)||(reduce_green_time==0))//設置紅綠燈時長時任一設置按鈕都可觸發{TR0 = 0; //關閉定時器P2=0x00; //清零P2寄存器EW_led=1; //EW_led、NS_led引腳也在P2寄存器內,但是后面需要這兩個按鈕結束設置紅綠燈時長任務,故而這兩個引腳要拉高NS_led=1;while(1){data_del(temp_data,red_time,green_time);//顯示當前紅綠燈時長NS_SMG_drive(temp_data);EW_SMG_drive(temp_data);if(add_red_time==0) //判斷加紅燈時間按鈕是否按下{delay(5); //消抖if(add_red_time==0){red_time++; //紅燈時間自加if(red_time>99) //限制紅燈時間最大值為99red_time=99;data_del(temp_data,red_time,red_time);//南北向數碼管顯示紅燈時長NS_SMG_drive(temp_data);}while(!add_red_time); //等待加紅燈時間按鈕彈起}if(add_green_time==0) //判斷加綠燈時間按鈕是否按下{delay(5);if(add_green_time==0){green_time++; //綠燈時間自加if(green_time>95) //限制綠燈時間最大值95green_time=95;data_del(temp_data,green_time,green_time);//東西向數碼管顯示綠燈時長EW_SMG_drive(temp_data);}while(!add_green_time); //等待加綠燈時間按鈕彈起}if(reduce_red_time==0) //判斷減紅燈時間按鈕是否按下{delay(5);if(reduce_red_time==0){red_time--; //紅燈時間自減if(red_time<10) //限制紅燈時間最小值10red_time=10;data_del(temp_data,red_time,red_time);NS_SMG_drive(temp_data);}while(!reduce_red_time); //等待減紅燈時間按鈕彈起}if(reduce_green_time==0) //判斷減綠燈時間按鈕是否按下{delay(5);if(reduce_green_time==0){green_time--; //綠燈時間自減if(green_time<5) //限制綠燈時間最小值5green_time=5;data_del(temp_data,green_time,green_time);EW_SMG_drive(temp_data);}while(!reduce_green_time); //等待減綠燈時間按鈕彈起}if((NS_led==0)||(EW_led==0)) //任一緊急控制按鈕按下則結束設置紅路燈時長任務{break;}}while((!NS_led)||(!EW_led)); //等待緊急控制按鈕彈起TR0 = 1; //開啟定時器yellow_time=red_time-green_time; //更新黃燈時間} }void Urgent() //紅綠燈緊急控制 {if((NS_led==0)||(EW_led==0)) //任一緊急控制按鈕按下觸發{TR0 = 0; //關閉定時器P2=0x00;EW_led=1;NS_led=1;EW_1=1; //關閉所有數碼管EW_2=1;NS_1=1;NS_2=1;while((!NS_led)||(!EW_led)); //判斷緊急控制按鈕按是否彈起while(1){if(NS_R_G_flag) //根據NS_R_G_flag狀態交替亮紅燈或者綠燈{NS_green=1; NS_red=0; } else{NS_red=1; NS_green=0; }if(EW_R_G_flag) //根據EW_R_G_flag狀態交替亮紅燈或者綠燈{EW_green=1; EW_red=0; }else{EW_red=1;EW_green=0; } if(NS_led==0) //判斷南北向緊急控制按鈕是否按下{delay(5);if(NS_led==0){NS_R_G_flag=!NS_R_G_flag; //NS_R_G_flag狀態取反 }while(!NS_led); //等待南北向緊急控制按鈕彈起}if(EW_led==0) //判斷東西向緊急控制按鈕是否按下{delay(5);if(EW_led==0){EW_R_G_flag=!EW_R_G_flag; //EW_R_G_flag狀態取反 }while(!EW_led); //等待東西向緊急控制按鈕彈起} if((add_red_time==0)||(add_green_time==0)||(reduce_red_time==0)||(reduce_green_time==0))//任一紅綠燈設置時長按鈕按下結束緊急控制人物{TR0 = 1; //開啟定時器break;}}while((!add_red_time)||(!add_green_time)||(!reduce_red_time)||(!reduce_green_time));//等待紅綠燈時間設置按鈕彈起 P2=0x00;EW_led=1;NS_led=1;} }void main() {Init();while(1){Time_del(); //時間處理data_del(display_data,NS_second,EW_second);//數據處理NS_SMG_drive(display_data); //南北向數碼管驅動EW_SMG_drive(display_data); //東西向數碼管驅動R_G_Y_led(); //紅綠燈驅動Set_time(); //紅綠燈時長設置Urgent(); //緊急控制} }void Timer0(void) interrupt 1 //定時器中斷 {TH0 = 0x3C;TL0 = 0xB0;count++; //觸發中斷后計數值自加,定時器中斷每50ms觸發一次 }工程下載
鏈接:https://pan.baidu.com/s/1P0Gj6PmNfffJdsEe5j6JGA
提取碼:0yzj
注
由于后續發現了些小問題,程序有所修改,網盤中的代碼由于一些原因暫時不能更新,以本篇博客為準。
總結
以上是生活随笔為你收集整理的51单片机——交通灯的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【接口篇 / Wan】(6.4) ❀ 0
- 下一篇: java——自定义字段转译