基于51单片机的交通灯设计(含Proteus仿真和原理图及芯片头文件等资料)
基于51单片机的交通灯设计(附有Proteus仿真和原理图)
该设计,难点在于程序编写时对于定时器中断,标志位的灵活使用,其次是对数码管的控制。
注:
1.单片机型号是“stc10f08xe”,Keil软件中不包含stc10.h这个头文件,与原理图和仿真文件一起附在附件中了。
2.此型号的单片机端口驱动能力不够,采用的推挽输出,增强对小灯的驱动能力,改善实际显示效果
3.按下plus button 可以增加此干道的通行时间,minus button可以减少通行时间,stop button对应紧急情况,所有路口红灯亮。
4.下载附件后若无法查看,建议修改文件格式为“zip”,然后解压查看。
/****************************************交通灯程序*********************************************/
/*
作者:Eric
功能:以南北方向为主干道,东西方向为次干道。
1、实现主干道通行15秒转通行注意状态,黄灯亮3秒。这段时间内次干道保持红灯常亮 (由数码管显示时间)
2、次干道通行10秒转通行注意状态,黄灯亮2秒。这段时间内主干道保持红灯常亮 (由数码管显示时间)
3、紧急按键按下,所有路口红灯
/************************************调用头文件、宏定义*****************************************/
#include<stc10.h>
#define D P1
#define uchar unsigned char
#define uint unsigned int
/*******************************************函数声明******************************************/
void z1(void);//南北通
void z2(void);//南北注意
void z3(void);//东西通
void z4(void);//东西注意
void gb(void); //全关
void jinji(void);//紧急状态,红灯全亮
void sm(void); //键盘扫描
void plus(); //加一扫描
void minus(); //减一扫描
void plus2();
void minus2();
void timer(void);//定时器T1初始化
void time1(void);//定义定时器T1中断服务程序
void display(void);//显示函数
void delay(uint a);//10ms延时函数
/*************************************定义数组,全局变量***************************************/
uint duan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0~9断码数组
uint y,gw,sw,gw2,sw2; //全局变量
int time,s,times,time2,times2,time3;
/*********************************定义12个小灯、数码管位、按键*********************************/
/*************12个小灯*******************/ //数码管位选// // 按键 //
sbit d1 =P2^0; sbit d2 =P2^1; sbit d3= P2^2; sbit w1=P0^0; sbit H1 =P3^6; sbit H2=P3^7;
sbit d4 =P2^3; sbit d5 =P2^4; sbit d6= P2^5; sbit w2=P0^1; sbit key1 =P0^5;
sbit d7 =P2^6; sbit d8 =P2^7; sbit d9= P3^2; sbit w3=P0^2; sbit key2 =P0^6;
sbit d10=P3^3; sbit d11=P3^4; sbit d12=P3^5; sbit w4=P0^3; sbit key3 =P0^7;
/*********************************************主函数***********************************************/
void main(void)
{
times=18;
time=15;
time2=10;
times2=12;
y=0,s=0; //定时器溢出计数初始化
P1M1=0X00; //推挽输出,增加数码管亮度
P1M0=0XFF;
timer(); //启动定时器T1
while(1)
{
z1(); //主干道通行,绿灯15秒
z2(); //主干道注意,黄灯 3秒
z3(); //次干道通行,绿灯10秒
z4(); //次干道注意,黄灯 2秒
}
}
/******************不同状态函数、定时器初始化、定时器中断服务函数************************/
void z1(void)//南北通行,东西禁止
{
while(s<time)
{
sm();
plus();
minus();
if(TR1==1)
{
//蓝 /黄 /红
d4 =0;d5 =1;d6 =1;//北
d10=0;d11=1;d12=1;//南
d7 =1;d8 =1;d9 =0;//东
d1 =1;d2 =1;d3 =0;//西
}
sw2=(time-s)/10; //数码管十位(南北主干道)
gw2=(time-s)%10; //数码管个位
sw=(times-s)/10;
gw=(times-s)%10;
display(); //显示
gb(); //关闭
} s=0;//对定时时间标志位清零重置
}
void z2(void)//南北注意,东西禁止
{
time3=3;
while(s<time3)
{
sm();
if(TR1==1)
{
//蓝 /黄 /红
d4 =1;d5 =0;d6 =1;//北
d10=1;d11=0;d12=1;//南
d7 =1;d8 =1;d9 =0;//东
d1 =1;d2 =1;d3 =0;//西
}
sw2=(time3-s)/10; //数码管十位(南北主干道)
gw2=(time3-s)%10; //数码管个位
sw=sw2; //东西次干道
gw=gw2;
display(); //显示
gb(); //关闭
} s=0;
}
void z3(void)//东西通行,南北禁止
{
while(s<time2)
{
sm();
plus2();
minus2();
//蓝 /黄 /红
d4 =1;d5 =1;d6 =0;//北
d10=1;d11=1;d12=0;//南
d7 =0;d8 =1;d9 =1;//东
d1 =0;d2 =1;d3 =1;//西
sw2=(times2-s)/10;; //南北主干道
gw2=(times2-s)%10;
sw=(time2-s)/10; //数码管十位(东西次干道)
gw=(time2-s)%10; //数码管个位
display(); //显示
gb(); //关闭
} s=0;
}
void z4(void)//东西注意,南北禁止
{
time3=2;
while(s<time3)
{
sm();
//蓝 /黄 /红
d4 =1;d5 =1;d6 =0;//北
d10=1;d11=1;d12=0;//南
d7 =1;d8 =0;d9 =1;//东
d1 =1;d2 =0;d3 =1;//西
sw=(time3-s)/10; //东西次干道_数码管十位
gw=(time3-s)%10; //东西次干道_数码管个位
sw2=sw; //南北主干道
gw2=gw;
display(); //显示
gb(); //关闭
} s=0;
}
void jinji(void)//红灯全亮,其余全灭,紧急状态
{
//蓝 /黄 /红
d4 =1;d5 =1;d6 =0;//北
d10=1;d11=1;d12=0;//南
d7 =1;d8 =1;d9 =0;//东
d1 =1;d2 =1;d3 =0;//西
}
void gb(void)//全部关闭
{
//蓝 /黄 /红
d4 =1;d5 =1;d6 =1;//北
d10=1;d11=1;d12=1;//南
d7 =1;d8 =1;d9 =1;//东
d1 =1;d2 =1;d3 =1;//西
}
void delay(uint a) //@11.0592MHz 10ms延时(使用烧录软件生成的延时代码)
{
for(a;a>0;a--)
{
unsigned char i, j;
i = 18;
j = 235;
do
{
while (--j);
} while (--i);
}
}
void display() //数码管显示
{
w1=0; //十位
D=duan[sw];
delay(1);
w1=1;
D=0X00;
w2=0; //个位
D=duan[gw];
delay(1);
w2=1;
D=0x00;
w3=0; //十位
D=duan[sw2];
delay(1);
w3=1;
D=0X00;
w4=0; //个位
D=duan[gw2];
delay(1);
w4=1;
D=0x00;
}
void timer(void)
{
TMOD=0X10;
TH1=(65536-50000)/256; //50ms定时
TL1=(65536-50000)%256;
EA=1;
ET1=1;
TR1=1;
}
void time1(void) interrupt 3 //定时器T1中断服务程序
{
TH1=(65536-50000)/256; //50ms定时
TL1=(65536-50000)%256;
y++;
if(y==20)
{s++; y=0;}
}
void sm(void)//紧急状态扫描函数
{
H1=0; //按键另一端置0,当按键按下相当于接地,由原理图,没有按下时,通过上拉电阻拉高了
if(key1==0) //判断按键是否按下
{
delay(2); //消抖
while(!key1) //松手检测
TR1=!TR1; //关闭定时器
while(key1==1) //四个方向全为红灯,进入紧急状态
{
gb();
jinji(); //打开紧急状态
gw=gw2=sw=sw2=8;
display();
}
while(key1==0) //松手检测
display();
TR1=1; //打开定时器,跳出
}
}
void plus()
{
H1=0; //按键另一端置0,当按键按下相当于接地,由原理图,没有按下时,通过上拉电阻拉高了
if(key2==0) //判断按键是否按下
delay(2); //消抖
if(key2==0)
{
time+=1;
times+=1;}
while(!key2); //松手检测
}
void minus()
{
H1=0; //按键另一端置0,当按键按下相当于接地,由原理图,没有按下时,通过上拉电阻拉高了
if(key3==0) //判断按键是否按下
delay(2); //消抖
if(key3==0){
time-=1;
times-=1;}
while(!key3); //松手检测
}
void plus2()
{
H2=0; //按键另一端置0,当按键按下相当于接地,由原理图,没有按下时,通过上拉电阻拉高了
if(key2==0) //判断按键是否按下,在这里相当于key5
delay(2); //消抖
if(key2==0)
{
time2+=1;
times2+=1;}
while(!key2); //松手检测
}
void minus2()
{
H2=0; //按键另一端置0,当按键按下相当于接地,由原理图,没有按下时,通过上拉电阻拉高了
if(key3==0) //判断按键是否按下,这里相当于key6
delay(2); //消抖
if(key3==0){
time2-=1;
times2-=1;}
while(!key3); //松手检测
}