標(biāo)題: 51單片機(jī)交通燈項(xiàng)目(Proteus仿真及源碼) [打印本頁(yè)]

作者: 靈夢(mèng)hc    時(shí)間: 2019-10-20 09:31
標(biāo)題: 51單片機(jī)交通燈項(xiàng)目(Proteus仿真及源碼)
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


摘 要... I
一、設(shè)計(jì)要求以及總體方案介紹... 1
1.2交通燈總體方案介紹... 1
1.3元件清單... 2
二、交通燈各模塊及程序設(shè)計(jì)... 2
2.1數(shù)碼管顯示模塊... 3
2.2紅綠燈模塊... 6
2.3按鍵模塊... 6
三、仿真與部分實(shí)物演示... 8
3.1南北通行... 8
3.2東西通行... 8
3.3夜間模式... 8
設(shè)計(jì)心得... 9
附 錄... 10

為了節(jié)省按鍵占用的I/O口,也為了去除查詢按鍵的時(shí)間占用,減輕CPU的負(fù)擔(dān),所以按鍵使用外部中斷的方式,通過(guò)74HC573擴(kuò)展中斷。此時(shí)只需要使用三個(gè)I/O口,使用中斷的好處是只有觸發(fā)中斷時(shí)程序才回去執(zhí)行按鍵功能,增加了程序運(yùn)行的效率。
具體內(nèi)容見(jiàn)交通燈壓縮包,附有源代碼,仿真文件,仿真實(shí)物視頻


1、東西方向、南北方向均有紅、黃、綠三種信號(hào)燈,初始紅燈
30秒,黃燈閃爍3秒,綠燈30秒,東西方向紅燈時(shí)刻,南北方向綠燈,南北方向綠燈,東西方向紅燈;
2、按鍵調(diào)節(jié)與控制功能,通過(guò)按鍵,可以控制某一個(gè)方向長(zhǎng)時(shí)間綠燈,另一個(gè)方向長(zhǎng)時(shí)間紅燈;通過(guò)按鍵可以調(diào)整某一個(gè)方向的紅燈時(shí)長(zhǎng),比如調(diào)整東西方向紅燈40秒,綠燈20秒,于此同時(shí),南北方向紅燈20秒,綠燈40秒。
3、夜間模式按鈕按下,所有方向顯示黃燈閃爍
4、實(shí)時(shí)提醒燈亮的剩余時(shí)間
1.2 交通燈總體方案介紹
初始狀態(tài):東西方向綠燈,南北紅燈,南北時(shí)間為13秒,東西方向?yàn)?0秒。
while循環(huán):有按鍵檢測(cè)函數(shù),有按鍵執(zhí)行程序;數(shù)碼管顯示函數(shù)。
定時(shí)器T0中斷函數(shù):計(jì)時(shí)時(shí)間為50ms,當(dāng)計(jì)時(shí)20次計(jì)時(shí)變量加到20后清零,時(shí)間為1s,此時(shí)讓數(shù)碼管顯示的數(shù)自減,判斷紅綠燈的狀態(tài)是否需要改變。
外部中斷0中斷函數(shù):將標(biāo)志變量flag置1,并讀取P2口的值,用以判斷按鍵按下。

1.3 原件清單

  名稱
  
型號(hào)
數(shù)量
  單片機(jī)
  
STC89C52RC

  排阻
  
10k/4.7K
1
  發(fā)光二極管
  
紅黃綠
4/4/4
  晶振
  
12MHZ
1
  電容
  
10uf  30pf
1/2
  電阻
  
10K/1K/0.33K
4/7/14
  按鍵
  
4
7
  數(shù)碼管
  
兩位八段
4
  74HC573/74LS148
  

2/1
  導(dǎo)線
  
15cm
若干
  杜邦線
  
15cm/10cm
若干
  焊錫
  

若干
  單排插針
  
SIP20
若干
  DIP40芯片座子
  


1
  DC插座
  

1
  US轉(zhuǎn)DC002電源線
  

1
  三極管
  
S9012
4
  萬(wàn)用板  
  
7*9cm/9*15cm
1/1
、交通燈各模塊
2.1 數(shù)碼管顯示模塊
對(duì)于共陰極數(shù)碼管來(lái)說(shuō),當(dāng)某個(gè)發(fā)光二極管的陽(yáng)極為高電平時(shí),發(fā)光二極管點(diǎn)亮,相應(yīng)的段被顯示。同樣,共陽(yáng)極數(shù)碼管的陽(yáng)極連接在一起,公共陽(yáng)極接+5V,當(dāng)某個(gè)發(fā)光二極管的陰極接低電平時(shí),該發(fā)光二極管被點(diǎn)亮,相應(yīng)的段被顯示。共陰極數(shù)碼
管是把所有l(wèi)ed的陰極連接到共同接點(diǎn)COM,而每個(gè)led的陽(yáng)極分別為A、B、C、D、E、F、G及DP(小數(shù)點(diǎn)),如下圖所示。圖中的8個(gè)led分別與A~DP各段相對(duì)應(yīng),通過(guò)控制各個(gè)led的亮滅來(lái)顯示數(shù)字。
由于對(duì)面的數(shù)碼管的顯示是相同的,所以將相對(duì)的數(shù)碼管的位選端接在一起,當(dāng)需要顯示數(shù)字時(shí)同時(shí)選中個(gè)位或十位,實(shí)現(xiàn)同時(shí)顯示。
其中數(shù)碼管的顯示用到了74HC573鎖存器,數(shù)碼管的段選端連在鎖存器的輸出端,東西南北的數(shù)碼管一共用了四個(gè)位選(因?yàn)橄鄬?duì)的位選連在了一起,所以共四個(gè))并連接在第二個(gè)鎖存器的輸出端。如圖所示:

U2為段選鎖存器,U3為位選鎖存器。由于是共陰極數(shù)碼管,當(dāng)數(shù)碼管亮起時(shí)位選端的電流為幾個(gè)LED的電流之和,設(shè)每個(gè)數(shù)碼管段的驅(qū)動(dòng)電流為10ma—15ma,則位選端的電流會(huì)很大,如果直接導(dǎo)入鎖存器的引腳可能會(huì)損壞引腳或減小鎖存器的壽命。為了減小導(dǎo)入鎖存器引腳的電流,采用三極管將位選端的大部分電流導(dǎo)入GND,極小的電流會(huì)導(dǎo)入鎖存器的引腳,從而解決了該問(wèn)題。以下是三極管電路:
還有就是U2的輸入端和U3的輸入端都是接P0口,在顯示數(shù)碼管時(shí)需要切換使能兩個(gè)鎖存器。其中U2的輸出端直接接在數(shù)碼管上時(shí)可能會(huì)產(chǎn)生較大的電流,使數(shù)碼管段燒毀,所以需要串聯(lián)一個(gè)限流電阻。
設(shè)置數(shù)碼管段的驅(qū)動(dòng)電流為ID=15ma,這個(gè)電流點(diǎn)亮度好,并且有一定的裕度,即使電源輸出電壓偏高也不會(huì)燒毀LED,限流電阻值
R = (VCC-VCE– VOL– VLED) / ID
VCC為5v供電,VCE為三極管C、E間飽和電壓,估為0.2v,VOL為74hc573輸出低電平時(shí)電壓,不同灌電流,此值不一樣,估為0.2v,具體查看規(guī)格書(shū),VLED為紅光驅(qū)動(dòng)電壓,估為1.7v,根據(jù)上式可算出限流電阻為R= 200R。為保險(xiǎn)起見(jiàn)選用330歐姆的電阻,電流大概在10ma—15ma。
為了數(shù)碼管的倒計(jì)時(shí)為準(zhǔn)確倒計(jì)時(shí),所以不能采用平時(shí)的delay方法,而是要用更精確的定時(shí)器來(lái)實(shí)現(xiàn)倒計(jì)時(shí)。在定時(shí)器T0中斷中的主要工作是將數(shù)碼管要顯示的數(shù)字變量每隔一秒自減,然后根據(jù)情況使顯示數(shù)字變量做相應(yīng)的變化。
2.2 紅綠燈模塊
首先要了解紅綠燈的亮滅規(guī)則:假設(shè)南北紅燈,東西綠燈,南北的時(shí)間為13秒,東西時(shí)間為10秒。然后開(kāi)始倒計(jì)時(shí),當(dāng)東西倒計(jì)時(shí)為1秒時(shí),此時(shí)南北為4秒,下一秒東西變?yōu)?秒(和此時(shí)的南北一樣),然后東西黃燈每隔一秒閃爍一次,兩個(gè)方向同時(shí)倒計(jì)時(shí),當(dāng)時(shí)間減為0時(shí)南北變?yōu)榫G燈,東西變?yōu)榧t燈。南北的時(shí)間為開(kāi)始設(shè)置的通行時(shí)間(假設(shè)南北的通行時(shí)間為15秒),則東西從18秒(15+3)開(kāi)始倒計(jì)時(shí)(因?yàn)辄S燈的閃爍時(shí)間為3秒,所以紅燈時(shí)間=綠燈時(shí)間+黃燈時(shí)間)。然后后面和前面的過(guò)程一樣。
為了讓紅綠燈能準(zhǔn)確的按照準(zhǔn)確的“秒”去亮滅,所以此處也要采用定時(shí)器來(lái)實(shí)現(xiàn)。通過(guò)代碼實(shí)現(xiàn)以上功能,代碼見(jiàn)附錄。
2.3 按鍵模塊
為了讓交通燈實(shí)現(xiàn)所要求的功能,則需要加獨(dú)立按鍵實(shí)現(xiàn)。該項(xiàng)目一共使用了七個(gè)按鍵,每一個(gè)按鍵都對(duì)應(yīng)一個(gè)特定的功能。如第一個(gè)按鍵(南北通行):此時(shí)需要將定時(shí)器關(guān)閉,定時(shí)器不再計(jì)數(shù),通過(guò)P1口控制南北綠燈亮,東西紅燈亮,并改變顯示標(biāo)志位,關(guān)閉數(shù)碼管;第二個(gè)按鍵(東西通行):如第一個(gè)按鍵的功能做細(xì)微改變;第三個(gè)按鍵(夜間模式):此按鍵按下時(shí),關(guān)閉定時(shí)器,改變顯示標(biāo)志位,關(guān)閉數(shù)碼管,并在while循環(huán)中判斷此按鍵,實(shí)現(xiàn)黃燈閃爍。第四位和第五位(加減時(shí)間):第四位減時(shí)間,第五位加時(shí)間,負(fù)責(zé)加減南北通行時(shí)間(最低減到00,最高加到99),按下時(shí)定時(shí)器停止計(jì)數(shù),交通燈熄滅,計(jì)數(shù)變量加或減;第六個(gè)按鍵和第七個(gè)按鍵:第七個(gè)按鍵為切換按鍵,按下時(shí)南北方向切換為東西方向,此時(shí)加減時(shí)間為東西方向,一次類推:第六個(gè)按鍵為確認(rèn)鍵,調(diào)整完時(shí)間后按下此鍵交通燈開(kāi)始運(yùn)行。(具體程序見(jiàn)附錄)

單片機(jī)源程序如下:
  1. #include<reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. sbit dula=P3^6;          //段選鎖存器鎖存端
  5. sbit wela=P3^7;          //位選鎖存器鎖存端

  6. uchar time1=13;  //初值南北13秒
  7. uchar time2=10;  //初值東西10秒
  8. uchar t1=13,t2=10,chose=0;
  9. uchar time1_2,temp=0,p=0,tab;
  10. uchar shi1,ge1,shi2,ge2,q;
  11. uchar status,key,flag;

  12. //共陰極數(shù)字顯示編碼
  13. uchar code table[]={0x3f,0x06,0x5b,0x4f,
  14.                        0x66,0x6d,0x7d,0x07,
  15.                        0x7f,0x6f};
  16. uchar code wei[]={0xfd,0xfe,0xf7,0xfb,
  17.                                   0xdf,0xef,0x7f,0xbf}; //位選

  18. void delay(uint x)
  19. {
  20.                 uint i,j;
  21.                 for(i=x;i>0;i--)                        //定時(shí)x毫秒
  22.                         for(j=110;j>0;j--);
  23. }
  24. void display(uint ge1,uint shi1,uint ge2,uint shi2)        //數(shù)碼管顯示
  25. {
  26.         //顯示北
  27.         wela=1; //打開(kāi)位選鎖存器
  28.         P0=wei[0];        //送入位選碼(北個(gè)位)
  29.         wela=0; //關(guān)閉位選鎖存器
  30.         P0=0;  //消影
  31.         dula=1; //打開(kāi)段選鎖存器
  32.         P0=table[ge1]; //送入段選
  33.         dula=0;        //關(guān)閉段選鎖存器
  34.         delay(1);

  35.         wela=1; //打開(kāi)位選鎖存器
  36.         P0=wei[1];        //送入位選碼(北十位)
  37.         wela=0; //關(guān)閉位選鎖存器
  38.         P0=0;
  39.         dula=1; //打開(kāi)段選鎖存器
  40.         P0=table[shi1]; //送入段選
  41.         dula=0;        //關(guān)閉段選鎖存器
  42.         delay(1);

  43.         //顯示東西
  44.         wela=1; //打開(kāi)位選鎖存器
  45.         P0=wei[2];        //送入位選碼(東個(gè)位)
  46.         wela=0; //關(guān)閉位選鎖存器
  47.         P0=0;
  48.         dula=1; //打開(kāi)段選鎖存器
  49.         P0=table[ge2];
  50.         dula=0;        //關(guān)閉段選鎖存器
  51.         delay(1);

  52.         wela=1; //打開(kāi)位選鎖存器
  53.         P0=wei[3];        //送入位選碼(東十位)
  54.         wela=0; //關(guān)閉位選鎖存器
  55.         P0=0;        
  56.         dula=1; //打開(kāi)段選鎖存器
  57.         P0=table[shi2];
  58.         dula=0;        //關(guān)閉段選鎖存器
  59.         delay(1);
  60. }
  61. void key1_6()
  62. {
  63.         //第一個(gè)按鍵(南北通行)
  64.         if(key==1)
  65.         {
  66.                 TR0=0;  //定時(shí)器0停止計(jì)時(shí)
  67.                 P1=0x0c; //南北通行
  68.                 p=1;        //數(shù)碼管顯示99
  69.         }
  70.         //第二個(gè)按鍵(東西通行)
  71.         if(key==2)
  72.         {
  73.                 TR0=0;  //定時(shí)器0停止計(jì)時(shí)
  74.                 P1=0x21; //東西通行
  75.                 p=1;
  76.         }
  77.         //第三個(gè)按鍵(夜間模式)
  78.         if(key==3)
  79.         {
  80.                 TR0=0;  //關(guān)閉定時(shí)器
  81.                 p=1;
  82.         }
  83.         //第四個(gè)按鍵(減時(shí)間)
  84.         if(key==4)
  85.         {
  86.                 p=0;                        
  87.                 TR0=0;  //定時(shí)器0停止計(jì)時(shí)
  88.                 P1=0;        //燈滅
  89.                 if(chose==0)  //減南北方向
  90.                 {
  91.                         if(time1>0)          //最低減到0
  92.                         {
  93.                                 time1--;
  94.                                 t1=time1;
  95.                         }
  96.                 }
  97.                 if(chose==1)  //減東西方向
  98.                 {
  99.                         if(time2>0)
  100.                         {
  101.                                 time2--;
  102.                                 t2=time2;
  103.                         }
  104.                 }
  105.         }
  106.         //第五個(gè)按鍵(加時(shí)間)
  107.         if(key==5)
  108.         {
  109.                 p=0;
  110.                 TR0=0;  //定時(shí)器0停止計(jì)時(shí)
  111.                 P1=0;        //燈滅
  112.                 if(chose==0)  //加南北方向
  113.                 {
  114.                         if(time1<99)   //最多加到99
  115.                         {
  116.                                 time1++;
  117.                                 t1=time1;
  118.                         }
  119.                 }
  120.                 if(chose==1)  //加?xùn)|西方向
  121.                 {
  122.                         if(time2<99)
  123.                         {
  124.                                 time2++;
  125.                                 t2=time2;
  126.                         }
  127.                 }
  128.         }
  129.         //第六個(gè)按鍵(加減后確定工作)
  130.         if(key==6)
  131.         {
  132.                 if(time1>time2)
  133.                         time1=time2+3;
  134.                 else
  135.                         time2=time1+3;
  136.                 temp=0;         //計(jì)數(shù)值清零
  137.                 p=0;
  138.                 P1=0x21;  //南北紅燈,東西綠燈        
  139.                 TR0=1;  //定時(shí)器0開(kāi)始計(jì)時(shí)
  140.         }
  141.         //第七個(gè)按鍵(切換)
  142.         if(key==7)
  143.         {
  144.                 p=0;
  145.                 chose=!chose;  
  146.         }
  147. }
  148. void dis()
  149. {
  150.         wela=1;
  151.         P0=0xff;
  152.         wela=0;
  153. }         
  154. void main()
  155. {
  156.         P1=0x21;  //剛開(kāi)始南北的紅燈亮,東西的綠燈亮
  157.         TMOD=0x01;
  158.         TH0=(65535-50000)/256;
  159.         TL0=(65535-50000)%256;   //初值
  160.         EA=1;           //打開(kāi)總中斷
  161.         ET0=1;           //定時(shí)器0允許中斷
  162.         TR0=1;           //定時(shí)器0開(kāi)始計(jì)時(shí)
  163.         EX0=1;           //外部中斷0允許位
  164.         IT0=1;           //外部中斷0觸發(fā)方式(下降沿)
  165.         while(1)
  166.         {
  167.                 if(flag)
  168.                 {
  169.                         switch(status)                   //判斷按鍵
  170.                         {
  171.                                 case 0xfe:key=1;break;
  172.                                 case 0xfd:key=2;break;
  173.                                 case 0xfc:key=3;break;
  174.                                 case 0xfb:key=4;break;
  175.                                 case 0xfa:key=5;break;
  176.                                 case 0xf9:key=6;break;
  177.                                 case 0xf8:key=7;break;
  178.                         }
  179.                         key1_6();   //按鍵程序
  180.                         flag=0;
  181.                 }        
  182.                 if(!p)
  183.                 {
  184.                         shi1=time1/10;        //南北十位
  185.                         ge1=time1%10;        //南北個(gè)位
  186.                         shi2=time2/10;        //東西十位
  187.                         ge2=time2%10;        //東西個(gè)位        
  188.                         display(ge1,shi1,ge2,shi2); //顯示函數(shù)
  189.                 }
  190.             if(p)
  191.                         dis();         //不顯示函數(shù)
  192.                 if(key==3)          //夜間模式
  193.                 {
  194.                         P0=0xff;
  195.                         q=!q;
  196.                         if(q!=0)
  197.                                 P1=0x12;
  198.                         else
  199.                                 P1=0;
  200.                         delay(200);
  201.                 }
  202.         }  
  203. }         
  204. void ext0() interrupt 0
  205. {
  206.         flag=1;
  207.         status=P2;        
  208. }
  209. void timer() interrupt 1   //定時(shí)中斷程序
  210. {
  211.         TH0=(65535-50000)/256;
  212.         TL0=(65535-50000)%256;                //重新賦初值
  213.         temp++;
  214.         if(temp==20)   //說(shuō)明過(guò)去了1秒
  215.         {
  216.                 temp=0;   //清零,重新加到20
  217.                 //東西方向南北方向時(shí)間自減
  218.                 time1--;
  219.                 time2--;
  220.                 if(time1>time2)        //南北大于東西
  221.                 {
  222.                         time1=time2+3;
  223.                         P1=0x21;        //南北紅燈亮起,東西綠燈亮起
  224.                         if(time2==0&&time1==3)  
  225.                         {
  226.                                 time2=3;  //重新賦南北和東西的差值,與南北方向一起倒計(jì)時(shí)
  227.                                 P1=0x11;  //東西黃燈亮起,東西綠燈關(guān)閉
  228.                                 tab=0;         //標(biāo)志位
  229.                         }        
  230.                 }
  231.                 if(time1<time2)        //南北小于東西
  232.                 {        
  233.                         time2=time1+3;               
  234.                         P1=0x0c;        //南北綠燈亮起,東西紅燈亮起
  235.                         if(time1==0&&time2==3)  
  236.                         {
  237.                                 time1=3;  //重新賦南北和東西的差值,與東西方向一起倒計(jì)時(shí)
  238.                                 P1=0x0a;  //南北黃燈亮起,南北綠燈關(guān)閉
  239.                                 tab=1;        //標(biāo)志位
  240.                         }        
  241.                 }
  242.                 if(!tab)                   //黃燈閃爍三秒
  243.                 {
  244.                         if(time1==2&&time2==2)
  245.                                 P1=0x01;
  246.                         if(time1==1&&time2==1)
  247.                                 P1=0x11;
  248.                 }
  249.                 if(tab)
  250.                 {
  251.                         if(time1==2&&time2==2)
  252.                                 P1=0x08;
  253.                         if(time1==1&&time2==1)
  254.                                 P1=0x0a;
  255.                 }        
  256.                 if(time1==0&&time2==0&&tab==0)  //東西倒計(jì)時(shí)結(jié)束
  257.                 {
  258.                         time1=t1;
  259.                         time2=t1+3;
  260.                         P1=0x0c;   //東西紅燈,南北綠燈
  261.                 }
  262.                 if(time1==0&&time2==0&&tab==1)  //南北倒計(jì)時(shí)結(jié)束
  263.                 {
  264.                         time1=t2+3;
  265.                         time2=t2;
  266.                         P1=0x21;   //南北紅燈,東西綠燈
  267.                 }        
  268.         }        
  269. }
復(fù)制代碼

所有資料51hei提供下載:
交通燈.zip (4.65 MB, 下載次數(shù): 547)


作者: lslsls    時(shí)間: 2019-11-15 21:20
很好,很強(qiáng)大,模式多樣。
作者: CHH724    時(shí)間: 2019-11-19 08:54
附件里面有仿真圖文件嗎
作者: duanjiagn110    時(shí)間: 2019-12-4 20:50
不行啊,數(shù)碼管數(shù)字一直在閃動(dòng),倒計(jì)時(shí)都不減少的
作者: zlh123456789    時(shí)間: 2020-5-31 16:53
里面的仿真文件沒(méi)有錯(cuò)誤吧
作者: 淡淡地    時(shí)間: 2020-6-1 12:54
樓主,貼里面有protues原理圖仿真文件嗎
作者: sxr2912719    時(shí)間: 2020-6-5 11:39
有用嗎??????
作者: WangSuNan1997    時(shí)間: 2020-10-15 16:26
謝謝樓主,不過(guò)仿真有問(wèn)題
作者: 清茶煮酒    時(shí)間: 2020-10-29 17:45
有仿真嗎
作者: 992039    時(shí)間: 2020-12-12 21:15
學(xué)習(xí)了,比我考慮的周全
作者: 莊周的小燕    時(shí)間: 2020-12-17 16:19
模式多樣。
作者: 123456shs    時(shí)間: 2021-1-3 20:42
模式真多




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1