# 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  阅读(2170)  评论(0编辑  收藏  举报