交通燈程序在單片機入門級別的眾多程序中屬于較為復雜的,其中還用到了intrins.h頭文件,給眾多學習者造成困擾。
本人經(jīng)過學習,在前人的基礎(chǔ)之上,對每一行比較重要的程序均做了注釋說明。希望幫助到列位黑友。
特別說明,intrins.h頭文件的添加與*.c文件的添加步驟實際上是一樣的。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
單片機源程序如下:
- #include<reg51.h>
- #include<intrins.h>
- typedef unsigned char uchar;
- typedef unsigned int uint;
- sbit k1 = P1^6;
- sbit k2 = P1^7;
- sbit k3 = P2^7;
- sbit k4 = P3^0;
- sbit yellowled_dx=P1^1; //東西黃燈
- sbit yellowled_nb=P1^4; //南北黃燈
- uchar code table[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
- uchar dig; //位選
- uchar led=0; //偏移量
- uchar buf[4];
- uchar sec_dx=39;//東西數(shù)碼指示值
- uchar sec_nb=39;//南北數(shù)碼指示值
- uchar settime_dx;
- uchar settime_nb;//倒計時設(shè)置的鍵值保存
- uchar b; //定時器中斷次數(shù)
- bit time; //燈狀態(tài)循環(huán)標志,借助time 實現(xiàn)判斷東西通行還是南北通行
- bit int0_time; //中斷強行標志
- bit set; //調(diào)時方向切換鍵標志
- /*************************************************
- 函數(shù)功能:軟件延時(約50ms)
- **************************************************/
- void delay(uint ms)
- {
- uint j,k;
- for(j=0;j<ms;j++)
- for(k=0;k<124;k++);
- }
- /*************************************************
- 函數(shù)功能:加 1 調(diào)整
- **************************************************/
- void key_ad1()
- {
- TR0=0; //關(guān)定時器
- if(set==0)
- sec_nb++; //南北加1S
- else
- sec_dx++;//東西加1S
- if(sec_nb==100)
- sec_nb=1;//加到100置1
- if(sec_dx==100)
- sec_dx=1;//加到100置1
- }
- /*************************************************
- 函數(shù)功能:減 1 調(diào)整
- **************************************************/
- void key_dec1()
- {
- TR0=0;//關(guān)定時器
- if(set==0)
- sec_nb--; //南北減1S
- else
- sec_dx--; //東西減1S
- if(sec_nb==0)
- sec_nb=99;//減到0重置99
- if( sec_dx==0 )
- sec_dx=99;//減到0重置99
- }
- /*************************************************
- 函數(shù)功能:按鍵k1-k4掃描
- **************************************************/
- void key()
- {
- if(k1==0)
- {
- delay(10);
- if(k1==0)
- {
- while(k1==0);
- key_ad1();
- }
- }
- if(k2==0)
- {
- delay(10);
- if(k2==0)
- {
- while(k2==0);
- key_dec1();
- }
- }
- if(k4==0)
- {
- delay(10);
- if(k4==0)
- {
- while(k4==0);
- set=!set;
- }
- }
- if(k3==0&&int0_time==1) //確認調(diào)完(k3按下),同時中斷強行標志為1
- {
- TR0=1; //啟動定時器
- sec_nb=59;
- sec_dx=59;
- int0_time=0;//清標志
- }
- else if(k3==0&&int0_time==0)//確認調(diào)完(k3按下),同時中斷強行標志為0
- {
- TR0=1;
- settime_nb=sec_nb; //設(shè)置的鍵值返回保存
- settime_dx=sec_dx; //設(shè)置的鍵值返回保存
- }
- }
- /*************************************************
- 函數(shù)功能:顯示
- **************************************************/
- void display()
- {
- /*************************************************
- 以下6行實現(xiàn)給buf[0-3]賦值,決定數(shù)碼管要顯示的數(shù)值
- **************************************************/
- buf[1]=sec_dx/10; //第1位 東西秒十位
- buf[2]=sec_dx%10; //第2位 東西秒個位
- buf[3]=sec_nb/10; //第3位 南北秒十位
- buf[0]=sec_nb%10; //第4位 南北秒個位
- P0=table[buf[led]];//賦初值(因為已經(jīng)給led賦初值=0,buf[0]=sec_nb%10)
- delay(2); //延時
- /*************************************************
- 以下6行實現(xiàn)給P2^0-3賦值,實現(xiàn)數(shù)碼管的循環(huán)顯示
- **************************************************/
- P2=dig; //給P2賦值dig,因為使用P2口低4位,如dig = 1110,則P2.0=0,對應LED不亮
- dig=_crol_(dig,1); //dig數(shù)值按位向左 1 位帶循環(huán)(如1110-1101-1011-0111-1110)
- led++; //在這里實現(xiàn)led = 0、1、2、3,從而實現(xiàn)動態(tài)循環(huán)顯示
- if(led==4) //led只有 0、1、2、3 四位,分別對應buf[]的值,根據(jù)此值查表table[]
- {
- led=0;
- dig=0xfe;
- }
- }
- void main()
- {
- TMOD=0x01; //T0計數(shù)器工作在模式1
- TH0=0x3C; //定時50000毫秒
- TL0=0xB0; //定時50000毫秒
- EA=1; //開總中斷
- ET0=1; //定時器T0溢出中斷允許(溢出中斷必須開啟,否則無法計數(shù))
- TR0=1; //啟動定時器T0
- EX0=1; //T0的外部中斷允許
- EX1=1; //T1的外部中斷允許
- P1=0Xf3; // P1口低四位0011,對應南北紅燈亮,東西黃燈亮
- while(1)
- {
- key(); //調(diào)用按鍵掃描程序
- display(); //調(diào)用顯示程序
- }
- }
- void T0_server() interrupt 1 //T0中斷服務程序
- {
- b++;
- if(b==10) // 定時器中斷次數(shù)。
- {
- b=0;
- sec_dx--;
- sec_nb--;
- //南北黃燈閃爍判斷
- if(sec_nb==3&&time==0)
- {
- yellowled_nb=1;//南北黃燈亮
- delay(300);
- yellowled_nb=0;
- }
- if(sec_nb==2&&time==0)
- {
- yellowled_nb=1;//南北黃燈亮
- delay(300);
- yellowled_nb=0;
- }
- if(sec_nb==1&&time==0)
- {
- yellowled_nb=1;//南北黃燈亮
- delay(300);
- yellowled_nb=0;
- }
- //東西黃燈閃判斷
- if(sec_dx==3&&time==1)
- {
- yellowled_dx=1;//南北黃燈亮
- delay(300);
- yellowled_dx=0;
- }
- if(sec_dx==2&&time==1)
- {
- yellowled_dx=1;//南北黃燈亮
- delay(300);
- yellowled_dx=0;
- }
- if(sec_dx==1&&time==1)
- {
- yellowled_dx=1;//南北黃燈亮
- delay(300);
- yellowled_dx=0;
- }
- if(sec_dx==0||sec_nb==0) //東西或南北先到達1S時即開始重新計時
- {
- sec_dx=settime_dx;
- sec_nb=settime_nb; //第一次循環(huán)結(jié)束重置
- if(time==1) //借助time 實現(xiàn)判斷東西通行還是南北通行
- {
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
基于51單片機交通燈的設(shè)計.zip
(94.47 KB, 下載次數(shù): 32)
2020-5-29 16:48 上傳
點擊文件名下載附件
|