多功能定时装置资料.docx
《多功能定时装置资料.docx》由会员分享,可在线阅读,更多相关《多功能定时装置资料.docx(37页珍藏版)》请在冰豆网上搜索。
多功能定时装置资料
单片机课程设计
题目:
多功能定时装置
日期:
2011年6月
一、设计要求:
1)选择LED或LCD显示,可显示年、月、日、时、分、秒、星期、农历日期、节日、节气等
(根据实际情况,选择部分或全部功能实现)
2)会使用实时钟芯片
3)选择蜂鸣器电路,实现闹钟设置和报警功能
4)选择按键功能,设计实现时钟校正功能
5)整点报时功能
6)上电或RESET后能自动显示当前时间(时:
分:
秒):
首次上电复位显示0时0分0秒,以后每次RESET均显示正确的当前时间
附加实现功能:
1)可以显示0.1—100s的秒表,最小单位为0.1秒
2)通过按键控制秒表清零、暂停、继续、退出等功能
3)秒表可以分组存储(最多10组),批量显示
4)具有倒计时功能
二、所使用的硬件
1.ADUC848管脚图
ADUC848管脚图如图1所示。
图1ADUC848管脚
2.电源模块
电源模块原理图如图2所示。
图2电源模块
3.数码管
该模块原理如图3所示。
图3数码管驱动电路
4.RS232串口
串口连接原理图如图4所示。
图4RS232串口模块
5.蜂鸣器
该模块原理图如图5所示。
图5蜂鸣器
6.按键输入
该模块原理如图6所示。
图6按键模块
三、程序流程图
1)主流程图如图8所示:
图8主程序流程图
2)秒表正计时子程序流程图如图9所示:
图9秒表正计时流程图
3)秒表倒计时子程序流程图如图10所示
图10秒表倒计时流程图
四、程序
1.主程序(miao_biao.c)如下:
#include
#include"keypp.h"
#include"iic.h"
#defineucharunsignedchar
#defineuintunsignedint
unsignedcharb[7]={45,59,11,2,7,6,11},clock1[2]={12,0},clock2[2]={12,1};
codeunsignedchartab[]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x19,0x00};
//共阴数码管0-9显示
codeunsignedchartab2[]={0x39,0xff};//、全灭
voiddelay(unsignedintcnt);//延时子程序
unsignedchargetkey1();
unsignedchargetkey2();//读键盘
voidtim(void);//中断
voidKeyDelay(unsignedintKeyJsTime);//键盘扫描延时
voiddisplay(ucharbit7,ucharbit6,ucharbit5,ucharbit4,
ucharbit3,ucharbit2,ucharbit1,ucharbit0);//显示子程序
voidReadTime(unsignedcharTIME[7]);//DS1307读时间
voidSetTime(unsignedcharTIME[7]);//设置时间初值
voidSwitchRTC(unsignedcharSWITCH);
voidiicdelay(unsignedinttimes);
voidiicstart(void);
voidiicstop(void);
voidiicack(void);
bitiicreadack();
voidiicnack();
voidiicwriteda(unsignedcharda);
unsignedchariicreadda();
voidiicdelay(unsignedintt);
uchardis_num_h;//显示记录数据的组别十位
uchardis_num_l;//显示记录数据的组别个位
uchardis_min_h;//要显示的分的十位;
uchardis_min_l;//要显示的分的个位;
uchardis_sec_h;//要显示的秒的十位;
uchardis_sec_l;//要显示的秒的个位;
uchardis_dsec;//要显示的0.1秒;
ucharmin=0x00;
ucharsec=0x00;
uchardsec=0x00;
ucharen,i,clocken1=0,clocken2=0;
main()
{
unsignedcharquzhi,xianshi,symbol=0x55,set,set1=0x55,ce;
unsignedcharc[30];
unsignedcharnum,num1,j,k,stop=1;
PLLCON&=0xf8;//设置频率为12.58MHz
TMOD=0x01;//定时器工作模式设置
TH0=0xce;//设定初值
TL0=0x00;
IE=0x82;//中断控制,10000010,EA=1开总中断,ET0=1:
定时器0中断允许
I2CCON=0xE8;//开启iic通信;
SetTime(b);//设定初始时间;
SwitchRTC
(1);
while
(1)
{
ReadTime(time);
if(((clock1[0]==time[1])&&(clock1[1]==time[2])&&(clocken1==0)&&stop)||
((clock2[0]==time[1])&&(clock2[1]==time[2])&&(clocken2==0)&&stop))//闹钟时间到
{
PWM0H=205;PWM1L=500;PWMCON=0x21;//蜂鸣器响
KeyDelay(333);//延时
PWM1H=0;PWM1L=0;PWMCON=0x00;
KeyDelay(333);
if(getkey1()==12)//键12按下时蜂鸣器停止蜂鸣
stop=0;//无12键按下时,响一分钟后自动停止
}
if((time[1]==clock1[0]+1)||(time[1]==clock1[0]+1))stop=1;
//一分钟后重新开启蜂鸣使能,以便下次闹钟顺利反应
if((time[0]==0)&&(time[1]==0))//整点时,蜂鸣提醒
{
i=1;
while(i)
{
PWM0H=50;PWM1L=100;PWMCON=0x21;//蜂鸣器响
KeyDelay(333);//延时
PWM1H=0;PWM1L=0;PWMCON=0x00;//蜂鸣器关
KeyDelay(333);
i++;//控制蜂鸣器响的时间
if(i==5)i=0;
}
}
en=getkey1();
if((en==0x80)||(en==0x55))//无键按下或有多个键按下时,视为无效,en仍为之前按键值
en=symbol;
if(xianshi==8)
display(dis_num_h,dis_num_l,dis_min_h,dis_min_l,
dis_sec_h,dis_sec_l,0xff,dis_dsec);//显示已记录的值
///////////////////////////////////////////////////////////////////////////////////
if(en==1)//按键1按下,显示北京时间,年月日星期
{
symbol=1;
display(tab[time[6]/10],tab[time[6]%10],tab[time[5]/10],tab[time[5]%10],
tab[time[4]/10],tab[time[4]%10],0xff,tab[time[3]%10]);
}
////////////////////////////////////////////////////////////////////////////////////
elseif(en==2)//按键2按下,显示北京时间,时分秒
{
symbol=2;
display(tab2[clocken1],tab2[clocken2],tab[time[2]/10],tab[time[2]%10],tab[time[1]/10],
tab[time[1]%10],tab[time[0]/10],tab[time[0]%10]);
}
////////////////////////////////////////////////////////////////////////////////////
elseif(en==3)//按键3按下,秒表进入正计时工作模式
{
min=0;
sec=0;
dsec=0;
num=1;
symbol=3;
while
(1)
{
quzhi=getkey1();
if(num<11)//最多可取值十组
display(dis_min_h,dis_min_l,0xff,0xff,dis_sec_h,dis_sec_l,0xff,dis_dsec);
else//取值多于十组时将“FULL”送显示
display(0x71,0x83,0xe3,0xe3,0xff,0xff,0xff,0xff);
if(quzhi==5) //按键5按下时,启动或关闭定时器,赋取值组别num初值
{
quzhi=0x55;
if(TR0==1)TR0=0;
elseTR0=1;
}elseif(quzhi==6)//按键6按下时,秒表读值
{
quzhi=0x55;
c[3*(num-1)+2]=dsec;//读出的值放在c[]中,依次存放各组的分、秒、十分秒
c[3*(num-1)+1]=sec;
c[3*(num-1)+0]=min;
num++;
}elseif(quzhi==7)//按键7按下,计时结束,清零,赋读值组别num1初值
{
TR0=0;
num1=1;
symbol=0x55;
min=0;
sec=0;
dsec=0;
break;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////
elseif(en==4)//按键4按下,秒表进入倒计时模式
{
symbol=4;
j=0;
for(i=0;i<=30;i++)c[i]=0;//将数组c清零
while
(1)
{
display(dis_min_h,dis_min_l,0xff,0xff,dis_sec_h,dis_sec_l,0xff,dis_dsec);
set=getkey1();//送入倒计时初值
while(j<5)//依次输入分十位、分个位、秒十位、秒个位、十分秒,设置初值
{
ce=getkey1();
display(tab[c[0]],tab[c[1]],0xff,0xff,tab[c[2]],tab[c[3]],0xff,tab[c[4]]);
if((ce!
=0x55)&&(ce!
=0x80))//按键有效时将值存入c中
{
if(ce>9)ce=0;
c[j]=ce;
j++;
}
min=c[0]*10+c[1];//转化为分、秒及十分秒
sec=c[2]*10+c[3];
dsec=c[4];
}
dis_min_h=tab[min/10];//分、秒及十分秒显示值的处理
dis_min_l=tab[min%10];
dis_sec_h=tab[sec/10];
dis_sec_l=tab[sec%10];
dis_dsec=tab[dsec];
if(set==5)//按键5按下,倒计时开始
{
set=0x55;
TR0=1;
TF0=1;
}
if((min==0)&&(sec==0)&&(dsec==0))//倒计时完成
{
while(i)
{
PWM0H=50;PWM1L=100;PWMCON=0x21;//蜂鸣器响
KeyDelay(333);//延时
PWM1H=0;PWM1L=0;PWMCON=0x00;
KeyDelay(333);
i++;
if(i==200)
{
i=0;
break;
}
}
}
if(set==7)//按键7按下,结束,清零,跳出倒计时模式
{
symbol=0x55;
min=0;
sec=0;
dsec=0;
for(i=0;i<30;i++)c[i]=0;
ce=0x55;
break;
}
}
}
elseif(en==8)//按键8按下,将8给xianshi,读出num1组数据
{
symbol=0x55;
xianshi=8;
dis_num_h=tab[num1/10];
dis_num_l=tab[num1%10];
dis_min_h=tab[c[(num1-1)*3+0]/10];
dis_min_l=tab[c[(num1-1)*3+0]%10];
dis_sec_h=tab[c[(num1-1)*3+1]/10];
dis_sec_l=tab[c[(num1-1)*3+1]%10];
dis_dsec=tab[c[(num1-1)*3+2]];
num1++;//更新num1值
if(num1>num)//超出取值数组时将xianshi信号置为无效
{
xianshi=0x55;
}
}
elseif(en==9)//按键9按下,进入北京时间的设置
{
symbol=0x55;
j=0;
for(i=0;i<=6;i++)b[i]=0;//清零
for(i=0;i<=30;i++)c[i]=0;
while
(1)
{
while(j<=13)
{
ce=getkey1();
if(j<=5)//先分别显示输入时分秒
display(tab[b[2]/10],tab[b[2]%10],0xff,tab[b[1]/10],
tab[b[1]%10],0xff,tab[b[0]/10],tab[b[0]%10]);
elseif(j<=13)//再显示输入的年月日和星期,最后一个按键退出显示
display(tab[b[6]/10],tab[b[6]%10],tab[b[5]/10],
tab[b[5]%10],tab[b[4]/10],tab[b[4]%10],0xff,tab[b[3]%10]);
if(ce==10)break;//按键10按下,跳出设时
elseif((ce!
=0x55)&&(ce!
=0x80))//将有效按键值送数组c中
{if(ce>9)ce=0;
c[j]=ce;
j++;
}
b[2]=c[0]*10+c[1];//处理数组c中数据,放入数组b中正确位置
b[1]=c[2]*10+c[3];
b[0]=c[4]*10+c[5];
b[6]=c[6]*10+c[7];
b[5]=c[8]*10+c[9];
b[4]=c[10]*10+c[11];
b[3]=c[12];
}
ReadTime(time);//读取当前时间
c[13]=time[2]/10;//将当前时间值处理后存入数组c第14至第26号单元中
c[14]=time[2]%10;
c[15]=time[1]/10;
c[16]=time[1]%10;
c[17]=time[0]/10;
c[18]=time[0]%10;
c[19]=time[6]/10;
c[20]=time[6]%10;
c[21]=time[5]/10;
c[22]=time[5]%10;
c[23]=time[4]/10;
c[24]=time[4]%10;
c[25]=time[3]%10;
for(k=j;k<=12;k++)//对于没有重置的数据保持当前数据
{
c[k]=c[k+13];
}
b[2]=c[0]*10+c[1];//将改好的时间数据处理后送给数组b
b[1]=c[2]*10+c[3];
b[0]=c[4]*10+c[5];
b[6]=c[6]*10+c[7];
b[5]=c[8]*10+c[9];
b[4]=c[10]*10+c[11];
b[3]=c[12];
SetTime(b);//设置时间
break;
}
}elseif(en==13)//按键13按下,改变闹钟1开关状态
{
if(clocken1==0)clocken1=1;
elseif(clocken1==1)clocken1=0;
}elseif(en==14)//按键14按下,进入闹钟1时间设置
{
symbol=0x55;
j=0;
for(i=0;i<=30;i++)c[i]=0;
while
(1)
{
while(j<=4)//共输入4个数据,之后若按键则闪显后跳出
{
ce=getkey1();
display(tab[clock1[1]/10],tab[clock1[1]%10],0xff,0xff,
tab[clock1[0]/10],tab[clock1[0]%10],0xff,0xff);
if((ce!
=0x55)&&(ce!
=0x80))//将有效数据放入数组c中
{
if(ce>9)ce=0;//输入数据大于九是令该次输入为零
c[j]=ce;
j++;
}
clock1[1]=c[0]*10+c[1];//将输入的分、时依次放入数组clock1中
clock1[0]=c[2]*10+c[3];
}
break;
}
}elseif(en==15)//按键15按下,改变闹钟2开关状态
{
if(clocken2==0)clocken2=1;
elseif(clocken2==1)clocken2=0;
}elseif(en==0)//按键0按下,进入闹钟2时间设置,程序类似对闹钟1的时间设置
{
symbol=0x55;
j=0;
for(i=0;i<=30;i++)c[i]=0;
while
(1)
{
while(j<=4)
{
ce=getkey1();
display(tab[clock2[1]/10],tab[clock2[1]%10],0xff,0xff,
tab[clock2[0]/10],tab[clock2[0]%10],0xff,0xff);
if((ce!
=0x55)&&(ce!
=0x80))
{
if(ce>9)ce=0;
c[j]=ce;
j++;
}
clock2[1]=c[0]*10+c[1];
clock2[0]=c[2]*10+c[3];
}
break;
}
}
}
}
/********************************/
/*延时函数程序*/
/********************************/
voiddelay(unsignedintcnt)//用于动态扫描数码管的延时程序
{
while(--cnt);
}
/********************************/
/*数码管显示函数*/
/********************************/
voiddisplay(ucharbit7,ucharbit6,ucharbit5,
ucharbit4,ucharbit3,ucharbit2,ucharbit1,ucharbit0)
//从左至右依次显示,各位显示均有延时
{
P2=0x08;
P0=bit7;
delay(500)