单片机课设定时闹钟.docx
- 文档编号:9585096
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:25
- 大小:231.38KB
单片机课设定时闹钟.docx
《单片机课设定时闹钟.docx》由会员分享,可在线阅读,更多相关《单片机课设定时闹钟.docx(25页珍藏版)》请在冰豆网上搜索。
单片机课设定时闹钟
专业
姓名
学号
指导老师
完成时间
关键字1
1.6串口通信图8
参考文献
摘要
本设计采用ATMELAT89C52MCU作为处理器核心,用数码管作为数据显示工具,蜂鸣器实现响铃功能,独立式键盘K20-K27控制时钟,串口用于设置时钟和闹钟时间来制作一个定时闹钟。
秒数走位由MCU内部11.0592MHz的晶振提供精确定时实现,并循环扫描,在数码管上显示。
本设计的关键是键盘的动态扫描和按键消抖,难点是串口数据的传送和处理。
本设计运用C51编程,由于C语言具有语法简单、代码简洁且执行效率高等优点,使得C语言广泛运用于各种程序设计的代码编辑工具中。
运用C语言编程,增强了程序可读性;使得开发人员能够将精力用在如何设计程序上来,提高了开发效率。
关键字:
单片机动态扫描按键消抖C51编程
正文
一、系统设计
1.1设计目标
利用动态数码管作为显示器,K20-K27作为输入按键,蜂鸣器作为声音输出制作一个定时闹钟。
要求:
1、正确显示时分。
2、可以利用按钮调整时间和设定闹钟时间。
3、当时间到达设定的闹钟时间时,蜂鸣器发出嘀、嘀、嘀的报警声。
提示:
利用定时器作为时间的基准。
提高:
通过串口在PC上设定时间和闹钟
1.2硬件设计
本设计中涉及到的硬件模块有C52、独立键盘、数码管、PC(含keil软件、烧写工具、串口调试工具等)
1.2.1C52
核心处理器。
对传送的各个指令和数据进行处理。
供其他模块用到的主要引脚有:
P0:
送码值;P2:
送位选信号,连接键盘;TXD、RXD:
串口通信;P3.7:
蜂鸣器
1.2.2独立键盘K20-K27
键盘分为独立键盘和矩阵式键盘。
扫描方法有逐行扫描法和行列翻转法。
在本设计中用到的键盘是独立式键盘K20-K27,分别连接到MCUC52的P2口,采用逐行扫描法,又由于只有一行,故只需扫描一次即可。
在键盘按键时,需要考虑到键盘消抖问题。
键盘消抖分为硬件消抖和软件消抖。
在本设计中,直接采用软件延时delay2(),达到消抖功能,代码不长,又节省硬件资源。
独立键盘K20-K27连接到C52管脚P2和数码管。
各键功能:
K20:
编辑时间,以递增方式控制时针数值,包括时钟和闹钟
K21:
编辑时间,以递增方式控制分针数值,包括时钟和闹钟
K22:
时钟模式切换到闹钟模式
K23:
退出闹钟模式,并保存闹钟时间,开启闹钟
K24:
时钟模式和秒数显示模式切换
K25:
未用到,供功能扩充使用
K26:
开闹钟
K27:
关闹钟
1.2.3数码管
数码管用于显示当前时间,闹钟时间和秒数。
数码管显示分为静态显示和动态显示。
静态显示时,各数码管在显示过程中持续得到送显信号,与各数码管接口的I/O口线是专用的。
静态显示需借助C52串口完成。
动态显示时,各数码管在显示过程中轮流得到送显信号,与各数码管接口的I/O口线是共用的。
在动态显示过程中,数码管常亮是通过循环扫描送显信号实现。
本设计中用到的数码管为共阴极接法,阴极接位选信号,即C52P2口,阳极接P0口,接受码值。
时钟和闹钟模式下,显示时针数值和分针数值。
秒数显示模式下,只有两个数码管亮,显示当前时间秒值。
1.2.4PC
在PC端除了编辑软件Keil和烧写工具外,另一个很重要的工具就是串口调试工具。
串口工具通过串口线与C52通信。
PC端到C52传送数据,控制写当前时间和设置闹钟。
C52到PC端传送数据,提示PC送到C52的数据有误,并在串口界面上显示字符串“error!
”,供以提示。
在PC端的串口工具选项设置与代码中串口设计参数匹配。
波特率为9600,数据位8位,停止位1位。
采用十六进制Hex发送。
根据上述硬件设计,有如下硬件间系统框图1。
1.3软件设计
1.3.1时钟
时钟设计有两个方案,一:
利用程序计数延时定时;二:
利用定时器定时。
考虑到,程序定时不准确,误差大,而定时器c52内部晶振提供的时钟,能够精确定时,所以,本设计采用定时器给各模块提供准确时钟。
对于时钟,主要用在走秒,即定时器定时时间为1s,考虑到,设计中需要用到串口进行数据传送,而且对用C52,1s属于长定时,所以定时器采用定时器timer0。
timer0工作在方式1,定时设置为50ms,即初始值为TH0=0x4c,TL0=0x01,再通过一个标志位flag来控制次数,初始值为20,则定时时间刚好为1s。
1.3.2时间显示模式
从设计要求看,本设计至少要涉及到两个模式:
(1)时钟模式;
(2)闹钟模式。
时钟模式下,数码管实时显示当前时间,闹钟模式下,显示设置的闹钟时间,并且闹钟模式下,数码管显示的值闪烁,以区别于时钟模式,这样更易于区分这两种模式。
这两个模式通过K22和K23来切换,K22从时钟模式进入闹钟模式,K23退出闹钟模式,并保存当前设置的闹钟时间,并置位闹钟状态位flag1=0(flag1=0,开闹钟;flag1=1,关闹钟),此外,时钟、闹钟模式下均为可编辑状态,K20、K21分别控制时针数值和分针数值。
为了更接近现实的时钟,本设计提供第三种模式--秒数显示模式。
这个模式下,4个数码管只有两个亮,用来显示秒数值,通过键K24切换到此模式,和退出此模式,对于秒数,其控制权在定时器timer0,不提供编辑功能。
1.3.3振铃
此功能的实现主要依靠实验箱上的蜂鸣器,当当前时间到达闹钟时间时,RD=0,开始振铃,蜂鸣器响。
本设计中,在振铃状态,提供关闹铃功能,通过K27关闹钟,置闹钟状态位flag1=1,关闹钟;若是需要打开闹钟,则可按键K26,置flag1=0。
1.3.4串口
此功能用于,在PC上通过串口工具,传送数据到C52,进而控制数码管值,即设置时间和闹钟。
在实现串口功能,搭配用了定时器timer2,timer2工作于方式2,即8位自动重装。
timer2作为波特率发生器,给串口提供数据传送速率。
本设计中,波特率为9600,故timer2初始值为TH1=0xfd,TL1=0xfd。
在本设计中,在时钟模式和闹钟模式下,串口数据逐位传送,分别传给时针数值和分针数值。
更具人性化的是,本设计提供错误提。
当传送时针数值时,数据大于23,或传送分针数值时,数据大于59时,C52通过串口向PC传送错误提示“error!
”,提示数据传送错误。
1.3.5键盘扫描
本设计中键盘采用独立键盘K20-K27。
读取键盘值通过:
P2=0xff;key_pressed=P2;key_pressed则为读取到的键盘值,再匹配从而知道按了哪个键。
在键盘扫描设计中,一个关键技术是键盘消抖。
这里通过延时程序delay2()延时一段时间,再读取键盘值,判断是键盘抖动还是正常按下的值。
1.4三个模式间状态图
1.5键盘控制程序走向流程图
图3中为体现的功能及操作有以下几点:
1.5.1计数模块count()
计数功能依靠定时器timer0的中断,定时1s,当前时间走1秒。
1.5.2振铃模块music()
该功能由蜂鸣器完成。
置RD=0时,蜂鸣器响。
此外蜂鸣器响有一个前提条件:
振铃处于开状态,即标志flag1=0。
1.5.3显示模块display()
该功能显示当前时间或闹钟时间或秒数。
控制条件有:
标志CS:
CS=0:
显示当前时间时、分;CS=1:
显示当前时间秒;CS=2:
闹钟状态;
标志flag2:
控制闹钟状态下闪烁显示。
1.6串口通信图
1.5.1串口向MCU送数据
送时针值时,数值大小小于24,送分针数值,数值小于60。
1.5.2MCU向串口送错误提示信息
串口向MCU送数据不满足上述条件时,送“error!
”提示信息。
1.5.3数据显示
若串口传送的数据满足上述条件,则在数码管上显示,否则保持不变。
2实验结果与讨论
2.1程序烧写
通过烧写程序将源码烧到单片机中。
数码管初始显示为00.00,与程序设置count_m,count_h吻合。
2.2程序调试
2.2.1按键K20和K21,时、分值分别增加,一直按着,则时间持续变化。
但不是很稳定,有待改进。
2.2.2按键K22,数码管进入闹钟编辑状态,并且显示数值交替闪烁。
与程序设置
if(flag2<=10&&CS==2){P2=0xff;}
else{if(flag2>=20){flag2=0;}
一致(flag2在定时器中断中改变)。
2.2.3按键K23,退出闹钟编辑状态。
保存当前闹钟设置值count_m_alarm=count_x;count_h_alarm=count_y,开启闹钟flag1=0。
2.2.4按键K24,切换到秒显示状态。
再按一次切回时钟模式。
2.2.5按键K26,关闭闹钟;按键K27,开启闹钟。
在当前时间时、分值与闹钟设置值匹配时,这两个键的功能吻合。
2.3串口发送。
打开串口调试工具,选择端口,设置其它选项,分两次传送,如两次均发送十六进制数09,数码管显示值如附图6。
若设置时针值大于23,设置分针值大于59,则提示错误,显示结果如附图7。
3结论
3.1综合上述所有描述,本设计完成了闹钟基本的功能。
此外,添加了其他功能。
如,本闹钟不仅可以显示时间时、分值,闹钟值,还可以显示秒数。
具有闹钟开、关功能。
对提高部分做了扩充,可以提示是否有数据设置错误。
3.2本设计很好地完成了闹钟设计,具有自己的特色。
美中不足的是,通过键盘设置时钟时,数值不易把握;闹钟响时,声音比较怪。
3.3自我体会
本次课程设计,加深了对理论知识的实践,学到了很多课堂上没有学到的知识。
对单片机的了解和应用更深一层。
课程设计往往具有一定的趣味性,更能激起大家的兴趣,对知识的深入理解只会是有百利而无一害。
与课堂上讲的理论知识不同的是,课堂上都是采用汇编语言,而到了真正设计时,更多的是采用C语言编程,这样更加的简单,提高了开发的效率。
参考文献
[1]田希晖薛亮儒.C51单片机技术教程[M].北京,人民邮电出版社.2007
[2]张友德赵志英涂时亮.单片微型机原理、应用与实验(第五版)[M]上海,复旦大学出版社.2006
附录
1、程序源代码
#include
unsignedcharcount_s,count_m,count_h;//秒、分、时时间
unsignedcharcount_x,count_y,count_m_alarm=0,count_h_alarm=23;//count_x,count_y记录当前时间;count_m_alarm=0,count_h_alarm=23:
预置闹钟时间,同时用于保存闹钟设置
unsignedcharflag=0,flag1=0,flag2=0;//flag0:
中断时间=timer0初始值*flag;flag2:
控制闹钟状态下闪烁,区别于正常时钟模式
unsignedchardis_duanma[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共阴码表
unsignedcharCS;//当前显示的计数段;CS=0:
显示时、分,时钟状态;CS=1:
显示秒数;CS=2:
闹钟编辑状态;
unsignedchartag=0;//串口输入数据,区别时、分
unsignedcharERROR[]="error!
";//串口输入出错,提示字符串
voiddisplay();
voiddelay()//动态扫描延时
{
unsignedintcount_delay;
for(count_delay=0;count_delay<=1000;count_delay++);
}
voiddelay2()//按键消抖延迟
{
unsignedintcount_delay;
for(count_delay=0;count_delay<=10000;count_delay++);
}
voidmusic()//蜂鸣器发声
{
if(flag1==0)
RD=0;
}
voidcount()//计数模块
{
if(count_s>=59)
{
count_s=0;
if(count_m>=59)//>=:
由于进位的原因
{
count_m=0;
if(count_h>=23)
{
count_h=0;
}
else
count_h++;
}
else
count_m++;
}
else
{
count_s++;
}
}
voidIntT0()interrupt1//定时器T0中断,计数
{
TH0=0x4c;//重置初始值
TL0=0x01;
flag++;
flag2++;
if(flag==20)//timer0中断时间被乘数
{
//中断次数,即中断时间到达,重置中断次数
flag=0;
count();
}
elseif(count_m!
=count_m_alarm|count_h!
=count_h_alarm)
{
//当前时间与闹钟时间不匹配,表示不在闹钟状态,关闭蜂鸣器
RD=1;
}
elseif(count_m==count_m_alarm&&count_h==count_h_alarm)
{
//当前时间与闹钟时间匹配,表示在闹钟状态,开启蜂鸣器
music();
}
}
voidsendError()
{
unsignedchari=0;
ES=0;
for(i=0;i<7;i++)
{
SBUF=ERROR[i];
while(!
TI);
TI=0;
}
ES=1;
}
voidIntS()interrupt4
{
unsignedcharserialData;
if(RI==1)
{
serialData=SBUF;
if(tag==0)//时
{
if(serialData>23)
{
sendError();
gotoloop2;
}
}
elseif(tag==1)//分
{
if(serialData>59)
{
sendError();
gotoloop2;
}
}
if(CS==2)//闹钟状态
{
if(tag==0)//时
{
count_y=SBUF;
tag++;
}
elseif(tag==1)//分
{
count_x=SBUF;
tag=0;
}
}
elseif(CS==0)//时钟状态
{
if(tag==0)//时
{
count_h=SBUF;
tag++;
}
elseif(tag==1)//分
{
count_m=SBUF;
tag=0;
}
}
loop2:
display();
RI=0;
}
}
voiddisplay()//显示译码;P0送码值;P2送位选信号(高四位P24-P27)
{
if(flag2<=10&&CS==2)
P2=0xff;
else
{
if(flag2>=20)
flag2=0;
elseif(CS==1)//显示秒状态,送秒数
{
//下1
P0=dis_duanma[count_x%10];
P2=0x7f;
delay();
//下2
P0=dis_duanma[count_x/10];
P2=0xbf;
delay();
}
else//显示时分状态,送时、分
{
//送分
//下1
P0=dis_duanma[count_x%10];
P2=0x7f;
delay();
//下2
P0=dis_duanma[count_x/10];
P2=0xbf;
delay();
//送时
//上2
P0=dis_duanma[count_y%10]+0x80;
P2=0xdf;
delay();
//上1
P0=dis_duanma[count_y/10];
P2=0xef;
delay();
}
}
}
voidmain()//主函数
{
unsignedcharkey_pressed;//检测按键是否按下
TMOD=0x21;//定时器方式寄存器,timer1:
工作方式2,配合串口;timer0工作方式1,16定时
PS=0;//中断优先级寄存器IP,
PT0=1;//timer0中断优先级高于串口中断
TH0=0x4c;//初始化方式1初始值,T=(12/fosc)*(2^16-a)us,
TL0=0x01;//a=0x4501=19457d,T=0.05s
TH1=0xfd;//初始化方式2,8位自动重装,初始值X=2^n-(2^SMOD*fosc/(32*波特率*12));
TL1=0xfd;//波特率=9600
SCON=0x50;//串口控制寄存器,方式1,(1+8+1)位
PCON=0x00;//电源控制寄存器,SMOD=0,波特率不加倍
EA=1;//中断允许寄存器,允许中断
ES=1;//串口中断允许
ET0=1;//timer0中断允许
TR0=1;//定时器控制寄存器(TCON),启动timer0
TR1=1;//启动timer1
while
(1)
{
RD=1;//关闭蜂鸣器
loop1:
if(CS==1)//CS当前状态是显示秒还是时、分
{
count_x=count_s;//将秒送给显示寄存器
count_y=0;
}
else
{
count_x=count_m;//送分给显示寄存器(时钟状态模式)
count_y=count_h;//送时给显示寄存器
}
display();//调用显示子函数
P2=0xff;//先写一再读取
key_pressed=P2;//读取键盘值
if((key_pressed&0x01)==0x00&&CS==0)//判断按下的按键是否为编辑时,如果正在显示秒,则不予以回应
{
delay2();//消抖
P2=0xff;
key_pressed=P2;//再判断
if((key_pressed&0x01)==0x00)
{
if(count_h>=23)
count_h=0;
else
count_h++;
}
}
elseif((key_pressed&0x02)==0x00&&CS==0)//判断是否按下时编辑按键,如果正在显示秒,则不予以回应
{
delay2();//延时消抖
P2=0xff;
key_pressed=P2;
if((key_pressed&0x02)==0x00)
{
if(count_m>=59)
count_m=0;
else
count_m++;
}
}
elseif((key_pressed&0x04)==0x00)//按下闹钟调节按键
{
delay2();//延时消抖
P2=0xff;
if((key_pressed&0x04)==0x00)
{
CS=2;
count_x=count_m_alarm;//读取闹钟设置
count_y=count_h_alarm;//读取闹钟设置
loop:
display();//显示闹钟设置时间
P2=0xff;
key_pressed=P2;
if((key_pressed&0x01)==0)//按下编辑时按键
{
delay2();
P2=0xff;
key_pressed=P2;
if((key_pressed&0x01)==0)
{
if(count_y>=23)
count_y=0;
else
count_y++;
}
}
elseif((key_pressed&0x02)==0)//编辑分按键
{
delay2();
P2=0xff;
key_pressed=P2;
if((key_pressed&0x02)==0)
{
if(count_x>=59)
count_x=0;
else
count_x++;
}
}
elseif((key_pressed&0x08)==0x00)//退出设置按键
{
delay2();
P2=0xff;
key_pressed=P2;
if((key_pressed&0x08)==0x00)
{
count_m_alarm=count_x;//保存闹钟设置
count_h_alarm=count_y;//保存闹钟设置
CS=0;//撤销编辑状态
if(flag1==1)
{
flag1=0;
}
gotoloop1;//跳出闹钟编辑设置
}
}
gotoloop;//处于闹钟编辑状态,刷新设置的闹钟时间
}
}
elseif((key_pressed&0x10)==0)//按下显示状态按键(显示时分或者显示秒)
{
delay2();
P2=0xff;
key_pressed=P2;
if((key_pressed&0x10)==0)
{
if(CS>=1)
CS=0;
else
CS++;
}
}
elseif((key_pressed&0x40)==0)
{
delay2()
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 定时 闹钟