51单片机 题目五 简易交通灯控制器设计 【具体要求】 1. 东西方向为主干道,南北方向为副干道; 2. 主干道红灯亮15秒(副干道绿灯亮15秒),主干道绿灯亮20秒(副干道红灯亮20秒)。 3. 红绿灯切换中间应有3秒的黄灯过渡; 4. 显示计时。 5. 断电再次启动能够按照电前的状态进行进行显示
时间: 2023-06-15 20:05:39 浏览: 91
这是一个比较典型的交通灯控制器的设计,需要使用定时器来控制红绿灯的切换和计时功能。以下是一个简单的实现思路:
1. 定义两个变量表示主干道和副干道的状态,例如主干道状态为1,副干道状态为0。
2. 利用定时器中断来实现计时功能,每秒钟减少1秒钟的计时值。
3. 当主干道状态为1时,先让主干道红灯亮15秒(副干道绿灯亮15秒),然后再让主干道绿灯亮20秒(副干道红灯亮20秒),中间需要有3秒钟的黄灯过渡。
4. 当副干道状态为1时,同样进行红绿灯切换,只不过主副干道的红绿灯时间互换。
5. 在每次切换红绿灯时,需要重置计时器的计时值。
6. 在程序启动时,需要读取之前的状态,以便能够恢复之前的状态。
以下是一种可能的代码实现:
```c
#include <reg51.h>
#define MAIN_ROAD 1
#define SIDE_ROAD 0
#define RED 0
#define YELLOW 1
#define GREEN 2
sbit main_road_red_light = P1^0;
sbit main_road_yellow_light = P1^1;
sbit main_road_green_light = P1^2;
sbit side_road_red_light = P1^3;
sbit side_road_yellow_light = P1^4;
sbit side_road_green_light = P1^5;
sbit timer_led = P1^6;
unsigned char main_road_status = MAIN_ROAD;
unsigned char side_road_status = SIDE_ROAD;
unsigned char main_road_light = RED;
unsigned char side_road_light = GREEN;
unsigned char timer_value = 0;
void delay_ms(unsigned int ms)
{
unsigned int i,j;
for(i=0;i<ms;i++)
{
for(j=0;j<125;j++);
}
}
void timer_init()
{
TMOD |= 0x01; // 设置定时器0为模式1
TH0 = 0xff; // 定时1ms
TL0 = 0x9c;
ET0 = 1; // 允许定时器0中断
TR0 = 1; // 启动定时器0
EA = 1; // 开启总中断
}
void timer0_isr() interrupt 1
{
TH0 = 0xff; // 定时1ms
TL0 = 0x9c;
timer_led = !timer_led; // 定时器LED灯闪烁
if(timer_value > 0)
{
timer_value--;
}
}
void set_main_road_light(unsigned char light)
{
switch(light)
{
case RED:
main_road_red_light = 1;
main_road_yellow_light = 0;
main_road_green_light = 0;
break;
case YELLOW:
main_road_red_light = 0;
main_road_yellow_light = 1;
main_road_green_light = 0;
break;
case GREEN:
main_road_red_light = 0;
main_road_yellow_light = 0;
main_road_green_light = 1;
break;
}
}
void set_side_road_light(unsigned char light)
{
switch(light)
{
case RED:
side_road_red_light = 1;
side_road_yellow_light = 0;
side_road_green_light = 0;
break;
case YELLOW:
side_road_red_light = 0;
side_road_yellow_light = 1;
side_road_green_light = 0;
break;
case GREEN:
side_road_red_light = 0;
side_road_yellow_light = 0;
side_road_green_light = 1;
break;
}
}
void switch_light()
{
if(main_road_status == MAIN_ROAD)
{
switch(main_road_light)
{
case RED:
set_main_road_light(YELLOW);
set_side_road_light(RED);
main_road_light = YELLOW;
timer_value = 3;
break;
case YELLOW:
set_main_road_light(GREEN);
set_side_road_light(RED);
main_road_light = GREEN;
timer_value = 20;
break;
case GREEN:
set_main_road_light(YELLOW);
set_side_road_light(RED);
main_road_light = YELLOW;
timer_value = 3;
main_road_status = SIDE_ROAD;
side_road_status = MAIN_ROAD;
break;
}
}
else
{
switch(side_road_light)
{
case RED:
set_side_road_light(YELLOW);
set_main_road_light(RED);
side_road_light = YELLOW;
timer_value = 3;
break;
case YELLOW:
set_side_road_light(GREEN);
set_main_road_light(RED);
side_road_light = GREEN;
timer_value = 20;
break;
case GREEN:
set_side_road_light(YELLOW);
set_main_road_light(RED);
side_road_light = YELLOW;
timer_value = 3;
side_road_status = MAIN_ROAD;
main_road_status = SIDE_ROAD;
break;
}
}
}
void main()
{
unsigned char prev_main_road_status;
unsigned char prev_main_road_light;
unsigned char prev_side_road_status;
unsigned char prev_side_road_light;
timer_init();
prev_main_road_status = MAIN_ROAD;
prev_main_road_light = RED;
prev_side_road_status = SIDE_ROAD;
prev_side_road_light = GREEN;
while(1)
{
if(timer_value == 0)
{
switch_light();
}
if(main_road_status != prev_main_road_status || side_road_status != prev_side_road_status ||
main_road_light != prev_main_road_light || side_road_light != prev_side_road_light)
{
// 保存当前状态
prev_main_road_status = main_road_status;
prev_main_road_light = main_road_light;
prev_side_road_status = side_road_status;
prev_side_road_light = side_road_light;
// 显示状态
// TODO: 显示状态的代码
}
delay_ms(100);
}
}
```
需要注意的是,在代码中还需要增加对断电保存状态的处理,可以使用 EEPROM 或者 Flash 来保存状态。另外,代码中只是简单地使用了延时来模拟计时功能,实际上可以使用定时器来实现更精确的计时。
阅读全文