单片机课程设计 可调数字钟 (来自河北大学)_单片机课程设计数字钟
单片机课程设计 可调数字钟 (来自河北大学)由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“单片机课程设计数字钟”。
单片机课程设计 201244xxxx xx 12xx
一、绪论
单片机正朝着高性能和多品种的方向发展,下一步的趋势将是继续向着CMOS化、低功耗、小体积、大容量、高性能、低价格和外围电路内装化等几个方面发展。单片机应用的重要意义还在于,它从根本上改变了传统控制系统的设计思想和设计方法。以前必须由模拟电路或数字电路实现的大部分功能,现在已经能用单片机通过软件方法来实现了。
用单片机设计制作数字钟是单片机的一个典型应用。通过设计制作一个数字钟,我们可以充分了解单片机的工作原理,学会如何用单片机实现数据的处理以及设备的控制等。设计制作一个数字钟虽然简单,但涉及到的内容却十分广博。
本课程设计是基于单片机时钟的LED显示,通过单片机产生计数功能,经由LED数码管显示,显示时间时、分、秒,并用按键进行时间调整,同时带有整点报时功能。
本课程设计只是设计制作一个功能简单的数字钟,旨在通过对简单的硬件和软件的操作和应用以实现用数码管显示的数字钟,尝试基本的电路设计和单片机的C语言编程以及锻炼实践动手能力。
二、整体设计
本设计采用51单片机内部定时器产生时钟来进行准确计时,时分秒由3个变量来记录,定义按键功能,来实现时钟的调节,最终是由LED数码管来动态显示时间。
三、硬件电路设计
3.1 总体电路设计
单片机课程设计 201244xxxx xx 12xx
3.2信号处理电路
3.3单片机最小系统电路
单片机课程设计 201244xxxx xx 12xx
单片机外围电路有时钟电路和复位电路等,时钟电路采用的是内部时钟方式,在单片机内部有一振荡电路,在外部的XTAL1和XTAL2引脚外接石英石英晶体(晶振)就构成了自激振荡器课在单片机内部产生时钟脉冲信号,两电容作用是稳定频率和快速起振,晶振的振荡频率我们采用的是经典值12MHz。
复位电路采用的是上电复位和按键复位均有效的方式,单片机执行复位操作后进入初始化状态。
主要功能引脚能能如下:
P0的8位引脚产生8位段选信号,用于数码管显示;
P1.0口控制着电路板上的绿色指示灯的亮灭,其中1为灭,0为亮; P2口各引脚功能:
P2.0~ P2.2分别连接3-8译码器的A、B、C输入端,编程时需要写P2.0~ P2.2口来实现控制六个数码管的逐个显示;
P2.3连接3-8译码器的使能端,编程时需要对P2.3写入0;
P2.7~ P2.4分别连接K1~K4按键,编程时,需要通过读取P2.7~ P2.4的值获取按键状态;
3.4 显示电路设计
单片机课程设计 201244xxxx xx 12xx
3.5 串口通信电路设计
3.6 电源电路设计
单片机课程设计 201244xxxx xx 12xx
3.7 按键控制电路设计
本次设计采用了4个独立的按键K1,K2,K3,K4用于后期时间的调整,其分别与单片机的P2.7~ P2.4引脚连接,编程时,需要通过读取P2.7~ P2.4的值获取按键状态。各按键经由上拉电阻与VCC相连,当按键按下时,与按键相连接的引脚为低电平,按键弹起时是高电平,即一次按键按下,为一个下降沿和一个上升沿。
单片机课程设计 201244xxxx xx 12xx
四、软件设计
4.1 程序设计总体思路
本次设计要实现数字钟的可调功能,我把程序分化为五个模块分别进行编写,分别为时间处理子程序、显示子程序、按键扫描子程序、整点报时子程序以及中断子程序。
4.2 各模块程序设计
4.2.1 时间处理子程序
在此模块中把秒sec设置为六十进制,分钟min设置为六十进制,小时hour设置为二十四进制,即当时间增加1s时,将显示部分的“秒”位加一,加到60以后进位为“分”,“秒”位清零;当“分”累加到60后进位为 “时”,“分” 位清零;当“时”位为24以后,所有位清零后重新开始记时。时间处理子程序如下:
void proc()
//时间处理子程序 { if(sec==60)
//秒变量满60进一 {sec=0;min++;if(min==60)//分变量满60进一 {min=0;hour++;if(hour==24)//时变量满24进一
{hour=0;} } } }
4.2.2 时钟显示子程序
此段子程序用于实现数码管的动态显示,分为段选和片选。当系统处于正常计时状态时,数码管正常显示时钟,时与分之间和分与秒之间的小数点以1Hz的频率闪烁;当调节按键按下时,adjust_flag==1,小数点停止闪烁,当调节哪一位时(时、分、秒),哪一位的个位的小数点常亮,便于显示哪一位正在处于调节
单片机课程设计 201244xxxx xx 12xx 状态。
时钟显示子程序如下:
void display()
//时钟显示子程序 { a=0;b=0;c=0;//位选,刷新小时的十位
P0=zixing[hour/10];//段选,将小时的十位数的字形赋给P0输出显示 delay(3);//延时3ms
a=1;b=0;c=0;
//位选,刷新小时的个位
if(adjust_flag==0&TR0==1)//正常计时时,时的个位的小数点闪烁 {if(dot==1)P0=(zixing[(hour%10)]);else P0=(zixing[(hour%10)])|0X80;} //字形码的单片机课程设计 201244xxxx xx 12xx P0=(zixing[(sec%10)])|0X80;//秒的个位小数点常亮 else P0=(zixing[(sec%10)]);//正常计数和调节其他位时,小数点都不亮 delay(3);}
4.2.3 检测按键子程序
按键扫描子程序即扫描读取K1、K2、K3、K4,如果有按键按下,则做相应的处理。规定按键的功能如下:
K4(P2.4):调节按键,当按一下K4时,由时间状态进入调节状态,调节标志变量adjust_flag=1,此时若adjust_selc==1,调秒;再按一下,adjust_selc==2,则调分;再按一下,adjust_selc==3,则调时;再按一下,adjust_selc==4,adjust_selc=0,按一下K3或K2,由调节状态便成为时钟显示状态。
K3(P2.5):加1按键,在调节状态下即adjust_flag=1,按一下K3按键则相应的调节位加1;
K2(P2.6):减1按键,在调节状态下即adjust_flag=1,按一下K2按键则相应的调节位减1。
检测按键子程序如下:
void testkey()
//检测按键子程序 {
if(P2_4==0)
//K4键按下时 {display();display();display();display();display();
//用延时进行消抖处理 if(P2_4==0){TR0=0;
//调时按键按下时,关闭定时器,停止计时 adjust_flag=1;
//调节标志置1,进入调时状态 if(adjust_selc
} if(P2_5==0&&adjust_flag==1)//K3加1键功能定义 {display();display();
单片机课程设计 201244xxxx xx 12xx display();display();display();
//用延时进行防抖处理 if(P2_5==0){switch(adjust_selc)//定义各调节模式下的按键功能 {
case 1:
//调秒 if(sec
//调分 if(min
//调时 if(hour
//定时器重新赋初值,开始计时 TL0=0xb0;TR0=1;display();break;default:break;}}} if(P2_6==0&&adjust_flag==1)
//K2减1键功能定义 {display();display();display();display();display();
//用延时进行按键防抖 if(P2_6==0){switch(adjust_selc)//定义各调节模式下的按键功能 {
case 1:
//调秒 if(sec>0)sec--;else sec=59;break;
单片机课程设计 201244xxxx xx 12xx case 2:
//调分 if(min>0)min--;else min=59;break;case 3:
//调时 if(hour>0)hour--;else hour=23;break;case 4:adjust_flag=0;
//确认状态时,按一下K2则进入时钟计时模式 TH0=0x3c;
//定时器重新赋初值,开始计时 TL0=0xb0;TR0=1;display();break;default:break;}}} }
4.2.4整点时绿灯点亮子程序
绿灯与P1.0相连,通过P2.7口控制P1.0的电平,用标志变量clock_flag记录按键K1的状态,K1按一次整点绿灯点亮功能开启,在分和秒都为0时,即整点时,绿灯亮一下;K1再按一次,定时功能关闭,整点时绿灯不再点亮。
整点时绿灯点亮子程序:
void clock()
//整点绿灯亮子程序,此功能开启后,遇整点时绿灯亮一下 { if(P2_7==0){display();display();display();display();display();//延时使按键去抖动
if(P2_7==0)//P2_7对应K1按键,按一次开启整点报时功能,再按一下关闭 clock_flag=~clock_flag;}
if(clock_flag==1&&sec==0&&min==0)green=0;
//整点到来时,绿灯亮一下
单片机课程设计 201244xxxx xx 12xx else green=1;//否则,绿灯常灭 }
4.2.5 中断子程序
利用定时器0方式1,50ms中断一次。计数初值为65536-50000=15536=3cb0,则TH0=0x3c,TL0=0xb0,工作方式设置:TMOD=0x01,即定时器0,方式1,计时方式。在中断程序中,定义两个记录中断次数的变量count1和count2,其中count1满10清零,用来产生小数点的闪烁频率,dot为1Hz,count2满20清零,即50ms溢出一次,20次共是1s,此时秒变量sec自加1.中断服务子程序:
void int_T0()interrupt 1 //定义中断子程序,采用T0方式1,50ms中断一次 { TH0=0x3c;//设置定时初值 TL0=0xb0;TMOD=0x01;//设置工作模式 if(count1
//定义频率为1Hz的小数点闪烁变量 else {count1=0;dot=~dot;}
if(count2
//中断次数满20时,即满一秒,秒位自加1,count2清零重新计数
}
4.2.6 主程序
主程序中设置定时初值以及定时器的工作方式,开中断,然后利用while(1)语句,反复执行各个子程序。
主程序如下:
void main()
//主函数 { P2=0xff;
//初始化P2口,全设为1 TMOD = 0x01;//time0为定时器,方式1
单片机课程设计 201244xxxx xx 12xx TH0=0x3c;
//赋计时初值 TL0=0xb0;EA=1;//开总中断
ET0=1;
//T0中断允许 TR0=1;//T0开中断
en=0;
//3-8译码器处于工作状态 while(1)//时时检测 { testkey();
//检测按键 proc();//时间处理程序调用 display();
//显示时间
clock();
//整点报时
} }
五、收获与总结
通过本次的单片机课程设计,我本人收获很大。
首先,以前在学习单片机原理及应用时,老师所讲授的是汇编语言,而此次课程设计需要使用C语言,因此通过自己课下学习相关单片机教学视频以及教学资料了解了基于51单片机的C语言程序的编写以及相关软件使用。
其次,通过此次单片机课程设计,更加深入掌握了51单片机的结构与原理,包括51单片机内部定时系统的开启与设置、中断调用和如何使用单片机内部时钟实现精确计时以及如何对单片机的双向口进行读写操作等。除此之外,也更加深入理解了数码管动态扫描显示原理。
最后,通过连续几天以来不断地编程、下载和调试,自己形成了一定的编程逻辑思维。
附:单片机设计完整程序
#include #define uchar unsigned char //宏定义 #define uint unsigned int
uchar code zixing[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//定义共阴数码管的数字字形数组 uchar sec;//定义秒变量 uchar min;
//定义分变量 uchar hour;//定义时变量
uchar count1;//记录中断次数,满10归零,产生1Hz频率,用于小数点闪烁 uchar count2;
//记录中断次数,满20归零,用于秒自加1 uchar adjust_selc=4;
//记录调节按键按下次数的变量,用于选择调节位置
单片机课程设计 201244xxxx xx 12xx bit adjust_flag;
//定义按键调节标志
bit clock_flag;
//定义整点时绿灯闪烁标志
bit dot;
//定义小数点闪烁频率变量,以1Hz的频率亮暗变化 sbit a=P2^0;sbit b=P2^1;
//定义3-8译码器输入端口a,b,c sbit c=P2^2;sbit en=P2^3;
//使能端
sbit P2_4=P2^4;
// 调时按键K4,根据按键的次数来确定调节模式 sbit P2_5=P2^5;
//加按键K3 sbit P2_6=P2^6;
//减按键K2 sbit P2_7=P2^7;
//整点时绿灯闪烁功能按键K1 sbit green=P1^0;
//整点时绿灯亮一下
void proc()
//时间处理子程序 { if(sec==60)
//秒设为60进制 {sec=0;min++;if(min==60)//分设为60进制 {min=0;hour++;if(hour==24)//时设为24进制 {hour=0;} } } }
void delay(uchar xms)
// 延时子程序 { uint i,j;for(i=0;i
//x毫秒延时 for(j=0;j
void display()
//时钟显示子程序 { a=0;b=0;c=0;//位选,刷新小时的十位
P0=zixing[hour/10];//段选,将小时的十位数的字形赋给P0输出显示 delay(3);//延时3ms
a=1;b=0;c=0;
//位选,刷新小时的个位
if(adjust_flag==0&TR0==1)//正常计时时,时的个位的小数点闪烁 {if(dot==1)P0=(zixing[(hour%10)]);else P0=(zixing[(hour%10)])|0X80;} //字形码的单片机课程设计 201244xxxx xx 12xx else if(adjust_selc==3)//如果处于调节状态下的调时模式 P0=(zixing[(hour%10)])|0X80;//时的个位,小数点常亮 else P0=(zixing[(hour%10)]);//调节其他位时,小数点则不亮 delay(3);
a=0;b=1;c=0;
//位选,刷新分的十位 P0=zixing[min/10];delay(3);
a=1;b=1;c=0;//位选,刷新分的个位
if(adjust_flag==0&TR0==1)//正常计时时,分的个位的小数点闪烁 {if(dot==1)P0=(zixing[(min%10)]);else P0=(zixing[(min%10)])|0X80;} else if(adjust_selc==2)
//如果处于调节状态下的调分模式 P0=(zixing[(min%10)])|0X80;
//分的小数点常亮 else P0=(zixing[(min%10)]);//调节其他位时小数点则不亮 delay(3);
a=0;b=0;c=1;//位选,刷新秒的十位 P0=zixing[sec/10];delay(3);
a=1;b=0;c=1;//位选,刷新秒的个位
if(adjust_selc==1)
//如果处于调节状态下的调秒模式 P0=(zixing[(sec%10)])|0X80;//秒的个位小数点常亮 else P0=(zixing[(sec%10)]);//正常计数和调节其他位时,小数点都不亮 delay(3);}
void testkey()
//检测按键子程序 { if(P2_4==0)
//K4键按下时 {display();display();display();display();display();
//用延时进行消抖处理 if(P2_4==0)
单片机课程设计 201244xxxx xx 12xx {TR0=0;
//调时按键按下时,关闭定时器,停止计时 adjust_flag=1;
//调节标志置1,进入调时状态 if(adjust_selc
//更改调节位置 else adjust_selc=1;}
} if(P2_5==0&&adjust_flag==1)//K3加1键功能定义 {display();display();display();display();display();//用延时进行防抖处理 if(P2_5==0){switch(adjust_selc)//定义各调节模式下的按键功能 {
case 1:
//调秒 if(sec
//调分 if(min
//调时 if(hour
//确认状态时,按一下K3则进入时钟计时模式 TH0=0x3c;
//定时器重新赋初值,开始计时 TL0=0xb0;TR0=1;display();break;default:break;}}} if(P2_6==0&&adjust_flag==1)
//K2减1键功能定义 {display();display();display();display();
单片机课程设计 201244xxxx xx 12xx display();
//用延时进行按键防抖 if(P2_6==0){switch(adjust_selc)//定义各调节模式下的按键功能 { case 1:
//调秒 if(sec>0)sec--;else sec=59;break;case 2:
//调分 if(min>0)min--;else min=59;break;case 3:
//调时 if(hour>0)hour--;else hour=23;break;case 4:adjust_flag=0;//确认状态时,按一下K2则进入时钟计时模式 TH0=0x3c;
//定时器重新赋初值,开始计时 TL0=0xb0;TR0=1;display();break;default:break;}}} }
void clock()
//整点绿灯亮子程序,此功能开启后,遇整点时绿灯亮一下 { if(P2_7==0){display();display();display();display();display();//延时使按键去抖动
if(P2_7==0)//P2_7对应K1按键,按一次开启整点报时功能,再按一下关闭 clock_flag=~clock_flag;}
if(clock_flag==1&&sec==0&&min==0)green=0;
//整点到来时,绿灯亮一下
单片机课程设计 201244xxxx xx 12xx else green=1;//否则,绿灯常灭
}
void int_T0()interrupt 1 //定义中断子程序,采用定时器0方式1,50ms中断一次 { TH0=0x3c;//设置定时初值 TL0=0xb0;TMOD=0x01;//设置工作模式 if(count1
//定义频率为1Hz的小数点闪烁变量 else {count1=0;dot=~dot;} if(count2
//中断次数满20时,即满一秒,秒位自加1,count2清零重新计数
}
void main()
//主函数 { P2=0xff;
//初始化P2口,全设为1 TMOD = 0x01;//time0为定时器,方式1 TH0=0x3c;
//赋计时初值 TL0=0xb0;EA=1;//开总中断
ET0=1;
//T0中断允许 TR0=1;//T0开中断
en=0;
//3-8译码器处于工作状态 while(1)//时时检测
{
testkey();
//检测按键 proc();//时间处理程序调用 display();
//显示时间
clock();
//整点报时
} }