数字时钟设计报告.docx
《数字时钟设计报告.docx》由会员分享,可在线阅读,更多相关《数字时钟设计报告.docx(22页珍藏版)》请在冰豆网上搜索。
数字时钟设计报告
单片机实验报告
题目:
数字时钟的设计
指导老师:
班级:
姓名:
学号:
一、实验目的
通过实践设计出能准确显示时、分、秒的时钟,并可以调时、定时,包括蜂鸣器的整点报时与闹钟功能。
二、实验要求
基本功能:
准确计时,以数字形式显示时间,24时制;具备时、分调整和整点报时功能。
扩展功能:
定时与闹钟功能
三、设计方案及论证
Ⅰ、硬件部分:
1、时钟显示
用七段LED数码管来实现,采用共阳管和PNP驱动方式。
PNP工作于开关状态,基极通过1K的电阻连到单片机的P2口。
为节省P口,将六位数码管的8段段选端分别并接并加上470Ω的限流电阻,由P0口控制,给低电平的段会被点亮。
因为六位管的段被并接只能通过动态扫描的方式来显示,即利用管子的余晖和人眼的视觉残留实现六位管子在“同一时间”显示不同的值,而扫描这是靠位选的轮流有效实现。
如左图。
2、整点报时和闹钟铃
此部分用一个5V有源蜂鸣器来做,同样用PNP作为开关来控制,此外为防止其可能的方向电压尖峰在蜂鸣器两端反接一个IN4148二极管来保护。
如右图。
3、校时、定时
此部分由4个按键控制,如下图,key1和key3用来选定要调校的时、分的位,被选中的为将闪烁;key2用来是选中的为按相应的进制增1变化;key4是进入定时模式,定时的时数改变与调时方法相同。
4、单片机最小系统
本实验采用STC89C52RC单片机,指令系统完全与51兼容。
其最小系统包含电源电路、晶振电路、复位电路。
本实验才用STC单片机的典型系统,各模块参数配置如图:
其中晶振频率为12MHz,震荡部分电容为30pF的瓷片电容。
复位电路采用图示的兼有上电复位和按键复位功能的方式,其中的电容为10uF电解电容。
5、硬件系统全电路图
Ⅱ、软件部分
软件部分主要有两大块:
一是上电后程序靠定时器T1产生的中断而实现的常规时钟显示,这里面就是要处理时、分、秒的六位数字的循环和进位问题。
按照24时制的规则,其进位逻辑为:
秒的个位为十进制(0~9)满10向秒的十位进1,而秒的十位为六进制(0~5)满6向分的个位进1,分与秒相似,时的个位在时的十位为0、1的时候也是10进制,而在时的十位为2的时候则只是0到4就进位了。
但时的十位是3进制的(0~2)。
m0++;
if(m0==10)
{m0=0;
m1++;
if(m1==6)
{
m1=0;
f0++;
if(f0==10)
{
f0=0;
f1++;
if(f1==6)
{
f1=0;
h0++;
if(h0==10)
{
h0=0;
h1++;
}
}
}
}
}
二是程序监控4个按键的状态并进行相应处理。
本实验中我们并未利用外中断来监控键盘,只是在主函数中用一个函数key_scan()来不停地扫4个键的状态并进行相应处理,这一部分的程序中主要的问题是按键抖动的去除,试验中,我们用的是软件延时的办法。
四、心得体会
通过本次课程设计,我学习到了很多,也收获了很多。
总结如下:
一、我对单片机的理论知识有了进一步的掌握,对单片机的原理和实际应用有了更多地理解和掌握。
二、我对单片机的C语言编程有了更深刻的认识和更扎实的掌握,我们不断修改,不断尝试,对源代码各个模块的函数都有了一个非常深入的掌握。
三、理论与实践相结合才能更好的理解和掌握所学的知识。
五、附件(程序源代码)
#include
sbitk1=P1^4;
sbitk2=P1^5;
sbitk3=P1^6;
sbitk4=P1^7;
sbitvoice=P3^6;//蜂鸣器使能端
unsignedcharcodeduan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};//段的共阳编码:
0、1、2、3、4、5、6、7、8、9、灭灯
unsignedcharcodewei[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};//共阳位选编码:
第0位、第1位、第2位、第3位、第4位、第5位、第6位、第7位
unsignedcharm0=0,m1=0,f0=0,f1=0,h0=0,h1=0,num=0,con=0;//正常时钟模式
unsignedchard_f0=0,d_f1=0,d_h0=0,d_h1=0,d_con=0;//定时模式相关变量
unsignedshan=0;//闪烁函数中量、灭的次数的控制变量
unsignedsound=0;//蜂鸣器叫与不叫的次数的控制变量
bitxiang=0;//蜂鸣器使能变量
bitdingshi=0;//定时模式的使能变量
bitnaozhong=0,only=0;//闹钟的止叫控制变量
voidinit();//初始化定时器1
voiddisplay();//正常时钟显示
voidd_display();//定时模式的显示
voiddelay_ms(unsigned);//非准确延时
voidkey_scan();//按键扫描、处理函数
voidshanshuo(unsignedchar);//数码管闪烁显示
voidfengming(unsigned);//蜂鸣器叫
//**********************************************************************main()
voidmain()
{init();
while
(1)
{key_scan();
//整点报时
if(m0==0&&m1==0&&f0==0&&f1==0)xiang=1;
if(m0==2&&m1==0&&f0==0&&f1==0){voice=1;xiang=0;}//蜂鸣器叫两声
//闹钟
if(h1==d_h1&&h0==d_h0&&f1==d_f1&&f0==d_f0&&naozhong==0&&only==1)naozhong=1;//预定时间到
if(naozhong==1&&(k1==0||k2==0||k3==0||k4==0)){naozhong=0;only=0;voice=1;while(!
k1);while(!
k2);while(!
k3);while(!
k4);}//禁止闹钟叫
if(only==0&&h1!
=d_h1&&h0!
=d_h0&&f1!
=d_f1&&f0!
=d_f0)only=1;//时刻唤醒闹钟、另外,在退出定时模式时也能唤醒闹钟
//正常显示
if(dingshi==0)display();
//闹钟定时模式
if(dingshi==1)d_display();
}
}
//*************************************************************************
//********************************************************************init()
/*参数:
无
返回值:
无
功能:
设置T1计数器相关的特殊功能寄存器,初始化计时器T1
细节:
备注:
*/
voidinit()
{
TMOD=0X10;
TH1=0X3C;TL1=0XB0;
EA=1;
ET1=1;
TR1=1;
}
//*************************************************************************
//*******************************************************TI_time()interrupt3
/*参数:
返回值:
功能:
细节:
备注:
*/
voidTI_time()interrupt3
{
TH1=0X3C;TL1=0XB0;
num++;
if(num==20)
{
num=0;
m0++;
if(m0==10)
{m0=0;
m1++;
if(m1==6)
{m1=0;
f0++;
if(f0==10)
{
f0=0;
f1++;
if(f1==6)
{
f1=0;
h0++;
if(h0==10)
{h0=0;
h1++;
}
}
}
}
}
}
if(h1==2)
{if(h0==4)
{
h0=0;h1=0;
}
}
}
//*********************************************************************
//**************************************************************display()
/*参数:
返回值:
功能:
细节:
备注:
*/
voiddisplay()
{
intj;
for(j=0;j<8;j++)
{P2=wei[j];
switch(j)
{
case0:
if(!
naozhong&&xiang)fengming(400);if(naozhong==1)fengming(200);
P0=duan[m0];delay_ms
(1);P0=0xff;break;
case1:
P0=duan[m1];delay_ms
(1);P0=0xff;break;
case3:
if(con==1)shanshuo(f0);elseP0=duan[f0];delay_ms
(1);P0=0xff;break;
case4:
if(con==2)shanshuo(f1);elseP0=duan[f1];delay_ms
(1);P0=0xff;break;
case6:
if(con==3)shanshuo(h0);elseP0=duan[h0];delay_ms
(1);P0=0xff;break;
case7:
if(con==4)shanshuo(h1);elseP0=duan[h1];delay_ms
(1);P0=0xff;break;
}
}
}
//********************************************************************
//**********************************************************d_display()
/*参数:
返回值:
功能:
细节:
备注:
*/
voidd_display()
{intj;
for(j=0;j<8;j++)
{P2=wei[j];
switch(j)
{
case0:
P0=0xff;delay_ms
(1);break;
case1:
P0=0xff;delay_ms
(1);break;
case3:
if(d_con==1)shanshuo(d_f0);elseP0=duan[d_f0];delay_ms
(1);P0=0xff;break;
case4:
if(d_con==2)shanshuo(d_f1);elseP0=duan[d_f1];delay_ms
(1);P0=0xff;break;
case6:
if(d_con==3)shanshuo(d_h0);elseP0=duan[d_h0];delay_ms
(1);P0=0xff;break;
case7:
if(d_con==4)shanshuo(d_h1);elseP0=duan[d_h1];delay_ms
(1);P0=0xff;break;
}
}
}
//*********************************************************************
//***********************************************************keyscan()
/*参数:
返回值:
功能:
细节:
备注:
*/
voidkey_scan()
{
//****************************************调时
if(dingshi==0&&naozhong==0)
{if(k1==0)//调时选位
{delay_ms(60);//去抖动延时
if(k1==0)
{con++;
if(con==5)con=0;
while(!
k1);//程序会停在这里,所以此时会没有任何显示.但时间的进位并没有停,因为中断有优先权。
即时间还在走
}
}
if(k3==0)//tiao时选位
{delay_ms(60);//去抖动延时
if(k3==0)
{con--;
if(con==-1)con=4;
while(!
k3);//程序会停在这里,所以此时会没有任何显示但时间的进位并没有停
}
}
if(con==1&&k2==0)//调分的个位++
{
delay_ms(60);
if(k2==0)
{
f0++;
if(f0==10)f0=0;
while(!
k2);//程序会停在这里,所以此时会没有任何显示但时间的进位并没有停
}
}
if(con==2&&k2==0)//调分的十位++
{
delay_ms(60);
if(k2==0)
{
f1++;
if(f1==6)f1=0;
while(!
k2);//程序会停在这里,所以此时会没有任何显示但时间的进位并没有停
}
}
if(con==3&&k2==0)//调时的个位++
{delay_ms(60);
if(k2==0)
{
if(h1==1||h1==0)
{
h0++;
if(h0==10)h0=0;
}
if(h1==2)
{
h0++;
if(h0==4)h0=0;
}
while(!
k2);//程序会停在这里,所以此时会没有任何显示但时间的进位并没有停
}
}
if(con==4&&k2==0)//调时的十位++
{
delay_ms(60);
if(k2==0)
{
h1++;
if(h1==3)h1=0;
while(!
k2);//程序会停在这里,所以此时会没有任何显示但时间的进位并没有停
}
}
if(k4==0)//启动定时功能
{
delay_ms(60);//去抖动延时
if(k4==0)
{
dingshi=1;
while(!
k4);
}
}
}
//**************************************************定时
if(dingshi==1&&naozhong==0)
{
if(k4==0)//退出定时功能
{
delay_ms(60);//去抖动延时
if(k4==0)
{
dingshi=0;
only=1;
d_con=0;
while(!
k4);
}
}
if(k3==0)//定时选位
{
delay_ms(60);//去抖动延时
if(k3==0)
{
d_con--;
if(d_con==-1)d_con=4;
while(!
k3);//程序会停在这里,所以此时会没有任何显示但时间的进位并没有停
}
}
if(k1==0)//定时选位
{
delay_ms(60);//去抖动延时
if(k1==0)
{
d_con++;
if(d_con==5)d_con=0;
while(!
k1);//程序会停在这里,所以此时会没有任何显示.但时间的进位并没有停,因为中断有优先权。
即时间还在走
}
}
if(d_con==1&&k2==0)//调定时分的个位++
{
delay_ms(60);
if(k2==0)
{
d_f0++;
if(d_f0==10)d_f0=0;
while(!
k2);
}//程序会停在这里,所以此时会没有任何显示但时间的进位并没有停
}
if(d_con==2&&k2==0)//调定时分的十位++
{delay_ms(60);
if(k2==0)
{d_f1++;
if(d_f1==6)d_f1=0;
while(!
k2);
}//程序会停在这里,所以此时会没有任何显示但时间的进位并没有停
}
if(d_con==3&&k2==0)//调定时时的个位++
{delay_ms(60);
if(k2==0)
{if(d_h1==1||d_h1==0)
{d_h0++;
if(d_h0==10)d_h0=0;
}
if(d_h1==2)
{d_h0++;
if(d_h0==4)d_h0=0;
}
while(!
k2);//程序会停在这里,所以此时会没有任何显示但时间的进位并没有停
}
}
if(d_con==4&&k2==0)//调定时时的十位++
{delay_ms(60);
if(k2==0)
{d_h1++;
if(d_h1==3)d_h1=0;
while(!
k2);//程序会停在这里,所以此时会没有任何显示但时间的进位并没有停
}
}
}
}//keyscan()
//*************************************************************************
//*****************************************************************shanshuo()
/*参数:
返回值:
功能:
细节:
备注:
*/
voidshanshuo(unsignedcharw)
{
shan++;
if(shan<35)P0=duan[10];
elseP0=duan[w];
if(shan>=70)shan=0;
}
//*************************************************************************
//*****************************************************************fengming()
/*参数:
返回值:
功能:
细节:
备注:
*/
voidfengming(unsignedx)
{sound++;
if(soundelsevoice=1;
if(sound>=2*x)sound=0;
}
//*************************************************************************
//*****************************************************************delay_ms()
/*参数:
返回值:
功能:
细节:
备注:
*/
voiddelay_ms(unsignedt)//六分之一毫秒
{inti,j;
for(i=0;ifor(j=0;j<120;j++);}