1、《单片机原理及应用》 课程设计报告 题目:倒数计数器 专 业: 电气工程及其自动化 班 级: 10电气 学生姓名: 李启应 学 号: 101401010202 指导教师: 郑老师 胡老师 时 间: 2013 年 6月 19日----20 13 年 6月 28 日 目录 第一章 设计题目分析、方案及元器件选择 3 1.1设计任务及要求 3 1
2、2 方案选择 4 1.3 元器件选择 4 第二章 系统电路设计 5 2.1 设计说明 5 2.2 部分硬件方案论述 5 2.3 硬件连接图 6 2.4 元件清单 7 2.4.1 AT89C51芯片 7 2.4.2 字符型LCD1602 8 2.4.3 晶振电路 10 2.4.4 按键控制模块 11 2.4.5 其他元件 12 2.5 绘制过程中遇到的问题及解决办法 13 第三章 系统软件设计 14 3.1 软件设计 14 3.2 编程过程中
3、遇到的问题及解决办法 15 第四章 连接调试 16 4.1 系统的仿真与调试 16 第五章 心得体会 17 参考文献 19 附录 19 第一章 设计题目分析、方案及元器件选择 1.1 设计任务及要求 设计任务:利用AT89C51单片机结合LED显示器设计一个简易的倒数计数器,可用来煮方便面、煮开水或小睡片刻等。做一小段时间倒计数,当倒计数为0时,红色LED灯闪烁,通知倒计数终了,该做应该做的事。 设计要求:定时闹钟的基本功能如下。 ● 显示格式为“分分:秒秒”。 用4个按键操作来设置当前想要倒计数的时间。一旦按下键则开始倒计数,当计数为0时,发出
4、一阵音乐声。 程序执行后工作指示灯LED闪烁,表示程序开始执行,按下操作键K1~K4动作如下。 ● K1--可调整倒计数的时间1~60分钟。 ● K2--设置倒计数的时间为5分钟,显示“0500”。 ● K3--设置倒计数的时间为10分钟,显示“1000”。 ● K4--设置倒计数的时间为20分钟,显示“2000”。 按下K1键则在LED上显示出设置画面。此时,若: a. 按操作键K2--增加倒计数的时间1分钟。 b. 按操作键K3--减少倒计数的时间1分钟。 c. 按操作键K4--设置完成 本题可以考虑用LCD来实现,则显示更加清楚。 可扩充功能: ● 增加时钟及闹
5、铃功能 ● 增加秒表计数功能。 ● 增加万年历显示“年月日”。 ● 增加多组倒计数功能。 1.2 方案总体思路 用单片机8051控制程序执行,通过LCD动态扫描来显示倒计时,每次执行中断时判断计时是否继续倒计时。同时通过按键扫描的方式来判断是否有输入更改倒计时的控制信息,通过8051的处理来达到对倒计时的更新,当倒计时结束时,驱动蜂鸣器发出一首音乐。 1.3 元器件选 音乐倒数计数器倒数所用到的元件有:单片机芯片AT89C51、LCD1602液晶显示、蜂鸣器、LED灯、按键、电阻、电容、晶振等。 第二章 系统电路设计 2
6、1 设计说明 音乐倒数计数器倒数的时间通过数字显示,控制器使用单片机AT89C51。该计数器系统主要由计数器模块、LCD显示器模块、蜂鸣器模块、键盘模块、复位模块等部分组成。总体设计方框图如图1所示。 图1 总体设计方框图 2.2部分硬件方案论述 ◆LCD1602显示方式的方案比较。 方案一:采用花样显示,花样显示是指LCD显示某一屏字符时,采取从左到右或者是从右到左的整屏移动的显示方式。在这种显示方式下,给人的感觉就是程序是在执行的,同时如果控制好了移动一屏的时间间隔的话,在整体视觉上可以达到很好的效果。 方案二
7、采用静态显示,静态显示是指LCD显示某一屏字符时,时钟保持当前字符的显示,不使用移屏显示。便于控制,同时能够满足正常的显示效果。 由于在显示中存在播放时间的动态变化,这样的话,即使是不产生整屏移动,也能给人动态感,也易于控制。基于以上各种特点,我选择了方案二。 2.3 硬件连接图 电路硬件连接图主要以单片机芯片AT89C51作为核心控制器,由字符型LCD1602显示器、LED-RED灯、按键控制模块以及其他元件(电容电阻元件、电解电容元件)等组成。且按键控制模块设计中使用单个按键实现单个功能,控制方式实现较简单。硬件连接图如图2所示。 图2 电路硬件连接图 2.4 元件清
8、单 2.4.1 AT89C51芯片 AT89C51芯片图如下图3所示。 图3 AT89C51芯片图 主要性能: 与MCS-51单片机产品兼容 、8K字节在系统可编程Flash存储器、 1000次擦写周期、全静态操作:0Hz~33Hz 、三级加密程序存储器 、 32个可编程I/O口线、三个16位定时器/计数器八个中断源、全双工UART串行通道、 低功耗空闲和掉电模式 、掉电后中断可唤醒 、看门狗定时器 、双数据指针、掉电标识符 。 功能特性描述: AT89C51是一种低功耗、高性能CMOS8位微控制器,具有 8K 在系统可编程Flash 存储器。使用高密度非易失性存储器技术制造
9、与工业80C51 产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8 位CPU 和在线系统可编程Flash,使得AT89C51为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。 AT89C51具有以下标准功能: 8k字节Flash,256字节RAM, 32 位I/O 口线,看门狗定时器,2 个数据指针,三个16 位 定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。另外,AT89C51可降至0Hz静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU 停止工作,允许RAM、定时器/计数器、串口、中断继
10、续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。8 位微控制器 8K字节在系统可编程 Flash。 2.4.2 字符型LCD1602 字符型lcd1602如下图4所示。 图4 LCD1602图 1602字符型LCD通常有14条引脚线或16条引脚线的LCD,多出来的2条线是背光电源线。VCC(15脚)和地线GND(16脚),其控制原理与14脚的LCD完全一样,各引脚符号及其功能表如下表1所示。 表1 LCD各引脚及其功能表 引脚 符号 功能说明 1 VSS 一般接地 2 VDD 接电源(
11、5V) 3 V0 液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。 4 RS RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。 4 RS RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。 5 R/W R/W为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作。 6 E E(或EN)端为使能(enable)端,下降沿使能。 7 DB0 低4位三态、 双向数据总线 0位(最低位) 8 DB1 低4位三态
12、 双向数据总线 1位 9 DB2 低4位三态、 双向数据总线 2位 10 DB3 低4位三态、 双向数据总线 3位 11 DB4 高4位三态、 双向数据总线 4位 12 DB5 高4位三态、 双向数据总线 5位 13 DB6 高4位三态、 双向数据总线 6位 14 DB7 高4位三态、 双向数据总线 7位(最高位)(也是busy flag) 15 BLA 背光电源正极 16 BLK 背光 电源负极 2.4.3 晶振电路 时钟是单片机的心脏,单片机各功能部件的运行都是以时钟频率为基准,有条不紊地一拍一拍地工作。因此,时钟频率直接影响单
13、片机的速度,时钟电路的质量也直接影响单片机系统稳定性。常用的时钟电路有两种方式,一种是内部时钟方式,另一种是外部时钟方式。 单片机必须在时钟的驱动下才能工作。在单片机内部有一个时钟振荡电路,只要外界一个振荡源就能产生一定的时钟信号送到单片机内部的各个单元,决定单片机的工作速度。本系统使用的是内部时钟方式。晶振电路如下图5所示。 图5 晶振电路图 一般选用石英晶体振荡器。此电路在加电大约延迟10ms后振荡器起振,在XTAL2引脚产生幅度为3V左右的正弦波时钟信号,其振荡频率主要由石英晶振的频率确定。电路中两个电容C1、C2的作用有两个:一是帮助振荡器起振;二是对振荡器的频率进行微调。本系统
14、的C1、C2的值为30pf。 单片机在工作时,有内部振荡器产生或由外直接输入的送至内部控制逻辑单元的时钟信号的周期称为时钟周期。其大小是时钟信号频率的倒数,f表示。图5-2中的时钟频率为12MHz,即f=12MHz,则时钟周期为1/12us。 2.4.4 按键控制模块 按键用于控制数码显示、LCD显示、扬声器等模块的工作。通过扫描按键是否按下,来设定各模块的工作情况,使各模块可以在按键的控制下,有序地进行工作。设计中使用单个按键实现单个功能,属于较为简单的控制方式,在多功能系统设计的试验中我们使用四个按键分别与单片机的p1.0、p1.1、p1.2、p1.3相连。通过按下相应的按键来处理相
15、应的程序。如下图6所示。 图6 按键控制模块图 2.4.5 其它元件 其它元件图如下图7所示。 图7 其他元件图 2.5 绘制中遇到的问题及解决办法 在绘图的过程中主要出现的问题是有些元器件在protues中找不到,出现这样的问题是对protues软件的应用不是很熟悉,当遇到找不的元器件时,就只有通过网络来查找。 第三章 系统软件设计 3.1软件设计 音乐倒数计数器软件设计部分包括程序流程图
16、以及源程序。主程序开始初始化,然后扫描键盘、复位电路和计数器。当键盘按键有按下时,调整计数器值,LCD显示新值。当复位键有按下时,计数器复位为初值,重新倒计数。当计数器值倒计为0时,蜂鸣器发出声音,计数器停止倒计,程序结束。流程图如图8,图9及图10所示,源程序见附录。 图8 主程序流程图 图9 LCD显示流程图 图10 按键流程图 3.2 编程过程中遇到的问题及解决办法 编写的源程序见附录所示。在编程的过程中,遇到了如下问题: 一、 按键的设置,怎样设置按键满足题目要求。 二、 蜂鸣器的铃声设置,在倒数的时间到了后铃声响,怎么在程序中编写等问题。
17、 解决办法是同过网络和向老师请教帮助解决问题,如音乐铃声是通过载入不同的计数初值,产生频率不同的方波,输入到蜂鸣器(SOUNER)中,使其发出频率不同的声音。本设计中单片机晶振为1.0592MHz,通过计算各音阶频率,可得1、2、3、4、5、6、7共7个音应赋给定时器的初值为64580、64684、64777、64820、64898、64968、65030。在此基础上,可将乐曲的简谱转化为单片机可以“识别”的“数组谱”,进一步加入对音长、休止符等的控制量后,可以实现音乐的播放。 第四章 连接调试 4.1系统的仿真与调试 本设计主要进行软硬件联调,软硬件联调是指把调试无误的软件程序
18、加载进单片机芯片内部,通上电源后,检查是否有预期的显示器倒数计数以及蜂鸣器报警的效果,如果没有则需要检测软件是否在实现功能上有欠缺即程序加载是否有问题,调试前必须保证源程序准确无误,调试结果如图11。 图11 系统的仿真与调试图 第五章 心得体会 参考文献 单片机原理及应用技术 清华大学出版社 (万隆 巴奉丽 主编) 单片机原理及接口技术 第三版(李朝青编) 单片机C语言程序设计完全自学
19、手册(郭惠 吴迅编)
基于Proteus的单片机系统设计与仿真实例(蒋辉平 周国雄 编)
附录
源程序如下:
#include
20、 uint code table1[]={64580,64684,64777,64820,64898,64968,65030}; sbit key1=P1^0; sbit key2=P1^1; sbit key3=P1^2; sbit key4=P1^3; sbit P1_4=P1^4; sbit RS=P2^0; sbit RW=P2^1; sbit E=P2^2; sbit led_red=P2^3; void write_time(uint addr,uint date); //延时函数 void delay(uint z) { uint x,y;
21、for(x=z;x>0;x--) for(y=110;y>0;y--); } //延时1S void delay1(void) { uchar a,b,c; for(c=13;c>0;c--) for(b=247;b>0;b--) for(a=142;a>0;a--); _nop_(); } //1602写命令函数 void write_com(uchar com) { RS=0; P3=com; delay(5); E=1; delay(10); E=0; } //1
22、602写数据函数 void write_date(uchar date) { RS=1; P3=date; delay(5); E=1; delay(10); E=0; } //按键1处理函数 void KEY1() { while(flag1) { if(key2==0) { delay(time); if(key2==0) { if(minute<=59) minute=minute+1; write_time(7,minute);
23、 } } if(key3==0) { delay(time); if(key3==0) { if(minute>0) minute=minute-1; write_time(7,minute); } } if(key4==0) { delay(150); if(key4==0) { flag1=0; flag =1; TR0=1; } } } } //按键2处理函数 vo
24、id KEY2() { minute=5; write_time(7,minute); while(flag2) { if(key4==0) { delay(time); if(key4==0) { flag2=0; flag =1; TR0=1; } } } } //按键3处理函数 void KEY3() { minute=10; write_time(7,minute); while(flag3) {
25、 if(key4==0) { delay(time); if(key4==0) { flag3=0; flag =1; TR0=1; } } } } //按键4处理函数 void KEY4() { minute=20; write_time(7,minute); while(flag4) { if(key4==0) { delay(150); if(key4==0) { f
26、lag4=0; flag =1; TR0=1; } } } } void write_time(uint addr,uint date) { uint ge,shi; ge=date%10; shi=date/10; write_com(0x80+addr); write_date(0x30+shi); write_date(0x30+ge); if(addr==7&&date==0) j=1; if(j==1&&addr==10&&date==0) { flag0=1;
27、 TR0=0; TR1=1; flag5=1; } } //初始化函数 void init() { P1=0xff; RW=0; write_com(0x38); write_com(0x0c); write_com(0x06); write_com(0x80); TMOD=0x11; TH0=(65536-50000)/256; TL0=(65536-50000)%256; TH1=0xfc; TL1=0x44; ET1=1; ET0=1; EA=1; flag0=1;
28、 for(num=0;num<12;num++) { write_date(dis[num]); delay(20); } } void start() { if(key1==0) { delay(time); if(key1==0) { flag0=0; flag1=1; KEY1(); } } if(key2==0) { delay(time); if(key2==0) { flag0=0; flag2=1; K
29、EY2(); } } if(key3==0) { delay(time); if(key3==0) { flag0=0; flag3=1; KEY3(); } } if(key4==0) { delay(150); if(key4==0) { flag0=0; flag4=1; KEY4(); } } } void write_time0() { minute=minute-1; write_time(7,minute); w
30、rite_time(10,59); flag=0; } void counter() { if(t==20) { led_red=led_red^1; if(flag==1) write_time0(); t=0; second=second-1; write_time(10,second); if(k==1&&second==59) { if(minute>0) minute=minute-1; write_time(7,minute);
31、 } if(second==0) { k=1; second=60; } } } int main() { init(); while(1) { while(flag0) start(); counter(); while(flag5) { delay1(); i++; if(i>7) i=0; } } return 0; } void inter0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256; t++; } void initer1() interrupt 3 { TH1=table1[i]/256; TL1=table1[i]%256; P1_4=~P1_4; if(key4==0) { delay(100); if(key4==0) { TR1=0; flag5=0; k=0; j=0; } } } 28






