一、设计要求
利用单片机的中断、定时器等功能,将定时器、中断的知识应用到交通信号灯控制系统中。要实现的功能是:正常交通信号灯模式为绿灯亮灯时间为30秒,黄灯亮灯时间为5秒,红灯亮灯时间为35秒,十字路口四个方向分别利用数码管显示倒计时数字,南北方向与东西方向交替执行。加入按键控制,按键1(K2)按下一次,实现倒计时加一,可重复执行;按键2(K3)按下一次,实现倒计时减一,可重复执行;按键3(K1)按下一次,实现倒计时设置确定和恢复正常交通信号灯模式;按键4(K4)按下,实现南北方向交通管制模式;按键5(K5)按下,实现东西方向交通管制模式;按键6(K6)按下,实现交警管制交通模式;按键7(K7)按下一次,实现可定时夜间交通模式;按键8(K8)按下一次,实现可定时优先主干道通行模式。按下K7和K8按键各一次,实现夜间至早高峰结束无人托管模式。
二、设计思路
(一)正常交通信号灯模式设计
1、倒计时数字显示设计
*在硬件电路方面,数码管采用4个两位七段共阴数码管,段码输入端与单片机输出段码端对应连接,公共端与单片机输出数码管动态显示信号端对应连接。
*在程序设计方面,定义一个全局变量 djs 作为倒计时数,将变量除以 10 得到数码管十位数字,变量取 10 的余得到数码管的个位数字,数码管的具体实现,采用数组存放0-9共阴极数字段码,我采取 number[] = {0-9的段码}; 刚好 number[数字] = 数字的段码;两个数字的依次显示(延时1ms),数码管动态显示得以实现数码管倒计时数字的显示。
int number[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void smg_display()
{
int b1,b2;
b1 = djs/10;
b2 = djs%10;
P0 = number[b1];
smg1 = 0;
delay1ms();
smg1 = 1;
P0 = number[b2];
smg2 = 0;
delay1ms();
smg2 = 1;
}
2、红绿灯显示设计
*在硬件电路方面,使用发光颜色为绿色、黄色、红色的LED作为红绿灯显示载体。担心单片机输出电流不能使 LED 发挥出最好的效果,所以采用 LED 低电平点亮。
*在程序设计方面,定义两个方向的红绿黄灯函数 EW_display()、SN_display() 通过一个标志位 led_flag 来改变红绿灯方向的来回切换。变换时间通过定时器的定时功能实现,设置定时器T1为1ms溢出一次,让变量 timer_1s 每 1ms 增加一次,增加 1000 次刚好为 1s ,作为倒计时秒计时,当 timer_1s 等于 1000 时,djs 减一,实现倒计时功能。让变量 timer_500ms 每 1ms 增加一次,增加 500 次刚好为 0.5s ,作为黄灯闪烁的时间,当 timer_500ms 等于 500 时,标志位 star_flag 取反,实现对黄灯的点亮和熄灭,实现黄灯的闪烁效果,每 0.5s 闪烁一次。(在定时器T1中断服务函数中实现)
int timer_1s = 0; //用于定时器计数变量
int djs =35; //倒计时,不区分主次干道,一视同仁
bit led_flag = 0; //决定哪路先通行 0 南北 1 东西 详见main函数
int timer_500ms = 0; //用于定时器计数变量
bit star_flag = 0; //黄灯闪烁效果,此位用来高低电平变换来实现黄灯闪烁的效果
void Timer1Init(void) //1毫秒@12.000MHz
{
TMOD = 0x10;
TL1 = 0x18; //设置定时初值
TH1 = 0xFC; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //开定时器1中断
EA = 1; //开总中断
}
void timer1() interrupt 3
{
TF1=0;
TL1 = 0x18;
TH1 = 0xFC;
timer_1s++;
timer_500ms++;
if(timer_1s==1000)
{
timer_1s=0;
djs--;
if(djs<0)
{
djs=35;
led_flag=~led_flag;
}
}
if(timer_500ms==500)
{
timer_500ms=0;
star_flag=~star_flag;
}
}
(二)按键功能设计
*在硬件电路方面,(下文按键使用 K 表示),K1实现倒计时设置确定和恢复正常交通信号灯模式,K2实现倒计时加一,K3实现倒计时减一,K4实现南北方向交通管制模式,K5实现东西方向交通管制模式,K6实现交警交通管制模式,K7实现可定时夜间交通模式, K8实现可定时优先主干道通行模式。K1、K2、K3、K7、K8采用轻触开关,K4、K5、K6采用自锁开关。
*在程序设计方面,K1、K2、K3、K4、K5、K6都是在主函数内部函数触发实现的,K7、K8是触发外部中断来实现的。以下为各按键功能实现的程序设计:
//按键
void key()
{
if(k1!=1) //确定键(开启定时器)
{
TR1=1;
}
if(k2!=1) //加键
{
smg_display(); //调用数码管显示函数
if(k2!=1) //消抖,再次检测按键
{
TR1=0; //关闭定时器
djs++; //倒计时变量加一
if(djs>=99) //设置倒计时最大值
{
djs=99;
}
do //防止按键抖动
{
smg_display();
}
while(k2!=1);
}
}
if(k3!=1) //减键
{
smg_display(); //调用数码管显示函数
if(k3!=1) //消抖,再次检测按键
{
TR1=0; //关闭定时器
djs--; //倒计时变量减一
if(djs<=0) //设置倒计时最小值
{
djs=0;
}
do //防止按键抖动
{
smg_display();
}
while(k3!=1);
}
}
if(k4!=1) //管制南北,东西通行
{
smg_display2(); //数码管显示特定样式
TR1=0; //关闭定时器
EW_go(); //东西通行
do //防止抖动
{
smg_display2();
}
while(k4!=1);
}
if(k5!=1) //管制东西,南北通行
{
smg_display2(); //数码管显示特定样式
TR1=0; //关闭定时器
SN_go(); //南北通行
do //防止抖动
{
smg_display2();
}
while(k5!=1);
}
if(k6!=1) //交警管制
{
smg_display2(); //数码管显示特定样式
TR1=0; //关闭定时器
light_red(); //四个方向都为红灯
do //防止抖动
{
smg_display2();
}
while(k6!=1);
}
}
void Init0() interrupt 0 //夜间模式
{
unsigned int i;
unsigned long int j = 10; //0-4294967295
//1 hour 2 3 4 5 6 7 8 9 10 11 12
//60*60=3600 7200 10800 14400 18000 21600 25200 28800 32400 36000 39600 43200
// 13 14 15 16 17 18 19 20 21 22 23 24
//46800 50400 54000 57600 61200 64800 68400 72000 75600 79200 82800 86400
smg_out();
while(j)
{
for(i=0;i<2;i++)
{
SN_green=1;
SN_red=1;
SN_yellow=i;
EW_green=1;
EW_red=1;
EW_yellow=i;
delay500ms();
}
j--;
}
}
void Init1() interrupt 2 //主干道与非主干道优先级模式
{
unsigned int i,f,k=5;
unsigned long int t=2; //T = (主干道djs + 非主干道djs)*t/2
//t = 2*T/(主干道djs + 非主干道djs)
smg_display();
while(t)
{
for(i=0;i<2;i++)
{
if(i==0)
{
djs = 15;
do
{
for(f=0;f<500;f++)
{
light_out();
SN_green=0;
EW_red=0;
smg_display();
}
djs--;
smg_display();
if(djs==5)
{
while(k)
{
for(f=0;f<500;f++)
{
light_out();
SN_green=1;
SN_yellow = 0;
EW_red=0;
smg_display();
}
djs--;
smg_display();
k--;
}
k=5;
}
}
while(djs>0);
if(djs==0)
{
for(f=0;f<500;f++)
{
light_out();
SN_green=1;
SN_yellow = 0;
EW_red=0;
smg_display();
}
}
}
if(i==1)
{
djs = 10;
do
{
for(f=0;f<500;f++)
{
smg_display();
light_out();
EW_green=0;
SN_red=0;
}
djs--;
if(djs==5)
{
while(k)
{
for(f=0;f<500;f++)
{
light_out();
EW_green=1;
EW_yellow = 0;
SN_red=0;
smg_display();
}
djs--;
smg_display();
k--;
}
k=5;
}
}
while(djs>0);
if(djs==0)
{
for(f=0;f<500;f++)
{
light_out();
EW_green=1;
EW_yellow = 0;
SN_red=0;
smg_display();
}
}
}
}
t--;
}
}
文章内容版权归作者阎子君所有,转载请与我联系获得授权许可
