单片机课设智能交通灯(共27页).doc
精选优质文档-倾情为你奉上序 号11单片机原理及接口技术课程设计说明书题 目: 基于单片机的现代交通灯的设计 学 院: 国际教育学院 班 级: 机电141班 学 号: 4 姓 名: 刘浩乐 指导教师: 徐爱军 日 期: 2017年 9月 30 日 河南科技大学2017 至 2018 学年 第 一 学期专心-专注-专业课程设计任务书 学生姓名: 刘浩乐 班级: 机电141班 学号:4一、 设计题目基于单片机的现代交通灯的设计二、 设计要求设计任务:1. 设计一款带左转、直行、右转三种通行绿灯,参见实物效果图; 2. 带紧急按钮功能,当紧急按钮按下时,所有方向均亮起红灯; 3. 夜间运行模式按钮,按下时,所有方向黄灯闪烁; 4* 可更在线修改红绿灯等待时间; 5* 实现显示倒计时功能; 6 其他功能(创新部分)提示: 1. Proteus里的traffic模块为传统交通灯模型(只有红、绿、黄三色); 现可用单管LED(或LED点阵)来取代左右转指示,或直行指示。2.实物效果图 指导教师: 日期: 2017年 9月 4日目 录1设计目的1.每个方向具有绿灯左拐、右拐、直行,人行道蓝灯,提示红灯、黄灯6种通行指示;2.数码管显示倒计时;3.在紧急情况下按下紧急模式按钮所有路口均亮红灯,蜂鸣器报警提醒;4.夜间按下夜间模式按钮,所有方向的黄灯闪烁;5.普通模式下按下初值设定按钮可修改红绿灯等待间隔时间;6.数码管显示红灯倒计时;7.创新功能: (1)倒计时到3s时蜂鸣器鸣叫;(2)紧急模式下蜂鸣器报警;(3)普通模式、紧急模式、夜间模式可相互跳转,不用重新复位。2设计思路1) 设计硬件电路2) 设计电源电路3) 设计振荡电路4) 设计复位电路5) 设计显示电路6) 设计中断系统7) 设计功能控制电路8) 设计初值输入电路9) 设计报警电路3设计过程3.1硬件电路设计硬件电路由AT89C51、MAX7219、4个2位共阴数码管、LED灯、S8050三极管、4×4矩阵键盘等组成。主控制器采用AT89C51,是ATMEL公司生产的一款性能稳定的8位单片机,AT89C51具有1个8KB的FLASH程序存储器,1个512字节的RAM,4个8位的双向可位寻址I/O端口,3个16位定时、计数器及1个串行口和6个二级中断结构。单片机的P0口用于控制南北及东西的通行灯, P1.0-P1.2口用于控制Max7219驱动4组2位LED数码管,键盘赋值采用P2口,蜂鸣器报警使用P1.3,夜间模式使用P1.5。它们之间的联系如(图3-1)所示:AT89C51 南北通行灯(2组)东西通行灯(2组)2位LED灯显示(4组)键盘输入上电复位振荡电路驱动MAX7219蜂鸣器报警电路图3-1-1 硬件电路联系图 图3-1-2 单片机最小系统何谓单片机最小系统?实际上是以最小的外围电路就能让单片机正常工作,这样的电路支持成为单片机最小系统电路。一般情况下,单片机的最小系统由电源供电、晶振电路及复位电路组成。3.2 单片机电源电路电源电路不单单是为单片机运行提供工作电压,还需要对单片机的外围电路提供工作电源。这里提供2种电源供电方案:1) USB接口供电具有USB接口的设备一般工作电压都为5V。计算机上的USB接口(图3-2)可以输出稳定的+5V电压,最大额定电流为500mA,足以满足本设计的要求。需要注意电路不能出现短路,以免损坏电脑的USB接口。 图3-2-1 USB接口要注意,接口上的电源为四只引脚的最旁边的两个,而中间的两个引脚是USB的差分数据线,在本设计中不需要使用。2) 7805稳压管电路电源电路的设计也可使用7805的稳压三极管IC,该IC只有三条引脚输出,分别是输入端、接地端和输出端。电源所需的外围元件极少,电路内部还有过流、过热及调整管的保护电路,使用起来可靠、方便,而且价格便宜。3.3 振荡电路设计图3-3振荡电路 单片机的运行需要一个时钟频率,类似我们的计算机的CPU主频的高低,现在计算机的CPU一般用GHz来左单位。而我们的51单片机常用到的时钟频率有12MHz,11.0592MHz,这些时钟频率都是依靠外部晶振产生的。晶振连接到单片机的XTAL1、XTAL2引脚处。电路上的晶振旁有两个无极性电容,容量为22PF。这两个电容称晶振的负载电容,分别接在晶振的两个脚上和对地的电容,一般在几十皮发,它会影响到晶振的谐振频率和输出幅度。 晶振的负载电容=(Cd*Cg)/(Cd+Cg)+Cic+C (3.1) 式中Cd,Cg为分别接在晶振的两个脚上和对地的电容,Cic(集成电路内部电容)+C(PCB上电容)经验值为3至5pf。设计需要考虑到串行通信的使用,为了减少误码率提高通信质量,因此选用11.059MHz晶振。3.4复位电路设计当单片机上电后,通过复位电路(图3-4)使得单片机的PC指针复位到0000H。这时,单片机就从0000H地址开始执行代码。理论上51单片机的复位需要12个时钟周期的高电平,系统中使用一个0.1Uf极性电容和1K电阻组成的复位电路。系统通电后,电容开始充电,此时单片机复位引脚输入的是高电平。当电容充满电后,复位引脚输入变为低电平,单片机完成复位,开始从0000H执行代码。复位电路延时时间计算公式如下:T = C*R T = 10*(10-6) * (103) = 100 ms (3.2) 图3-4 单片机复位电路3.5 显示电路设计设计4组交通指示灯。红灯表示停止通行;黄灯表示等一等,绿灯分别实现左转、直行、右转,蓝灯亮表示人行道通行;设计4组2位LED数码显示电路,用来表示允许停车或通行的时间,与MAX7219串行输入/输出共阴极显示驱动器相接的。MAX7219是一种集成化的串行输入/输出共阴极显示驱动器,它连接微处理器与8位数字的7段数字LED显示,也可以连接条线图显示器或者64个独立的LED。其上包括一个片上的B型BCD编码器、多路扫描回路,段字驱动器,而且还有一个8*8的静态RAM用来存储每一个数据。 图3-5-1 Max7219引脚图图3-5-2 交通灯布局图3.6 中断电路89C51具备完善的中断功能,有两个外中断、两个定时器/计数器中断,可以满足不同的控制要求,并具有优先级别选择。3.7 功能控制电路的设计按钮S1实现复位功能;K3实现在线时间调整;按钮K2实现夜间模式;K4实现紧急模式。 图3-7 功能按钮3.8 初值输入电路的设计初始化的时候修改红绿灯通行时间,使用4*4矩阵键盘进行设置,接单片机P2口。图3-8 4X4矩阵键盘3.9 报警电路的设计报警电路,使用5V有源蜂鸣器,采用S8050三极管驱动,原理电路如下; 图3-9报警示意图4设计仿真 通过Proteus软件对系统硬件设计和软件设计结合仿真,从仿真的效果检查系统设计存在的错误或者缺陷,这样可以比较有针对性地进行系统硬件设计和软件设计的修改。4.1 Proteus仿真软件简介Proteus软件是英国Labcenter electronics公司出版的EDA工具软件(该软件中国总代理为广州风标电子技术有限公司)。它不仅具有其它EDA工具软件的仿真功能,还能仿真单片机及外围器件。它是目前最好的仿真单片机及外围器件的工具。虽然目前国内推广刚起步,但已受到单片机爱好者、从事单片机教学的教师、致力于单片机开发应用的科技工作者的青睐。Proteus是世界上著名的EDA工具(仿真软件),从原理图布图、代码调试到单片机与外围电路协同仿真,一键切换到PCB设计,真正实现了从概念到产品的完整设计。是目前世界上唯一将电路仿真软件、PCB设计软件和虚拟模型仿真软件三合一的设计平台,其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等,2010年即将增加Cortex和DSP系列处理器,并持续增加其他系列处理器模型。在编译方面,它也支持IAR、Keil和MPLAB等多种编译器。在PROTEUS绘制好原理图后,调入已编译好的目标代码文件:*.HEX,可以在PROTEUS的原理图中看到模拟的实物运行状态和过程。PROTEUS 是单片机课堂教学的先进助手。PROTEUS不仅可将许多单片机实例功能形象化,也可将许多单片机实例运行过程形象化。前者可在相当程度上得到实物演示实验的效果,后者则是实物演示实验难以达到的效果。它的元器件、连接线路等却和传统的单片机实验硬件高度对应。这在相当程度上替代了传统的单片机实验教学的功能,例:元器件选择、电路连接、电路检测、电路修改、运行结果等。 课程设计、毕业设计是学生走向就业的重要实践环节。由于PROTEUS提供了实验室无法相比的大量的元器件库,提供了修改电路设计的灵活性、提供了实验室在数量、质量上难以相比的虚拟仪器、仪表,因而也提供了培养学生实践精神、创造精神的平台。 随着科技的发展,“”已成为许多设计部门重要的前期设计手段。它具有设计灵活,结果、过程的统一的特点。可使设计时间大为缩短、耗资大为减少,也可降低工程制造的风险。相信在单片机开发应用中PROTEUS也能茯得愈来愈广泛的应用。 使用Proteus 软件进行单片机设计, 是和计算机多媒体技术相结合的综合运用,有利于培养学生的电路设计能力及仿真软件的操作能力;在和全国大学生电子设计竞赛中,我们使用 Proteus 开发环境对学生进行培训,在不需要硬件投入的条件下,学生普遍反映,对单片机的学习比单纯学习书本知识更容易接受,更容易提高。4.2 Proteus仿真软件的使用运行Proteus软件后,新建一个仿真空白界面。按照在Protel软件上设计的硬件原理图重新在Proteus上搭建硬件电路。当中有些元件是因仿真库中不包含或者演示效果不理想的,需要使用其他器件替换。在Proteus搭建硬件电路的另一个好处是不需根据实际工作电路完成设计也可以正常工作,如单片机的最小系统可以在Proteus忽略搭建。只需要从元件库中调用51系列的单片机,双击该单片机即可设置晶振频率等参数。这个优点同时也是Proteus不可忽视的弱点,在某些电路实际设计存在错误,但是在Proteus还是能进行仿真并且将错误忽略。由此可见,仿真软件上能正常运行的系统,并不完全代表是没有存在缺陷的系统。设计好的仿真电路如下:图4-2 仿真电路图4.3 Proteus仿真过程完成硬件电路的搭建,以及程序代码的编写后,可通过点击单片机加载程序编译后生成的二进制文件999.hex,实现硬件与程序的结合仿真。具体过程如下:1) 双击仿真图上的单片机,出现编辑元器件的对话框。2) 加载对应的程序编译后二进制文件(999.hex)。 3) 点击开始运行仿真按钮 若硬件设计没有出现逻辑错误,开始运行仿真,运行的效果如下图所示:图4-3 普通模式仿真效果图图4-4 夜间模式仿真效果图图4-4 紧急模式仿真效果图 图4-4 PCB效果图5 总结经过这几个星期的学习和设计,现代交通灯设计完毕。其功能基本满足要求。但由于个人知识、能力、经验以及设计时间等因素限制,这套系统还不是很完美,存在一定程度的不足,比如夜间模式不能设定初值,初值设定只能倒序输入数字。在现实使用中,某些地方设置不够灵活,比如四个交通灯显示时间都一样,这些问题将在后续时间开发工作中进行补充。参考文献1 余锡存,曹国华.单片机原理及接口技术.西安电子科技大学出版社,2007.122 郭天祥.新概念51单片机C语言教程J.电子工业出版社,2009,13 潭浩强.C语言程序设计.清华大学出版社,2010.6.附录:单片机程序#include <reg51.h>/*独立按键接口*/sbit key_1 = P14; sbit key_2 = P15; sbit key_3 = P16;sbit key_4 = P17;/*交通灯定义 */Unsigned char second,second2,count2=0,count1=0,flag1,flag2,flag3,flag4,shuru1,shuru2,shuru3,shuru4,night=0;data disdata4,i,num1,num2,num3,A,C;sbit buzzer = P13; /报警接口sbit redC1 = P00; /东西向:红灯sbit yellowC2 = P01; / 黄灯sbit greenC3 = P02; / 直右转绿灯sbit greenC4 = P03; /左转绿灯sbit redB1 = P04; /南北向:红灯sbit yellowB2 = P05; / 黄灯sbit greenB3 = P06; / 直右转绿灯sbit greenB4 = P07; /左转绿灯/*MAX7219*/#define DIG_0 0x01 /定义max7219数码管*/#define DIG_1 0x02#define DIG_2 0x03#define DIG_3 0x04#define DIG_4 0x05#define DIG_5 0x06#define DIG_6 0x07#define DIG_7 0x08sbit CLK = P10; /max7219接口sbit LOAD = P11; sbit DIN = P12;#define DECODE_MODE 0x09 /max7219参数设置#define INTENSITY 0x0A#define SCAN_LIMIT 0x0B#define SHUT_DOWN 0x0C#define DISPLAY_TEST 0x0F void Write_Max7219_byte(unsigned char temp) /向max7219写一字节unsigned char i;for (i=0;i<8;i+)CLK=0;DIN=(bit)(temp&0x80);temp<<=1;CLK=1; void Write_Max7219(unsigned char address,unsigned char dat)/向max7219写入地址,数据LOAD=0;Write_Max7219_byte(address);Write_Max7219_byte(dat);LOAD=1;void Init_Max7219(void) /MAX7219初始化/Write_Max7219(SHUT_DOWN, 0x01); Write_Max7219(DISPLAY_TEST, 0x00); Write_Max7219(DECODE_MODE, 0xff); Write_Max7219(SCAN_LIMIT, 0x07); Write_Max7219(INTENSITY, 0x04); /*延时程序*/void delay(unsigned int xms) unsigned int i,j;for(i=xms;i>0;i-)for(j=123;j>0;j-); /*定时器、中断初始化*/void Init_Timer_interrupt() TMOD =0x11; /定时器0、1设置16位定时方式 10ms in 12M crystal TH0=0xd8; /定时器0赋初值 TL0=0xf0; TH1=0xd8; /定时器1赋初值 TL1=0xf0; IE =0x8f; /打开全部中断(除串行口) IT0=0; /外部中断设为电平出发 IT1=0; /*键盘 */#define P P2unsigned char keyscan() unsigned char temp,key=16; P=0xfe; /将第一行线置为高电平,其余行线全部为高电平 temp=P; /读取P3口当前状态值赋给临时变量temp,用于后面计算 temp=temp&0xf0; /将temp与0xf0进行与运算,然后将结果赋给temp.if(temp!=0xf0)/如果temp不等于0xf0,说明有键按下delay(10);/延时去抖temp=P;/重新读一次P3口数据temp=temp&0xf0;if(temp!=0xf0)temp=P;/重新读取一次P2口数据switch(temp)/判断那个按键被按下case 0xee:key=1;break;case 0xde:key=2;break;case 0xbe:key=3;break;case 0x7e:key=10;break;while(temp!=0xf0)/等待按键释放temp=P;temp=temp&0xf0; return(key);P=0xfd;temp=P;temp=temp&0xf0;if(temp!=0xf0)delay(10);temp=P;temp=temp&0xf0;if(temp!=0xf0)temp=P;switch(temp)temp=P;case 0xed:key=4;break;case 0xdd:key=5;break;case 0xbd:key=6;break;case 0x7d:key=11;break;while(temp!=0xf0)temp=P;temp=temp&0xf0; return(key);P=0xfb;temp=P;temp=temp&0xf0;if(temp!=0xf0)delay(10);temp=P;temp=temp&0xf0;if(temp!=0xf0)temp=P;switch(temp)case 0xeb:key=7;break;case 0xdb:key=8;break;case 0xbb:key=9;break;case 0x7b:key=12;break;while(temp!=0xf0)temp=P;temp=temp&0xf0;return(key);P=0xf7;temp=P;temp=temp&0xf0;if(temp!=0xf0)delay(10);temp=P;temp=temp&0xf0;if(temp!=0xf0)temp=P;switch(temp)case 0xe7:key=14;break;case 0xd7:key=0;break;case 0xb7:key=15;break;case 0x77:key=13;break;while(temp!=0xf0)temp=P;temp=temp&0xf0; return(key); return(key); /*模式*/void model_one() /模式一普通模式 if(key_1=0) delay(100); if(key_1=0) while(!key_1);/等待按键松开 night=0; /模式一处理逻辑 buzzer=0; Init_Max7219(); /max7219初始化 redC1=0,greenC3=1,greenC4=0,yellowC2=0; /普通模式,状态设定 redB1=1,greenB3=0,greenB4=0,yellowB2=0; Init_Timer_interrupt(); TR0=1; /开定时器0 void model_two() /模式二夜间模式 if(key_2=0) delay(100); if(key_2=0) while(!key_2);/等待按键松开 buzzer=0; redC1=0,greenC3=0,greenC4=0,yellowC2=0; /关闭所有交通灯 redB1=0,greenB3=0,greenB4=0,yellowB2=0; night=1; /模式二处理逻辑 TR0=1; void model_three()/模式三初值设定模式 if(key_3=0) delay(100); if(key_3=0) while(!key_3);/等待按键松开 TR0=0; /模式三处理逻辑 buzzer=0; night=0; i=0; for(i=0;i<4;i+) /输入4位09的数,跳出循环 while(1) A=keyscan(); if(A!=16) disdatai=A; break; num1=disdata3*10+disdata2; num2=disdata1*10+disdata0; shuru1=num1; /东西向通行时间赋初值 shuru2=num2; /南北向通行时间赋初值 TR0=1; second=shuru1; void model_four() /模式四紧急模式 if(key_4=0) delay(100); if(key_4=0) while(!key_4); /等待按键松开 /模式四处理逻辑 redC1=1,greenC3=0,greenC4=0,yellowC2=0;/紧急状态,红灯全亮 redB1=1,greenB3=0,greenB4=0,yellowB2=0; TR0=0; buzzer=1; /紧急状态,蜂鸣器报警 /*主程序*/void main() shuru1=20,shuru2=10; /K1未按下,赋原始初值,东西20s,南北10s second=shuru1;buzzer=0; while(1) / RST_(); model_one(); model_two(); model_three(); model_four();/*定时中断0服务程序*/void Interrupt_Timer0() interrupt 1 shuru3=shuru1+5;shuru4=shuru2+5;TH0=0xd8; /定时器0重新赋值TL0=0xf0;count1+;if (count1=100) /100次为1s count1=0; second-; /second 减1 if(night=0) if(second<=3) /second<3s时,绿灯灭,黄灯闪烁、蜂鸣器报警 switch(flag1) /flag1为黄灯闪烁标志,为0东西黄灯闪烁,为1南北方向黄灯闪烁 case 0:greenC3=0;greenC4=0;yellowC2=!yellowC2;buzzer=!buzzer;break; case 1:greenB3=0;greenB4=0;yellowB2=!yellowB2;buzzer=!buzzer;break; if(second=0) /second读尽时,依据flag2标志,更改second值 switch(flag2) /flag2=0时,second=shuru2,读尽时flag2取反;flag2=1时,second=shuru1,读尽时flag2取反 case 0: /同时红绿灯状态变化 buzzer=0;flag1=0;second=shuru4; /东西黄灯闪 redC1=0;greenC3=0;greenC4=1;yellowC2=0; /东西左转 redB1=1;greenB3=0;greenB4=0;yellowB2=0;flag2+; / 南北禁行 break; case 1: buzzer=0;flag1=1;second=shuru2; /南北黄灯闪 redC1=1;greenC3=0;greenC4=0;yellowC2=0; /东西禁行 redB1=0;greenB3=1;greenB4=0;yellowB2=0;flag2+; /南北直行右转 break; case 2: buzzer=0;flag1=1;second=shuru1; /东西黄灯闪 redC1=0;greenC3=1;greenC4=0;yellowC2=0; /东西直行右转 redB1=1;greenB3=0;greenB4=0;yellowB2=0;flag2+; /南北禁行 break; case 3: buzzer=0;flag1=0;second=shuru3; /南北黄灯闪 redC1=1;greenC3=0;greenC4=0;yellowC2=0; /东西禁行 redB1=0;greenB3=0;greenB4=1;yellowB2=0;flag2=0; /南北左转 break; elseif(second=0) second=shuru1; yellowC2=!yellowC2; yellowB2=!yellowB2; Write_Max7219(DIG_0,second/10); Write_Max7219(DIG_1,second%10); Write_Max7219(DIG_2,second/10); Write_Max7219(DIG_3,second%10); Write_Max7219(DIG_4,second/10); Write_Max7219(DIG_5,second%10); Write_Max7219(DIG_6,second/10); Write_Max7219(DIG_7,second%10);