单片机系统
课程设计
题目名称:基于89C52的智能交通灯设计
专业班级:测控技术与仪器1304班
学生姓名:田留阳
学号:[1**********]1
指导教师:郭广灵
单片机系统 课程设计任务书
目 录
1系统概述···························1
1.1 课程设计目的·························1
1.2 设计内容···························1
1.3 实现目标···························1 2 方案论证····························1
2.1 电源提供方案·························2
2.2 显示界面方案·························2 3 硬件设计····························3
3.1系统的原理方框图·······················3
3.2 主电路····························3
3.3 I/O分配···························6
3.4I/O接线图··························10
3.5 元器件选型··························10 4 软件设计·····························11
4.1 软件设计流程··························12
4.2梯形图·····························13
4.3 交通灯定时器模块·······················14 5系统调试····························14
5.1 软件调试····························14
5.2 硬件调试···························15 设计心得·····························19 参考文献·····························20 附件一······························21 附件二······························22 附件三······························23
1 系统概述
1.1 课程设计的目的
(1)加强对单片机和汇编语言的认识,充分掌握和理解设计各部分 的工作原理、设计过程、选择芯片器件、模块化编程等多项知识。
(2)用单片机模拟实现具体应用,使个人设计能够真正使用。
(3)把理论知识与实践相结合,充分发挥个人能力,并在实践中锻炼。
(4)提高利用已学知识分析和解决问题的能力。
(5)提高实践动手能力。
1.2 设计内容
本系统采用单片机AT89S52来设计交通灯控制器,实现了能根据实际车流量通过AT89S52芯片的P1口设置红、绿灯燃亮时间的功能;红绿灯循环点亮,倒计时剩5秒时黄灯闪烁警示。本系统实用性强、操作简单、扩展功能强。
1.3 实现的目标
通过数码管显示实现各个路口车辆通过或者等待的时间,同时控制按键可以实现对紧急事件的处理。从而从一定程度上解决交通拥挤现象。
2 方案论证
本设计以单片机为核心,以LED数码管作为倒计时指示,根据设计的要求我们考虑了各功能模块的几种设计方案,以求最佳方案,实现实时显示系统各种状态,系统还增设了根据交通拥挤情况可分别设置主干道和次干道的通行时间,以提高效率,缓减交通拥挤。
2.1 电源提供方案
为使模块稳定工作,须有可靠电源。本次设计考虑了两种电源方案:
方案一:采用独立的稳压电源。此方案的优点是稳定可靠,且有各种成熟电路可供选用;缺点是各模块都采用独立电源,会使系统复杂,且可能影响电路电平。
方案二:采用单片机控制模块提供电源。该方案的优点是系统简明扼要,节约成本;缺点是输出功率不高。
综上所述,选择第二种方案。
2.2 显示界面方案
该系统要求完成倒计时功能。基于上述原因,本次设计考虑了两种方案: 方案一:完全采用点阵式LED显示。这种方案功能强大,可方便的显示各种英文字符,汉字,图形等,但实现复杂,且须完成大量的软件工作。
方案二:完全采用数码管显示。这种方案优点是实现简单,可以完成倒计时功能。缺点是功能较少,只能显示有限的符号和数码字符。根据本设计的要求,方案二已经满足了要求,所以本次设计采用方案二以实现系统的显示功能。
2.3 输入方案
这里同样讨论了两种方案:
方案一:采用8155扩展I/O口、键盘及显示等。该方案的优点是使用灵活可编程,并且有RAM及计数器。若用该方案,可提供较多I/O口,但操作起来稍显复杂。
方案二:直接在I/O口线上接上按键开关。因为设计时精简和优化了电路,所以剩余的端口资源还比较多。
由于该系统是对交通灯及数码管的控制,只需用单片机本身的I/O口就可实现,且本身的计数器及RAM已经够用,故选择方案二。
3硬件设计
3.1系统的原理方框图
交通灯控制的框图如下图所示,主要有控制电路、按键电路、晶振电路、复位电路、显示电路、电源电路等电路组成。
图3.1:方框图
3.2主电路
3.2.1 复位电路设计
MCS-52的复位输入引脚RST为MCS-52提供了初始化的手段,可以使程序从指定处开始执行,在MCS-52的时钟电路工作后,只要RST引脚上出现超过两个机器周期以上的高电平时,即可产生复位的操作,只要RST保持高电平,则MCS-52循环复位,只有单RET由高电平变成低电平以后,MCS-52才从0000H地址开始执行程序,本系统采用按键复位方式的复位电路。
图3.2.1:复位电路
3.2.2 外部晶振时钟电路设计
MCS-52的时钟可以由两种方式产生,一种是内部方式,利用芯片内部的振荡电路;另外一种为外部方式,本论文根据实际需要和简便,采用内部振荡方式,MCS-52内部有一个用于构成振荡器的高增益反相放大器,引脚XTAL1和XTAL2分别是此放大器的输入端和输出端,这个放大器与作为反馈元件的片外晶体或陶瓷谐振器一起构成了一个自激振荡器。
MCS-52虽然有内部振荡电路,但要形成时钟,必须外接元件,所以实际构成的振荡时钟电路,外接晶振以及电容C1和C2构成了并联谐振电路接在放大器的反馈回路中,对接电容的值虽然没有严格的要求,但电容的大小会影响振荡频率的高低,振荡器的稳定性,起振的快速性和温度的稳定性。晶振的频率可在
1.2MHZ~12MHZ之间任选,电容C1和C2的典型值在20pf~100pf之间选择,由于本系统用到定时器,为了方便计算,采用了12MHZ的晶振,采用电容选择30pf。
图3.2.2:外部晶振时钟电路
3.2.3显示模块电路设计
该模块由共阳LED数码管组成,利用数码管的动态扫描原理,由三极管进行锁存,当控制数码管的IO口P20和P21为低电平时(及三极管基极为低电平),则三极管导通,VCC通三极管给数码管供电,则数码管被点亮,利用数码管点亮的余辉和人眼的视觉暂留原理,则看起来数码管是同时被点亮的。
图3.2.3:显示模块电路
从设计完成的任务与要求来看,显示通行时间必须用二位数码管,从节省硬件资源的角度考虑,可采用扫描的方式来处理,对于7段数码管,占用7个单片机的I/O口,另外设置2个电子开关对2位显示进行配合,占用2个I/O端口,十字路口共需4组红绿灯,加上转换黄灯,一共是12只灯,须用12个端口进行控制,加上两个方向的紧急通行按钮,占2个I/O端口和一个蜂鸣器端口,因此实际占用的单片机I/O口为24个,为此,我们可以选用51系列单片机中的ATAT89S52来作为中央处理器。这款单片机的I/O口作为输出时,具有较大的吸收电流能力,因此我们可以选用共阳型数码管,这样由单片机的I/O口就可以直接驱动,能简化硬件电路的设计。
3.3I/O分配
AT89S52单片机是一款低功耗、低电压、高性能CMOS8位单片机,片内含8KB(可经受1000次擦写周期)的FLASH可编程可反复擦写的只读程序存储器(EPROM),器件采用CMOS工艺和ATMEL公司的高密度,非易失性存储器(NURAM)技术制造,其输出引脚和指令系统都与MCS-51兼容,片内的FLASH存储器允许在系统内可改编程序或用常规的非易失性存储编程器来编程。因此,AT89C52是一种功能强,灵活性高且价格合理的单片机,可方便的应用在各个控制领域。
AT89S52具有以下主要性能:
1.8KB可改编程序FLASH存储器;
2.全表态工作 :0~24HZ;
3.256X8字节内部RAM;
4.32个外部双向输入,输出(I、O)口;
引脚说明如下图所示。
图3.3:引脚图
引脚功能说明如下:
VCC:电源电压。
GND:地。
P0口:P0口是一组8位漏极开路型双向I/O口,也即地址/数据线复用口。作为输出口时,每位能吸收电流的方式驱动8个TTL逻辑门电路,对端口写“1”可作为高阻抗输入端。
在访问外部数据储存器或程序储存器时,这组口线分时转换地址(低8位)和数据总线复用,在访问期间激活内部上拉电阻。FLASH编程时,P0口接收指令字节,而在程序校验时,输出指令字节,校验时,要求外接上拉电阻。
P1口:P1是一个带内部上拉电阻的8位双向I/O口,P1的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作为输入口。作为输入口使用时,
因为内部存在
上拉电阻,某个引脚被外部信号拉低时会输出一个电流。FLASH编程和程序校验期间,P1接收低8位地址。
P2口:P2是一个带内部上拉电阻的8位双向I/O口,P2的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作为输入口。作为输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流。在访问外部程序储存器或16位地址的外部数据储存器(例如执行MOVX@DPTR指令)时,P2口送出高8位地址数据。在访问8位地址的外部数据储存器(例如执行MOVX@RI指令)时,P2口线上的内容(也即特殊功能寄存器(SFR)区中R2寄存器的内容),在整个访问期间不改变。P3口:P3是一个带内部上拉电阻的8位双向I/O口,P3的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作为输入口。作为输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流。
P3除了作为一般的I/O口线外,更重要的用途是它的第二功能,具体功能说明如表3-1。
P3口还接收一些用于FLASH闪速存储器编程和程序校的控制信号。 RST:复位输入。当振荡器工作时,RST引脚出现两个机器周期以上高电平将使单片机复位
ALE/PROG:当访问外部程序存储器或数据存储器时,ALE(地址锁存允许)输出脉冲用于锁存地址的低8位字节。
表3-1 P3口的第二功能表
不访问外部存储器,ALE仍以是时钟振荡频率的1/6输出固定的正脉冲信号,因此他可对外输出时钟或用于定时目的。要注意的是:每当访问外部数据存储器时将跳过一个ALE脉冲。对FLASH存储器编程期间,该引脚还用于输入编程脉冲(PROG)。
如有必要,可通过对特殊功能寄存器(SFR)区中的8EH单元的D0位置位,可禁止ALE操作。该位置位后,只有一条MOVX和MOVC指令ALE才会被激活。此外,该引脚会被微弱拉高,单片机执行外部程序时,应设置ALE无效。
PSEN:程序储存允许(PSEN)输出是外部程序存储器的读选通信号,当AT80C51由外部程序存储器取指令(或数据)时,每个机器周期两次PSEN有效,即输出两个脉冲。在此期间,当访问外部数据存储器,这两次有效的PSEN信号不出现。
EA/VPP:外部访问允许。欲使CPU仅访问外部程序储存器(地址为0000H-FFFFH),EA端必须保持低电平(接地)。需要注意的是:如果加密位LB1被编程,复位时内部会锁存EA端状态。如EA端为高电平(Vcc端),CPU则执行内部程序储存器中的指令。
FLASH储存器编程时,该引脚加上+12V的编程允许电源Vpp,当然这必须是该器件是使用12v编程电压。
XTAL1:振荡器反相放大器的及内部时钟发生器的输入端。 XTAL2:振荡器反相放大器的输出端
3.4 I/O接线图
接线图如下图所示:
图3.4:接线图
3.5 元器件选型
3.5.1 三极管选型
三极管选型时,以下几个参数必须考虑:
(1)ICM集电极最大允许电流
(2)BVCEO,基极开路时,集电极-发射极反向击穿电压 > 电源电压 * 70%,有感电路 降额使用,并加保护电路;
(3) PCM,集电极最大允许耗散功率,降额70%使用。 基于小功率的考虑,本次设计采用了9012系列的三极管。 具体实物如下图所示:
图1:电路图 图2:实物
3.5.2 自锁开关选型
图3:实物 图4:电路如下所示
4 软件设计
4.1 软件设计思想
软件总体设计主要完成各部分的软件控制和协调。本系统主程序模块主要完成的工作是对系统的初始化,发送显示数据,同时对键盘进行扫描,等待外部中断,以及根据所需要的功能进行相应的操作。
交通灯根据其显示情况可以分为四个状态,可以通过定时来控制每个状态的时间;通过定时也可以向LED数码管中每隔1秒送一个数,显示该状态剩余的时间。其流程图如图所示。
图4.1:流程图
图4.1.2:交通灯运行状态
4.2 流程图
主程序流程图如下图所示:
4.3 交通灯定时器模块
AT89S52单片机内部有3个定时器T0,T1和T2,本次设计中使用T0工作在方式1,即16位定时器,定时50ms,20次中断产生秒信号,从而控制红绿灯的点亮时间。
工作方式寄存器TMOD用来设置T0、T1的工作方式。这次实习中设置TMOD=0x01,即T0工作于方式0(16位定时器)。
内部定时器/计数器用作定时器时,是对机器周期计数,每个机器周期的长度是12个振荡周期。定时常数的设置可用一下方式计算:
机器周期=12/12MHz=1us (65536-定时常数)*1.0us=50ms 所以定时常数是50000。
5 系统调试
5.1 软件调试
初步测试时,出现提示如图1所示
图1:软件调试
出错原因:没有开机自检初始化 当再次测试时,出现下列错误:
图2:软件调试
出错原因:缺少宏定义
5.2 硬件调试
图1:硬件调试
出错原因:数码管管脚没有连接正确
图2:硬件调试
出错原因:经检验,不是软件的问题,并且用万用表检测后确定是二极管出故障。
图3:硬件调试
出错原因:经过不停地检验,确定不是软件问题,硬件连接的电路也没出错,检测到是线路连接不稳定。
经过不停地调试后,正常工作情况如下图所示;
图4:正常情况
紧急情况下如下图所示:
图5:紧急情况下
设计心得
本文介绍了一种基于AT89S52单片机的交通灯的设计方法,完成了系统的硬件设计与制作,详细介绍了系统硬件设计的过程,并结合软件系统完成了整个系统的软、硬件联调,系统工作良好,实现了基本功能。
通过本次设计,巩固了我学习过的专业知识,也使我把理论与实践从真正意义上相结合了起来,锻炼了借助互联网络搜集、查阅相关文献资料和组织材料的综合能力,从中我也认识到自己的不足之处,我会在日后的学习中加以改进与提高。
经过这次课程设计,我在各方面都有很大的提高。学到了很多不曾学过的东西,也使我学会了更好地利用一些资源和工具如图书馆及一些软件查阅资料。在设计过程中也遇到很多的困难,遇到一些原理性不懂的时候就要去有针对性地查找资料或者请教知道老师和其他同学,然后加以吸收利用,提高了自己的应用能力,扩充了自己的知识储备,同时提高了动手能力。
本次课程设计让我认识到自己的动手能力还有待提高,而且我准备在后期增加一个红外线传感器,来检测车流量,从而实现交通灯根据具体情况自行设置时间。
参 考 文 献
[1] 刘勇.数字电路[M].电子工业出版社.2004
[2] 杨子文.单片机原理及应用[M].西安电子科技大学出版社.2006
[3] 刘华东.单片机原理与应用(第2版)[M].电子工业出版社.2006.8 [4] 胡汉才.单片机原理及其接口技术[M].清华大学出版社,2006.
[5] 沈精虎.电路设计与制版Protel99入门与提高[M].人民邮电出版社,2004. [6] 范风强,兰婵丽.单片机语言C51应用实战集锦[M].电子工业出版社.,2001.
附件一:
元件清单如下图所示:
系统原理图如图所示:
源程序如下:
#include //调用单片机头文件
#define uchar unsigned char //宏定义"uchar"代替"unsigned char"。 #define uint unsigned int //宏定义"uint"用来定义无符号整型数。
#include "eeprom52.h"
//数码管段选定义 0 1 2 3 4 5 6 7 8 9 uchar smg_du[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, // A B C D E F 不显示
0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff}; //断码
uchar dis_smg[8] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8}; uchar smg_i = 4; //显示数码管的个位数
//数码管位选定义
sbit smg_we1 = P2^0; //数码管位选定义 sbit smg_we2 = P2^1; sbit smg_we3 = P3^6; sbit smg_we4 = P3^7;
char dx_s = 0; //东西 南北 倒计时变量 sbit dx_red = P2^4; //东西红灯 sbit dx_green = P2^3; //东西绿灯 sbit dx_yellow = P2^2; //东西黄灯
sbit nb_red = P2^7; //南北红灯 sbit nb_green = P2^6; //南北绿灯 sbit nb_yellow = P2^5; //南北黄灯
uchar flag_jtd_mode; //交通灯的模式 根据时间 bit flag_1s = 0; bit flag_500ms;
bit flag_dx_nb; //东西南北模式
code
uchar flag_5m_value;
uchar i;
uchar flag_alarm; //模式
uchar dx_time = 30,nb_time = 20; //东西、南北的时间 uchar flag_jdgz ; //交通管制
/***********************数码位选函数*****************************/ void smg_we_switch(uchar i) {
switch(i)
{
case 0: smg_we1 = 0; smg_we2 = 1; smg_we3 = 1; smg_we4 = 1; break; case 1: smg_we1 = 1; smg_we2 = 0; smg_we3 = 1; smg_we4 = 1; break; case 2: smg_we1 = 1; smg_we2 = 1; smg_we3 = 0; smg_we4 = 1; break; case 3: smg_we1 = 1; smg_we2 = 1; smg_we3 = 1; smg_we4 = 0; break; } }
/******************把数据保存到单片机内部eeprom中******************/ void write_eeprom() {
SectorErase(0x2000);
byte_write(0x2000, dx_time); byte_write(0x2001, nb_time);
byte_write(0x2058, a_a); }
/******************把数据从单片机内部*****************/ void read_eeprom() {
dx_time = byte_read(0x2000); nb_time = byte_read(0x2001);
a_a = byte_read(0x2058); }
eeprom中读出来
/**************开机自检eeprom初始化*****************/ void init_eeprom() ///开机自检eeprom初始化 {
read_eeprom(); //先读
if(a_a != 1) //新的单片机初始单片机内问eeprom {
a_a = 1;
dx_time = 30;
nb_time = 20; //东西、南北的时间 write_eeprom(); //保存数据
} }
/******************************************************************** * 名称 : delay_1ms() * 功能 : 延时1ms函数 * 输入 : q * 输出 : 无
***********************************************************************/
void delay_1ms(uint q) {
uint i,j;
for(i=0;i
for(j=0;j
/******************************************************************** * 名称 : display() * 功能 : 数码管显示 * 输入 : 无 * 输出 : 无
***********************************************************************/
void display()
uchar i;
for(i=0;i
P0 = 0xff; //消隐 smg_we_switch(i); //位选 P0 = dis_smg[i]; //段选 delay_1ms(3); }
}
/*********************定时器0、定时器1初始化******************/ void time0_init() {
EA = 1; //开总中断
TMOD = 0X11; //定时器0、定时器1工作方式1 ET0 = 1; //开定时器0中断 TR0 = 1; //允许定时器0定时 // ET1 = 1; //开定时器1中断 // TR1 = 1; //允许定时器1定时 }
/*********************交通灯处理函*********************************/ void jiaotongdeng_dis() {
if(flag_1s == 1) {
flag_1s = 0; if(dx_s == 0) {
if(flag_dx_nb == 1)
dx_s = nb_time; //南北时间 else
dx_s = dx_time; //东西时间 flag_dx_nb = ~flag_dx_nb; }
dx_s --;
数
}
dis_smg[0] = smg_du[dx_s % 10] ; dis_smg[1] = smg_du[dx_s / 10] ; dis_smg[2] = smg_du[dx_s % 10] ; dis_smg[3] = smg_du[dx_s / 10] ;
/***********************南北时间*********************************/ if(flag_dx_nb == 0) {
if(dx_s > 5) {
dx_red = 1; //灭 dx_green = 0; //亮 dx_yellow = 1; //灭 nb_red = 0; //亮 nb_green = 1; //灭 nb_yellow = 1; //灭 flag_5m_value = 0;
}else if(dx_s
dx_red = 1; //灭 dx_green = 1; //灭 nb_red = 0; //亮 nb_green = 1; //灭 nb_yellow = 1; //灭 if(flag_500ms == 0) {
dx_yellow = 0;//亮 }
else
{
dx_yellow = 1;//灭 } } }
/***********************东西时间*********************************/ if(flag_dx_nb == 1) {
{
dx_red = 0; //亮 dx_green = 1; //灭 dx_yellow = 1; //灭 nb_red = 1; //灭 nb_green = 0; //亮 nb_yellow = 1; //灭 flag_5m_value = 0;
}else if(dx_s
dx_red = 0; //灭 dx_green = 1; //灭 dx_yellow = 1; //灭 nb_red = 1; //灭 nb_green = 1; //灭
if(flag_500ms == 0) //黄灯闪烁 {
nb_yellow = 0; //亮 }
else {
nb_yellow = 1; //灭 } } } }
/********************独立按键程序*****************/ uchar key_can; //按键值
void key() //独立按键程序 {
static uchar key_new;
key_can = 20; //按键值还原 P1 |= 0x1f;
if((P1 & 0x1f) != 0x1f) //按键按下 {
28
if(((P1 & 0x1f) != 0x1f) && (key_new == 1)) { //确认是按键按下 key_new = 0;
switch(P1 & 0x1f) {
case 0x1e: key_can = 1; break; //得到按键值 case 0x1d: key_can = 2; break; //得到按键值 case 0x1b: key_can = 3; break; //得到按键值 case 0x17: key_can = 4; break; //得到按键值 }
} }
else
key_new = 1; }
uchar menu_1,flag_s;
/********************设置函数*****************/ void key_with() {
if(key_can == 4) //交通管制按键 {
flag_jdgz ++; if(flag_jdgz > 5) flag_jdgz = 0;
if(flag_jdgz == 1) // 全部亮红灯 {
dx_red = 0; //亮 dx_green = 1; //灭 dx_yellow = 1; //灭 nb_red = 0; //亮 nb_green = 1; //灭
nb_yellow = 1; //灭 }
if(flag_jdgz == 2) // 东西红灯 南北绿灯
29
dx_red = 0; //亮 dx_green = 1; //灭 dx_yellow = 1; //灭 nb_red = 1; //灭 nb_green = 0; //亮
nb_yellow = 1; //灭 }
if(flag_jdgz == 3) // 南北红灯 {
dx_red = 1; //灭
dx_green = 0; //亮 dx_yellow = 1; //灭 nb_red = 0; //亮 nb_green = 1; //灭
nb_yellow = 1; //灭 }
if(flag_jdgz == 4) // 南北绿灯 {
dx_red = 1; //灭
dx_green = 0; //亮 dx_yellow = 1; //灭 nb_red = 1; //灭 nb_green = 0; //亮
nb_yellow = 1; //灭 }
if(flag_jdgz == 5) // 南北黄灯 {
dx_red = 1; //灭
dx_green = 1; //灭
dx_yellow = 0; //亮 nb_red = 1; //灭 nb_green = 1; //灭 nb_yellow = 0; //亮 } }
if(key_can == 1) //设置键 {
30
东西绿灯东西绿灯东西黄灯
}
if(menu_1 >= 3) {
menu_1 = 0; }
if(menu_1 == 1) //设置东西的时间 {
if(key_can == 2) { dx_time ++ ; //加1 if(dx_time > 99) dx_time = 99; }
if(key_can == 3) {
dx_time -- ; //减1 if(dx_time
dx_time = 10;
}
dis_smg[0] = smg_du[10] ; //显示为A dis_smg[1] = smg_du[10] ; //显示为A dis_smg[2] = smg_du[dx_time % 10] ; dis_smg[3] = smg_du[dx_time / 10] ; write_eeprom(); //保存数据 }
if(menu_1 == 2) //设置南北的时间 {
if(key_can == 2) {
nb_time ++ ; //加1 if(nb_time > 99) nb_time = 99; }
if(key_can == 3) {
nb_time -- ; //减1
31
//显示东西设置的时候
}
}
nb_time = 10; }
dis_smg[0] = smg_du[11] ; //显示为B dis_smg[1] = smg_du[11] ; //显示为B dis_smg[2] = smg_du[nb_time % 10] ; dis_smg[3] = smg_du[nb_time / 10] ; write_eeprom(); //保存数据
//显示东西设置的时候
/******************************************************************** * 名称 : main()
* 功能 : 实现灯的闪烁 * 输入 : 无 * 输出 : 无
***********************************************************************/
void main()
{
time0_init();
init_eeprom(); ///开机自检eeprom初始化 dx_s = nb_time; //东西时间 while(1) {
key();
if(key_can
if((menu_1 == 0) && (flag_jdgz == 0)) jiaotongdeng_dis(); display(); } }
/*********************定时器0中断服务程序************************/ void time0_int() interrupt 1
32
{
static uchar value; //定时10ms中断一次 TH0 = 0x3c;
TL0 = 0xb0; //50ms value ++;
flag_5m_value++;
if(flag_5m_value % 10 == 0) flag_500ms = ~flag_500ms; if(value >= 20) {
value = 0;
flag_1s = 1; } }
33
34
单片机系统
课程设计
题目名称:基于89C52的智能交通灯设计
专业班级:测控技术与仪器1304班
学生姓名:田留阳
学号:[1**********]1
指导教师:郭广灵
单片机系统 课程设计任务书
目 录
1系统概述···························1
1.1 课程设计目的·························1
1.2 设计内容···························1
1.3 实现目标···························1 2 方案论证····························1
2.1 电源提供方案·························2
2.2 显示界面方案·························2 3 硬件设计····························3
3.1系统的原理方框图·······················3
3.2 主电路····························3
3.3 I/O分配···························6
3.4I/O接线图··························10
3.5 元器件选型··························10 4 软件设计·····························11
4.1 软件设计流程··························12
4.2梯形图·····························13
4.3 交通灯定时器模块·······················14 5系统调试····························14
5.1 软件调试····························14
5.2 硬件调试···························15 设计心得·····························19 参考文献·····························20 附件一······························21 附件二······························22 附件三······························23
1 系统概述
1.1 课程设计的目的
(1)加强对单片机和汇编语言的认识,充分掌握和理解设计各部分 的工作原理、设计过程、选择芯片器件、模块化编程等多项知识。
(2)用单片机模拟实现具体应用,使个人设计能够真正使用。
(3)把理论知识与实践相结合,充分发挥个人能力,并在实践中锻炼。
(4)提高利用已学知识分析和解决问题的能力。
(5)提高实践动手能力。
1.2 设计内容
本系统采用单片机AT89S52来设计交通灯控制器,实现了能根据实际车流量通过AT89S52芯片的P1口设置红、绿灯燃亮时间的功能;红绿灯循环点亮,倒计时剩5秒时黄灯闪烁警示。本系统实用性强、操作简单、扩展功能强。
1.3 实现的目标
通过数码管显示实现各个路口车辆通过或者等待的时间,同时控制按键可以实现对紧急事件的处理。从而从一定程度上解决交通拥挤现象。
2 方案论证
本设计以单片机为核心,以LED数码管作为倒计时指示,根据设计的要求我们考虑了各功能模块的几种设计方案,以求最佳方案,实现实时显示系统各种状态,系统还增设了根据交通拥挤情况可分别设置主干道和次干道的通行时间,以提高效率,缓减交通拥挤。
2.1 电源提供方案
为使模块稳定工作,须有可靠电源。本次设计考虑了两种电源方案:
方案一:采用独立的稳压电源。此方案的优点是稳定可靠,且有各种成熟电路可供选用;缺点是各模块都采用独立电源,会使系统复杂,且可能影响电路电平。
方案二:采用单片机控制模块提供电源。该方案的优点是系统简明扼要,节约成本;缺点是输出功率不高。
综上所述,选择第二种方案。
2.2 显示界面方案
该系统要求完成倒计时功能。基于上述原因,本次设计考虑了两种方案: 方案一:完全采用点阵式LED显示。这种方案功能强大,可方便的显示各种英文字符,汉字,图形等,但实现复杂,且须完成大量的软件工作。
方案二:完全采用数码管显示。这种方案优点是实现简单,可以完成倒计时功能。缺点是功能较少,只能显示有限的符号和数码字符。根据本设计的要求,方案二已经满足了要求,所以本次设计采用方案二以实现系统的显示功能。
2.3 输入方案
这里同样讨论了两种方案:
方案一:采用8155扩展I/O口、键盘及显示等。该方案的优点是使用灵活可编程,并且有RAM及计数器。若用该方案,可提供较多I/O口,但操作起来稍显复杂。
方案二:直接在I/O口线上接上按键开关。因为设计时精简和优化了电路,所以剩余的端口资源还比较多。
由于该系统是对交通灯及数码管的控制,只需用单片机本身的I/O口就可实现,且本身的计数器及RAM已经够用,故选择方案二。
3硬件设计
3.1系统的原理方框图
交通灯控制的框图如下图所示,主要有控制电路、按键电路、晶振电路、复位电路、显示电路、电源电路等电路组成。
图3.1:方框图
3.2主电路
3.2.1 复位电路设计
MCS-52的复位输入引脚RST为MCS-52提供了初始化的手段,可以使程序从指定处开始执行,在MCS-52的时钟电路工作后,只要RST引脚上出现超过两个机器周期以上的高电平时,即可产生复位的操作,只要RST保持高电平,则MCS-52循环复位,只有单RET由高电平变成低电平以后,MCS-52才从0000H地址开始执行程序,本系统采用按键复位方式的复位电路。
图3.2.1:复位电路
3.2.2 外部晶振时钟电路设计
MCS-52的时钟可以由两种方式产生,一种是内部方式,利用芯片内部的振荡电路;另外一种为外部方式,本论文根据实际需要和简便,采用内部振荡方式,MCS-52内部有一个用于构成振荡器的高增益反相放大器,引脚XTAL1和XTAL2分别是此放大器的输入端和输出端,这个放大器与作为反馈元件的片外晶体或陶瓷谐振器一起构成了一个自激振荡器。
MCS-52虽然有内部振荡电路,但要形成时钟,必须外接元件,所以实际构成的振荡时钟电路,外接晶振以及电容C1和C2构成了并联谐振电路接在放大器的反馈回路中,对接电容的值虽然没有严格的要求,但电容的大小会影响振荡频率的高低,振荡器的稳定性,起振的快速性和温度的稳定性。晶振的频率可在
1.2MHZ~12MHZ之间任选,电容C1和C2的典型值在20pf~100pf之间选择,由于本系统用到定时器,为了方便计算,采用了12MHZ的晶振,采用电容选择30pf。
图3.2.2:外部晶振时钟电路
3.2.3显示模块电路设计
该模块由共阳LED数码管组成,利用数码管的动态扫描原理,由三极管进行锁存,当控制数码管的IO口P20和P21为低电平时(及三极管基极为低电平),则三极管导通,VCC通三极管给数码管供电,则数码管被点亮,利用数码管点亮的余辉和人眼的视觉暂留原理,则看起来数码管是同时被点亮的。
图3.2.3:显示模块电路
从设计完成的任务与要求来看,显示通行时间必须用二位数码管,从节省硬件资源的角度考虑,可采用扫描的方式来处理,对于7段数码管,占用7个单片机的I/O口,另外设置2个电子开关对2位显示进行配合,占用2个I/O端口,十字路口共需4组红绿灯,加上转换黄灯,一共是12只灯,须用12个端口进行控制,加上两个方向的紧急通行按钮,占2个I/O端口和一个蜂鸣器端口,因此实际占用的单片机I/O口为24个,为此,我们可以选用51系列单片机中的ATAT89S52来作为中央处理器。这款单片机的I/O口作为输出时,具有较大的吸收电流能力,因此我们可以选用共阳型数码管,这样由单片机的I/O口就可以直接驱动,能简化硬件电路的设计。
3.3I/O分配
AT89S52单片机是一款低功耗、低电压、高性能CMOS8位单片机,片内含8KB(可经受1000次擦写周期)的FLASH可编程可反复擦写的只读程序存储器(EPROM),器件采用CMOS工艺和ATMEL公司的高密度,非易失性存储器(NURAM)技术制造,其输出引脚和指令系统都与MCS-51兼容,片内的FLASH存储器允许在系统内可改编程序或用常规的非易失性存储编程器来编程。因此,AT89C52是一种功能强,灵活性高且价格合理的单片机,可方便的应用在各个控制领域。
AT89S52具有以下主要性能:
1.8KB可改编程序FLASH存储器;
2.全表态工作 :0~24HZ;
3.256X8字节内部RAM;
4.32个外部双向输入,输出(I、O)口;
引脚说明如下图所示。
图3.3:引脚图
引脚功能说明如下:
VCC:电源电压。
GND:地。
P0口:P0口是一组8位漏极开路型双向I/O口,也即地址/数据线复用口。作为输出口时,每位能吸收电流的方式驱动8个TTL逻辑门电路,对端口写“1”可作为高阻抗输入端。
在访问外部数据储存器或程序储存器时,这组口线分时转换地址(低8位)和数据总线复用,在访问期间激活内部上拉电阻。FLASH编程时,P0口接收指令字节,而在程序校验时,输出指令字节,校验时,要求外接上拉电阻。
P1口:P1是一个带内部上拉电阻的8位双向I/O口,P1的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作为输入口。作为输入口使用时,
因为内部存在
上拉电阻,某个引脚被外部信号拉低时会输出一个电流。FLASH编程和程序校验期间,P1接收低8位地址。
P2口:P2是一个带内部上拉电阻的8位双向I/O口,P2的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作为输入口。作为输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流。在访问外部程序储存器或16位地址的外部数据储存器(例如执行MOVX@DPTR指令)时,P2口送出高8位地址数据。在访问8位地址的外部数据储存器(例如执行MOVX@RI指令)时,P2口线上的内容(也即特殊功能寄存器(SFR)区中R2寄存器的内容),在整个访问期间不改变。P3口:P3是一个带内部上拉电阻的8位双向I/O口,P3的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作为输入口。作为输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流。
P3除了作为一般的I/O口线外,更重要的用途是它的第二功能,具体功能说明如表3-1。
P3口还接收一些用于FLASH闪速存储器编程和程序校的控制信号。 RST:复位输入。当振荡器工作时,RST引脚出现两个机器周期以上高电平将使单片机复位
ALE/PROG:当访问外部程序存储器或数据存储器时,ALE(地址锁存允许)输出脉冲用于锁存地址的低8位字节。
表3-1 P3口的第二功能表
不访问外部存储器,ALE仍以是时钟振荡频率的1/6输出固定的正脉冲信号,因此他可对外输出时钟或用于定时目的。要注意的是:每当访问外部数据存储器时将跳过一个ALE脉冲。对FLASH存储器编程期间,该引脚还用于输入编程脉冲(PROG)。
如有必要,可通过对特殊功能寄存器(SFR)区中的8EH单元的D0位置位,可禁止ALE操作。该位置位后,只有一条MOVX和MOVC指令ALE才会被激活。此外,该引脚会被微弱拉高,单片机执行外部程序时,应设置ALE无效。
PSEN:程序储存允许(PSEN)输出是外部程序存储器的读选通信号,当AT80C51由外部程序存储器取指令(或数据)时,每个机器周期两次PSEN有效,即输出两个脉冲。在此期间,当访问外部数据存储器,这两次有效的PSEN信号不出现。
EA/VPP:外部访问允许。欲使CPU仅访问外部程序储存器(地址为0000H-FFFFH),EA端必须保持低电平(接地)。需要注意的是:如果加密位LB1被编程,复位时内部会锁存EA端状态。如EA端为高电平(Vcc端),CPU则执行内部程序储存器中的指令。
FLASH储存器编程时,该引脚加上+12V的编程允许电源Vpp,当然这必须是该器件是使用12v编程电压。
XTAL1:振荡器反相放大器的及内部时钟发生器的输入端。 XTAL2:振荡器反相放大器的输出端
3.4 I/O接线图
接线图如下图所示:
图3.4:接线图
3.5 元器件选型
3.5.1 三极管选型
三极管选型时,以下几个参数必须考虑:
(1)ICM集电极最大允许电流
(2)BVCEO,基极开路时,集电极-发射极反向击穿电压 > 电源电压 * 70%,有感电路 降额使用,并加保护电路;
(3) PCM,集电极最大允许耗散功率,降额70%使用。 基于小功率的考虑,本次设计采用了9012系列的三极管。 具体实物如下图所示:
图1:电路图 图2:实物
3.5.2 自锁开关选型
图3:实物 图4:电路如下所示
4 软件设计
4.1 软件设计思想
软件总体设计主要完成各部分的软件控制和协调。本系统主程序模块主要完成的工作是对系统的初始化,发送显示数据,同时对键盘进行扫描,等待外部中断,以及根据所需要的功能进行相应的操作。
交通灯根据其显示情况可以分为四个状态,可以通过定时来控制每个状态的时间;通过定时也可以向LED数码管中每隔1秒送一个数,显示该状态剩余的时间。其流程图如图所示。
图4.1:流程图
图4.1.2:交通灯运行状态
4.2 流程图
主程序流程图如下图所示:
4.3 交通灯定时器模块
AT89S52单片机内部有3个定时器T0,T1和T2,本次设计中使用T0工作在方式1,即16位定时器,定时50ms,20次中断产生秒信号,从而控制红绿灯的点亮时间。
工作方式寄存器TMOD用来设置T0、T1的工作方式。这次实习中设置TMOD=0x01,即T0工作于方式0(16位定时器)。
内部定时器/计数器用作定时器时,是对机器周期计数,每个机器周期的长度是12个振荡周期。定时常数的设置可用一下方式计算:
机器周期=12/12MHz=1us (65536-定时常数)*1.0us=50ms 所以定时常数是50000。
5 系统调试
5.1 软件调试
初步测试时,出现提示如图1所示
图1:软件调试
出错原因:没有开机自检初始化 当再次测试时,出现下列错误:
图2:软件调试
出错原因:缺少宏定义
5.2 硬件调试
图1:硬件调试
出错原因:数码管管脚没有连接正确
图2:硬件调试
出错原因:经检验,不是软件的问题,并且用万用表检测后确定是二极管出故障。
图3:硬件调试
出错原因:经过不停地检验,确定不是软件问题,硬件连接的电路也没出错,检测到是线路连接不稳定。
经过不停地调试后,正常工作情况如下图所示;
图4:正常情况
紧急情况下如下图所示:
图5:紧急情况下
设计心得
本文介绍了一种基于AT89S52单片机的交通灯的设计方法,完成了系统的硬件设计与制作,详细介绍了系统硬件设计的过程,并结合软件系统完成了整个系统的软、硬件联调,系统工作良好,实现了基本功能。
通过本次设计,巩固了我学习过的专业知识,也使我把理论与实践从真正意义上相结合了起来,锻炼了借助互联网络搜集、查阅相关文献资料和组织材料的综合能力,从中我也认识到自己的不足之处,我会在日后的学习中加以改进与提高。
经过这次课程设计,我在各方面都有很大的提高。学到了很多不曾学过的东西,也使我学会了更好地利用一些资源和工具如图书馆及一些软件查阅资料。在设计过程中也遇到很多的困难,遇到一些原理性不懂的时候就要去有针对性地查找资料或者请教知道老师和其他同学,然后加以吸收利用,提高了自己的应用能力,扩充了自己的知识储备,同时提高了动手能力。
本次课程设计让我认识到自己的动手能力还有待提高,而且我准备在后期增加一个红外线传感器,来检测车流量,从而实现交通灯根据具体情况自行设置时间。
参 考 文 献
[1] 刘勇.数字电路[M].电子工业出版社.2004
[2] 杨子文.单片机原理及应用[M].西安电子科技大学出版社.2006
[3] 刘华东.单片机原理与应用(第2版)[M].电子工业出版社.2006.8 [4] 胡汉才.单片机原理及其接口技术[M].清华大学出版社,2006.
[5] 沈精虎.电路设计与制版Protel99入门与提高[M].人民邮电出版社,2004. [6] 范风强,兰婵丽.单片机语言C51应用实战集锦[M].电子工业出版社.,2001.
附件一:
元件清单如下图所示:
系统原理图如图所示:
源程序如下:
#include //调用单片机头文件
#define uchar unsigned char //宏定义"uchar"代替"unsigned char"。 #define uint unsigned int //宏定义"uint"用来定义无符号整型数。
#include "eeprom52.h"
//数码管段选定义 0 1 2 3 4 5 6 7 8 9 uchar smg_du[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, // A B C D E F 不显示
0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff}; //断码
uchar dis_smg[8] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8}; uchar smg_i = 4; //显示数码管的个位数
//数码管位选定义
sbit smg_we1 = P2^0; //数码管位选定义 sbit smg_we2 = P2^1; sbit smg_we3 = P3^6; sbit smg_we4 = P3^7;
char dx_s = 0; //东西 南北 倒计时变量 sbit dx_red = P2^4; //东西红灯 sbit dx_green = P2^3; //东西绿灯 sbit dx_yellow = P2^2; //东西黄灯
sbit nb_red = P2^7; //南北红灯 sbit nb_green = P2^6; //南北绿灯 sbit nb_yellow = P2^5; //南北黄灯
uchar flag_jtd_mode; //交通灯的模式 根据时间 bit flag_1s = 0; bit flag_500ms;
bit flag_dx_nb; //东西南北模式
code
uchar flag_5m_value;
uchar i;
uchar flag_alarm; //模式
uchar dx_time = 30,nb_time = 20; //东西、南北的时间 uchar flag_jdgz ; //交通管制
/***********************数码位选函数*****************************/ void smg_we_switch(uchar i) {
switch(i)
{
case 0: smg_we1 = 0; smg_we2 = 1; smg_we3 = 1; smg_we4 = 1; break; case 1: smg_we1 = 1; smg_we2 = 0; smg_we3 = 1; smg_we4 = 1; break; case 2: smg_we1 = 1; smg_we2 = 1; smg_we3 = 0; smg_we4 = 1; break; case 3: smg_we1 = 1; smg_we2 = 1; smg_we3 = 1; smg_we4 = 0; break; } }
/******************把数据保存到单片机内部eeprom中******************/ void write_eeprom() {
SectorErase(0x2000);
byte_write(0x2000, dx_time); byte_write(0x2001, nb_time);
byte_write(0x2058, a_a); }
/******************把数据从单片机内部*****************/ void read_eeprom() {
dx_time = byte_read(0x2000); nb_time = byte_read(0x2001);
a_a = byte_read(0x2058); }
eeprom中读出来
/**************开机自检eeprom初始化*****************/ void init_eeprom() ///开机自检eeprom初始化 {
read_eeprom(); //先读
if(a_a != 1) //新的单片机初始单片机内问eeprom {
a_a = 1;
dx_time = 30;
nb_time = 20; //东西、南北的时间 write_eeprom(); //保存数据
} }
/******************************************************************** * 名称 : delay_1ms() * 功能 : 延时1ms函数 * 输入 : q * 输出 : 无
***********************************************************************/
void delay_1ms(uint q) {
uint i,j;
for(i=0;i
for(j=0;j
/******************************************************************** * 名称 : display() * 功能 : 数码管显示 * 输入 : 无 * 输出 : 无
***********************************************************************/
void display()
uchar i;
for(i=0;i
P0 = 0xff; //消隐 smg_we_switch(i); //位选 P0 = dis_smg[i]; //段选 delay_1ms(3); }
}
/*********************定时器0、定时器1初始化******************/ void time0_init() {
EA = 1; //开总中断
TMOD = 0X11; //定时器0、定时器1工作方式1 ET0 = 1; //开定时器0中断 TR0 = 1; //允许定时器0定时 // ET1 = 1; //开定时器1中断 // TR1 = 1; //允许定时器1定时 }
/*********************交通灯处理函*********************************/ void jiaotongdeng_dis() {
if(flag_1s == 1) {
flag_1s = 0; if(dx_s == 0) {
if(flag_dx_nb == 1)
dx_s = nb_time; //南北时间 else
dx_s = dx_time; //东西时间 flag_dx_nb = ~flag_dx_nb; }
dx_s --;
数
}
dis_smg[0] = smg_du[dx_s % 10] ; dis_smg[1] = smg_du[dx_s / 10] ; dis_smg[2] = smg_du[dx_s % 10] ; dis_smg[3] = smg_du[dx_s / 10] ;
/***********************南北时间*********************************/ if(flag_dx_nb == 0) {
if(dx_s > 5) {
dx_red = 1; //灭 dx_green = 0; //亮 dx_yellow = 1; //灭 nb_red = 0; //亮 nb_green = 1; //灭 nb_yellow = 1; //灭 flag_5m_value = 0;
}else if(dx_s
dx_red = 1; //灭 dx_green = 1; //灭 nb_red = 0; //亮 nb_green = 1; //灭 nb_yellow = 1; //灭 if(flag_500ms == 0) {
dx_yellow = 0;//亮 }
else
{
dx_yellow = 1;//灭 } } }
/***********************东西时间*********************************/ if(flag_dx_nb == 1) {
{
dx_red = 0; //亮 dx_green = 1; //灭 dx_yellow = 1; //灭 nb_red = 1; //灭 nb_green = 0; //亮 nb_yellow = 1; //灭 flag_5m_value = 0;
}else if(dx_s
dx_red = 0; //灭 dx_green = 1; //灭 dx_yellow = 1; //灭 nb_red = 1; //灭 nb_green = 1; //灭
if(flag_500ms == 0) //黄灯闪烁 {
nb_yellow = 0; //亮 }
else {
nb_yellow = 1; //灭 } } } }
/********************独立按键程序*****************/ uchar key_can; //按键值
void key() //独立按键程序 {
static uchar key_new;
key_can = 20; //按键值还原 P1 |= 0x1f;
if((P1 & 0x1f) != 0x1f) //按键按下 {
28
if(((P1 & 0x1f) != 0x1f) && (key_new == 1)) { //确认是按键按下 key_new = 0;
switch(P1 & 0x1f) {
case 0x1e: key_can = 1; break; //得到按键值 case 0x1d: key_can = 2; break; //得到按键值 case 0x1b: key_can = 3; break; //得到按键值 case 0x17: key_can = 4; break; //得到按键值 }
} }
else
key_new = 1; }
uchar menu_1,flag_s;
/********************设置函数*****************/ void key_with() {
if(key_can == 4) //交通管制按键 {
flag_jdgz ++; if(flag_jdgz > 5) flag_jdgz = 0;
if(flag_jdgz == 1) // 全部亮红灯 {
dx_red = 0; //亮 dx_green = 1; //灭 dx_yellow = 1; //灭 nb_red = 0; //亮 nb_green = 1; //灭
nb_yellow = 1; //灭 }
if(flag_jdgz == 2) // 东西红灯 南北绿灯
29
dx_red = 0; //亮 dx_green = 1; //灭 dx_yellow = 1; //灭 nb_red = 1; //灭 nb_green = 0; //亮
nb_yellow = 1; //灭 }
if(flag_jdgz == 3) // 南北红灯 {
dx_red = 1; //灭
dx_green = 0; //亮 dx_yellow = 1; //灭 nb_red = 0; //亮 nb_green = 1; //灭
nb_yellow = 1; //灭 }
if(flag_jdgz == 4) // 南北绿灯 {
dx_red = 1; //灭
dx_green = 0; //亮 dx_yellow = 1; //灭 nb_red = 1; //灭 nb_green = 0; //亮
nb_yellow = 1; //灭 }
if(flag_jdgz == 5) // 南北黄灯 {
dx_red = 1; //灭
dx_green = 1; //灭
dx_yellow = 0; //亮 nb_red = 1; //灭 nb_green = 1; //灭 nb_yellow = 0; //亮 } }
if(key_can == 1) //设置键 {
30
东西绿灯东西绿灯东西黄灯
}
if(menu_1 >= 3) {
menu_1 = 0; }
if(menu_1 == 1) //设置东西的时间 {
if(key_can == 2) { dx_time ++ ; //加1 if(dx_time > 99) dx_time = 99; }
if(key_can == 3) {
dx_time -- ; //减1 if(dx_time
dx_time = 10;
}
dis_smg[0] = smg_du[10] ; //显示为A dis_smg[1] = smg_du[10] ; //显示为A dis_smg[2] = smg_du[dx_time % 10] ; dis_smg[3] = smg_du[dx_time / 10] ; write_eeprom(); //保存数据 }
if(menu_1 == 2) //设置南北的时间 {
if(key_can == 2) {
nb_time ++ ; //加1 if(nb_time > 99) nb_time = 99; }
if(key_can == 3) {
nb_time -- ; //减1
31
//显示东西设置的时候
}
}
nb_time = 10; }
dis_smg[0] = smg_du[11] ; //显示为B dis_smg[1] = smg_du[11] ; //显示为B dis_smg[2] = smg_du[nb_time % 10] ; dis_smg[3] = smg_du[nb_time / 10] ; write_eeprom(); //保存数据
//显示东西设置的时候
/******************************************************************** * 名称 : main()
* 功能 : 实现灯的闪烁 * 输入 : 无 * 输出 : 无
***********************************************************************/
void main()
{
time0_init();
init_eeprom(); ///开机自检eeprom初始化 dx_s = nb_time; //东西时间 while(1) {
key();
if(key_can
if((menu_1 == 0) && (flag_jdgz == 0)) jiaotongdeng_dis(); display(); } }
/*********************定时器0中断服务程序************************/ void time0_int() interrupt 1
32
{
static uchar value; //定时10ms中断一次 TH0 = 0x3c;
TL0 = 0xb0; //50ms value ++;
flag_5m_value++;
if(flag_5m_value % 10 == 0) flag_500ms = ~flag_500ms; if(value >= 20) {
value = 0;
flag_1s = 1; } }
33
34