Proteus仿真原理图:
程序如下:
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
uchar data buf[4]
uchar data sec_dx=20//东西数默认
uchar data sec_nb=30//南北默认值
uchar data set_timedx=20
uchar data set_timenb=30
int n
uchar data b//定时器中断次数
sbit k1=P1^6//定义5组开关
sbit k2=P1^7
sbit k3=P2^7
sbit k4=P3^0
sbit k5=P3^1
sbit Yellow_nb=P2^5 //南北黄灯标志
sbit Yellow_dx=P2^2 //东西黄灯标志
sbit Green_nb=P2^4
sbit Green_dx=P2^1
sbit Buzz=P3^7
bit Buzzer_Indicate
bit time=0//灯状态循环标志
bit set=1//调时方向切换键标志
uchar code table[11]={ //共阴极字型码
0x3f, //--0
0x06, //--1
0x5b, //--2
0x4f, //--3
0x66, //--4
0x6d, //--5
0x7d, //--6
0x07, //--7
0x7f, //--8
0x6f, //--9
0x00 //--NULL
}
//函数的声明部分
void delay(int ms)//延时子程序
void key()//按键扫描子程序
void key_to1()//键处理子程序
void key_to2()
void key_to3()
void display()//显示子程序
void logo() //开机LOGO
void Buzzer()
//主程序
void main()
{
TMOD=0X01
TH0=0XD8
TL0=0XF0
EA=1
ET0=1
TR0=1
EX0=1
EX1=1
logo()
P2=0Xc3// 开始默认状态,东西绿灯,南北黄灯
sec_nb=sec_dx+5
while(1)
{
key()//调用按键扫描程序
display()//调用显示程序
Buzzer()
}
}
//函数的定义部分
void key() //按键扫描子程序
{
if(k1!=1)
{
delay(10)
if(k1!=1)
{
while(k1!=1)
{
key_to1()
for(n=0n<40n++)
{ display()}
}
}
}
if(k2!=1)
{
delay(10)
if(k2!=1)
{
while(k2!=1)
{
key_to2()
for(n=0n<40n++)
{ display()}
}
}
}
if(k3!=1)
{
TR0=1 //启动定时器
Buzzer_Indicate=0
sec_nb=set_timenb //从中断回复,仍显示设置过的数值
sec_dx=set_timedx
if(time==0)
{ P2=0X99sec_nb=sec_dx+5}
else { P2=0xC3sec_dx=sec_nb+5}
}
if(k4!=1)
{
delay(5)
if(k4!=1)
{
while(k4!=1)
set=!set
}
}
if(k5!=1)
{
delay(5)
if(k5!=1)
{
while(k5!=1)
key_to3()
}
}
}
void display() //显示子程序
{
buf[1]=sec_dx/10//第1位 东西秒十位
buf[2]=sec_dx%10//第2位 东西秒个位
buf[3]=sec_nb/10//第3位 南北秒十位
buf[0]=sec_nb%10//第4位 南北秒个位
P1=0xff // 初始灯为灭的
P0=0x00
P1=0xfe //片选LCD1
P0=table[buf[1]]
delay(1)
P1=0xff
P0=0x00
P1=0xfd //片选LCD2
P0=table[buf[2]]
delay(1)
P1=0xff
P0=0x00
P1=0Xfb //片选LCD3
P0=table[buf[3]]
delay(1)
P1=0xff
P0=0x00
P1=0Xf7
P0=table[buf[0]] //片选LCD4
delay(1)
}
void time0(void) interrupt 1 using 1 //定时中断子程序
{
b++
if(b==19) // 定时器中断次数
{ b=0
sec_dx--
sec_nb--
if(sec_nb<=5&&time==0) //东西黄灯闪
{ Green_dx=0Yellow_dx=!Yellow_dx}
if(sec_dx<=5&&time==1) //南北黄灯闪
{ Green_nb=0Yellow_nb=!Yellow_nb}
if(sec_dx==0&&sec_nb==5)
sec_dx=5
if(sec_nb==0&&sec_dx==5)
sec_nb=5
if(time==0&&sec_nb==0)
{ P2=0x99time=!timesec_nb=set_timenbsec_dx=set_timenb+5}
if(time==1&&sec_dx==0)
{P2=0Xc3time=!timesec_dx=set_timedxsec_nb=set_timedx+5}
}
}
void key_to1() //键盘处理子程序之+
{
TR0=0 //关定时器
if(set==0)
set_timenb++ //南北加1S
else
set_timedx++ //东西加1S
if(set_timenb==100)
set_timenb=1
if( set_timedx==100)
set_timedx=1 //加到100置1
sec_nb=set_timenb //设置的数值赋给东西南北
sec_dx=set_timedx
}
void key_to2() //键盘处理子程序之-
{
TR0=0 //关定时器
if(set==0)
set_timenb-- //南北减1S
else
set_timedx-- //东西减1S
if(set_timenb==0)
set_timenb=99
if( set_timedx==0 )
set_timedx=99 //减到1重置99
sec_nb=set_timenb //设置的数值赋给东西南北
sec_dx=set_timedx
}
void key_to3() //键盘处理之紧急车通行
{
TR0=0
P2=0Xc9
sec_dx=00
sec_nb=00
Buzzer_Indicate=1
}
void int0(void) interrupt 0 using 1 //只允许东西通行
{
TR0=0
P2=0Xc3
Buzzer_Indicate=0
sec_dx=00
sec_nb=00
}
void int1(void) interrupt 2 using 1 //只允许南北通行
{
TR0=0
P2=0X99
Buzzer_Indicate=0
sec_nb=00
sec_dx=00
}
void logo()//开机的Logo "- - - -"
{ for(n=0n<50n++)
{
P0=0x40
P1=0xfe
delay(1)
P1=0xfd
delay(1)
P1=0Xfb
delay(1)
P1=0Xf7
delay(1)
P1 = 0xff
}
}
void Buzzer()
{
if(Buzzer_Indicate==1)
Buzz=!Buzz
else Buzz=0
}
void delay(int ms) //延时子程序
{
uint j,k
for(j=0j<msj++)
for(k=0k<124k++)
}
简单I/O实验(交通灯控制)
一.实验要求
以74LS273作为输出口,控制4个双色LED灯(可发红,绿,黄光),模拟交通灯管理。
二.实验目的
1.学习在单片机系统中扩展简单I/O接口的方法。
2.学习数据输出程序的设计方法。
3.学习模拟交通灯控制的方法。
4.学习双色灯的使用。
三.实验电路及连线
四.实验说明
1.因为本实验是交通灯控制实验,所以要先了解实际交通灯的变化规律。假设一个十字路口为东西南北走向。初始状态0为东西红灯,南北红灯。然后转状态1南北绿灯通车,东西红灯。过一段时间转状态2,南北绿灯闪几次转亮黄灯,延时几秒,东西仍然红灯。再转状态3,东西绿灯通车,南北红灯。过一段时间转状态4,东西绿灯闪几次转亮黄灯,延时几秒,南北仍然红灯。最后循环至状态1。
2.双色LED是由一个红色LED管芯和一个绿色LED管芯封装在一起,公用负端。当红色正端加高电平,绿色正端加低电平时,红灯亮;红色正端加低电平,绿色正端加高电平时,绿灯亮;两端都加高电平时,黄灯亮。
五.实验程序框图
程序框图:
源代码:
ORG 0000H
LJMP START
ORG 0040H
START:
MOV SP,#60H
LCALL STATUS0 初始状态(都是红灯)
CIRCLE: LCALL STATUS1 南北绿灯,东西红灯
LCALL STATUS2 南北绿灯闪转黄灯,东西红灯
LCALL STATUS3 南北红灯,东西绿灯
LCALL STATUS4 南北红灯,东西绿灯闪转黄灯
LJMP CIRCLE
STATUS0: 南北红灯,东西红灯
MOV DPTR,#8300H
MOV A,#0FH
MOVX @DPTR,A
MOV R2,#10 延时1秒
LCALL DELAY
RET
STATUS1: 南北绿灯,东西红灯
MOV DPTR,#08300H
MOV A,#5AH 南北绿灯,东西红灯
MOVX @DPTR,A
MOV R2,#50 延时5秒
LCALL DELAY
RET
STATUS2: 南北绿灯闪转黄灯,东西红灯
MOV DPTR,#8300H
MOV R3,#03H 绿灯闪3次
FLASH: MOV A,#5FH
MOVX @DPTR,A
MOV R2,#03H
LCALL DELAY
MOV A,#5AH
MOVX @DPTR,A
MOV R2,#03H
LCALL DELAY
DJNZ R3,FLASH
MOV A,#0AH 南北黄灯,东西红灯
MOVX @DPTR,A
MOV R2,#10 延时1秒
LCALL DELAY
RET
STATUS3: 南北红灯,东西绿灯
MOV DPTR,#8300H
MOV A,#0A5H
MOVX @DPTR,A
MOV R2,#50 延时5秒
LCALL DELAY
RET
STATUS4: 南北红灯,东西绿灯闪转黄灯
MOV DPTR,#8300H
MOV R3,#03H 绿灯闪3次
FLASH1: MOV A,#0AFH
MOVX @DPTR,A
MOV R2,#03H
LCALL DELAY
MOV A,#0A5H
MOVX @DPTR,A
MOV R2,#03H
LCALL DELAY
DJNZ R3,FLASH1
MOV A,#05H 南北红灯,东西黄灯
MOVX @DPTR,A
MOV R2,#10 延时1秒
LCALL DELAY
NOP
RET
DELAY: 延时子程序
PUSH 2
PUSH 1
PUSH 0
DELAY1: MOV 1,#00H
DELAY2: MOV 0,#0B2H
DJNZ 0,$
DJNZ 1,DELAY2 延时 100 mS
DJNZ 2,DELAY1
POP 0
POP 1
POP 2
RET
END
硬件电路设计
此电中路设计采用AT89C51单片机,74LS47(数码管驱动)74LS373(数码管驱动输出锁存),8个数码管显示其延时值,四个红、黄、绿指示灯。硬件设计关键在于,延时显示时,要考虑到当个位数字显示时,要确保十位数字显示输出的不变。因此,可加输出锁存器。在延时最后三秒时,要让黄灯进行闪烁,并同时显示数字(这一步在软件设计上很关键)。
(1)电路连接图:
三、软件程序(C语言)
以下是整个设计的软件程序,直接可以编译成*。Hex代码。通过以上电路,下载到单片机,可直接运行。
//*****************************////程序名:十字路口交通灯控制
//编写人:黄庭剑
//初写时间:2009年1月2日
//程序功能:南北为车行道,延时60秒东西方向为人行道,延时20秒,且在最后3秒黄灯显示2秒钟再实现切换.
//CPU说明:AT89C51型单片机 24MHZ晶体振荡器
//完成时间:2009年1月6日
//*****************************//
#include<stdio.h>
#include<reg51.h>
#include<intrins.h>
sfr p0 = 0x80
sfr p1 = 0x90
sfr p2 = 0xA0
sfr p3 = 0xb0 //这部分内容其实在“#include<reg51.h>”里已经有,但里面定义的必须区分大小写,在这里,因为我程序采用的是小写,reg51.h里对各个端口与寄存器的定义都是大写,所以在编译连接时,会报错,所以,在本设计程序里,我只用到了端口,在这里也就只定义了四个,而没有去改reg51.h里面的内容。其实两者是一样的。
sbit sw = p0^0
sbit OE =P0^6
sbit LE =P0^7 //74LS373锁存器控制端定义
char display[]={ 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99 } //p1口的数码管时间显示调用,利用74L74BCD码,8位驱动输出 //函数声明 begin
void delay1(int count)
void delay_long(int number1,int number2)
void people_car_drive()
//函数声明end
//***********************//延时子程序
void delay1(int count)
{ int i
for(i=counti>0i--)
{ }
}
void delay_long(int number1,int number2)
{
int a,b
for(a=number1a>0a--)
{
for(b=number2b>0b--)
{ _nop_() }
}
}
//**********************//延时子程序
void people_car_drive()
{
int p_1=2,i,j=9,p_2=6 //****************//行人通行时,延时20秒
p2=0x09 //南北红灯亮
p3=0x24 //东西绿灯亮
while(p_1-->0)
{ LE=1
OE=0
if(p_1==0){OE=1} //当十位数减到0时,只显示个位数
p1=display[p_1]
delay1(1000)
LE=0
j=9
for(i=10i>0i--)
{
if(p_1==0&&j==3)break //减到3时退出循环,让其黄灯闪烁显示
p1=display[j--]
delay_long(16000,2)
if(sw==1)return
}
}
//*******************************************************************************//
p2=0x12 //南北黄灯闪烁三秒,以提醒行人注意
p3=0x12
p1=display[3]
delay_long(8000,1)
p2=0x00
p3=0x00
delay_long(14000,1)
p2=0x12
p3=0x12
p1=display[2]
delay_long(8000,1)
p2=0x00
p3=0x00
delay_long(14000,1)
p2=0x12
p3=0x12
p1=display[1]
delay_long(8000,1)
p2=0x00
p3=0x00
delay_long(14000,1)
//*****************以下是车辆通行时延时60秒//
p2=0x24 //南北绿灯亮
p3=0x09 //东西红灯亮
while(p_2-->0)
{ LE=1
OE=0
if(p_2==0){OE=1} //当十位数减到0时,只显示个位数
p1=display[p_2]
delay1(1000)
LE=0
j=9
for(i=10i>0i--)
{
if(p_2==0&&j==3)break //减到2时退出循环
p1=display[j--]
delay_long(16000,2)
if(sw==1)return
}
}
p2=0x12 //南北黄灯闪烁三秒,以提醒行人注意
p3=0x12
p1=display[3]
delay_long(8000,1)
p2=0x00
p3=0x00
delay_long(14000,1)
p2=0x12
p3=0x12
p1=display[2]
delay_long(8000,1)
p2=0x00
p3=0x00
delay_long(14000,1)
p2=0x12
p3=0x12
p1=display[1]
delay_long(8000,1)
p2=0x00
p3=0x00
delay_long(14000,1) //南北黄灯闪烁三秒完毕
}
void main() //主函数入口处
{
p0=0x01
p1=0x00
p2=0x00
p3=0x00 //初始化各端口
{ while(1)
{
if(sw==0)
{ people_car_drive()}
else
{
p2=0x00
p3=0x00 //关闭所有交通灯
}
}
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)