51单片机实现交通信号灯的实验,我用51开发板上的LED8+LED9作为绿灯、LED5+LED6作为黄灯、LED2+LED3作为红灯。同时,我用两个数码管作为秒表的倒计时显示。实验现象是默认的是从39秒绿灯开始亮的,39秒过后切换到黄灯,3秒后又从黄灯切换到红灯。这个程序如果自己想搭建也是非常简单的,不管你是毕业设计还是业余爱好,都可以很完美的实现出来,做出一个属于自己的交通信号灯。你只要两个数码管和三个灯,就可以用以下程序实现出来,当然你需要稍微改下必要的代码参数,因为我这样用的是6个LED灯。如果你想改红绿灯的时间,改下里面参数就可以实现了。下面是详细代码。

#include<reg52.h>

sbit ADDR3=P1^3;
sbit ENLED=P1^4;

unsigned char code LedChar[]={  //数码管显示字符转换表
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E

};
unsigned char LedBuff[7] = {    //数码管+独立LED显示缓冲区
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
bit flag1s=1;
unsigned char T0RH=0;
unsigned char T0RL=0;

void ConfigTimer0(unsigned int ms);
void TrafficLight();

void main(){

	EA=1;        //开总中断	
	ENLED=0;     //使能数码管和LED
	ADDR3=1;
	ConfigTimer0(1);    //配置T0定时1ms
	
	while(1){
	    if(flag1s){    //每秒执行一次交通信号灯刷新
	        flag1s=0;
	        TrafficLight();
	    }
	}
    }
    
void ConfigTimer0(unsigned int ms){
    
    unsigned long tmp;        //临时变量
    tmp=11059200/12;           //定时器计数频率
    tmp=(tmp*ms)/1000;        //计算所需的计数值
    tmp=65536-tmp;            //计算定时器重载值
    tmp=tmp+18;                //补偿中断响应延时造成的误差
    T0RH=(unsigned char) (tmp>>8); //定时器重载值拆分为高低字节
    T0RL=(unsigned cahr) tmp;
    TMOD &=0xF0;        //清零To的控制位
    TMOD |=0x01;        //配置T0为模式1
    TH0 = T0RH;        //加载T0重载值
    TL0 = T0RL;
    ET0 = 1;            //使能T0中断
    TR0 = 1;            //启动T0
}
void TrafficLight(){

   static unsigned char color=2; //默认红灯
   static unsigned char timer = 0;
   
   if(timer==0){
       switch(color){
           case 0:        //绿灯亮
           color=1;
           timer=2;
           LedBuff[6]=0xE7;
           break;
           
           case 1:
           color=2;       //红灯亮
           timer=29;
           LedBuff[6]=0xFC;
           break;
           
           case 2:        
           color=0;        //切换到绿灯
           timer=39;
           LedBuff[6]=0x3F;
           break;
           
           default;
           break;
           
       }
   }else{
       timer--;
   }
   LedBuff[0]=LedChar[timer%10];
   LedBuff[1]=LedChar[timer/10];
    
}

void LedScan(){
    
    static unsigned char i=0;        //动态扫描索引
    P0 = 0xFF;                    //关闭所有段选位,显示消隐
    P1 = (P1 & 0xF8) |i;        //位选索引值赋值到P1口低3位
    P0 = LedBuff[i];            //缓冲区索引违章的数据送到P0口    
    if(i<6)                       //索引递增循环,遍历整个缓冲区
        i++;
    else
        i=0;
}

void InterruptTimer0() interrupt 1{
    
    static unsigned int tmr1s=0;        //1秒定时器
    TH0 = T0RH;        //重新加载重载值
    TL0 = T0RL;
    LedScan();        //LED扫描显示
    tmr1s++;        //1秒定时器处理
    if(tmr1s>=1000){
        tmr1s=0;
        flag1s=1;    //设置秒定时标志
    }
}