基于51单片机交通灯设计
(仿真+程序)
功能介绍
具体功能:
1.一个数码管显示倒计时,LED作为红绿黄灯;
2.开始运行全红灯倒计时5秒,之后循环南北绿灯30秒,黄灯3秒,东西绿灯25秒,黄灯3秒;
3.按键长按可以设置四路口全变红灯;
演示视频:
基于51单片机交通灯设计—1个数码管、禁止通行
添加图片注释,不超过 140 字(可选)
程序
//包含头文件
/***微信公众号:木子单片机********/
#include<reg51.h>
#include <intrins.h>
//宏定义
#define uchar unsigned char
#define uint unsigned int
#include "eeprom52.h" //信息存储位置的头文件
sbit k1=P1^0;
sbit k2=P1^1;
sbit k3=P1^2;
sbit k4=P1^3;
sbit k5=P1^4;
sbit k6=P1^5;
sbit k7=P1^6;
sbit k8=P1^7; //选手按键
sbit start=P3^0; //主持人按键开始
sbit reset=P3^1; //复位
sbit add1=P3^2; //抢答时间调整,加1
sbit dec1=P3^3; //抢答时间调整,减1
sbit add2=P3^4; //答题时间调整,加1
sbit dec2=P3^5; //答题时间调整,减1
//uchar code tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77}; //0-9代码
unsigned char code tab[]={0x5F,0x44,0x9D,0xD5,0xC6,0xD3,0xDB,0x45,0xDF,0xD7, 0xCE,0xC7,0xDC}; //数字0-9的编码 和H q d
uchar shiwei,gewei,xuanshou,count,p,second;
uchar qd_time,dt_time; //抢答时间,答题时间
uint t,m,n,a,a1,a2,a3,a4,a5,a6,a7,a8;
sbit beep=P3^6; //蜂鸣器
bit qd; //抢答标志位,=1时开启抢答
bit dt; //答题标志位,=1时开启答题
bit disp_qd_dt; //显示抢答还是答题时间标志位,=0时是显示抢答时间,=1时是显示答题时间
void Timer()
{
TMOD=0x01; //定义工作方式
TH0=0x3C; //初值15536,计数50000次,每次1uS,总计50ms
TL0=0xB0;
IE=0x82; //这里是中断优先级控制EA=1(开总中断),ET0=1(定时器0允许中断),这里用定时器0来定时
TR0=0; //开启定时器定时
}
void tim(void) interrupt 1 using 1 //为定时中断T0
{
TH0=0x3C; //重新赋值
TL0=0xB0;
TR0=1;
count++; //计数一次时50ms,20次为1s
if((second<=10)&&(count==10)&&(dt==1)) //计时到500ms时,根据需要蜂鸣器闪烁
beep=0;
if(count==20) //20*50ms=1秒
{
count=0;
if(second>=1)
second--; //秒减1
else
TR0=0;
if((second<=10)&&(dt==1)) //当秒见到10以下时,控制蜂鸣器闪烁鸣响
beep=1;
}
}
void delay(uint z) //延时函数
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--); //约1ms
}
/******************把数据保存到单片机内部eeprom中******************/
void write_eeprom()
{
SectorErase(0x2000);
byte_write(0x2000, qd_time);
byte_write(0x2001, dt_time);
byte_write(0x2060, a_a);
}
/******************把数据从单片机内部eeprom中读出来*****************/
void read_eeprom()
{
qd_time = byte_read(0x2000);
dt_time = byte_read(0x2001);
a_a = byte_read(0x2060);
}
/**************开机自检eeprom初始化*****************/
void init_eeprom()
{
read_eeprom(); //先读
if(a_a != 1) //新的单片机初始单片机内问eeprom
{
qd_time = 30;
dt_time = 60;
a_a = 1;
write_eeprom(); //保存数据
}
}
void display (void) //显示函数
{
unsigned char shiwei,gewei,xuanshou;
shiwei=tab[second/10]; //将秒数据拆开成两个一位数
gewei=tab[second%10];
xuanshou=tab[p];
P0=gewei; //送入P0口的gewei数据
P2=0x7F; //个位位选
delay(5); //延时5ms
P2=0xFF; //关闭位选,防止出现鬼影 下同
P0=shiwei; //显示十位
P2=0xBF; //打开显示时间十位的位选
delay(5);
P2=0xFF;
P0=0x80; //显示横线
P2=0xDF;
delay(5);
P2=0xFF;
P0=xuanshou;
P2=0xEF; //选手位选
delay(5);
P2=0xFF;
}
void keyscan(void) //按键扫描函数
{
if(add1==0) //判断抢答时间加键是否按下
{
display(); //延时去抖
if(add1==0) //再次判断按键是否按下
{
p=11; //显示q 代表抢答时间设置
disp_qd_dt=0; //显示抢答时间
qd_time++; //抢答时间加
if(qd_time>=99) //最大值可以加到99
qd_time=99;
}
second=qd_time; //将抢答时间赋值秒数据,用于计时
do
display(); //调用显示函数
while(add1==0); //按键释放
write_eeprom(); //保存数据
}
if(dec1==0) //键按键是否按下
{
display(); //用显示函数代替延时去抖,防止按下按键时屏幕的闪烁
if(dec1==0) //再次判断按键是否按下
{
p=11; //显示q
disp_qd_dt=0; //标志位置0
qd_time--; //抢答时间减
if(qd_time<=1) //时间减最低值1
qd_time=1;
}
second=qd_time; //将抢答时间赋值秒,用于倒计时
do
display(); //调用显示函数
while(dec1==0); //按键释放
write_eeprom(); //保存数据
}
if(add2==0) //答题时间设置参照抢答时间设置部分注释
{
display();
if(add2==0)
{
p=12;
disp_qd_dt=1;
dt_time++;
if(dt_time>=99)
dt_time=99;
}
second=dt_time;
do
display();
while(add2==0);
write_eeprom(); //保存数据
}
if(dec2==0)
{
display();
if(dec2==0)
{
p=12;
disp_qd_dt=1;
dt_time--;
if(dt_time<=1)
dt_time=1;
}
second=dt_time;
do
display();
while(dec2==0);
write_eeprom(); //保存数据
}
}
void init() //初始化函数
{
t=0;
beep=1;
p=10; //选手号初始为显示H,表示等待
second=qd_time; //将抢答时间赋值秒
}
硬件设计
使用元器件:
单片机:AT89C51;
(注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)
设计资料
01仿真图
本设计使用Proteus7.8和Proteus8.9两个版本设计!具体如图!
添加图片注释,不超过 140 字(可选)
02程序
本设计使用软件keil5版本编程设计!具体如图!
添加图片注释,不超过 140 字(可选)
03设计资料
资料获取请关注同名公众号,全部资料包括程序(含注释)、仿真源文件等。具体内容如下,全网最全!!
资料获取请观看前面演示视频!
点赞分享一起学习成长。