基于80C51单片机的交通灯设计.docx
《基于80C51单片机的交通灯设计.docx》由会员分享,可在线阅读,更多相关《基于80C51单片机的交通灯设计.docx(19页珍藏版)》请在冰豆网上搜索。
基于80C51单片机的交通灯设计
基于80C51单片机的交通灯设计
———————————————————————————————— 作者:
————————————————————————————————日期:
基于80C51单片机的交通灯设计
班级:
电信1101
姓名:
XXXX
学号:
0703110107
一、设计说明及材料清单
(一)设计说明:
本交通灯的设计简化了十字路交通灯,只将东西和南北两个路向的交通灯情况表示出来,但也做了很多改进,设计了针对不同时间段不同的控制方案,并且采用串口通讯可将不同的控制方案下载到芯片中,外接掉电保存程序的非易失性存储芯片和掉电仍可计时的时钟芯片,以保证计时的正确性。
(二)材料清单:
二、电路原理图设计
本设计共用到四款主要芯片,分别为单片机芯片80C51、EEPROM芯片AT24C02、时钟芯片DS1302和转串口芯片MAX232。
(一)下图为80C51单片机芯片的管脚图,80C51有两个16位定时计数器,两个外中断,两个定时计数中断,及一个串行中断,并有4个8位并行输入口即I/O口。
80C51内部有时钟电路,但需要石英晶体和微调电容外接,本系统中采用12MHz的晶振频率。
(二)下图为AT24C02芯片的原理图,该芯片是一种带有I2C总线结构的EEPROM芯片,通过SDA和SCL端口与总线连接,具有非易失性,掉电仍可保存程序。
其管脚功能如下:
管脚名称 功能 说明
A0、A1、A2 器件地址选择 本设计全部接地
SDA 串行数据、地址 与单片机的P1.6连接进行数据、地址的传输
SCL 串行时钟 与单片机的P1.7相连,串行时钟信号输入
WP 写保护 WP=1,只能对其读,写禁止,所以令WP=0
VCC +1.8V~6.0V工作电压 电源输入
GND 地 接地引脚
(三)下图是时钟芯片的电路原理图,DS1307是一款低功耗,地址和数据通过两线双向的串行总线的传输,节省单片机资源,该芯片可以提供秒,分,小时等信息,芯片有一个内置的电源感应电路,具有掉电检测和电池切换功能,本设计中需要其停电后继续计时。
其中的7引脚是方波的输出端,可接入单片机的可引起中断的端口,利用引脚7产生的方波引起中断,从而显示时间的变化。
(四)下图是MAX232芯片的原理图,因为设计要求与电脑有串口通讯,就是将交通灯不同时间段程序控制方案通过串口下载到单片机里,单片机上有一个全双工的串行通讯口,但电脑的串口是RS232电平的,而单片机的串口是TTL电平的,两者之间必须有一个电平转换电路,所以采用了专用芯片MAX232进行转换,下图中的7、8端口分别和电脑上的RS232端口的2、3连接,芯片的9和10端口与单片机的串口相连,如下图所示:
(五)下图为交通灯的总体原理图(不包括上述芯片原理图),根据要求选择六只LED灯作为东西和南北方向的红绿黄交通灯,并且每个方向上有时间计数提示,每个方向有两位数码管动态显示,最大为99,采用共阴极7段数码管,单片机通过驱动器SN7404的放大电流驱动每位数码管。
P1.0至P1.5控制六只LED灯,数码管由P0.0至P0.6控制进行段选,P2.0至P2.3控制位选。
三、程序设计
(一)系统框图:
(二)主程序如下:
#include"reg51.h"
#include
#define EW_H0
#defineEW_L1
#defineSN_H2
#defineSN_L3
//函数声明
voidEW_NONE();
voidEW_RED();
void EW_YELLOW();
void EW_GREEN();
void SN_NONE();
voidSN_RED();
void SN_YELLOW();
voidSN_GREEN();
voidLED_INIT();
voidLED_WRITE(intdat,intcon);
//根据原理图定义交通灯的引脚
sbitEW_LED_RED=P1^0;
sbitEW_LED_YELLOW=P1^1;
sbitEW_LED_GREEN = P1^2;
sbitSN_LED_RED= P1^3;
sbitSN_LED_YELLOW = P1^4;
sbitSN_LED_GREEN=P1^5;
//定义P2^0-P2^3=LED数码管控制
sbitEW_weixuan_H=P2^0;
sbit EW_weixuan_L =P2^1;
sbitSN_weixuan_H=P2^2;
sbitSN_weixuan_L=P2^3;
//定义P0^0-P0^7=LED数码管段选引脚
sbitLED_DATA_A=P0^0;
sbit LED_DATA_B=P0^1;
sbitLED_DATA_C =P0^2;
sbitLED_DATA_D=P0^3;
sbitLED_DATA_E= P0^4;
sbit LED_DATA_F=P0^5;
sbitLED_DATA_G= P0^6;
sbitSCL =P1^6;
sbitSDA=P1^7;
//变量声明
unsignedcharcounter,ew_sign,sn_sign,ew_time,sn_time,hour
//定义段码
codecharLED_CODE[10]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
/*main函数开始*/
main()
{
ﻩ counter=3;//计数器,每3600s查询一次当前hour
ﻩ ew_sign= 0;//东西标志位,0代表红灯,1代表绿灯,2代表黄灯
sn_sign = 0;//南北标志位,0代表红灯,1代表绿灯,2代表黄灯
ﻩew_time=3;//东西时间
ﻩ sn_time =3;//南北时间
ﻩ hour=24;//当前hour
unsignedew_total_time[24] = {1,1,1,1,1,30,30,30,30,30,30,30,60,60,60,60,30,30,
30,30,30,30}//东西各时间段绿灯亮总时间
unsignedcharsn_total_time[24]={1,1,1,1,1,30,30,60,60,60,60,60,30,30,30,30,30,
30,30,30,30,30}//南北各时间段绿灯亮总时间
LED_INTI();
EW_RED();
ﻩSN_RED();
ﻩwhile
(1)
ﻩ{
ﻩif(counter== 0)
{
ﻩhour=GET_HOUR();
ﻩﻩcounter=3600;
ﻩﻩswitch(hour)
{
ﻩﻩcase5:
ﻩﻩﻩﻩew_time =30;
ﻩﻩsn_time= 33;
ﻩﻩﻩew_sign =1;
ﻩﻩﻩﻩsn_sign = 0;
ﻩﻩﻩEW_GREEN();
ﻩSN_RED();
ﻩﻩbreak;
ﻩcase7:
ﻩew_time= 30;
ﻩﻩﻩﻩsn_time= 33;
ﻩﻩﻩﻩﻩew_sign=1;
ﻩﻩsn_sign =0;
ﻩﻩEW_GREEN();
ﻩﻩﻩﻩSN_RED();
ﻩﻩﻩﻩbreak;
case12:
ﻩew_time=60;
ﻩﻩsn_time=63;
ﻩﻩﻩﻩew_sign = 1;
ﻩﻩsn_sign = 0;
ﻩﻩEW_GREEN();
ﻩSN_RED();
ﻩﻩﻩbreak;
ﻩﻩcase18:
ﻩﻩﻩew_time=30;
ﻩﻩsn_time=33;
ﻩﻩew_sign=1;
ﻩﻩsn_sign=0;
ﻩﻩﻩEW_GREEN();
ﻩﻩﻩSN_RED();
ﻩﻩbreak;
ﻩﻩﻩdefault:
ﻩbreak;
ﻩ}
ﻩﻩ}
ﻩif(ew_time== 0)
ﻩﻩ{
ﻩﻩswitch(ew_sign)
ﻩﻩﻩ{
ﻩcase0:
ﻩew_sign=1;
ﻩﻩﻩew_time=ew_total_time[hour];
ﻩﻩEW_GREEN();
ﻩﻩﻩﻩﻩbreak;
ﻩﻩcase1:
ﻩﻩﻩﻩew_sign=2;
ﻩﻩﻩew_time =3;
ﻩﻩﻩEW_YELLOW();
ﻩﻩﻩbreak;
ﻩﻩﻩcase 2:
ﻩﻩew_sign = 0;
ﻩew_time =sn_total_time[hour]+3;
ﻩﻩﻩEW_RED();
ﻩbreak;
ﻩﻩ}
}
ﻩﻩif(sn_time== 0)
ﻩ{
ﻩswitch(sn_sign)
ﻩﻩ{
ﻩﻩcase0:
ﻩﻩﻩﻩsn_sign= 1;
ﻩﻩﻩsn_time= sn_total_time[hour];
ﻩSN_GREEN();
ﻩﻩﻩﻩbreak;
ﻩﻩﻩcase1:
ﻩﻩﻩsn_sign=2;
ﻩﻩsn_time=3;
ﻩﻩﻩSN_YELLOW();
ﻩbreak;
ﻩcase 2:
ﻩﻩsn_sign = 0;
ﻩﻩsn_time= ew_total_time[hour] +3;
ﻩﻩSN_RED();
ﻩﻩbreak;
ﻩ}
ﻩ}
ﻩﻩLED_WRITE(ew_time/10,EW_H);
ﻩLED_WRITE(ew_time%10,EW_L);
ﻩﻩLED_WRITE(sn_time/10,SN_H);
ﻩﻩLED_WRITE(sn_time%10,SN_L);
}
}
//main函数到此结束,以下是所用到函数的定义
/*所用函数的定义*/
voidLED_INIT()
{
ﻩLED=0x00;
ﻩEW_weixuan_H=1;
ﻩEW_weixuan_L=1;
ﻩSN_weixuan_H=1;
ﻩSN_weixuan_L=1;
}
void LED_WRITE(intdat,intcon)
{
EW_weixuan_H=0;
ﻩEW_weixuan_L=0;
SN_weixuan_H=0;
SN_weixuan_L=0;
ﻩif(dat <10)
{
ﻩLED= LED_CODE[dat];
ﻩswitch(con)
ﻩ{
caseEW_H:
ﻩ{
ﻩﻩEW_weixuan_H=1;
ﻩbreak;
ﻩﻩ}
ﻩﻩcaseEW_L:
ﻩﻩ{
ﻩﻩEW_weixuan_L= 1;
ﻩﻩﻩbreak;
ﻩﻩﻩ}
ﻩcaseSN_H:
ﻩ{
ﻩﻩSN_weixuan_H=1;
ﻩﻩﻩbreak;
ﻩﻩ}
caseSN_L:
ﻩﻩﻩ{
ﻩSN_weixuan_L= 1;
ﻩﻩbreak;
ﻩ}
}
ﻩ}
}
void timer_int()interrupt0
{
ﻩEA=0;
counter--;
switch(hour)
ﻩ{
ﻩﻩcase0:
ﻩﻩcase1:
ﻩcase 2:
case 3:
case 4:
ﻩﻩﻩEW_YELLOW();
ﻩSN_YELLOW();
ﻩﻩEW_NONE();
ﻩSN_NONE();
ﻩﻩbreak;
ﻩﻩdefault:
ﻩﻩew_time--;
ﻩsn_time--;
if(ew_sign==1 &&ew_time<=3&&ew_time >0)
ﻩ{ﻩﻩ
ﻩﻩﻩEW_GREEN();
ﻩEW_NONE();
ﻩﻩﻩ}
ﻩif(sn_sign==1&& sn_time<=3&&sn_time>0)
ﻩﻩﻩ{
ﻩﻩSN_GREEN();
SN_NONE();
ﻩﻩﻩ}
ﻩﻩbreak;
}
ﻩEA=1;
}
/* 延迟函数定义*/
voidDELAY2()
{
ﻩ_nop_();
_nop_();
}//延迟2us
void DELAY4()
{
ﻩDELAY2();
DELAY2();
}//延迟4us
voidDELAY8()
{
DELAY4();
ﻩDELAY4();
}//延迟8us
//
voidIIC_WRITE(unsigned chardat)
{
unsignedchartemp;
ﻩfor(temp= 0;temp< 8;temp++)
{
ﻩSCL=0;
if((dat <<temp) & 0x80)
ﻩ{
ﻩSDA=1;
ﻩ}
else
ﻩﻩ{
ﻩﻩSDA=0;
ﻩﻩ}
DELAY2();
SCL=1;
DELAY4();
SCL=0;
}
ﻩDELAY4();
SDA=1;
DELAY2();
ﻩSCL=1;
DELAY4();
SCL=0;
}
unsignedchar GET_HOUR()
{
//START
hour=0;
unsignedchar temp;
ﻩSDA= 1;
SCL=1;
ﻩDELAY8();
SDA =0;
ﻩDELAY8();
ﻩ
//WRITE
IIC_WRITE(0XD0);
ﻩ
//HOURADDRESS
IIC_WRITE(0X02);
//RESTART
SDA=1;
ﻩSCL= 1;
DELAY8();
ﻩSDA=0;
DELAY8();
ﻩ
//READ
IIC_WRITE(0XD1);
ﻩ
//READHOUR
SDA=1;
ﻩfor(temp=0; temp<8;temp++)
{
ﻩhour= hour<<1;
SCL=1;
ﻩDELAY2();
if(SDA ==1)
ﻩ{
ﻩﻩhour++;
ﻩﻩ}
SCL=0;
}
ﻩ
//SENDNOACK
SDA =1;
SCL=1;
DELAY4();
SCL=0;
//STOP
ﻩSDA = 0;
ﻩSCL =1;
DELAY8();
ﻩSDA=1;
DELAY4();
SCL =0;
ﻩreturnhour;
}
四、心得体会
通过这次的实验设计,我深入了对单片机的了解,也明白了日常生活中处处有自动控制的例子,其中不乏有各种系列的单片机,同时我也认识到对单片机的学习应该更加深入才能得心应手,虽然只是一个芯片而已,但是如果你具备足够的知识,就可以充分利用,根据自己的设想就可以做出各种实用的东西,而我现在发现自己基本还处于初级阶段,需要更加努力,特别是编程能力,当然也有收获,首先我对protel的使用更有信心了,又发现了其中的一些功能,同时我也了解了一些其它芯片,比如EEPROM存储芯片AT24C02的非易失性,DS1302时钟芯片可以精确的计时,为了与电脑进行串口通讯必须采用转串口芯片比如MAX232,从而实现单片机的TTL电平到RS232电平的转换。
总之这次设计实验收获不少,反省也不少,但重要的是更激发了我对单片机学习的热情。