要求:
1、双向圆灯控制(没有左右拐的),带读秒倒计时显示
2、灯变换之间的时间必须可以修改,设计必要的按键和指示电路
可参考
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit red1 = P1^0; // 红灯1
sbit yellow1 = P1^1; // 黄灯1
sbit green1 = P1^2; // 绿灯1
sbit red2 = P1^3; // 红灯2
sbit yellow2 = P1^4; // 黄灯2
sbit green2 = P1^5; // 绿灯2
sbit key1 = P3^0; // 按键1
sbit key2 = P3^1; // 按键2
sbit key3 = P3^2; // 按键3
sbit key4 = P3^3; // 按键4
sbit beep = P3^7; // 蜂鸣器
sbit dula = P2^6; // 读秒倒计时器段选
sbit wela = P2^7; // 读秒倒计时器位选
uchar code table[] = { // 数码管显示表
0x3f, // 0
0x06, // 1
0x5b, // 2
0x4f, // 3
0x66, // 4
0x6d, // 5
0x7d, // 6
0x07, // 7
0x7f, // 8
0x6f, // 9
};
uint time1 = 0; // 灯1计时器
uint time2 = 0; // 灯2计时器
uchar sec = 0; // 读秒计时器
void delay(uint t) // 延时函数
{
uint i, j;
for (i = 0; i < t; i++)
{
for (j = 0; j < 125; j++);
}
}
void display(uchar num) // 数码管显示函数
{
dula = 1; // 关闭段选
P0 = table[num]; // 显示数码
dula = 0; // 打开段选
}
void timer0() interrupt 1 // 定时器0中断服务函数
{
TH0 = 0xfc; // 重置定时器0初值
TL0 = 0x18;
time1++; // 灯1计时器加1
time2++; // 灯2计时器加1
if (sec > 0) // 如果读秒计时器大于0,继续计时
{
sec--;
}
}
void main()
{
uchar mode = 0; // 灯模式,0为绿灯亮,1为黄灯亮,2为红灯亮
uchar time = 10; // 灯变换时间,单位为秒
uchar i;
TMOD = 0x01; // 定时器0工作在模式1
TH0 = 0xfc; // 定时器0初值
TL0 = 0x18;
ET0 = 1; // 开启定时器0中断
EA = 1; // 开启总中断
TR0 = 1; // 启动定时器0
while (1)
{
if (key1 == 0) // 按键1按下,切换到灯1模式
{
mode = 0;
beep = 1; // 蜂鸣器响一声
delay(10);
beep = 0;
}
else if (key2 == 0) // 按键2按下,切换到灯2模式
{
mode = 0;
beep = 1; // 蜂鸣器响一声
delay(10);
beep = 0;
}
else if (key3 == 0) // 按键3按下,增加灯变换时间
{
time++;
if (time > 60)
{
time = 60;
}
beep = 1; // 蜂鸣器响一声
delay(10);
beep = 0;
}
else if (key4 == 0) // 按键4按下,减少灯变换时间
{
time--;
if (time < 10)
{
time = 10;
}
beep = 1; // 蜂鸣器响一声
delay(10);
beep = 0;
}
}
}
双向十字路口应该是4个倒计时显示和4组红绿灯控制吧?
基于51单片机简易十字路口交通灯_5s全黄闪烁
#include<reg52.h>
#include<intrins.h>
//数据类型定义
typedef unsigned char uchar;
typedef unsigned int uint;
void led_sacn();
void delay_ms(ms);
void seg_disp(uchar number,uchar wei);
#define ON 1 //LED给告电平亮灯
#define OFF 0 //LED给低电平灭灯
//通用IO引脚分配
sbit W0=P3^4;
sbit W1=P3^5;
sbit W2=P3^6;
sbit W3=P3^7;
sbit NS_G = P2^0;
sbit NS_Y = P2^1;
sbit NS_R = P2^2;
sbit WE_R = P2^3;
sbit WE_Y = P2^4;
sbit WE_G = P2^5;
bit flag1s;
bit half_1sflag;
uchar one_sec_flag,main_road_time,secondary_road_time,half_sec_flag;
//1秒定时标志位 南北方向显示时间 东西方向显示时间
uchar state=0;//正常模式不同状态
uchar code seg_du[]={0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
uchar main_green_straight_cnt=5,yellow_cnt =5,sec_green_straight_cnt =5;
//南北方向直行绿灯时间 _黄灯时间 _东西方向绿灯时间
void main()
{
EA=1; //开总中断
TMOD=0X01;//T0的工作模式为模式1
TH0=0X4C;
TL0=0X00;//11.0592M晶振 50ms定时初值
ET0=1; //允许定时器1中断
TR0=1;//启动定时器0
// state=2;
while(1)
{
led_sacn(); //LED和数码管显示,时刻刷新
if(flag1s) //一秒刷新一次
{
flag1s=0;
main_road_time--; //红绿灯倒计时时间减
secondary_road_time--;
}
if (half_1sflag){
half_1sflag = 0;
if(state == 0||state == 2){//黄灯闪烁
NS_Y =~NS_Y;
WE_Y =~WE_Y;
}
}
}
}
if(main_road_time==0 || secondary_road_time==0)//当南北方向或者东西方向倒数到0,切换状态。
//这一段程序只有倒计时为0才执行一次,执行完一次等下一次倒计时为0才再执行一次
{
switch(state)//改变红绿灯的状态
{
case 0:
{
state=1;//下次切换到下一个模式
main_road_time=main_green_straight_cnt;//南北方向直行绿灯通行时间
secondary_road_time=sec_green_straight_cnt;//东西方向红灯时间
NS_G = ON;
NS_Y = OFF;
NS_R = OFF;
WE_R = ON;
WE_Y = OFF;
WE_G = OFF;
}break;
case 1:
{
state=2;
main_road_time = yellow_cnt;//南北方向直行黄灯时间
secondary_road_time =yellow_cnt;
NS_G = OFF;
NS_Y = ON;
NS_R = OFF;
WE_R = OFF;
WE_Y = ON;
WE_G = OFF;
}break;
case 2:
{
state=3;
main_road_time=sec_green_straight_cnt;
secondary_road_time=sec_green_straight_cnt;
NS_G = OFF;
NS_Y = OFF;
NS_R = ON;
WE_R = OFF;
WE_Y = OFF;
WE_G = ON;
}break;
case 3:
{
state=0;
secondary_road_time=yellow_cnt;//黄灯时间
main_road_time=yellow_cnt;
NS_G = OFF;
NS_Y = ON;
NS_R = OFF;
WE_R = OFF;
WE_Y = ON;
WE_G = OFF;
}break;
default:break;
}
}
keil程序实现的 基于51单片机的程序,其核心在于倒计时以及控制LED灯的亮和灭。其中,倒计时可以通过delay延时和定时器实现。具体的程序,网上开源的代码不少,这里给你找到一些,应该对你有用:
比如这个基于51单片机简易十字路口交通灯: https://blog.csdn.net/weixin_52733843/article/details/126684698
还有和这个:51单片机|keilc51|实例:https://blog.csdn.net/zzztutu/article/details/124722534
有多急?