51单片机交通灯(定时器+38译码器+中断)

51单片机交通灯这个实例主要用到的知识点有:

>如何点亮LED

>38译码器位选与段选

>定时器控制

>中断控制

#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();                
        }
    }
}

 

posted @ 2018-06-10 21:11  ghostwu  阅读(2724)  评论(0编辑  收藏  举报
Copyright ©2017 ghostwu