51單片機交通燈(定時器+38譯碼器+中斷)

51單片機交通燈這個實例主要用到的知識點有:git

>如何點亮LEDspa

>38譯碼器位選與段選code

>定時器控制blog

>中斷控制it

#include <reg52.h>

/************ 交通燈 ***********/

#define GPIO_DIG P0  //數碼管顯示交通燈等待的時間
#define GPIO_TRAFFIC    P1 //定義交通燈

sbit RED10 = P1^0;                //上面的人行道紅燈
sbit GREEN10 = P1^1;             //上面的人行道綠燈
sbit RED11 = P1^2;                //上面的機動車通行紅燈
sbit YELLOW11 = P1^3;            //上面的機動車通行黃燈
sbit GREEN11 = P1^4;                //上面的機動車通行綠燈

sbit RED00 = P3^0;                //右邊的人行道紅燈
sbit GREEN00 = P3^1;             //右邊的人行道綠燈
sbit RED01 = P1^5;                //右邊的機動車通行紅燈
sbit YELLOW01 = P1^6;            //右邊的機動車通行黃燈
sbit GREEN01 = P1^7;                //右邊的機動車通行綠燈

//38譯碼器的位選輸入端
sbit A1 = P2^2;
sbit B1 = P2^3;
sbit C1 = P2^4;

typedef unsigned int u16;
typedef unsigned char u8;

u16 second = 1;

void timer_init(){
    TMOD |= 0x01;
      //定時器工做方式1,啓用T0定時器, GATE位爲0,用TCON的TR0控制T0定時器的啓動
    //設置定時器的初始計數值
    //計算方法
    //假設定時器爲1ms,一個機器週期爲 1/單片機的晶振頻率  即: 1/12M = 1us
    //而1個機器週期 = 12個時鐘週期 因此: n x 機器週期 = 1ms ===> n x 1us = 1ms
    //因此n = 1000,也就是通過1000個機器週期,定時器要溢出(從0開始計數)
    //因此定時器的初始值爲65535 - 1000 + 1 = 64536 ===> 0xFC18
    TH0 = 0xFC;  //計時器初始值的高8位
    TL0 = 0x18;  //計時器初始值的低8位
    EA = 1;  //總中斷開關
    ET0 = 1; //T0中斷
    TR0 = 1;//啓動T0定時器
}

void delay( u16 i ) {
    while( i-- );
}

void trigger_timer() interrupt 1{
    static u16 i = 0;
    TH0 = 0xFC;
    TL0 = 0x18;
    i++;
    if( i == 1000 ) { //1秒
        i = 0;
        second++;
    }
}

u8 digital[16] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 
                        0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c,
                        0x39, 0x5e, 0x79, 0x71 };
u8 DisplayData[8];

void showDigital(){
    int i = 0;
    for ( i = 0; i < 8; i++ ) {
        switch( i ) {
            case 0:  //位選第一個數碼管
                A1 = 0x0; B1 = 0x0; C1 = 0x0;
                break;
            case 1:
                A1 = 0x1; B1 = 0x0; C1 = 0x0;
                break;
            case 2:
                A1 = 0x0; B1 = 0x1; C1 = 0x0;
                break;
            case 3:
                A1 = 0x1; B1 = 0x1; C1 = 0x0;
                break;
            case 4:
                A1 = 0x0; B1 = 0x0; C1 = 0x1;
                break;
            case 5:
                A1 = 0x1; B1 = 0x0; C1 = 0x1;
                break;
            case 6:
                A1 = 0x0; B1 = 0x1; C1 = 0x1;
                break;
            case 7:
                A1 = 0x1; B1 = 0x1; C1 = 0x1;
                break;
        }
        GPIO_DIG = DisplayData[ i ];
        delay( 100 );
        GPIO_DIG = 0x00; //消隱
    }
}

void main(){
    u8 shiwei = 0, gewei = 0;
    timer_init();
    while( 1 ){
        if( second == 70 ) {  //紅綠燈總共70秒 而後輪迴
            second = 1;
        }
        
        if( second < 31 ) {
            DisplayData[0] = 0x00;  //數碼管1顯示的數字
            DisplayData[1] = 0x00;  //數碼管2顯示的數字
            shiwei = ( 30 - second ) % 100 / 10;
            gewei = ( 30 - second ) % 10;
            DisplayData[2] = digital[ shiwei ];
            DisplayData[3] = digital[ gewei ];

            DisplayData[4] = 0x00;  //數碼管5顯示的數字
            DisplayData[5] = 0x00;  //數碼管6顯示的數字
            DisplayData[6] = DisplayData[2];
            DisplayData[7] = DisplayData[3];

            //寶田路通行
            GPIO_TRAFFIC = 0xFF; //熄滅全部的燈
            RED00 = 1;
            GREEN00 = 1;

            GREEN11 = 0; //寶田路綠燈亮
            RED10 = 0;   //寶田路人行道 紅燈亮
            
            GREEN00 = 0; //前進路人行道綠燈亮
            RED01 = 0;    //前進路紅燈亮

            showDigital();
        } else if ( second < 36 ){  //黃燈切換

            DisplayData[0] = 0x00;  //數碼管1顯示的數字
            DisplayData[1] = 0x00;  //數碼管2顯示的數字
            shiwei = ( 35 - second ) % 100 / 10;
            gewei = ( 35 - second ) % 10;
            DisplayData[2] = digital[ shiwei ];
            DisplayData[3] = digital[ gewei ];

            DisplayData[4] = 0x00;  //數碼管5顯示的數字
            DisplayData[5] = 0x00;  //數碼管6顯示的數字
            DisplayData[6] = DisplayData[2];
            DisplayData[7] = DisplayData[3];

            //寶田路黃燈切換
            GPIO_TRAFFIC = 0xFF; //熄滅全部的燈
            RED00 = 1;
            GREEN00 = 1;

            YELLOW11 = 0; //寶田路黃燈亮
            RED10 = 0;   //寶田路人行道 紅燈亮
            
            GREEN00 = 0; //前進路人行道綠燈亮
            RED01 = 0;    //前進路紅燈亮

            showDigital();            
        } else if ( second < 66 ){  //前進路通行
        
            DisplayData[0] = 0x00;  //數碼管1顯示的數字
            DisplayData[1] = 0x00;  //數碼管2顯示的數字
            shiwei = ( 65 - second ) % 100 / 10;
            gewei = ( 65 - second ) % 10;
            DisplayData[2] = digital[ shiwei ];
            DisplayData[3] = digital[ gewei ];

            DisplayData[4] = 0x00;  //數碼管5顯示的數字
            DisplayData[5] = 0x00;  //數碼管6顯示的數字
            DisplayData[6] = DisplayData[2];
            DisplayData[7] = DisplayData[3];

            //前進路通行
            GPIO_TRAFFIC = 0xFF; //熄滅全部的燈
            RED00 = 1;
            GREEN00 = 1;
            
            GREEN01 = 0; //前進路綠燈亮
            RED00 = 0;   //前進路人行道 紅燈亮
            
            GREEN10 = 0; //寶田路人行道綠燈亮
            RED11 = 0;    //寶田路紅燈亮

            showDigital();    
        } else {   //黃燈切換
            DisplayData[0] = 0x00;  //數碼管1顯示的數字
            DisplayData[1] = 0x00;  //數碼管2顯示的數字
            shiwei = ( 70 - second ) % 100 / 10;
            gewei = ( 70 - second ) % 10;
            DisplayData[2] = digital[ shiwei ];
            DisplayData[3] = digital[ gewei ];

            DisplayData[4] = 0x00;  //數碼管5顯示的數字
            DisplayData[5] = 0x00;  //數碼管6顯示的數字
            DisplayData[6] = DisplayData[2];
            DisplayData[7] = DisplayData[3];

            //前進路通行
            GPIO_TRAFFIC = 0xFF; //熄滅全部的燈
            RED00 = 1;
            GREEN00 = 1;
            
            YELLOW01 = 0; //前進路黃燈亮
            RED00 = 0;   //前進路人行道 紅燈亮
            
            GREEN10 = 0; //寶田路人行道綠燈亮
            RED11 = 0;    //寶田路紅燈亮

            showDigital();                
        }
    }
}
相關文章
相關標籤/搜索