情境13智能数字钟的设计与制作.docx
- 文档编号:4056769
- 上传时间:2022-11-27
- 格式:DOCX
- 页数:21
- 大小:195.48KB
情境13智能数字钟的设计与制作.docx
《情境13智能数字钟的设计与制作.docx》由会员分享,可在线阅读,更多相关《情境13智能数字钟的设计与制作.docx(21页珍藏版)》请在冰豆网上搜索。
情境13智能数字钟的设计与制作
情境13智能数字钟的设计与制作
学习情境目标
通过学习智能数字钟的设计与实现方法,掌握一般单片机应用产品的设计思想和具体实现;并学会对设计内容及过程资料进行整理归档形成设计报告论文。
情境任务要求
要求设计具有如下功能的数字钟:
(1)自动计时,由6位LED显示器显示时、分、秒。
(2)具备校准功能,可以直接由0~9数字键设置当前时间。
(3)具备定时起闹功能。
(4)一天时差不超过1秒钟。
情境任务分析
计时方案:
利用MCS-51内部的定时/计数器进行中断定时,配合软件延时实现时、分、秒的计时。
该方案节省硬件成本,且能够使读者在定时/计数器的使用、中断及程序设计方面得到锻炼与提高,因此本系统将采用软件方法实现计时。
键盘/显示方案:
8255扩展,LED动态显示。
该方案硬件连接简单,但动态扫描的显示方式需占用CPU较多的时间,在单片机没有太多实时测控任务的情况下可以采用。
硬件电路设计
电路原理如图13.1所示。
数字钟电路的核心是89S51单片机,系统配备6位LED显示和4×3键盘,采用8255作为键盘/显示接口电路。
利用8255的A口作为6位LED显示的位选口,其中,PA0~PA5分别对应位LED0~LED5,B口则作为段选口,C口的低3位为键盘输入口,对应0~2行,A口同时用作键盘的列扫描口。
由于采用共阴极数码管,因此A口输出低电平选中相应的位,而B口输出高电平点亮相应的段。
P1.0接蜂鸣器,低电平驱动蜂鸣器鸣叫启闹。
由图13.1可见,8255的地址分配如下:
控制寄存器为0x7fff,定义为PORT;A口为0x7ffc,定义为PORTA;B口为0x7ffd,定义为PORTB;C口为0x7ffe,定义为PORTC。
图13.1参考电路图
系统工作流程:
(1)时间显示:
上电后,系统自动进入时钟显示,从00:
00:
00开始计时,此时可以设定当前时间。
(2)时间调整:
按下校时键,系统停止计时,进入时间设定状态,系统保持原有显示并停止计时,同时在时十位闪烁显示,等待键入当前时间。
按下0~9数字键可以顺序设置时、分、秒,并在相应LED管上显示设置值,直至6位设置完毕。
在任何位置再次按下校时键,则退出设置。
若时间设置符合规范,系统将自动由设定后的时间开始计时显示。
否则以原时间继续走时。
(3)闹钟设置/启闹/停闹:
按下闹铃键,系统继续走时,初始显示12:
00:
--(下一次再设置时显示原设置闹铃时间),进入闹钟设置状态,同时在时十位闪烁显示,等待键入启闹时间。
按下0~9数字键可以顺序进行相应的时间设置,并在相应LED管上显示设置值,直至4位设置完毕。
在任何位置再次按下闹铃键,则退出设置。
这将启动定时启闹功能,并恢复时间显示。
闹铃时间到,蜂鸣器鸣叫,直至重新按下闹铃键停闹。
软件设计
根据上述工作流程,软件设计可分为以下几个主要功能模块:
(1)主程序:
初始化与键盘监控,流程图如图13.2所示。
图13.2主程序流程图
(2)计时:
为定时器0中断服务子程序,完成刷新计时缓冲区的功能。
流程图如图13.3所示。
如前所述,系统定时采用定时器与软件循环相结合的方法。
定时器0每隔100ms溢出中断一次,则循环中断10次延时时间为1s,上述过程重复60次为1分,分计时60次为1小时,小时计时24次则时间重新回到00:
00:
00。
设系统使用6MHz的晶振,定时器0工作在方式1,则100ms定时对应的定时器初值可由下式计算得到:
定时时间=(216-定时器0初值)×(12/fosc),因此,定时器0初值=0x3cb0,即TH0=0x3c,TL0=0xb0。
图13.3计时程序流程图
(3)时间设置与闹钟设置:
由键盘输入设置当前时间与定时启闹时间。
流程图如图13.4所示。
将键盘输入的时间值合并为3位或2位压缩BCD码(时、分、秒)送入计时缓冲区和闹钟值缓冲区,作为当前计时起始时间或闹钟定时时间。
该模块的入口为计时缓冲区或闹钟值寄存区的首地址。
程序调用一个键盘设置子程序将键入的6位时间值送入显示缓冲区,然后将显示缓冲区中的6(或4)位BCD码合并为3(或2)位压缩BCD码,送入计时缓冲区或闹钟值缓冲区。
该程序同时作为时间值合法性检测程序,若键盘输入的小时值大于23,分和秒值大于59,则不合法,将取消本次设置。
另外为了设置时能明确当前设置位置,在等待键盘输入时,采用当前位闪烁显示提醒。
具体采用定时器1形成50ms中断,然后循环500ms显示另500ms不显示来完成。
图13.4时间设置和闹钟定时程序流程
(4)显示:
完成6位动态显示。
流程图如图13.5所示。
将显示缓冲区中的6位BCD码用动态扫描方式显示。
为此,必须首先将3字节计时缓冲区中的时、分、秒压缩BCD码拆分为6字节(百位、十位分别占有1字节)BCD码,这一功能由计时时间时分秒分拆送显示缓冲区子函数来实现。
需要注意的是,当按下时间或闹钟设置键后,在6(或4)位设置完成之前,应显示键入的数据,而不显示当前时间。
为此,我们设置了一个计时显示允许标志位,在时间/闹钟设置期间标志位1,不调用计时时间时分秒分拆送显示缓冲区子函数。
图13.5显示程序流程图
(5)键盘扫描:
判断是否有键按下,并求取键号。
流程图如图13.6所示。
图13.6键盘扫描流程图
(6)定时比较:
判断启闹时间到否?
如时间到,则启动蜂鸣器鸣叫。
流程图如图13.7所示。
图13.7定时比较流程图
将当前时间(计时缓冲区的值)与预设的启闹时间(闹钟设置寄存区的值)比较,二者完全相同时,启动蜂鸣器鸣叫,并置位闹钟标志位。
返回后,待重新按下闹铃键停闹,并清零闹钟标志。
源程序
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#definePORTXBYTE[0x7fff]/*8255控制口地址*/
#definePORTAXBYTE[0x7ffc]/*8255的A口地址*/
#definePORTBXBYTE[0x7ffd]/*8255的B口地址*/
#definePORTCXBYTE[0x7ffe]/*8255的C口地址*/
sbitalarm_beep=P1^0;//闹铃驱动
sbitled1=P1^1;
sbitled2=P1^2;
ucharmsecond=0;//时钟时间:
毫秒
ucharlocation;//标记调整时间时位置
ucharbuffer;//缓冲存储
uchartimes=0;//内部计数
uchartimebuf[3]={0,0,0};//时钟时间:
时,分,秒
ucharalarmbuf[2]={12,00};//闹铃时间:
时,分
uchardispbuf[6]={0,0,0,0,0,0};//显示缓冲区
bitalarm_fg=0;//清零闹钟标志位
bittimeset_fg=0;//允许计时显示
/*共阴极字型码表*/
ucharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,
0x40,0x00};
//01234567
//89abcdef
//-暗
/*定时器0中断服务子程序*/
/*6MHz晶振,定时100毫秒*/
voidclock(void)interrupt1
{
TL0=0xb7;
TH0=0x3c;
msecond++;
if(msecond==5){led1=~led1;led2=~led2;}//LED闪烁控制500ms
if(msecond==10)//1秒时间到
{
led1=~led1;
led2=~led2;
msecond=0;
timebuf[2]++;
if(timebuf[2]==60)//1分时间到
{
timebuf[2]=0;
timebuf[1]++;
if(timebuf[1]==60)//1时时间到
{
timebuf[1]=0;
timebuf[0]++;
if(timebuf[0]==24)timebuf[0]=0;//1天时间到
}
}
}
}
/*定时器1中断服务子程序*/
voidflash(void)interrupt3
{
TL1=0x58;//重置初值
TH1=0x9e;
times++;
if(times==10)//500ms时间到
{
buffer=dispbuf[location];
dispbuf[location]=17;
}
elseif(times==20)
{
times=0;
dispbuf[location]=buffer;
}
}
/*子函数*/
/*延时1ms*/
voiddelay()
{
uchari;
for(i=248;i>0;i--){;}
}
/*闹铃时间比较子程序*/
voidalarm(void)
{
if(timebuf[2]==0)//整分
{
if(timebuf[1]==alarmbuf[1])//分相同
{
if(timebuf[0]==alarmbuf[0])//时相同
{
alarm_beep=0;//启动闹钟鸣叫
alarm_fg=1;//置位闹钟标志
}
}
}
}
/*计时时间时分秒分拆送显示缓冲区*/
voidtime_to_disp(void)
{
uchari;
ucharj=0;
for(i=0;i<3;i++)
{
dispbuf[j]=timebuf[i]/10;//取时分秒高4位
j++;
dispbuf[j]=timebuf[i]%10;//取时分秒低4位
j++;
}
}
/*闹铃时间时分分拆送显示缓冲区*/
voidalarm_to_disp(void)
{
uchari;
ucharj=0;
for(i=0;i<2;i++)
{
dispbuf[j]=alarmbuf[i]/10;//取时分秒高4位
j++;
dispbuf[j]=alarmbuf[i]%10;//取时分秒低4位
j++;
}
}
/*显示子程序DISPLAY*/
voiddisplay(void)
{
uchari,selcode;
if(timeset_fg==0)time_to_disp();//允须计时则刷新显示缓冲区
selcode=0xfe;//首扫描码
for(i=0;i<6;i++)
{
PORTB=0x00;//段码送00关显示
PORTA=selcode;//先送位选通信号
PORTB=table[dispbuf[i]];//查表取段码
delay();//延时1ms
selcode=(selcode<<1)|0x01;//扫描显示下一数码管
}
}
/*键扫描函数*/
ucharkeyscan(void)
{
ucharscancode,tmpcode;
PORTB=0x00;//关显示,消阴影
PORTA=0x00;//发全0行扫描码
if((PORTC&0x07)!
=0x07)//若有键按下
{
display();//延时去抖动,以显示扫描时间做延时
alarm();//闹铃时间比较
PORTB=0x00;//关显示,消阴影
PORTA=0x00;
if((PORTC&0x07)!
=0x07)//延时后再判断一次,去除抖动影响
{//有键按下逐行扫描
scancode=0xfe;//首列扫描字
while((scancode&0x10)!
=0)
{
PORTA=scancode;//输出行扫描码
if((PORTC&0x07)!
=0x07)//本行有键按下
{
tmpcode=PORTC|0xf8;//保留行信息,只有该行数据位为0
tmpcode=(tmpcode<<4)|0x0f;//行信息转换到高4位存储
/*返回特征字节码,为1的位即对应于行和列*/
do{
display();//延时去抖动,以显示扫描时间做延时
alarm();//闹铃时间比较
PORTA=scancode;
}while((PORTC&0x07)!
=0x07);//等键抬起
return((~scancode)+(~tmpcode));
}
elsescancode=(scancode<<1)|0x01;//行扫描码左移一位
}
}
}
return(0);//无键按下,返回值为0
}
/*主程序*/
uchargetkeynum(void)
{
ucharkey,keynum=0;
if((key=keyscan())!
=0)//调用键盘扫描函数
{
switch(key)
{
case0x11:
//第1行第1列
keynum=10;//数字键0
break;
case0x21:
//第2行第1列
keynum=4;//数字键4
break;
case0x41:
//第3行第1列
keynum=8;//数字键8
break;
case0X12:
keynum=1;//数字键1
break;
case0X22:
keynum=5;//数字键5
break;
case0X42:
keynum=9;//数字键9
break;
case0X14:
keynum=2;//数字键2
break;
case0X24:
keynum=6;//数字键6
break;
case0X44:
keynum=11;//校时键
break;
case0X18:
keynum=3;//数字键3
break;
case0X28:
keynum=7;//数字键7
break;
case0X48:
keynum=12;//闹钟时间
break;
default:
break;
}
}
return(keynum);
}
/*键盘修改计时初值或闹铃时间子程序*/
voidmodify(uchardata*p,ucharnum)
{
uchari,buf;
ucharkey=0;
location=0;
for(i=0;i { do{TR1=1;key=getkeynum();display();}while(key==0); /*扫描键盘,并对键入数合法性检测,只有1-10*/ TR1=0;times=0;TL1=0x58;TH1=0x9e;//初始化,重要! ! if(key==10)key=0;//转换数字0 elseif(key>10)break; dispbuf[i]=key;//键值送显示缓冲区 key=0;//下次按键前,必须清零 location++; } buf=dispbuf[0]*10+dispbuf[1];//时 if(buf>23)return; else*p=buf;//送数据到时缓冲(计时或闹铃) p++;//地址调整 buf=dispbuf[2]*10+dispbuf[3]; if(buf>59)return; else*p=buf;//送数据到分缓冲(计时或闹铃) if(num>4) { p++;//地址调整 buf=dispbuf[4]*10+dispbuf[5]; if(buf>59)return; else*p=buf;//送数据到秒缓冲(计时) } } /*主程序*/ voidmain(void) { ucharkeyin; SP=0x50;//设置堆栈区 PORT=0x89;//8255初始化 alarm_beep=1;//闹铃禁声 TMOD=0x11;//定时器0工作在方式1,定时器1工作在方式1 TL0=0xb0;//定时器0初始化,6MHz晶振定时时间100ms TH0=0x3c; TL1=0x58;//定时器1初始化,6MHz晶振定时时间50ms TH1=0x9e; ET0=1;//定时器0允许中断 ET1=1;//定时器1允许中断 EA=1; TR0=1;//启动定时器0 while (1) { display();//扫描显示 alarm();//闹铃时间比较 keyin=getkeynum();//调用键盘扫描 if(keyin>10)//是校时键或清闹键 { if((keyin==12)&&(alarm_fg==1)) { alarm_beep=1;//闹钟正在闹响,停闹 alarm_fg=0;//清零闹钟标志 } else { led1=0;//停止LED灯闪 led2=0; timeset_fg=1;//置位时间设置标志,禁止显示计时时间 if(keyin==11) { TR0=0;//是则暂时停止计时 led1=0;//停止LED灯闪 led2=0; modify(timebuf,6); } else { alarm_to_disp();//闹铃时分送显示缓冲前四位 dispbuf[4]=16;dispbuf[5]=16; modify(alarmbuf,4);//调用时间设置/闹钟定时程序 } TR0=1;//重新开始计时 timeset_fg=0;//清零时间设置标志,恢复显示计时时间 } }//endofif(keyin>10) }//endofwhile (1) } 任务实施 1.利用proteus仿真软件绘制仿真电路原理图 2.C51程序的编译 按照情景一KeilC51编译软件的操作步骤对源程序进行编译和调试。 3.执行程序观察效果 将编译成功后的.HEX文件加载到CPU执行程序并软硬件联调。 4.拟制电气原理并设计印刷电路板图 假设外部仅提供9V直流电源,用Protel99完善绘制该任务详细电原理图并设计印刷电路板图。 5.书写设计报告 参考图13.8所列多功能计数器论文目录格式,将该任务完成情况整理完善形成论文。 摘要要求中英文。 图13.8多功能计数器论文目录 相关知识 1.KeilC与Proteus联合调试 (1)在KeilC中建立好项目文件以及编译成功后,单击“Project菜单/OptionsforTarget”选项或者点击工具栏的“optionfortarget”按钮 ,弹出窗口,点击“Debug”按钮,出现如图所示页面。 在出现的对话框里在右栏上部的下拉菜单里选中“ProteusVSMMonitor”。 并且还要点击一下“Use”前面表明选中的小圆点。 再点击“Setting”按钮,设置通信接口,在“Host”后面添上“127.0.0.1”,如果使用的不是同一台电脑,则需要在这里添上另一台电脑的IP地址(另一台电脑也应安装Proteus)。 在“Port”后面添加“8000”。 设置好的情形如图所示,点击“OK”按钮即可。 最后将工程编译,进入调试状态,并运行。 (2)Proteus的设置 进入Proteus的ISIS,鼠标左键点击菜单“调试”,选中“使用远程调试设备”,如图所示。 打开与KeilC的工程文件所对应的图形文件,此后,便可实现KeilC与Proteus连接调试。 (3)KeilC与Proteus连接仿真调试 最后,将KeilC中的工程编译,进入调试状态,再看看Proteus,已经发生变化了。 这时再执行KeilC中的程序(单步、全速都可以,也可以设置断点等),Proteus已经在进行仿真了。 2.数码管技术资料
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 情境13 智能数字钟的设计与制作 情境 13 智能 数字 设计 制作