
信息工程课程设计报告书
课 程 名 称 单片机微型计算机与接口技术
课程设计总评成绩
学生姓名、学 号
学 生 专 业 班级
指 导 教 师 姓名
课程设计起止日期 2013.1.7~2013.1.18
课程设计任务书
学生姓名: 专业班级:
指导教师: 工作单位: 信息工程系
题 目: 基于51单片机的数字电子表的设计
初始条件:
1.运用所学的单片机原理与接口技术知识和数字电路知识;
2.51单片机应用开发系统一套;
3.PC机及相关应用软件;
要求完成的主要任务:
1.完成数字电子表的设计和调试。
2.要求采用四位八段数码管显示时间和日期,并且可以用按键修改时间和日期。
3.撰写课程设计说明书。
4.课程设计说明书要求:引言、设计要求、系统结构、原理设计、各个模块的设计与实现、软件设计、调试过程、收获、体会及总结、参考文献、电路图和源程序。说明书使用A4打印纸计算机打印或手写,用Protel等绘图软件绘制电子线路图纸。
时间安排:
第1天 下达课程设计任务书和日程安排,根据任务书查找资料;
第2~3天 完成方案论证,单片机系统的设计;
第4~6天 参考有关文献,完成程序的编写;
第7~10天 调试硬件系统和软件程序;
第11~13天 结果分析整理、撰写课程设计报告;
第14~15天 验收和答辩。
指导教师签名: 2012 年 12 月 29 日
一、课程设计项目名称
基于51单片机的数字电子表的设计
二、项目设计目的及技术要求
目的:用51单片机在八段数码管上实现对时间日期的显示,并且能够修改时间和日期。
技术要求:1.完成数字电子表的设计和调试。
2.要求采用八段数码管显示时间和日期,并且可以用按键修改时间和日期。
3.可设定初始时间。
4.有方案比较。采用哪种方案比较简单,占用的资源少,就用哪种。
5.采用单片机C语言编程。
6.有硬件原理图,程序流程图。
三、项目设计方案论证(可行性方案、最佳方案、软件程序、硬件电路原理图和PCB图 )
总设计方案:以51核单片机为核心器件,配合其他外设完成对时间和日期的显示。并且能够通过设置按键能够修改时间和日期。然后采用单片机内部定时器0的中断产生“秒”的计数,“秒”计数采用60进制计时器,每累计60秒发出一个“分脉冲”信号,该信号将作为“分计数器”的时钟脉冲。“分计数器”也采用60进制计数器,每累计60分钟,发出一个“时脉冲”信号,该信号将被送到“时计数器”。“时计数器”采用24进制计时器,可实现对一天24小时的累计。每累计24小时,发出一个“日脉冲”信号,该信号将被送到“日期计数器”,“日期计数器” 采用30进制计时器,可实现对一月30天的累计同时进位月份和年份。译码显示电路将“时”、“分”、“秒”、“日期”计数器的输出状态送到八段显示译码器译码,通过八位LED八段显示器显示出来。
1.计时方案
方案一:采用实时时钟芯片。
实时时钟芯片具备年、月、日、时、分、秒计时功能和多点定时功能,计时数据每秒自动更新一次,不需程序干预。计算机可通过中断或查询方式读取计时数据并进行显示,因此实现计时功能不占用CPU的时间,程序简单。此外,实时时钟芯片多数带有锂电池做后备电源,具备永不停止的计时功能。
方案二:软件控制。
利用MCS-51内部的定时/计数器进行中断定时,配合软件延时实现时、分、秒的计时。该方案节省硬件成本,且能够使我们在定时/计数器的使用、中断及程序设计方面得到锻炼与提高,因此本系统采用软件方法实现计时。
2.显示方案
方案一:串口扩展,LED静态显示。
方案占用口资源少,利用串口扩展并口,实现静态显示,显示亮度有保证,但硬件开销大,电路复杂,信息刷新速度慢,比较适用于并行口资源较少的场合。
方案二:直接接口,LED动态显示。
用单片机的并行口作为显示接口,无需外扩接口芯片,但占用口资源较多,且动态扫描的显示方式需占用CPU较多的时间,在单片机没有太多外围接口及实时测控任务的情况下可以采用。
在本系统中,单片机没有太多外围接口接实时测控任务,因此采用方案二。
硬件系统:
根据硬件设计,由单片机的P2口控制位码输出,P0口控制段码输出。动态显示程序中,在单片机内部RAM中设置待显示数据缓冲区,由查表程序完成显示译码,将缓冲区内带显示数据转换成相应的段码,再将段码通过8051的P0口输出。
数码管连接电路如图2所示,P0口输出码型,P2口输出位选。锁存器74HC573起驱动作用,提供驱动电流供数码管发光。译码器74HC138将位选地址转换成位选信号,例如当前是第5个数码管显示,那么P2口输出位选地址05H,译码器输入CBA=110,输出位选信号Y7-Y0=11101111,其中Y5=0,第5个数码管选通并显示,其它数码管不显示。
数码管显示方式为动态扫描方式,当P0口送第一个数0的码型到锁存器时,P2送位选地址01H,即Y0=0,只有第一个数码管亮,显示0,其他数码管不显示。当P0口送第二个数1的码型到锁存器时,P2送位选地址02H,即Y1=0,只有第二个数码管亮,显示1,其他数码管不显示。即每次只有一个数码管点亮,8个数码管是轮流被点亮的,轮流点亮的间隔时间很短(一般用延时程序延时几个毫秒),由于视觉的暂留现象,看到的却好象全都点亮着,这就是动态扫描。
图1
图中C51与8位LED显示器的接口。74HC573的P00—P07作为段选码口,经过74LS138驱动与LED相连。74HC573的P00—P07作为位选码口,经过74LS138驱动与LED的位相连。将各个位选线直接连接在单片机的其中一个输出口,进行位扫描,完成动态的显示。
ATC51引脚图
ATC51单片机的P口特点:
P0口:是一个8位漏极开路输出型双向I/O端口。作为输出端口时,每位能以吸收电
流的方式驱动8 个TTL输入,对端口写1时,又可作高阻抗输入端用。
在访问外部程序或数据存储器时,它是时分多路转换的地址(低8位)/数据总线,
在访问期间将激活内部的上拉电阻。
P1口:P1口是一个带有内部上拉电阻的8位双向I/O端口。P1口的输出缓冲器可驱动
(吸收或输出电流方式)4个TTL输入。对端口写1时,通过内部的上拉电阻把端口拉到高
电位,这时可作输入口。P2口作输入口使用时,因为内部有上拉电阻,那些被外部信号
拉低的引脚会输出一个电流(Iil)。
P2口:P2口是一个带有内部上拉电阻的8位双向I/O端口。P2口的输出缓冲器可驱动
(吸收或输出电流方式)4个TTL输入。对端口写1时,通过内部的上拉电阻把端口拉到高
电位,这时可作输入口。P2口作输入口使用时,因为内部有上拉电阻,那些被外部信号
拉低的引脚会输出一个电流(Iil)。
在访问外部程序存储器时和16位外部地址的外部数据存储器(如执行 MOVX @DPTR)时,P2口送出高8位地址。在访问8位地址的外部数据存储器(如执行 MOVX @RI)时,P2口引脚上的内容(就是专用寄存器(SFR)区中的P2寄存器的内容),在整个访问期间不会改变。
P3口:P3口是一个带有内部上拉电阻的8位双向I/O端口。P3口的输出缓冲器可驱动(吸收或输出电流方式)4个TTL输入。对端口写1时,通过内部的上拉电阻把端口拉到高
电位,这时可作输入口。P3口作输入口使用时,因为内部有上拉电阻,那些被外部信号拉低的引脚会输出一个电流(Iil)。
74hc573引脚图及功能真值表逻辑图
SL74HC573 跟LS/AL573 的管脚一样。器件的输入是和标准CMOS 输出兼容 的;加上拉电阻,他们能和LS/ALSTTL 输出兼容。当锁存使能端为高时,这些器件的锁存对于数据是透明的(也就是说输出同步)。当锁存使能变低时,符合建立时间和保持时间的数据会被锁存。输出能直接接到CMOS,NMOS 和TTL 接口上。
操作电压范围:2.0V~6.0V。
低输入电流:1.0uA
CMOS 器件的高噪声抵抗特性
74HC573引脚图
74HC573功能表
数码管显示数字的码型由数码管的数据脚a~dp决定,图2为数码管的笔段分布图,由于是共阴极的,所以当a~dp为高电平时相应的笔段会亮,电路中P1.0~P1.7分别接数码管的a.b.c.d.e.f.g.dp,得到0~9这10个数字的码型如表1所示。
图3
表一
| 引脚 | P0.7 | P0.6 | P0.5 | P0.4 | P0.3 | P0.2 | P0.1 | P0.0 | 数字 | 码型 |
| 笔段 | dp | g | f | e | d | c | b | a | ||
| 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 3FH | |
| 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 06H | |
| 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 2 | 5BH | |
| 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 3 | 4FH | |
| 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 4 | 66H | |
| 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 5 | 6DH | |
| 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 6 | 7DH | |
| 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 7 | 07H | |
| 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 8 | 7FH | |
| 0 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 9 | 6FH | |
| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 小数点 | 80H |
按键模块
按建模块用来切换显示时间或日期,以及对时间和日期进行校正修改和相关设置功能,该系统只使用S1和S2两个按键。
主程序流程图如图所示:
程序如下:
#include sbit key_change=P3^0; //定义端口参数 sbit key=P3^1; sbit LED=P1^2; //定义指示灯参数 code unsigned char tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴数码管 0-9 unsigned char StrTab[8]; //定义缓冲区 unsigned char minute=55,hour=20,second,date=24 ,change,month=12 ,year=10,number; //定义并且初始化值 20:55:00 20101224 /******************************************************************/ /* 延时函数 */ /******************************************************************/ void delay(unsigned int cnt) { unsigned char x,y; for(x=cnt;x>0;x--) for(y=10;y>0;y--); } /******************************************************************/ /* 显示处理函数 */ /******************************************************************/ void display_time() { StrTab[0]=tab[hour/10]; StrTab[1]=tab[hour%10]; StrTab[2]=0x40; StrTab[3]=tab[minute/10]; StrTab[4]=tab[minute%10]; StrTab[5]=0x40; StrTab[6]=tab[second/10]; StrTab[7]=tab[second%10]; } void display_day() { StrTab[0]=0x5b; StrTab[1]=0x3f; StrTab[2]=tab[year/10]; StrTab[3]=tab[year%10]|0x80; StrTab[4]=tab[month/10]; StrTab[5]=tab[month%10]|0x80; StrTab[6]=tab[date/10]; StrTab[7]=tab[date%10]; } /******************************************************************/ /* LED数码管闪烁 */ /******************************************************************/ void sd_minute() { int i; for(i=10;i>=0;i--) { StrTab[0]=tab[hour/10]; StrTab[1]=tab[hour%10]; StrTab[2]=0x40; StrTab[3]=0x00; StrTab[4]=0x00; StrTab[5]=0x40; StrTab[6]=tab[second/10]; StrTab[7]=tab[second%10]; delay (1); //扫描间隙延时,时间太长会闪烁,太短会造成重影 display_time(); } } /******************************************************************/ /* 主函数 */ /******************************************************************/ void system() { TMOD |=0x01;//定时器0 10ms in 12M crystal 用于计时 TH0=0xd8; //初值 TL0=0xf0; ET0=1; TR0=1; TMOD |=0x10; //定时器1用于动态扫描 TH1=0xF8; //初值 TL1=0xf0; ET1=1; TR1=1; EA =1; } void display_time(); //调用显示处理 void deal_change() { if(key_change==0) { change++; while(!key_change) { display_time(); } change=change%5; } } void deal_change0() {if(change==0) { if(key==0) { number++; number=number%2; while(!key); } if(number==0) { display_time(); } if(number==1) { display_day(); } } } void deal_change1() { if(change==1) { display_time(); sd_minute(); if(key==0) { minute++; while(!key) { display_time(); } if(minute==60) { minute=0; hour++; if(hour==24) { date++; if(date==30) { month++; if (month>12) month=1; if (month==1) year++; } } } } } } void deal_change2() {if(change==2) { display_time(); if(key==0) { hour++; while(!key) { display_time(); } if(hour==24) { hour=0; date++; if(date==30) { month++; if (month>12) month=1; if (month==1) year++; } } } } } void deal_change3() {if(change==3) { display_day(); if(key==0) { date++; while(!key) { display_day(); } if(date==30) { date=1; month++; if(month>12) month=1; if(month==1) year++; } } } } void deal_change4() {if(change==4) { display_day(); if(key==0) { month++; if(month>12) month=1; if(month==1) year++; while(!key) display_day(); } } } /******************************************************************/ /* 定时器1中断 */ /******************************************************************/ void time1_isr(void) interrupt 3 using 0//定时器1用来动态扫描 { static unsigned char num; TH1=0xF8;//重入初值 TL1=0xf0; switch (num){ case 0:P2=0;P0=StrTab[num];break; //分别调用缓冲区的值进行扫描 case 1:P2=1;P0=StrTab[num];break; case 2:P2=2;P0=StrTab[num];break; case 3:P2=3;P0=StrTab[num];break; case 4:P2=4;P0=StrTab[num];break; case 5:P2=5;P0=StrTab[num];break; case 6:P2=6;P0=StrTab[num];break; case 7:P2=7;P0=StrTab[num];break; default:break; } num++; //扫描8次,使用8个数码管 if(num==8) num=0; } /******************************************************************/ /* 定时器0中断 */ /******************************************************************/ void tim(void) interrupt 1 using 1 {static unsigned char count;//定义内部静态变量 TH0=0xd8; //重新赋值 TL0=0xf0; count++; switch (count) { case 0: case 20: case 40: case 60: case 80:display_time(); //隔一定时间调用显示处理 break; //case 50:P1=~P1; //半秒 LED闪烁 // break; default:break; } if (count==100) { count=0; second++; //秒加1 if(second==60) { second=0; minute++; //分加1 if(minute==60) { minute=0; hour++; //时加1 if(hour==24) hour=0; date++; if(date==30) { date=0; month++; if(month>12) month =1; year++; } } } } } void main() { system(); while(1) { deal_change(); deal_change0(); deal_change1(); deal_change2(); deal_change3(); deal_change4(); } } 四、项目设计结果分析(分析试验过程中获得的数据、波形、现象或问题的正确性和必然性,分析产生不正确结果的原因和处理方法) 1.当程序下载完,在数码管显示的和预想中的电子表有很大出入,甚至是乱码。感觉是程序问题。开始查看程序,看了三遍,终于发现问题,分析改正过来后再试,终于完成。 2.在数码管显示的时候,分计时器抖动得很厉害,设定延迟抖动的原因是为了区分调节时间的时候好区分到底是调的哪一部分。延迟抖动过于长就会对按键有影响,会使得按键不灵敏,需要久按或长按按键数码管才有反应。这时候需要修改程序的延迟程序使延迟时间变短短些。 五、参考文摘(相关文摘不少于5篇,记录每篇文献的作者姓名.文献名称.文献发行城市:文献出版社,出版年;文献内容摘要, 每篇不少于100字) 1.《单片机微型计算机与接口技术》 2012年1月第四版 电子工业出版社 李群芳 肖看 张士军 编著 2.《51单片机应用开发速查手册》 2009年4月第1版 人民邮电出版社 王守中 赵朋朋 索世文 编著 3.《例说51单片机》(C语言版) 2008年4月第1版 人民邮电出版社 张义和 王敏男 许宏昌 余春长 编著 4.《C语言设计完全手册》 2006年4月第1版 人民邮电出版社 张立科 编著 5.《MCS-51单片机原理与接口技术》 2009年7月第2版 电子工业出版社 汪德彪 编著 课程设计评分表 1.所设计的程序运用了哪些模块? 答:运用了数码管显示模块、晶振模块、按键模块。 2.所运用到的模块都有什么作用? 答:数码管显示时间和日期,晶振模块将时钟芯片中的时、分读取到缓冲区内,并送到显示电路,按键模块用以校正时间和日期。 3.在硬件方面,单片机的什么口作为输出的? 答:P0口作为输出,P0.0~P0.7对应显示小时、分钟、秒钟。 指导教师综合评语: 指导教师(签名) 日 期: 年 月 日评 分 项 目 评分成绩 1.选题合理、目的明确(10分) 2.设计方案正确,具有可行性、创新性(30分) 3.项目工艺水平及测试性能达到技术要求(25分) 4.参考文摘不少于5篇(10分) 5.答辩(25分) 总 分(100分) 答辩记录:
