/******************************************************************************* 交通灯 ***********************************************************************************/ #include <reg51.h> #include <intrins.h> sbit LS138A = P2^2; //定义138译码器的输入A脚由P2.2控制 sbit LS138B = P2^3; //定义138译码器的输入脚B由P2.3控制 sbit LS138C = P2^4; //定义138译码器的输入脚C由P2.4控制 sbit BEEP = P1^5; char ch; bit read_flag= 0 ; //红绿灯 sbit L0_1 = P1^0; sbit L0_2 = P1^1; sbit L1_1 = P1^2; sbit L1_2 = P1^3; sbit L2_1 = P1^4; sbit L2_2 = P1^5; sbit L3_1 = P1^6; sbit L3_2 = P1^7; void delay(unsigned int i); //延时 void InitTimer(); //初始化定时器设置 void InitSerialInt(); //初始化中断 void SetStartTime(int pos, int time_1, int time_2); //设置各个数码管的倒计时开始时间 void SetLights(int time, int group); //亮灯设置 char DelayCNT = 0; int SecondCounts = 0; //每秒自增1,到100时重新回到0 int counter = 0; //辅助定时器实现 int start_time_1[4] = {99, 99, 99, 99}; //各个数码管的倒计时开始时间 int start_time_2[4] = {99, 99, 99, 99}; unsigned char timer_1[4] = {99, 99, 99, 99}; unsigned char timer_2[4] = {99, 99, 99, 99}; unsigned char show_1[4] = {99, 99, 99, 99}; unsigned char show_2[4] = {99, 99, 99, 99}; //此表为 LED 的字模, 共阴数码管 0-9 - unsigned char code Disp_Tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //标记灯的颜色 unsigned char color[4] = {0, 1, 0, 1}; char WillShine[4] = {0, 0, 0, 0}; //是否需要闪烁 char ShineCounter[4] = {0, 0, 0, 0};//闪烁计数器 /************主函数**********************/ main() { static int last = -1; unsigned int i, LedNumVal/*led要显示的两位数值*/ = 0; unsigned int LedOut[10]; int starttime = 0; //设置数码管计数初值 SetStartTime(0, 7, 8); SetStartTime(1, 8, 7); SetStartTime(2, 7, 8); SetStartTime(3, 8, 7); InitSerialInt(); InitTimer(); while(1) //进入循环状态 { if (RI) //RI接受中断标志 { RI=0; //清除RI接受中断标志 delay(10000); } LedNumVal = color[0] ? show_1[0] : show_2[0]; LedOut[0]=Disp_Tab[LedNumVal / 10]; LedOut[1]=Disp_Tab[LedNumVal % 10]|0x80; SetLights(LedNumVal, 0); LedNumVal = color[1] ? show_1[1] : show_2[1]; LedOut[2]=Disp_Tab[LedNumVal / 10]; LedOut[3]=Disp_Tab[LedNumVal % 10]|0x80; SetLights(LedNumVal, 1); LedNumVal = color[2] ? show_1[2] : show_2[2]; LedOut[4]=Disp_Tab[LedNumVal / 10]; LedOut[5]=Disp_Tab[LedNumVal % 10]|0x80; SetLights(LedNumVal, 2); LedNumVal = color[3] ? show_1[3] : show_2[3]; LedOut[6]=Disp_Tab[LedNumVal / 10]; LedOut[7]=Disp_Tab[LedNumVal % 10]|0x80; SetLights(LedNumVal, 3); for( i=0; i<9; i++) //实现8位动态扫描循环 { P0 = LedOut[i]; //将字模送到P0口显示 switch(i) //使用switch 语句控制位选 { case 0:LS138A=0; LS138B=0; LS138C=0; break; case 1:LS138A=1; LS138B=0; LS138C=0; break; case 2:LS138A=0; LS138B=1; LS138C=0; break; case 3:LS138A=1; LS138B=1; LS138C=0; break; case 4:LS138A=0; LS138B=0; LS138C=1; break; case 5:LS138A=1; LS138B=0; LS138C=1; break; case 6:LS138A=0; LS138B=1; LS138C=1; break; case 7:LS138A=1; LS138B=1; LS138C=1; break; } delay(5); } } } /*************************************************************************** * * * 延时程序 * ****************************************************************************/ void delay(unsigned int i) { char j; for(i; i > 0; i--) for(j = 200; j > 0; j--); } //初始化定时器0设置 void InitTimer() { //TMOD|=0x01;//定时器设置 16位 TMOD|= 0x21; TH0 = (65536 - 50000) / 256; TL0 = (65536 - 50000) % 256; ET0=1; TR0=1; EA=1; } //定时器的中断响应 //每秒 SecondCounts 自增1,最大到10 void Timer() interrupt 1 using 1 { int n = 0; TH0 = (65536 - 50000) / 256; TL0 = (65536 - 50000) % 256; //计算各数码管的值 if(++counter == 20) { counter = 0; SecondCounts++; if(SecondCounts == 100) SecondCounts = 0; for(; n < 4; n++) { if(color[n]) { timer_1[n]--; if(timer_1[n] == -1) color[n] = !color[n]; timer_2[n] = start_time_2[n]; show_2[n] = timer_2[n]; if(timer_1[n] > 3) show_1[n] = timer_1[n] - 3; else show_1[n] = timer_1[n]; } else { timer_2[n]--; show_2[n] = timer_2[n]; if(timer_2[n] == -1) color[n] = !color[n]; timer_1[n] = start_time_1[n]; show_1[n] = timer_1[n] - 3; } } } for(n = 0; n < 4; n++) { if(timer_1[n] < 4) { switch(n) { case 0: L0_1 = !L0_1; L0_2 = !L0_2; break; case 1: L1_1 = !L1_1; L1_2 = !L1_2; break; case 2: L2_1 = !L2_1; L2_2 = !L2_2; break; case 3: L3_1 = !L3_1; L3_2 = !L3_2; break; } } } } //设置各个数码管的倒计时开始时间 void SetStartTime(int pos, int time_1, int time_2) { start_time_1[pos] = time_1; timer_1[pos] = time_1; show_1[pos] = time_1 - 3; start_time_2[pos] = time_2; timer_2[pos] = time_2; show_2[pos] = time_2; } //亮灯设置 void SetLights(int time, int group) { switch(group) { case 0: L0_1 = color[group]; L0_2 = !color[group]; break; case 1: L1_1 = color[group]; L1_2 = !color[group]; break; case 2: L2_1 = color[group]; L2_2 = !color[group]; break; case 3: L3_1 = color[group]; L3_2 = !color[group]; break; } } //初始化中断 void InitSerialInt() { SCON = 0x50 ; //SCON: serail mode 1, 8-bit UART, enable ucvr //UART为模式1,8位数据,允许接收 TMOD |= 0x20 ; //TMOD: timer 1, mode 2, 8-bit reload //定时器1为模式2,8位自动重装 PCON |= 0x80 ; //SMOD=1; TH1 = 0xF3; // //baud*2 /* 波特率4800、数据位8、停止位1。效验位无 (12M) IE |= 0x90 ; //Enable Serial Interrupt TR1 = 1 ; // timer 1 run TI=1; } /**************************************************** 串口中断程序 ******************************************************/ void ser_int (void) interrupt 4 using 1 { static int n = 0; int i = 0; if (RI) { RI = 0 ; ch=SBUF; switch(n) { case 0: start_time_1[0] = ch;break; case 1: start_time_1[0] = start_time_1[0]*10 + ch;break; case 2: start_time_1[1] = ch;break; case 3: { start_time_1[1] = start_time_1[1]*10 + ch; start_time_1[2] = start_time_1[0]; start_time_1[3] = start_time_1[1]; start_time_2[0] = start_time_2[2] = start_time_1[1]; start_time_2[1] = start_time_2[3] = start_time_1[0]; for(; i < 4; i++) { timer_1[i] = start_time_1[i]; timer_2[i] = start_time_2[i]; show_1[i] = start_time_1[i]; show_2[i] = start_time_2[i]; WillShine[i] = 0; ShineCounter[i] = 0; } color[0] = color[2] = 0; color[1] = color[3] = 1; } n = -1; break; } n++; read_flag= 1 ; //就置位取数标志 } }