用单片机制作可调数字时钟要汇编语言程序
数字钟--基于单片机的汇编语言
MOV T2SCNTA,#00H
MOV T2SCNTB,#00H
MOV TEMP,#0FEH
LCALL DISP
MOV TMOD,#01H
MOV TH0,#(65536-2000) / 256
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV A,B
MOV @R1,A
DEC R1
RET
INT_T0:
MOV TH0,#(65536-2000) / 256
DEC R1
MOV A,B
MOV @R1,A
DEC R1
MOV A,#10
MOV@R1,A
DEC R1
MOV A,MINITE
MOV B,#10
LCALL DELY10MS
JB MINITEK,NK2
INC MINITE
MOV A,MINITE
CJNE A,#60,NM60
MOV MINITE,#00H
NM60: LCALL DISP
MOV P1,A
MOV A,DISPBIT
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P3,A
INC DISPBIT
MOV A,DISPBIT
CJNE A,#08H,KNA
1. 实验任务
(1. 开机时,显示12:00:00的时间开始计时;
(2. P0.0/AD0控制“秒”的调整,每按一次加1秒;
(3. P0.1/AD1控制“分”的调整,每按一次加1分;
(4. P0.2/AD2控制“时”的调整,每按一次加1个小时;
单片机制作数字钟(含万年历、秒表功能)
数字钟、万年历制作(基于单片机)电路原理图:程序://********************20131206****数字钟程序#pragma SMALL#include <reg51.h>#include <absacc.h>#include <intrins.h>//********************************************************* *********编译预处理void display(unsigned char *p); //显示函数,P为显示数据首地址unsigned char keytest(); //按键检测函数unsigned char search(); //按键识别函数void alarm(); //闹钟判断启动函数void ftion0(); //始终修改函数void ftion1(); //闹钟修改函数void ftion3(); //日期修改函数void cum(); //加1修改函数void minus(); //减1修改函数void jinzhi(); //进制修改函数void riqi(); //日期void stopwatch(); //秒表函数//********************************************************* *******函数声明sbit P2_7=P2^7;//********************************************************* *******端口定义unsigned char clockbuf[3]={0,0,0};unsigned char bellbuf[3]={0,0,0};unsigned char date[3]={1,1,1}; //日期存放数组unsigned char stop[3]={0,0,0};unsigned char msec1,msec2;unsigned char timdata,rtimdata,dtimdata;unsigned char count;unsigned char *dis_p;unsigned char or; //12进制控制标志unsigned char ri; //日期显示控制标志位unsigned char mb; //秒表控制标志位bit arm,rtim,rhour,rmin,hour,min,sec,day,mon,year; //定义位变量//********************************************************* *****全局变量定义void main(){unsigned char a;or=0; //12进制修改标志清零ri=0;mb=0;P2_7=0;arm=0;msec1=0;msec2=0;timdata=0;rtimdata=0;count=0;TMOD=0x12;TL0=0x06;TH0=0x06;TH1=(65536-10000)/256;TL1=(65536-10000)%256;EA=1;ET0=1;ET1=1;TR0=1;TR1=0;dis_p=clockbuf;while(1){a=keytest();if(a==0x78) //判断是否有键按下{display(dis_p);if(arm==1) alarm();}else{display(dis_p);a=keytest();if(a!=0x78){a=search();switch(a){case 0x00:ftion0();break;case 0x01:ftion1();break;case 0x02:cum();break;case 0x06:jinzhi();break;case 0x03:riqi();break;case 0x04:ftion3();break;case 0x05:minus();break;case 0x07:stopwatch();break;case 0x09:TR1=1;break;case 0x0a:TR1=0;break;case 0x0b:stop[0]=0;stop[1]=0;stop[2]=0;break;default:break;}}}}}//********************************************主函数【完】void display(unsigned char *p){unsigned char buffer[]={0,0,0,0,0,0};unsigned char k,i,j,m,temp;unsigned char led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};buffer[0]=p[0]/10;buffer[1]=p[0]%10;buffer[2]=p[1]/10;buffer[3]=p[1]%10;buffer[4]=p[2]/10;buffer[5]=p[2]%10;if((sec==0)&&(min==0)&&(hour==0)&&(rmin==0)&&(rhour==0)&&( day==0)&&(mon==0)&&(year==0)) //没有修改标志,正常显示{for(k=0;k<3;k++){temp=0x01;for(i=0;i<6;i++){P0=0x00; //段选端口j=buffer[i];P0=led[j];P1=~temp; //位选端口temp<<=1;for(m=0;m<200;m++);}}}else //若有修改标志,则按以下标志分别显示{if(sec==1||day==1){P1=0x1f;i=buffer[5];P0=led[i];for(m=0;m<200;m++);P1=0x2f;j=buffer[4];P0=led[j];for(m=0;m<200;m++);}if(min==1||rmin==1||mon==1){P1=0x3b;i=buffer[2];P0=led[i];for(m=0;m<200;m++);P1=0x37;j=buffer[3];P0=led[j];for(m=0;m<200;m++);}if(hour==1||rhour==1||year==1) {P1=0x3e;i=buffer[0];P0=led[i];for(m=0;m<200;m++);P1=0x3d;j=buffer[1];P0=led[j];for(m=0;m<200;m++);}}}//**********************************LED显示函数【完】unsigned char keytest(){unsigned char c;P2=0x78; //检测是否有键按下c=P2;c=c&0x78;return(c);}//******************************************键盘检测函数【完】unsigned char search(){unsigned char a,b,c,d,e;c=0x3f;a=0; //行号while(1){P2=c;d=P2;d=d&0x07;if(d==0x03){b=0;break;} //列号else if(d==0x05){b=1;break;}else if(d==0x06){b=2;break;}a++;c>>=1;if(a==5){a=0;c=0x3f;}}e=a*3+b;do{display(dis_p);}while((d=keytest())!=0x78);return(e);}//***********************************************查键值函数【完】void alarm(){if((clockbuf[0]==bellbuf[0])&&(clockbuf[1]==bellbuf[1])){P2_7=1;rtim=1;if(count==10){count=0;P2_7=0;arm=0;rtim=0;}}}//****************************************闹钟判断启动函数【完】void ftion0(){TR0=0;rhour=0;rmin=0;dis_p=clockbuf;rtimdata=0;timdata++;switch(timdata){case 0x01:sec=1;break;case 0x02:sec=0;min=1;break;case 0x03:min=0;hour=1;break;case 0x04:timdata=0;hour=0;TR0=1;break;default:break;}}//*********************************************时钟设置函数【完】void ftion1(){if(TR0==0) TR0=1;sec=0;min=0;hour=0;dis_p=bellbuf;timdata=0;rtimdata++;switch(rtimdata){case 0x01:rmin=1;break;case 0x02:rmin=0;rhour=1;break;case 0x03:rtimdata=0;rhour=0;arm=1;dis_p=clockbuf;break;default:break;}}//*********************************************闹钟设置函数【完】void ftion3(){if(TR0==0) TR0=1;day=0;mon=0;year=0;dis_p=date;timdata=0;rtimdata=0;dtimdata++;switch(dtimdata){case 0x01:day=1;break;case 0x02:day=0;mon=1;break;case 0x03:mon=0;year=1;break;case 0x04:dtimdata=0;year=0;dis_p=clockbuf;break;default:break;}}//*************************************************日期修改函数【完】void minus(){if(sec==1){if(0==clockbuf[2]) clockbuf[2]=59;else clockbuf[2]--;}else if(min==1){if(0==clockbuf[1]) clockbuf[1]=59;else clockbuf[1]--;}else if(hour==1){if(or==0) //判断进制{if(0==clockbuf[0]) clockbuf[0]=23;else clockbuf[0]--;}if(or==1){if(1==clockbuf[0]) clockbuf[0]=12;else clockbuf[0]--;}}else if(rmin==1){if(bellbuf[1]==0) bellbuf[1]=59;else bellbuf[1]--;}else if(rhour==1){if(or==0){if(bellbuf[0]==0) bellbuf[0]=23;else bellbuf[0]--;}if(or==1){if(bellbuf[0]==1) bellbuf[0]=12;else bellbuf[0]--;}}else if(day==1){if(date[2]==1) date[2]=31;else date[2]--;}else if(mon==1){if(date[1]==1) date[1]=12;else date[1]--;}else if(year==1){if(date[0]==1) date[0]=99;else date[0]--;}}//*************************************减1修改功能函数【完】void cum(){if(sec==1){if(59==clockbuf[2]) clockbuf[2]=0;else clockbuf[2]++;}else if(min==1){if(59==clockbuf[1]) clockbuf[1]=0;else clockbuf[1]++;}else if(hour==1){if(or==0) //判断进制{if(23==clockbuf[0]) clockbuf[0]=0;else clockbuf[0]++;}if(or==1){if(12==clockbuf[0]) clockbuf[0]=1;else clockbuf[0]++;}}else if(rmin==1){if(bellbuf[1]==59) bellbuf[1]=0;else bellbuf[1]++;}else if(rhour==1){if(or==0){if(bellbuf[0]==23) bellbuf[0]=0;else bellbuf[0]++;}if(or==1){if(bellbuf[0]==12) bellbuf[0]=1;else bellbuf[0]++;}}else if(day==1){if(date[2]==31) date[2]=1;else date[2]++;}else if(mon==1){if(date[1]==12) date[1]=1;else date[1]++;}else if(year==1){if(date[0]==99) date[0]=0;else date[0]++;}}//*************************************加1修改功能函数【完】void jinzhi(){if(or==0) or=1;else or=0;}//***********************************进制修改控制函数【完】void riqi(){if(ri==0){dis_p=date;}if(ri==1){dis_p=clockbuf;}ri++;if(ri==2) ri=0;}//********************************日期控显示函数【完】void stopwatch(){if(mb==0){dis_p=stop;mb=1;}else{mb=0;dis_p=clockbuf;}}//************秒表**********秒表**********秒表函数【完】void clock() interrupt 1{EA=0;if(msec1!=0x14) msec1++; //6MHz晶振定时10mselse{msec1=0;if(msec2!=100) msec2++; //定时1selse{if(rtim==1) count++; //闹钟启动标志计时10smsec2=0;if(clockbuf[2]!=59) clockbuf[2]++;else{clockbuf[2]=0;if(clockbuf[1]!=59) clockbuf[1]++;else{clockbuf[1]=0;if(or==0){if(clockbuf[0]!=23) clockbuf[0]++;else{clockbuf[0]=0;if((date[1]==1)||(date[1]==1)||(date[1]==1)||(date[1]==3)||(date[ 1]==5)||(date[1]==7)||(date[1]==8)||(date[1]==10)||(date[1]==12)){if(date[2]!=30) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}if((date[1]==4)||(date[1]==6)||(date[1]==9)||(date[1]==11)){if(date[2]!=29) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}if(date[1]==2){if((((date[0]%4==0)&&(date[0]%100!=0))||(date[0]%400==0))){if(date[2]!=28) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}else{if(date[2]!=27) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}}}}if(or==1){if(clockbuf[0]!=12) clockbuf[0]++;else{clockbuf[0]=0;if((date[1]==1)||(date[1]==1)||(date[1]==1)||(date[1]==3)||(date[ 1]==5)||(date[1]==7)||(date[1]==8)||(date[1]==10)||(date[1]==12)){if(date[2]!=30) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}if((date[1]==4)||(date[1]==6)||(date[1]==9)||(date[1]==11)){if(date[2]!=29) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}if(date[1]==2){if((((date[0]%4==0)&&(date[0]%100!=0))||(date[0]%400==0))){if(date[2]!=28) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}else{if(date[2]!=27) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}}}}}}}}EA=1;}//*******************************定时器0中断函数【完】void miaobiao() interrupt 3{TH1=(65536-10000)/256;TL1=(65536-10000)%256;if(stop[2]!=99) stop[2]++;else{stop[2]=0;if(stop[1]!=59) stop[1]++;else{stop[1]=0;if(stop[0]!=59) stop[0]++;else stop[0]=0;}}}//***********************************定时器1中断函数【完】。
51-数字时钟-89C52-单片机C语言程序
51-数字时钟-89C52-单片机C语言程序数字时钟89C52 单片机C语言程序STC89C52|/************** 【数字时钟】****************//****【功能】1、时间显示2、秒表3、闹钟4、日期显示都可以设置****/#include /*包含器件配置文件*/#define uchar unsigned char /*宏定义字符型数据整型数据*/ #define uint unsigned intuchar code H[] = {0x0f, 0x07, 0x0b, 0x0d, 0x0e}; /*按键【P3】端口断码用于按键*/ char Code[10] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d,0x7d, 0x07, 0x7f, 0x6f}; /*显示【0 1 2 3 4 5 6 7 8 9】数字的数码管的段码*/ uchar code C[] = {0x0, 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};/*列扫描控制LED1位2位3位4位5位6位7位8位*/uchar MON[]={0,31,28,31,30,31,30,31,31,30,31,30,31};uchar A;uchar BIN=0; /* 【BIN】作为倒计时开始的标志*/uchar hour = 0; /* 定义[时][分][秒] */uchar min = 0;uchar sec = 0;uint shi=12;uint fen=30;uchar Mmin=0;uchar Msec=30;uchar M0=0;uchar m=0;uchar year=9;uchar month=7;uchar month2;uchar day=19;uchar set1 = 1; /* set1=1 是调节时分秒set1=2时时调节年月日set=3时事调节闹钟*/uchar set2 = 1; /* set2=1时是调节【时】位set2=2时事调节【分】位*/uint x = 0; /* x 每【0.01s】自加一*/void Delay(uint k);void Timer0() /*定时器T0 5mS初始化*/{TMOD = 0x01; /*设置*定时器0**计数方式一* (每12个时钟脉冲计数一次)或IT0=1 第二种计数方式*/TH0 = (65536 - 10000) / 256; /*给定计时器高位赋予初值=15536/256*/TL0 = (65536 - 10000) % 256; /*给定计时器低位赋予初值=15536%256 */ET0 = 1; /*打开定时器外部终断0允许ET1是中断器1的开关*/ EA = 1; /*打开总中断允许*/TR0 = 1;}void T0_srv(void) interrupt 1 /*5mS定时中断服务函数秒分时的值*/{TH0 = (65536 - 10000) / 256; /*给定计时器高位赋予初值=15536/256*/TL0 = (65536 - 10000) % 256; /*给定计时器低位赋予初值=15536%256 */x++;if(x==100){sec++;x=0; /*没每一秒【sec】加一*/if(sec==60){min++;sec=0;if(min==60) /*每一分钟【min】加一*/ {min = 0;hour++;if(hour==24){hour = 0; /*每一小时【hour】加一*/ day++;if(year%4==0) /*是否闰年的判断*/ MON[2]=29;else MON[2]=28;if(day==MON[month]){day=0;month++;}}}}}if(BIN==1)if(Mmin!=0||Msec!=0){M0 = 100-x;if(M0==100){ if(Mmin>0){Msec--;if(Msec==0){Msec=60;Mmin-- ;}if(Msec==0) {Mmin=0;Msec=0;M0=0;} }if(Mmin==0){if(Msec!=0)Msec--;if(Msec==0){Msec=0;M0=0;}}}}if(Mmin==0&&Msec==0){M0=0;}} /*秒表分秒M0的赋值*/}void Scan_key() /*按键扫描函数【Scan_key()】*/ {P3=H[0];if(P3!=H[0])Delay(1);if(P3==H[4]){set1++;if(set1>4) set1 = 1;er1: if(P3==H[4]) goto er1; /*按下键后未释放,在此等候*/ }Delay(1);if(P3==H[3]){set2++;if(set2>3) set2 = 1;er2: if(P3==H[3]) goto er2; /*按下键后未释放,在此等候*/ }Delay(1);if(P3==H[1]){BIN++;if(BIN>1) BIN=0;er3: if(P3==H[1]) goto er3; /*按下键后未释放,在此等候*/ }}}void Time_show() /*时间的显示变量为【时】【分】【秒】*/ { P0 = Code[hour/10]; /*第一位数字显示【时】的【十】位*/ P2 = C[1];Delay(1);P0 = Code[hour%10]; /*第二位数字显示【时】的【个】位*/P2 = C[2];Delay(1);if(x/50==0)P0 = 0x40; /*第三位符号【-】的显示*/elseP0 = 0x00;P2 = C[3];Delay(1);P0 = Code[min/10]; /*第四位的数字的显示【分】的【十】位*/ P2 = C[4];Delay(1);P0 = Code[min%10]; /*第五位的数字显示【分】的【个】位*/ P2 = C[5];Delay(1);Delay(1);if(x/50==0)P0 = 0x40; /*第六位符号【-】的显示*/elseP0 = 0x00;P2 = C[6];Delay(1);P0 = Code[sec/10]; /*第七位数字的显示【秒】的【十】位显示*/P2 = C[7];Delay(1);P0 = Code[sec%10]; /*第八位数字的显示【秒】的【个】位显示*/ P2 = C[8];Delay(1);}void Year_show(){P0 = Code[year/10]; /*第一位数字显示【年】的【十】位*/P2 = C[1];Delay(1);P0 = Code[year%10]; /*第二位数字显示【年】的【个】位*/P2 = C[2];Delay(1);P0 = 0x40; /*第三位符号【-】的显示*/P2 = C[3];Delay(1);P0 = Code[month/10]; /*第四位的数字的显示【月】的【十】位*/P2 = C[4];Delay(1);P0 = Code[month%10]; /*第五位的数字显示【月】的【个】位*/P2 = C[5];Delay(1);Delay(1);P0 = 0x40; /*第六位符号【-】的显示*/P2 = C[6];Delay(1);P0 = Code[day/10]; /*第七位数字的显示【天】的【十】位显示*/P2 = C[7];Delay(1);P0 = Code[day%10]; /*第八位数字的显示【天】的【个】位显示*/ P2 = C[8];Delay(1);}void Clock_show(){P0 = Code[shi/10]; /*第一位数字显示【时】的【十】位*/P2 = C[4];P0 = Code[shi%10]; /*第二位数字显示【时】的【个】位*/P2 = C[5];Delay(1);P0 = 0x40; /*第三位符号【-】的显示*/P2 = C[6];Delay(1);P0 = Code[fen/10]; /*第四位的数字的显示【分】的【十】位*/ P2 = C[7];Delay(1);P0 = Code[fen%10]; /*第五位的数字显示【分】的【个】位*/P2 = C[8];Delay(1);}void Miao_show() /*时间的显示变量为【时】【分】【秒】*/ { P0 = Code[Mmin/10]; /*第一位数字显示【时】的【十】位*/P2 = C[1];Delay(1);P0 = Code[Mmin%10]; /*第二位数字显示【时】的【个】位*/ P2 = C[2];Delay(1);P0 = 0x40; /*第三位符号【-】的显示*/P2 = C[3];Delay(1);P0 = Code[Msec/10]; /*第四位的数字的显示【分】的【十】位*/ P2 = C[4];Delay(1);P0 = Code[Msec%10]; /*第五位的数字显示【分】的【个】位*/ P2 = C[5];Delay(1);P0 = 0x40; /*第六位符号【-】的显示*/P2 = C[6];Delay(1);P0 = Code[M0/10]; /*第七位数字的显示【秒】的【十】位显示*/P2 = C[7];Delay(1);P0 = Code[M0%10]; /*第八位数字的显示【秒】的【个】位显示*/ P2 = C[8];Delay(1);}void Time_set() /*调整时间的函数time_set() */{Scan_key();if(set1==1){if(set2==1) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) hour++; /*按一下第三行的键hour 就加一*/Delay(1);if(hour>24) hour=0;while(P3==H[2]); /*按键未释放,在此等候*/}if(set2==2) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) min++; /*按一下第三行的键hour 就加一*/Delay(1);if(min>60){ min=0; hour++;}while(P3==H[2]); /*按键未释放,在此等候*/}}}void Year_set() /*调整时间的函数time_set() */{Scan_key();if(set1==2){if(set2==1) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) year++; /*按一下第三行的键hour 就加一*/ Delay(1);if(year>100) year=0;while(P3==H[2]);}if(set2==2) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) month++; /*按一下第三行的键hour 就加一*/ Delay(1);if(month>12){ month=0; year++;}while(P3==H[2]);}if(set2==3){if(P3==H[2]) day++; /*按一下第三行的键hour 就加一*/ Delay(1);if(day>MON[month]){ day=0; month++;}while(P3==H[2]); /*按键未释放,在此等候*/}}}Clock_set(){Scan_key();if(set1==3){if(set2==1) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) shi++; /*按一下第三行的键hour 就加一*/ Delay(1);if(shi>24) shi=0;while(P3==H[2]); /*按键未释放,在此等候*/}if(set2==2) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) fen++; /*按一下第三行的键hour 就加一*/ Delay(1);if(fen>60){ fen=0; shi++;}while(P3==H[2]); /*按键未释放,在此等候*/}}}void Miao_set() /*调整时间的函数time_set() */{Scan_key();if(set1==4){if(set2==1) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) Mmin++; /*按一下第三行的键hour 就加一*/Delay(1);if(Mmin>24) Mmin=0;while(P3==H[2]); /*按键未释放,在此等候*/}if(set2==2) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) Msec++; /*按一下第三行的键hour 就加一*/ Delay(1);。
51单片机数字钟汇编程序
SEC EQU 32H ;秒即时时间\伪指令MIN EQU 31H ;分HOUR EQU 30H ;时DAY EQU 35H ;日MON EQU 34H ;月YEAR EQU 33H ;年MIN_1 EQU 41H ;分定时器1路、开存储单元HOUR_1 E QU 42H ;时DAY_1 EQU 43H ;MON_1 EQU 44H ;YEAR_1 EQU 45H ;MIN_11 EQU 40H ;分定时器1路、关存储单元HOUR_11 EQU 46H ;时DAY_11 EQU 47H ;日MON_11 EQU 48H ;月YEAR_11 EQU 49H ;年ORG 0000HLJMP MAINORG 0003H ;中断转换显示年月日、INT0(SB4键)LJMP WB0ORG 000BH ;计数中断T0、方式1LJMP TT0ORG 0013HLJMP WB1; 调整时间、定时、INT1(SB0键);------主程序ORG 0030HMAIN: MOV YEAR,#02;初始化付值MOV MON,#05MOV DAY,#01MOV HOUR,#00MOV MIN,#00MOV SEC,#00CLR 40H ;定时单元1路清零CLR 41HCLR 42HCLR 43HCLR 44HCLR 45HCLR 46HCLR 47HCLR 48HCLR 49H;-------开中断MOV TMOD,#01H ;计数、模式1、T0MOV TL0,#0B0H ;100SM 计数定时MOV TH0,#3CH ;CLR P3.0MOV 20H,#0AH ;10次*100SMSETB PT0 ;T0为最高级SETB TR0 ;允许计数SETB ET0 ;允许T0中断SETB EX0 ;允许INT0中断SETB EX1 ;允许INT1中断SETB EA ;开总中断;------显示、定时器启动判断LOOP: MOV R1,#30H; 存储单元MOV R4,#01H; 位选通MOV R3,#03H; 三组显示NEXT: MOV A,@R1 ;MOV B,#10 ;将存储单元转换成两高低两组的BCD码DIV ABSWAP AORL A,BMOV P0,A;输出MOV P2,R4INC R1 ;下一单元MOV A,R4 ;RL A ;位移MOV R4,ALCALL DE5SM ;延时0.5SMDJNZ R3,NEXT ;全扫描显示一偏;------判断定时输出(只编写了一路)CJNE R7,#88H,LOOP ;是8则开,否则、定时已关、转;---------开MOV A,YEARCJNE A,YEAR_1,LOOP_1;年比较,不等转关MOV A,MONCJNE A,MON_1,LOOP_1MOV A,DAYCJNE A,DAY_1,LOOP_1MOV A,HOURCJNE A,HOUR_1,LOOP_1MOV A,MINCJNE A,MIN_1,LOOP_1CPL P3.0;---------关LOOP_1:MOV A,YEARCJNE A,YEAR_11, LOOP;年比较MOV A,MONCJNE A,MON_11,LOOPMOV A,DAYCJNE A,DAY_11,LOOPMOV A,HOURCJNE A,HOUR_11,LOOPMOV A,MINCJNE A,MIN_11,LOOPCPL P3.0LJMP LOOP;-----年月日显示中断子程序WB0: PUSH PSWPUSH ACCPUSH BPUSH 01HPUSH 02HPUSH 03HPUSH 04HMOV R2,#0FFH ;中断扫描次数TURN: MOV R1,#33HMOV R4,#01HMOV R3,#03HNEXT_1:MOV A,@R1MOV B,#10DIV ABSWAP AORL A,BMOV P0,AMOV P2,R4INC R1RL AMOV R4,ALCALL DE5SMDJNZ R3,NEXT_1DJNZ R2,TURN ;反复显示一定时间后返回POP 04HPOP 03HPOP 02HPOP 01HPOP BPOP ACCPOP PSWRETI;-----计数中断服务子程序TT0: PUSH PSWPUSH ACCPUSH BPUSH 06HMOV TH0,#3CH;重装计数MOV TL0,#0BH;DJNZ 20H,OUT ;转到中断跳出pop程序MOV 20H,#0AH ; 重装:100*10=1000;-----进位程序INC S ECMOV R6,SEC ;CJNE R6,#60,OUT;比较MOV SEC,#00 ;INC MINMOV R6,MINCJNE R6,#60,OUTMOV MIN,#00INC HOURMOV R6,HOURCJNE R6,#25,OUTMOV HOUR,#00INC DAYMOV R5,MONCJNE R5,#1,MON_22;是否1月、不是转2 月MOV R5,DAYCJNE R5,#32,OUT ; 本月是否益出INC MONMOV DAY,#1LJMP OUTOUT: P OP 06HPOP BPOP ACCPOP PSWRETIMON_22:MOV R5,MONCJNE R5,#2,MON_33;是否2月、不是转3月MOV A,YEAR ;判断是否瑞年MOV B,#4DIV ABMOV A,BJNZ OUT_1;不是则转(A不为零则转)MOV R5,DAYCJNE R5,#30,OUT;如是瑞年、判断是否到29天INC M ONMOV DAY,#1LJMP OUTOUT_1:MOV R5,DAYCJNE R5,#29,OUT ;平年二月判断INC MONMOV DAY,#1LJMP OUTMON_33:MOV R5,MONCJNE R5,#3,MON_44MOV R5,DAYCJNE R5,#32,OUTINC MONMOV DAY,#1LJMP OUTMON_44:MOV R5,MONCJNE R5,#4,MON_55MOV R5,DAYCJNE R5,#31,OUTINC M ONMOV DAY,#1LJMP OUTMON_55:MOV R5,MONCJNE R5,#5,MON_66MOV R5,DAYCJNE R5,#32,OUTINC M ONMOV DAY,#1LJMP OUTMON_66:MOV R5,MONCJNE R5,#6,MON_77MOV R5,DAYCJNE R5,#31,OUTINC M ONMOV DAY,#1LJMP OUTMON_77:CJNE R5,#7,MON_88MOV R5,DAYCJNE R5,#32,L1INC M ONMOV DAY,#1L1: LJMP OUTMON_88:MOV R5,MONCJNE R5,#8,MON_99MOV R5,DAYCJNE R5,#32,L2INC M ONMOV DAY,#1L2: LJMP OUTMON_99:MOV R5,MONCJNE R5,#9,MON_00MOV R5,DAYCJNE R5,#31,L3INC M ONMOV DAY,#1L3: LJMP OUTMON_00:MOV R5,MONCJNE R5,#10,MON_AAMOV R5,DAYCJNE R5,#32,L4INC M ONMOV DAY,#1L4: LJMP OUTMON_AA:MOV R5,MONCJNE R5,#11,MON_BBMOV R5,DAYCJNE R5,#31,L5INC M ONMOV DAY,#1L5: LJMP OUTMON_BB:MOV R5,DAYCJNE R5,#32,L6INC Y EARMOV MON,#1L6: LJMP OUT;-----校对时间、定时调整中断WB1 : PUSH PSWPUSH ACCPUSH BPUSH 00HMOV P2,#00HSHOW_1:MOV A,#01H;显示1MOV P0,AMOV P2,#0FFH;三组数码管都显示1路LCALL READ ;调用读p1口键程序CJNE A,01H,SHOW_1;去抖后比较LCALL DE250SM ; 延时250秒CJNE A,#0FBH,ttT1LJMP SB3_1ttT1: CJNE A,#0FEH,SHOW_1AJMP SHOW_2;-------二组显示SHOW_2:MOV A,#02H; 显示2MOV P0,AMOV P2,#0FFH;LCALL READCJNE A,01H,SHOW_2 ;去抖后比较LCALL DE250SM; 延时250秒CJNE A,#0FBH,T2;不等转去判断此时SB3按了没LJMP SB3_2T2: CJNE A,#0FEH,SHOW_2AJMP SHOW_3;_------三组显示SHOW_3:MOV A,#03H; 显示3MOV P0,AMOV P2,#0FFH;位码LCALL READCJNE A,01H,SHOW_3;去抖后比较LCALL DE250SM;延时250秒CJNE A,#0FBH,T3;不等转去判断此时SB3按了没LJMP SB3_3T3: CJNE A,#0FEH,SHOW_3AJMP SHOW_4;------即时年单元调时、显示SHOW_4:MOV A,YEAR ;调出年单元MOV B,#10 ;BCD转换DIV A BSWAP AORL A,BMOV P0,A ;MOV P2,#01H;LCALL READLCALL DE250SMCJNE A,01H,SHOW_4 ;去抖CJNE A,#0FEH,KEY2_1 ;按SB2 转年调整AJMP MON_CH ;按SB1往下调月单元KEY2_1:CJNE A,#0FDH,SHOW_4LCALL YEAR_AD ; 调用年调整AJMP SHOW_4 ;MON_CH:MOV A,MON ; 月单元调整MOV B,#10DIV A BSWAP AORL A,BMOV P0,A ;MOV P2,#02H;LCALL READLCALL DE250SMCJNE A,01H,MON_CH ;去抖CJNE A,#0FEH,KEY2_2 ;按SB2 转月调整LJMP DAY_CH ;按SB1往下调日单元KEY2_2:CJNE A,#0FDH,MON_CHLCALL MON_AD ; 调用月调整LJMP MON_CH ;DAY_CH:MOV A,DAY ; 日单元调整MOV B,#10DIV A BSWAP AORL A,BMOV P0,A ;MOV P2,#04H;LCALL READLCALL DE250SMCJNE A,01H,DAY_CH ;去抖CJNE A,#0FEH,KEY2_3 ;按SB2 转日调整LJMP HOUR_CH ;按SB1往下调时单元KEY2_3:CJNE A,#0FDH,DAY_CHLCALL DAY_AD ; 调用日调整LJMP DAY_CHHOUR_CH:MOV A,HOUR ; 时单元调整MOV B,#10DIV A BSWAP AORL A,BMOV P0,A ;MOV P2,#01H;LCALL READLCALL DE250SMCJNE A,01H,HOUR_CH ;去抖CJNE A,#0FEH,KEY2_4 ;按SB2 转时调整AJMP MIN_CH ;按SB1往下调分单元KEY2_4:CJNE A,#0FDH,HOUR_CHLCALL HOUR_AD ; 调用时调整AJMP HOUR_CH ;MIN_CH:MOV A,MIN ; 分单元调整MOV B,#10DIV A BSWAP AORL A,BMOV P0,A ;MOV P2,#02H;LCALL READLCALL DE250SMCJNE A,01H,MIN_CH ;去抖CJNE A,#0FEH,KEY2_5 ;按SB2 转分调整AJMP SEC_CH ;按SB1往下调秒单元KEY2_5:CJNE A,#0FDH,MIN_CHLCALL MIN_AD ; 调用分调整LJMP MIN_CH ;SEC_CH:MOV A,SEC ; 秒单元调整MOV B,#10DIV A BSWAP AORL A,BMOV P0,A ;MOV P2,#04H;LCALL READLCALL DE250SMCJNE A,01H,SEC_CH ;去抖CJNE A,#0FEH,KEY2_6 ;按SB2 秒调整LJMP OUT_A ;按SB1跳出KEY2_6:CJNE A,#0FDH,SEC_CHCLR SEC ; 归零LJMP SEC_CH ;;-------按SB2\定时器年单元加1子程序SB3_2:LJMP SHOW_2 ;二路没编返回SB3_3:LJMP SHOW_3 ;三路没编返回SB3_1:MOV A,YEAR_1 ; 调时年单元MOV B,#10DIV A BSWAP AORL A,BMOV P0,AMOV P2,#01HLCALL READLCALL DE250SMCJNE A,01H,SB3_1CJNE A,#0FBH,KEY2_7 ;按SB2 转年调整LJMP MON_111 ;按SB1往下调月单元KEY2_7:CJNE A,#0FDH, SB3_1INC Y EAR_1 ; 1路年单元加1MOV R5,YEAR_1CJNE R5,#09,SB3_1 ;益出MOV YEAR_1,#00HAJMP SB3_1 ;;-------月单元加1子程序MON_111:MOV A,MON_1 ; 调时月单元显示MOV B,#10DIV A BSWAP AORL A,BMOV P0,AMOV P2,#02HLCALL READLCALL DE250SMCJNE A,01H,MON_111CJNE A,#0FBH,KEY2_8 ;按SB2 转月调整LJMP DAY_111KEY2_8:CJNE A,#0FDH,MON_111INC M ON_1 ;1路月单元加1MOV R5,MON_1CJNE R5,#13,MON_111;益出MOV MON_1,#01HAJMP MON_111 ; 转到月显;_------日单元加1子程序DAY_111:MOV A,DAY_1 ; 调时日单元显示提示MOV B,#10DIV A BSWAP AORL A,BMOV P0,AMOV P2,#04HLCALL READLCALL DE250SMCJNE A,01H,DAY_111CJNE A,#0FBH,KEY2_9 ;按SB2 转日调整LJMP HOUR_111KEY2_9:CJNE A,#0FDH,DAY_111INC D AY_1 ;1组日单元加1MOV R5,DAY_1CJNE R5,#32,DAY_111;益出MOV DAY_1,#01HAJMP DAY_111 ; 转到日显;-------按SB2时单元加1子程序HOUR_111:MOV A,HOUR_1 ; 调时时单元显示提示MOV B,#10DIV A BSWAP AORL A,BMOV P0,AMOV P2,#01HLCALL READLCALL DE250SMCJNE A,01H,HOUR_111CJNE A,#0FBH,KEY2_10 ; 按SB2 转时调整LJMP MIN_111KEY2_10:CJNE A,#0FDH,HOUR_111INC H OUR_1MOV R5,HOUR_1CJNE R5,#24,HOUR_111;益出MOV HOUR_1,#00HAJMP HOUR_111 ; 转到时显;-------分单元加1子程序MIN_111:MOV A,MIN_1 ; 调时分单元、并显示提示MOV B,#10DIV A BSWAP AORL A,BMOV P0,AMOV P2,#02HLCALL READLCALL DE250SMCJNE A,01H,MIN_111CJNE A,#0FBH,KEY2_11 ;按SB2 转分调整AJMP OFF_CH ;按SB3往下调定时:关单元KEY2_11:CJNE A,#0FDH, MIN_111INC M IN_1 ;1路分单元加1MOV R5,MIN_1CJNE R5,#60,MIN_111;益处MOV MIN_1,#00HAJMP MIN_111 ; 转到分显;年单元调整OFF_CH:MOV A,YEAR_11 ; 调时年单元MOV B,#10DIV A BSWAP AORL A,BMOV P0,AMOV P2,#01HLCALL READLCALL DE250SMCJNE A,01H,OFF_CHCJNE A,#0FBH,KEY2_F7 ;按SB2 转年调整LJMP MON_OFF ;按SB1往下调月单元KEY2_F7:CJNE A,#0FDH,OFF_CHINC Y EAR_11 ; 1路年单元加1MOV R5,YEAR_11CJNE R5,#09,OFF_CH ;益出MOV YEAR_11,#00HAJMP OFF_CH ;;-------月单元加1子程序MON_OFF:MOV A,MON_11 ; 调时月单元显示MOV B,#10DIV A BSWAP AORL A,BMOV P0,AMOV P2,#02HLCALL READLCALL DE250SMCJNE A,01H,MON_OFFCJNE A,#0FBH,KEY2_F8 ;按SB2 转月调整LJMP DAY_OFFKEY2_F8:CJNE A,#0FDH,MON_OFFINC M ON_11 ;1路月单元加1MOV R5,MON_11CJNE R5,#13,MON_OFF;益出MOV MON_11, #01HAJMP MON_OFF ; 转到月显;_------日单元加1子程序DAY_OFF:MOV A,DAY_11 ; 调时日单元显示提示MOV B,#10DIV A BSWAP AORL A,BMOV P0,AMOV P2,#04HLCALL READLCALL DE250SMCJNE A,01H,DAY_OFFCJNE A,#0FBH,KEY2_F9 ;按SB2 转日调整LJMP HOUR_OFFKEY2_F9:CJNE A,#0FDH,DAY_OFFINC D AY_11 ;1组日单元加1MOV R5,DAY_11CJNE R5,#32,DAY_OFF;益出MOV DAY_11,#01HAJMP DAY_OFF ; 转到日显;-------按SB2时单元加1子程序HOUR_OFF:MOV A,HOUR_11 ; 调时时单元显示提示MOV B,#10DIV A BSWAP AORL A,BMOV P0,AMOV P2,#01HLCALL READLCALL DE250SMCJNE A,01H,HOUR_OFFCJNE A,#0FBH,KEY2_F10 ; 按SB2 转时调整LJMP MIN_OFFKEY2_F10:CJNE A,#0FDH,HOUR_OFFINC H OUR_11MOV R5,HOUR_11CJNE R5,#24,HOUR_OFF;益出MOV HOUR_11,#00HAJMP HOUR_OFF ; 转到时显;-------分单元加1子程序MIN_OFF:MOV A,MIN_11 ; 调时分单元、并显示提示MOV B,#10DIV A BSWAP AORL A,BMOV P0,AMOV P2,#02HLCALL READLCALL DE250SMCJNE A,01H,MIN_OFFCJNE A,#0FBH,KEY2_F11 ;按SB2 转分调整LJMP ON_1 ;按SB3往下调定时:开与关KEY2_F11:CJNE A,#0FDH, MIN_OFFINC M IN_11 ;1路分单元加1MOV R5,MIN_11CJNE R5,#60,MIN_OFF;益处MOV MIN_11,#00HLJMP MIN_OFF ; 转到分显;-------开、关定时ON_1: CJNE A,#0FBH,MIN_OFFK1: MOV A,#88HMOV R7,AMOV P0,AMOV P2,#0FFH;三组都显示开LCALL READLCALL DE250SMCJNE A,01H,ON_1;去抖后比较CJNE A,#0FBH,KEY2_12 ;按SB2 转关LJMP OUT_A ;按SB3调出、处于开状态KEY2_12:CJNE A,#0FDH, K1k2: MOV A,#00H; 显示0关MOV R7,AMOV P0,AMOV P2,#0FFH;LCALL READLCALL DE250SMCJNE A,01H,K2;去抖后比较CJNE A,#0FBH,KEY2_13 ;按SB2 转开LJMP OUT_A ;SB3调出、处关状态KEY2_13:CJNE A,#0FDH,K2 ; 比较按了没LJMP K1 ; 按了SB2、转开OUT_A:POP 00HPOP BPOP ACCPOP PSWRETI;_------读取按键程序READ: MOV A,P1;读取按键MOV R1,ALCALL DE10MSMOV A,P1RET;_----延时程序DE5SM:PUSH 01HMOV R1,#0FFHDJNZ R1,$POP 01HRETDE10MS:PUSH 04HPUSH 05HMOV R4,#0AHDl1: MOV R5,#0FFHDl2: DJNZ R5,$DJNZ R4,Dl1POP 05HPOP 04HRETDE250SM:PUSH 02HPUSH 00HMOV R0,#0FFH DEL: MOV R2,#0FFHDJNZ R2,$DJNZ R0,DELPOP 00HPOP 02HRET;_---调整时间进位程序MIN_AD:INC MINMOV R6,MINCJNE R6,#60,OU1MOV MIN,#00OU1: RETHOUR_AD:INC HOURMOV R6,HOURCJNE R6,#25,OU2MOV HOUR,#00OU2: RETDAY_AD:INC DAYMOV R6,DAYCJNE R6,#32,OU3 ; 是否益出MOV DAY,#01HOU3: RETMON_AD:INC MONMOV R6,MONCJNE R6,#13,OU4 ; 是否益出MOV MON,#01HOU4: RETYEAR_AD:INC YEARMOV R6,YEARCJNE R6,#09,OU5;是否益出MOV YEAR,#00HOU5: RETEND。
51单片机电子闹钟程序(亲自编写,可用)
学校电子钟,有闹钟功能,按键可调时间,可调打铃时间,打铃时间长短显示,每个模块有功能注释。
其中正常时间显示和闹钟时间显示可用一个开关来调整。
芯片选择STC89C52程序:#include<reg51.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned int//定义显示段码uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};uchar codebbtime[]={0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; uchar clock[]={0,0,0,0};uchar clock1[]={12,30,0};uchar weikong[6];uchar bbduration=4;uchar lingtime=9;//学校打铃时间组uchar shangwu1[]={8,30};uchar shangwu2[]={10,0};uchar shangwu3[]={10,20};uchar shangwu4[]={11,50};uchar xiawu1[]={13,30};uchar xiawu2[]={15,00};uchar xiawu3[]={15,15};uchar xiawu4[]={16,45};//按键定义sbit mode=P1^7;sbit sec_clr=P1^0;sbit min_set_add=P1^3;sbit min_set_sub=P1^4;sbit hour_set_add=P1^1;sbit hour_set_sub=P1^2;sbit bb_set_add=P1^5;sbit bb_set_sub=P1^6;sbit speaker=P2^6;//延时函数void delay(unsigned int t){while(t--);//时钟进位函数void clockjinwei(){clock[0]++;if(clock[0]==20){clock[1]++;clock[0]=0;if(clock[1]==60){clock[2]++;clock[1]=0;if(clock[2]==60){clock[3]++;clock[2]=0;if(clock[3]==24)clock[3]=0;}}}}//定时器0中断服务函数void timer0(void) interrupt 1 using 1 {TMOD=0x01;TH0=0x3c;TL0=0xb0;clockjinwei();}//时钟分位显示函数void fenwei(){weikong[0]=clock[3]/10;weikong[1]=clock[3]%10;weikong[2]=clock[2]/10;weikong[3]=clock[2]%10;weikong[4]=clock[1]/10;weikong[5]=clock[1]%10;}//闹钟分位显示函数void naofen(){weikong[0]=clock1[0]/10;weikong[1]=clock1[0]%10;weikong[2]=clock1[1]/10;weikong[3]=clock1[1]%10;weikong[4]=clock1[2]/10;weikong[5]=clock1[2]%10; }//闹钟定时显示函数void naozhongdisplay(){uchar z,s;uchar x=0x01;naofen();for(z=0;z<6;z++){P2=0;P0=table[weikong[z]];P2=x;x=_crol_(x,1);for(s=0;s<255;s++);}}//时钟显示函数void display(){uchar i,j;uchar x=0x01;fenwei();for(i=0;i<6;i++){P2=0;P0=table[weikong[i]];P2=x;x=_crol_(x,1);for(j=0;j<255;j++);}}//总显示函数void zhongxian(){if(mode==1)delay(100);if(mode==1)display();if(mode==0)delay(100);if(mode==0)naozhongdisplay();}//按键处理程序void key_set(){zhongxian();P1=0xff;if(min_set_add==0){delay(100);if(min_set_add==0){if(mode==1){clock[2]++;if(clock[2]==60){clock[2]=0;}while(min_set_add==0)zhongxian();}}if(mode==0){clock1[1]++;if(clock1[1]==60){clock1[1]=0;}while(min_set_add==0)zhongxian();}}//if(min_set_sub==0){delay(100);if(min_set_sub==0){if(mode==1){clock[2]--;if(clock[2]==0)clock[2]=59;}while(min_set_sub==0)zhongxian();if(mode==0){clock1[1]--;if(clock1[1]==0)clock1[1]=59;}while(min_set_sub==0)zhongxian();}}//if(hour_set_add==0){delay(100);if(hour_set_add==0){if(mode==1){clock[3]++;if(clock[3]==24){clock[3]=0;}while(hour_set_add==0)zhongxian();}if(mode==0){clock1[0]++;if(clock1[0]==24){clock1[0]=0;}while(hour_set_add==0)zhongxian();}}}//if(hour_set_sub==0){delay(100);if(hour_set_sub==0){if(mode==1){clock[3]--;if(clock[3]==0)clock[3]=23;}while(hour_set_sub==0)zhongxian();if(mode==0){clock1[0]--;if(clock1[0]==0)clock1[0]=23;}while(hour_set_sub==0)zhongxian();}}//if(sec_clr==0){delay(100);if(sec_clr==0){clock[1]=0;}while(sec_clr==0)zhongxian();}}//闹钟响铃函数void bb(){if(clock[1]<=bbduration){speaker=1;delay(100);speaker=0;}else speaker=0;}//打铃函数void daling(){if(clock[1]<=lingtime){speaker=1;delay(100);speaker=0;}else speaker=0;}//时间比较函数void bijiao(){if(clock[3]==shangwu1[0]){if(clock[2]==shangwu1[1])daling();}if(clock[3]==shangwu2[0]){if(clock[2]==shangwu2[1])daling();}if(clock[3]==shangwu3[0]){if(clock[2]==shangwu3[1])daling();}if(clock[3]==shangwu4[0]){if(clock[2]==shangwu4[1])daling();}if(clock[3]==xiawu1[0]){if(clock[2]==xiawu1[1])daling();}if(clock[3]==xiawu2[0]){if(clock[2]==xiawu2[1])daling();}if(clock[3]==xiawu3[0]){if(clock[2]==xiawu3[1])daling();}if(clock[3]==xiawu4[0]){if(clock[2]==xiawu4[1])daling();}}//闹钟比较void naobijiao(){if(clock[3]==clock1[0]){if(clock[2]==clock1[1]||clock[2]==clock1[1]+1||clock[2]==clock1[1]+2) bb();}}//响铃时长显示函数void bbtimeshow(){P3=bbtime[bbduration];if(bbduration>15)bbduration=0;}//响铃按键处理函数void bbtime_set(){bbtimeshow();if(bb_set_add==0){delay(100);if(bb_set_add==0)bbduration++;while(bb_set_add==0)bbtimeshow();}if(bb_set_sub==0){delay(100);if(bb_set_sub==0)bbduration--;while(bb_set_sub==0)bbtimeshow();}}//主程序void main(){EA=1;ET0=1;TR0=1;while(1){key_set();bijiao();bbtime_set();naobijiao();}}电路图:分四部分显示:如果在学习这个程序过程中有什么问题,可以发邮件到******************询问。
基于汇编语言的51单片机可调数字钟的设计
目录摘要 (3)Abstract (4)引言 (5)第一章绪论 (6)1.1 课题的背景 (6)1.2课题的来源 (7)1.3课题的意义 (7)第二章设计目的及要求 (8)2.1设计目的 (8)2.2设计要求 (8)2.1.1 基本要求 (8)2.1.2 高级要求 (8)2.1.3毕业设计作品要求 (9)第三章系统方案选择与论证 (10)3.1方案选择 (10)3.1.1方案比较 (10)3.1.2 芯片的选择 (10)3.2方案论证 (11)3.2.1显示模块方案选择与论证 (11)3.2.2时钟信号方案选择与论证 (11)3.3电路设计最终方案 (12)第四章系统电路的总体方案 (13)4.1数字钟的工作原理 (13)4.1.1实现时钟计时的基本方法 (14)4.1.2数字钟的时间显示 (15)4.1.3数字钟的启、停及时间调整 (15)4.2总体设计 (16)第五章系统的硬件设计 (17)5.1 AT89C52单片机最小系统 (17)5.2单片机的概念 (17)5.2.1单片机的结构 (17)5.2.2单片机的功能介绍 (20)5.3复位电路 (23)5.4电源电路 (24)5.5时钟振荡电路 (24)5.6键盘控制电路 (24)5.7 LED数码管显示电路 (26)第六章系统的软件设计 (28)6.1系统软件设计流程图 (28)6.2 系统中断流程图 (29)6.3 子程序说明 (31)6.3.1 按键扫描 (31)6.3.2 数码管动态扫描 (32)第七章数字钟元件清单和软件介绍 (33)7.1数字钟元件清单 (33)7.2 软件介绍 (33)7.2.1软件调试 (34)7.2.2硬件调试 (34)第八章总结 (35)参考文献 (36)致谢 (37)附录 (38)附录一系统程序源代码 (38)附录二电路原理图 (44)基于汇编语言的51单片机可调数字钟的设计摘要在当今社会,随着计算机在社会领域的渗透和大规模集成电路的发展,单片机的应用正在不断地走向深入,由于它具有功能强,体积小,功耗低,价格便宜,工作可靠,使用方便等特点,因此它特别适合于与控制有关的系统,越来越广泛地应用于自动控制,智能化仪器,仪表,数据采集,军工产品以及家用电器等各个领域,单片机往往是作为一个核心部件来使用,在根据具体硬件结构,以及针对具体应用对象特点的软件相结合,以作完善。
单片机电子时钟报告及汇编代码
单片机电子日历时钟设计一、设计的目的及其意义(1)巩固、加深和扩大51系列单片机应用的知识面,提高综合及灵活运用所学知识解决工业控制的能力;(2)培养针对课题需要,选择和查阅有关手册、图表及文献资料的自学能力,提高组成系统、编程、调试的动手能力;(3)对课题设计方案的分析、选择、比较、熟悉用51单片机做系统开发、研制的过程,软硬件设计的方法、内容及步骤。
二、本实验设计的功能2.1 基本功能1)显示北京时间2)校准时间;3)使用汇编语言4)时、分、秒之间或年、月、日间以小数点分隔;2.2 扩展功能(1)显示公历日期(2)校准日期(3)运动秒表(4)闹钟功能三、总体设计方案本实验使用汇编语言设计,程序的流程图大致如下:主程序流程图:显示闹钟子程序流程图:运动秒表子程序流程图:校准闹钟,日期和时间的子程序流程图:四、源程序ORG 0000HAJMP BEGINORG 000BHLJMP TINTOYEARH EQU 30H ;年高位存放地址YEARL EQU 31H ;年低位存放地址MONTH EQU 32H ;月存放地址DAY EQU 33H ;日存放地址HOUR EQU 34H ;时存放地址MIN EQU 35H ;分存放地址SEC EQU 36H ;秒存放地址MSEC EQU 37H ;10ms存放地址SECM EQU 38HYDMSEC EQU 39H ;运动秒针存放地址YDSECM EQU 40HBEEP BIT P1^3 ;蜂鸣器AHOUR EQU 41H ;闹钟时存放地址AMIN EQU 42H ;闹钟分存放地址DEDA EQU 43H ;5ms计数值PFOUR BIT P0.4PFIVE BIT P0.5PSIX BIT P0.6PSEVEN BIT P0.7BEGIN:CALL INITIALLOOP:CALL SHOW_TIME1 ;默认为显示时间CALL RINGCALL SCAN_KEY ;键盘扫描CJNE A,#0EEH,JUDGE1 ;如果A=EEH,则显示日期年和月CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE1CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2CALL SHOW_DATE2JUDGE1:CJNE A,#0DEH,JUDGE2 ;如果A=DEH,则显示闹钟SA:CALL SHOW_ALARMCALL SCAN_KEYCJNE A,#0EEH,SA ;在显示闹钟时按下EEH键则是返回时间模式JUDGE2:CJNE A,#0EDH,JUDGE3 ;如果A=EDH,则依次调闹钟,日期和时间CALL ADJUSTJUDGE3:CJNE A,#0DDH,JUDGE4 ;如果A=DDH,则显示时间分,秒ST2:CALL SHOW_TIME2CALL SCAN_KEYCJNE A,#0EDH,OTHER ;在显示分,秒时按下EDH 键则是运动秒表模式CLRYD:MOV MSEC,#0MOV SECM,#0AJMP ST3OTHER:CJNE A,#0EEH,ST2 ;按下EEH键则是返回时间模式AJMP JUDGE4ST3: ;运动秒表计时开始MOV YDMSEC,MSECMOV YDSECM,SECMCALL SHOW_TIME3CALL SCAN_KEYCJNE A,#0DEH,ST3 ;按下DEH键则是停止秒表STOP:CALL SHOW_TIME3CALL SCAN_KEYCJNE A,#0DDH,OW ;按下DDH键,运动秒表则从零从新开始计时AJMP CLRYDOW: CJNE A,#0EDH,OTHERWISE ;按下EDH键则继续运动秒表的计时,仍按DEH停止秒表MOV MSEC,YDMSECMOV SECM,YDSECMAJMP ST3OTHERWISE:CJNE A,#0EEH,STOP ;按下EEH键返回时间模式JUDGE4:AJMP LOOPRING: ;若闹钟时钟为24,则闹钟为关闭状态MOV A,HOURCJNE A,AHOUR,RTMOV A,MINCJNE A,AMIN,RTCLR BEEPRT:RETSHOW_TIME1: ;显示时间(时和分)MOV DPTR,#TABLE ;数字编码表基址MOV A,MIN ;显示分,minMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#04H ;点亮第三个数码管CALL SHOW ;显示数值CALL DELAYMOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#08H ;点亮第四个数码管CALL SHOWCALL DELAYMOV A,HOUR ;显示小时,hourMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#01H ;点亮第一个数码管CALL SHOWCALL DELAYMOV DPTR,#TABLE2MOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#02H ;点亮第二个数码管CALL SHOWCALL DELAYMOV P0,#00HRETSHOW_TIME2: ;显示时间(分和秒)MOV DPTR,#TABLE ;数字编码表基址MOV A,SEC ;显示秒,secMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#04H ;点亮第三个数码管CALL SHOWCALL DELAYMOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#08H ;点亮第四个数码管CALL SHOWCALL DELAYMOV A,MIN ;显示分钟minMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#01H ;点亮第一个数码管CALL SHOWCALL DELAYMOV DPTR,#TABLE2MOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#02H ;点亮第二个数码管CALL SHOWCALL DELAYMOV P0,#00H ;P0置零,熄灭数码管RETSHOW_TIME3: ;显示运动秒针(s和10ms) MOV DPTR,#TABLE ;数字编码表基址MOV A,YDMSEC ;显示10msMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#04H ;点亮第三个数码管CALL SHOWCALL DELAYMOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#08H ;点亮第四个数码管CALL SHOWCALL DELAYMOV A,YDSECM ;显示秒MOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#01H ;点亮第一个数码管CALL SHOWCALL DELAYMOV DPTR,#TABLE2MOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#02H ;点亮第二个数码管CALL SHOWCALL DELAYMOV P0,#00H ;P0置零,熄灭数码管RETSHOW_DATE1: ;显示日期(年)MOV DPTR,#TABLE ;数字编码表基址MOV A,YEARHMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#01HCALL SHOWCALL DELAYMOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#02HCALL SHOWCALL DELAYMOV A,YEARLMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#04HCALL SHOWCALL DELAYMOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#08HCALL SHOWCALL DELAYRETSHOW_DATE2: ;显示日期(月和日)MOV DPTR,#TABLE ;数字编码表基址MOV A,DAYMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#04H ;点亮第3个数码管CALL SHOWCALL DELAYMOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#08H ;点亮第4个数码管CALL SHOWCALL DELAYMOV A,MONTHMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#01H ;点亮第1个数码管CALL SHOWCALL DELAYMOV DPTR,#TABLE2MOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#02H ;点亮第2个数码管CALL SHOWCALL DELAYMOV P0,#00HRETADJUST: ;调整闹钟,日期和时间ALARM1: ;调整闹钟的小时数MOV DPTR,#TABLEMOV A,AHOURMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#01H ;点亮第一个数码管CALL SHOWCALL DELAYMOV DPTR,#TABLE2MOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#02H ;点亮第二个数码管CALL SHOWCALL DELAYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCJNE A,#0DEH,CHECK1 ;如果A=DEH,则闹钟小时加1MOV A,AHOURCJNE A,#24,INC1MOV AHOUR,#0CALL LDELAYAJMP ALARM1INC1:INC AMOV AHOUR,ACALL LDELAYAJMP ALARM1CHECK1:CJNE A,#0EEH,CHECK2 ;如果A=EEH,则闹钟小时减1MOV A,AHOURCJNE A,#0,DEC1MOV AHOUR,#24 ;当闹钟时钟调到24的时候,则相当于关闭闹钟CALL LDELAYAJMP ALARM1DEC1:DEC AMOV AHOUR,ACALL LDELAYAL1:AJMP ALARM1CHECK2:CJNE A,#0DDH,CHECK3 ;如果A=DDH,则返回RETCHECK3:CJNE A,#0EDH,AL1 ;如果A=EDH,则调整闹钟的分钟数ALARM2: ;调整闹钟的分钟数MOV DPTR,#TABLEMOV A,AMINMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#04H ;点亮第三个数码管CALL SHOW ;显示数值CALL DELAYMOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#08H ;点亮第四个数码管CALL SHOWCALL DELAYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCJNE A,#0DEH,CHECK4 ;如果A=DEH,则闹钟分钟加1 MOV A,AMINCJNE A,#59,INC2MOV AMIN,#0CALL LDELAYAJMP ALARM2INC2:INC AMOV AMIN,ACALL LDELAYAJMP ALARM2CHECK4:CJNE A,#0EEH,CHECK5 ;如果A=EEH,则闹钟小时减1 MOV A,AMINCJNE A,#0,DEC2MOV AMIN,#59CALL LDELAYAJMP ALARM2DEC2:DEC AMOV AMIN,ACALL LDELAYAL2:AJMP ALARM2CHECK5:CJNE A,#0DDH,CHECK6 ;如果A=DDH,则返回RETCHECK6:CJNE A,#0EDH,AL2 ;如果A=EDH,则调整日期(年)DA TE1: ;调整年的高位MOV DPTR,#TABLEMOV A,YEARHMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#01H ;点亮第一个数码管CALL SHOWCALL DELAYMOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#02H ;点亮第二个数码管CALL SHOWCALL DELAYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCJNE A,#0DEH,CHECKYH1 ;如果A=DEH,则日期年高位加1MOV A,YEARHCJNE A,#99,INCYRH1MOV YEARH,#0CALL LDELAYAJMP DA TE1INCYRH1:INC AMOV YEARH,ACALL LDELAYAJMP DA TE1CHECKYH1:CJNE A,#0EEH,CHECKYH2 ;如果A=EEH,则日期年高位减1MOV A,YEARHCJNE A,#0,DECYRH1MOV YEARH,#99CALL LDELAYAD1:AJMP DA TE1DECYRH1:DEC AMOV YEARH,ACALL LDELAYAJMP DA TE1CHECKYH2:CJNE A,#0DDH,CHECKYH3 ;如果A=DDH,则返回RETCHECKYH3:CJNE A,#0EDH,AD1 ;如果A=EDH,则调整日期年的低位DA TE2: ;调整年的低位MOV DPTR,#TABLEMOV A,YEARLMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#04H ;点亮第3个数码管CALL SHOWCALL DELAYMOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#08H ;点亮第4个数码管CALL SHOWCALL DELAYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCJNE A,#0DEH,CHECKYL1MOV A,YEARLCJNE A,#99,INCYRL1MOV YEARL,#0CALL LDELAYAJMP DA TE2INCYRL1: ;年低位加1INC AMOV YEARL,ACALL LDELAYAJMP DA TE2CHECKYL1:CJNE A,#0EEH,CHECKYL2MOV A,YEARLCJNE A,#0,DECYRL1MOV YEARL,#99CALL LDELAYAD2: AJMP DA TE2DECYRL1: ;年低位减1DEC AMOV YEARL,ACALL LDELAYAJMP DA TE2CHECKYL2:CJNE A,#0DDH,CHECKYL3 ;返回RETCHECKYL3:CJNE A,#0EDH,AD2 ;跳到调整月,日MON:MOV DPTR,#TABLEMOV A,MONTHMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#01H ;点亮第一个数码管CALL SHOWCALL DELAYMOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#02H ;点亮第二个数码管CALL SHOWCALL DELAYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCJNE A,#0DEH,CHECKM1 ;如果A=DEH,则月份加1MOV A,MONTHCJNE A,#12,INCM1MOV MONTH,#1CALL LDELAYAM: AJMP MONINCM1:INC AMOV MONTH,ACALL LDELAYAJMP MONCHECKM1:CJNE A,#0EEH,CHECKM2 ;如果A=EEH,则月份减1MOV A,MONTHCJNE A,#1,DECM1MOV MONTH,#12CALL LDELAYAJMP MONDECM1:DEC AMOV MONTH,ACALL LDELAYAJMP MONCHECKM2:CJNE A,#0DDH,CHECKM3 ;如果A=DDH,则返回RETCHECKM3:CJNE A,#0EDH,AM ;如果A=EDH,则调整日ADAY:MOV DPTR,#TABLEMOV A,DAYMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#04H ;点亮第3个数码管CALL SHOWCALL DELAYMOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#08H ;点亮第4个数码管CALL SHOWCALL DELAYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCJNE A,#0DEH,CH1 //如果A=DEH,判断月份MOV A,MONTHCJNE A,#1,N2AJMP T31N2:CJNE A,#2,N3AJMP T2N3:CJNE A,#3,N4AJMP T31N4:CJNE A,#4,N5AJMP T30N5:CJNE A,#5,N6AJMP T31N6:CJNE A,#6,N7AJMP T30N7:CJNE A,#7,N8AJMP T31N8:CJNE A,#8,N9AJMP T31N9:CJNE A,#9,N10AJMP T30N10:CJNE A,#10,N11AJMP T31N11:CJNE A,#11,T31AJMP T30CH1:AJMP CHECKD1T31: //该月份有31天MOV A,DAYCJNE A,#31,INCD1 //判断是否为31号MOV DAY,#0CALL LDELAYAJMP ADAYINCD1:INC AMOV DAY,ACALL LDELAYAJMP ADAYT30: //该月份有30天MOV A,DAYCJNE A,#30,INCDD1 //判断是否为30号MOV DAY,#0CALL LDELAYAJMP ADAYINCDD1:INC AMOV DAY,ACALL LDELAYAJMP ADAYT2: ;特殊的2月MOV B,#4MOV A,YEARLCJNE A,#0,NORMAL1AJMP CENTURY1NORMAL1:DIV ABMOV A,BCJNE A,#0,COMMON1BISSEXTILE1:MOV A,DAY ;闰年CJNE A,#29,INC2DAY ;未够29天MOV DAY,#1CALL DELAYAJMP ADAYINC2DAY:INC DAYCALL LDELAYAJMP ADAYCOMMON1:MOV A,DAY ;平年CJNE A,#28,INC2DAY2 ;未够28天MOV DAY,#1CALL DELAYAJMP ADAYINC2DAY2:INC DAYCALL LDELAYAJMP ADAYCENTURY1: ;世纪年MOV A,YEARHDIV ABMOV A,BCJNE A,#0,COMMON1AJMP BISSEXTILE1CHECKD1:CJNE A,#0EEH,CH2MOV A,MONTHCJNE A,#1,NN2AJMP U31NN2:CJNE A,#2,NN3AJMP U2NN3:CJNE A,#3,NN4AJMP U31NN4:CJNE A,#4,NN5AJMP U30NN5:CJNE A,#5,NN6AJMP U31NN6:CJNE A,#6,NN7AJMP U30NN7:CJNE A,#7,NN8AJMP U31NN8:CJNE A,#8,NN9AJMP U31NN9:CJNE A,#9,NN10AJMP U30NN10:CJNE A,#10,NN11AJMP U31NN11:CJNE A,#11,U31AJMP U30CH2:AJMP CHECKD2U31:MOV A,DAYCJNE A,#0,DECD1MOV DAY,#31CALL LDELAYAJMP ADAYDECD1:DEC AMOV DAY,ACALL LDELAYAJMP ADAYU30:MOV A,DAYCJNE A,#0,DECDD1MOV DAY,#30CALL LDELAYAJMP ADAYDECDD1:DEC AMOV DAY,ACALL LDELAYAJMP ADAYU2: ;特殊的2月MOV A,YEARLCJNE A,#0,NORMAL2AJMP CENTURY2NORMAL2:DIV ABMOV A,BCJNE A,#0,COMMON2BISSEXTILE2:MOV A,DAY ;闰年CJNE A,#1,DEC2DAY ;未够29天MOV DAY,#29CALL DELAYAJMP ADAYDEC2DAY:DEC DAYCALL LDELAYAJMP ADAYCOMMON2:MOV A,DAY ;平年CJNE A,#1,DEC2DAY2 ;未够28天MOV DAY,#28CALL DELAYAJMP ADAYDEC2DAY2:DEC DAYCALL LDELAYADA:AJMP ADAYCENTURY2: ;世纪年MOV A,YEARHDIV ABMOV A,BCJNE A,#0,COMMON2AJMP BISSEXTILE2CHECKD2:CJNE A,#0DDH,CHECKD3 ;如果A=DDH,则返回RETCHECKD3:CJNE A,#0EDH,ADA ;如果A=EDH,则调整时间;跳到调整月,日TIME1: ;调整时间的小时数MOV DPTR,#TABLEMOV A,HOURMOV B,#10MOVC A,@A+DPTRANL P0,#0F0HORL P0,#01H ;点亮第一个数码管CALL SHOWCALL DELAYMOV DPTR,#TABLE2MOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#02H ;点亮第二个数码管CALL SHOWCALL DELAYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCJNE A,#0DEH,CHECKT1 ;时间小时数加1 MOV A,HOURCJNE A,#23,INCT1MOV HOUR,#0CALL LDELAYAJMP TIME1INCT1:INC AMOV HOUR,ACALL LDELAYAJMP TIME1CHECKT1:CJNE A,#0EEH,CHECKT2MOV A,HOURCJNE A,#0,DECT1MOV HOUR,#23CALL LDELAYTI1:AJMP TIME1DECT1: ;时间小时数减1 DEC AMOV HOUR,ACALL LDELAYAJMP TIME1CHECKT2:CJNE A,#0DDH,CHECKT3RETCHECKT3:CJNE A,#0EDH,TI1 ;调整时间的分钟数TIME2:MOV DPTR,#TABLE ;数字编码表基址MOV A,MINMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#04H ;点亮第三个数码管CALL SHOW ;显示数值CALL DELAYMOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#08H ;点亮第四个数码管CALL SHOWCALL DELAYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCALL SCAN_KEYCJNE A,#0DEH,CHECKT4MOV A,MINCJNE A,#59,INCT2MOV MIN,#0CALL LDELAYLJMP TIME2INCT2: ;时间分钟数加1 INC AMOV MIN,ACALL LDELAYLJMP TIME2CHECKT4:CJNE A,#0EEH,CHECKT5MOV A,MINCJNE A,#0,DECT2MOV MIN,#59CALL LDELAYLJMP TIME2DECT2: ;时间分钟数减1 DEC AMOV MIN,ACALL LDELAYTI2:LJMP TIME2CHECKT5:CJNE A,#0DDH,CHECKT6RETCHECKT6:CJNE A,#0EDH,TI2RETSHOW_ALARM: ;显示闹钟MOV DPTR,#TABLE ;数字编码表基址MOV A,AMINMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#04H ;点亮第三个数码管CALL SHOWCALL DELAYMOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#08H ;点亮第四个数码管CALL SHOWCALL DELAYMOV A,AHOURMOV B,#10DIV ABMOVC A,@A+DPTRANL P0,#0F0HORL P0,#01H ;点亮第一个数码管CALL SHOWCALL DELAYMOV DPTR,#TABLE2MOV A,BMOVC A,@A+DPTRANL P0,#0F0HORL P0,#02H ;点亮第二个数码管CALL SHOWCALL DELAYMOV P0,#00HRETSCAN_KEY: ;P2低4位控制行,高4位控制列MOV P2,#0FH ;行扫描MOV A,P2CJNE A,#0FH,KEY1 ;A不等于#0F,表示当前有键按下KEY1:CALL DELAYMOV A,P2CJNE A,#0FH,SCAN1 ;延时排除按键抖动情况MOV A,#0FFHRETSCAN1:MOV A,P2 ;记录行状态SCAN2:MOV P2,#0F0H ;列扫描MOV R6,P2ORL A,R6 ;行列读取结果相或得出键值,由A存放键值:RETINITIAL:MOV YEARH,#20 ;初始化控制变量MOV YEARL,#13MOV MONTH,#09MOV DAY,#20MOV HOUR,#10MOV MIN,#30MOV SEC,#46MOV MSEC,#00MOV SECM,#00MOV DEDA,#00MOV AHOUR,#10MOV AMIN,#31;对涉及到的中断,进行设置SETB EA ;开总中断SETB ES ;使能串口中断SETB ET0 ;使能定时器0中断SETB TR0 ;启动定时0CLR ET1 ;关定时器1中断CLR EX0 ;关外部中断0CLR EX1 ;关外部中断1MOV SCON,#50H ;SM0/SM1=0/1,设置成串口1方式,10位通用异步接发, ;8位数据,可变波特率,接收允许MOV TMOD,#21H ;T1: M1/M0=1/0 波特率发生器T1工作在模式2,8位自动重装初值定时计数;T0: M1/M0=0/1 工作在模式1,作16位定时器MOV PCON,#80H ;SMOD置1,使得波特率翻倍为2400x2=4800BPSMOV TH1,#0F3H ;预置初值(按照波特率2400BPS预置初值)MOV TL1,#0F3H ;预置初值(按照波特率2400BPS预置初值)SETB TR1 ;启动定时器T1SETB BEEP ;关闭蜂鸣器MOV TH0,#0ECHMOV TL0,#78HMOV P0,#00HRETDELAY: ;延迟子程序,延时10msMOV 05H,#100DE0: MOV 06H,#100DE1: DJNZ 06H,DE1DJNZ 05H,DE0RETLDELAY: ;延迟子程序,延时500ms MOV 07H,#50LDE0: MOV 05H,#100LDE1: MOV 06H,#100LDE2: DJNZ 06H,LDE2DJNZ 05H,LDE1LDE3: DJNZ 07H,LDE0RET;在数码管上显示数字SHOW: ;数码管显示函数MOV R6,AMOV R7,#01HS1:ANL A,R7 ;取出A的一位JNZ S3S2:CLR PSEVENAJMP S4S3:SETB PSEVENS4:SETB PFOUR ;将数据寄存器PSEVEN值移进移位寄存器NOPCLR PFOURNOPMOV A,R7RL AMOV R7,AMOV A,R6CJNE R7,#01H,S1 ;判断A的8位是否全部取出CLR PFIVENOPSETB PFIVERETTINTO: ;定时器0计时中断程序每隔5ms中断一次INC DEDAMOV 55H,DEDA ;运动秒针,低位MSEC每10ms计数ANL 55H,#01HMOV R6,55HCJNE R6,#0,POPACMOV R6,MSECCJNE R6,#99,INCMMOV MSEC,#00MOV R6,SECMCJNE R6,#59,INCSMOV SECM,#00AJMP POPACINCM:INC MSECAJMP POPACINCS:INC SECMPOPAC:MOV A,DEDACJNE A,#200,AGAIN ;判断是否1S到了MOV DEDA,#0SECOND:INC SECMOV A,SECCJNE A,#60,AGAIN ;判断是否1min到了MINUTE:MOV SEC,#0INC MINMOV A,MINCJNE A,#60,AGAIN ;判断是否1h到了HOURS:MOV MIN,#0MOV A,HOURCJNE A,#24,AGAINMOV A,MONTH ;辨别大月和小月CJNE A,#1,MONTH2AJMP THIRTY_ONE_DAYSMONTH2:CJNE A,#2,MONTH3AJMP FEBRUARYMONTH3:CJNE A,#3,MONTH4AJMP THIRTY_ONE_DAYSMONTH4:CJNE A,#4,MONTH5AJMP THIRTY_DAYSMONTH5:AJMP THIRTY_ONE_DAYSMONTH6:CJNE A,#6,MONTH7AJMP THIRTY_DAYSMONTH7:CJNE A,#7,MONTH8AJMP THIRTY_ONE_DAYSMONTH8:CJNE A,#8,MONTH9AJMP THIRTY_ONE_DAYSMONTH9:CJNE A,#9,MONTH10MONTH10:CJNE A,#10,MONTH11AJMP THIRTY_ONE_DAYSMONTH11:CJNE A,#11,MONTH12AJMP THIRTY_DAYSMONTH12:AJMP THIRTY_ONE_DAYSAGAIN:MOV TL0,#078HSETB TR0 ;启动定时器RETITHIRTY_ONE_DAYS: ;大月31天MOV HOUR,#0 ;时归0MOV A,DAYCJNE A,#31,INCDAY ;未够31天AJMP MONTHSAJMP AGAINTHIRTY_DAYS: ;小月30天MOV HOUR,#0 ;时归0MOV A,DAYCJNE A,#30,INCDAY2 ;未够30天AJMP MONTHSAJMP AGAINFEBRUARY: ;特殊的2月MOV B,#4MOV A,YEARLCJNE A,#0,NORMALAJMP CENTURYNORMAL:DIV ABCJNE A,#0,COMMONBISSEXTILE: ;闰年MOV HOUR,#0 ;时归0MOV A,DAYCJNE A,#29,INCDAY ;未够29天AJMP MONTHSCOMMON: ;平年MOV HOUR,#0 ;时归0CJNE A,#28,INCDAY ;未够28天AJMP MONTHSCENTURY: ;世纪年MOV A,YEARHMOV A,BCJNE A,#0,COMMONAJMP BISSEXTILEMONTHS:MOV DAY,#01CJNE A,#12,INCMONTHAJMP INCYEARINCMONTH:INC MONTHAJMP AGAININCYEAR: ;判断数字是否超出显示管显示范围MOV MONTH,#01MOV A,YEARLCJNE A,#99,INCYLAJMP GO_ONINCYL:INC YEARLGO_ON:MOV YEARL,#0MOV A,YEARHCJNE A,#99,INCYHAJMP ZEROINCYH:INC YEARHLJMP AGAINZERO:MOV YEARH,#0LJMP AGAINTABLE:DB 0FCH,60H,0DAH,0F2H,66H,0B6H,0BEH,0E0H,0FEH,0F6H ;0 1 2 34 5 6 7 8 9 ,不带小数点TABLE2:DB 0FDH,61H,0DBH,0F3H,67H,0B7H,0BFH,0E1H,0FFH,0F7H ;带小数点END五、系统的使用和操作说明按下开关,如下图所示显示初始设定的时间10:30分。
51单片机24小时闹钟时钟可调简单程序
51单片机24小时闹钟时钟可调简单程序#includeunsigned char seg[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; unsigned char con[6]={0x1,0x2,0x4,0x8,0x10,0x20};unsigned char mm=0;unsigned char ss=0;unsigned char hh=0;unsigned char count=100;unsigned char TH=01,TM=00,m;sbit S1=P3^3;sbit S2=P3^4;sbit S3=P3^5;sbit S4=P3^6;sbit S5=P3^7;sbit S6=P3^2;sbit bell=P3^0;main(){TMOD=1;TH0=-10000>>8;TL0=-10000; //10毫秒间隔EA=1;ET0=1;TR0=1;while(1);}void isr_time0() interrupt 1 //24小时{unsigned int i=0,j;unsigned char time[6];TH0=-10000>>8;TL0=-10000;count--;if(count==0){count=100;ss++;if(ss==60){ss=0;mm++;if(mm==60){mm=0;hh++;if(hh==24)hh=0;}}if(S5==0){TH++;} //闹钟调时if(S6==0){TM++;} //闹钟调分if(hh==TH){ unsigned int a,b,y;if(mm>=01){m=0;}if(mm==TM&&ss<10){if(m<10){do{m++;ss++; //ss确保闹钟时间继续for(a=0;a<1250;a++){bell=!bell;for(b=0;b<15;b++);} //取反for(y=0;y<1250;y++){bell=!bell;for(b=0;b<33;b++);}for(a=0;a<1250;a++){bell=!bell;for(b=0;b<15;b++);}for(a=0;a<1250;a++){bell=!bell;for(b=0;b<33;b++);}}while(m<10);}}}if(S1==0){hh++; //时钟加if(hh==24){hh=0;}}if(S2==0){mm++; //分钟加if(mm==60){ mm=0;hh++;}}if(S3==0&&hh>0){hh--; //时钟减if(hh==0){hh=23;}}if(S4==0&&mm>0){mm--; //分钟减if(mm==0){ mm=59;}}}time[3]=hh/10;time[2]=hh%10; //显示位time[1]=mm/10;time[0]=mm%10;for(i=0;i<6;i++){P2=con[i];if(i==1||i==2) //小数点P1=seg[time[i]]&0x7f;else P1=seg[time[i]];for(j=100;j>0;j--);}}。
单片机电子时钟汇编语言程序
51单片机架构下时钟控制程序;KEYA A键功能程序开启/关闭定时器;KEYB B键功能程序时值加1;KEYC C键功能程序分值加1;KEYD D键功能程序秒值加1;KEYE E键功能程序12/24时值转换;BEEP_BL整点报时;P0 显示接口;系统初始化程序****************************************************KEYA EQU P3.0 ;单片机控制设置KEYB EQU P3.1 ;单片机控制设置KEYC EQU P3.2 ;单片机控制设置KEYD EQU P3.3 ;单片机控制设置KEYE EQU P3.4 ;单片机控制设置BEEP EQU P3.7 ;单片机控制设置ORG 0000HAJMP MAIN ;转到系统初始化程序ORG 000BHAJMP PITO ;转到定时器0中断服务程序ORG 0100HMAIN: MOV SP, #60H ;确立堆栈区MOV TMOD, #01H ;设定定时器0为工作方式1MOV TL0, #0DCH ;装计数器初值MOV TH0, #0BHCLR 21H.0CLR TR0 ; TR0置"0",定时关闭SETB EA ; EA置"1",中断总允许SETB ET0 ; ET0置"1",定时器0中断; 允许MOV 30H, #10H ; 循环次数MOV 7EH, #0AH ; P.点显示初始化MOV R0, #79HMOV R1, #05HPP: MOV @R0, #0BHINC R0DJNZ R1, PPMOV R0, #31H ; 时、分、秒值存储单元清零Q00: MOV @R0, #00HINC R0DJNZ R1, Q00;监控程序**********************************************************LOOP: LCALL DIR ; 调显示子程序LCALL KEY ; 调键扫描子程序LOOP1: JB 20H.0, KEYA ; A键是否按下,是跳转到A键功能程序开启/关闭定时器JB 20H.1, KEYB ; B键是否按下,是跳转到B键功能程序时值加1JB 20H.2, KEYC ; C键是否按下,是跳转到C键功能程序分值加1JB 20H.3, KEYD ; D键是否按下,是跳转到D键功能程序秒值加1JB 20H.4, KEYE ; E键是否按下,是跳转到E键功能程序12/24时值转换LCALL DIRLJMP LOOP ; 跳转到监控程序;A键功能子程序****************************************************KEYA: CPL TR0 ;开启/关闭定时器SETB 21H.0AJMP LOOP ;返回;B键功能子程序****************************************************KEYB: JB TR0, KEYB1 ; 定时器是否运行,是跳转JNB 21H.0, KEYB2MOV R0, #36H ; 时值存储单元地址送R0LCALL DAAD1 ; 调加1子程序MOV A, R3 ; 时值加1后的值送累加器ALCALL BEEP_BL ; 整点报时XRL A, #12H ;时值是否到12时JNZ KEYB0 ;BACK: XRL A, #24H; 判是否到24时JNZ KEYB1 ; 时值是否到24时,否返回LCALL CLR0 ; 时值存储单元清零KEYB0: JB 20H.4, KEYB1; 是否启用12时值,否返回LCALL CLR0 ; 时值存储单元清零KEYB1: MOV 7DH, 35HMOV 7EH, 36HKEYB2: LJMP LOOP ; 返回监控程序;C键功能子程序****************************************************KEYC: JB 8CH, KEYC1 ; 定时器是否运行,否跳转MOV R0, #34H; 分值存储单元地址送R0LCALL DAAD1 ; 调加1子程序MOV A, R3 ; 分值加1后的值送累加器AXRL A, #60H ;JNZ KEYC1 ; 分值是否到60分,否返回LCALL CLR0 ; 分值存储单元清零KEYC1: MOV 7CH, 34HMOV 7BH, 33HKEYC2: LJMP LOOP ; 返回监控程序;D键功能子程序****************************************************KEYD: JB 8CH, KEYD1 ; 定时器是否运行,否跳转JNB 21H.0, KEYD2MOV R0, #32H ; 秒值存储单元地址送R0LCALL DAAD1 ; 调加1子程序MOV A, R3 ; 秒值加1后的值送R0XRL A, #60HJNZ KEYD1 ; 秒值是否到60秒,否返回LCALL CLR0 ; 秒值存储单元清0 KEYD1: MOV 79H, 31HMOV 7AH, 32HKEYD2: LJMP LOOP ; 返回监控程序;中断服务程序******************************************************PITO: PUSH PSW ;中断服务程序,现场保护PUSH ASETB RS0 ;选第三组通用寄存器SETB RS1MOV TL0, #0DCH ; 计数器重新加载MOV TH0, #0BHMOV A, 30H ;循环次数减1DEC AMOV 30H, AJNZ RETO ;不满16次,转RET0返回MOV 30H, #10H ;满16次开始计时操作MOV R0, #32H ;秒显示单元地址ACALL DAAD1 ; 秒加1MOV A, R3 ; 加1后秒值在R3中XRL A, #60H ; 判是否到60秒JNZ RETO ; 不到转RET0返回ACALL CLR0 ; 到60秒显示单元清0MOV R0, #34H ;分显示单元地址ACALL DAAD1 ; 分加1MOV A, R3 ; 加1后分值在R3中XRL A, #60H ; 判是否到60分JNZ RETO ; 不到转RET0返回ACALL CLR0 ; 到60分显示单元清0MOV R0, #36H ; 时显示单元地址ACALL DAAD1 ; 时加1MOV A, R3 ; 加1后时值在R3中LCALL BEEP_BL ; 整点报时XRL A, #12H ; 时值是否到12时JNZ KEYB3 ;XRL A, #24H ; 判是否到24时JNZ RETO ; 不到转RET0返回ACALL CLR0 ; 到24时显示单元清0 KEYB3:JB 20H.4, RETO; 是否启用12时值,否返回ACALL CLR0 ; 时值存储单元清零RETO: CLR RS0 ; 返回第0组通用寄存器CLR RS1POP A ; 现场恢复POP PSWMOV 79H, 31H ; 时、分、秒值放缓冲区MOV 7AH, 32HMOV 7BH, 33HMOV 7CH, 34HMOV 7DH, 35HMOV 7EH, 36HRETI ; 中断返回;加1子程序*******************************************************DAAD1: MOV A, @R0 ; 加1子程序,十位送ADEC R0SWAP A ; 十位数占高4位ORL A, @R0 ; 个位数占低4位ADD A, #01H ; 加1DA A ; 十进制调整MOV R3, A ; 全值暂存R3中ANL A, #0FH ; 屏蔽十位数,取出个位数MOV @R0, A ; 个位值送显示缓冲单元MOV A, R3INC R0ANL A, #0F0H ; 屏蔽个位数取出十位数SWAP A ; 使十位数占低四位MOV @R0, A ; 十位数送缓冲单元RET ; 返回CLR0: CLR A ; 清缓冲单元子程序MOV @R0, A ; 十位缓冲单元清"0"DEC R0MOV @R0, A ; 个位数缓冲单元清"0"RET ; 返回;键盘扫描子程序***************************************************KEY: LCALL KEYCHULI ; 调键值处理子程序JZ EXIT ; 没有键按下转到返回LCALL DIRLCALL DIR ; 调显示去抖动LCALL KEYCHULI ; 调键值处理子程序JZ EXIT ; 没有键按下转到返回MOV B, 20H ; 保存键值KEYSF: LCALL KEYCHULI ; 调键值处理子程序JZ KEY1 ; 键释放,转到恢复键值LCALL DIR ; 调显示子程序延时AJMP KEYSF ; 等到键释放KEY1: MOV 20H, B ; 键值送20H单元保存EXIT: RET ; 返回KEYCHULI: PUSH PSW ; 保护现场CLR RS1 ; 改变寄存器组号SETB RS0MOV P1, #0FFH ; 先向P1口写1MOV A, P1 ; P1口值送累加器ACPL A ; A值取反ANL A, #0FH ; 保存P1口的低4位MOV 20H, A ; A值送20H保存CLR RS1 ; 改变寄存器组号CLR RS0 ;POP PSW ; 恢复现场RET;显示子程序********************************************************DIR: PUSH PSW ; 恢复现场SETB RS1 ; 改变寄存器组号CLR RS0MOV R0, #79H ; 建立显示缓冲区首地址MOV R3, #0FBH ; 设置位控码LD0: MOV P2, R3 ; 送位控码MOV A, @R0 ; 缓冲区值送累加器A DISP1: ADD A, #1BHMOVC A, @A+PC ; 取段控码并送A中DISP2: MOV P0, A ; 送段控码MOV R2, #09H ; 设置延时循环次数ACALL DEY ; 延时点亮INC R0 ; 缓冲区地址加1MOV A, R3 ; 位控码送AJNB ACC.1, HERE ; 是否到最高位,是转到返回JB ACC.5, LD2RL ARL A ; 不到向显示器高位移位LD2:RL AMOV R3, A ; 位控值保存到R4中AJMP LD0 ; 继续扫描HERE: CLR RS0 ; 改变寄存器组号CLR RS1POP PSW ; 恢复现场RET ; 返回DBB: DB 0C0HDB 0F9HDB 0A4HDB 0B0HDB 99HDB 92HDB 82HDB 0F8HDB 80HDB 90HDB 0CHDB 0FFH;整点报时**********************************************************BEEP_BL: MOV R6,#100BL1:CALL BL2CPL BEEPDJNZ R6,BL1MOV R5,#25CALL DEYRET ;返回计时BL2:MOV R7,#180BL3:NOPDJNZ R7,BL3RET;延时子程序********************************************************DEY: PUSH 12HDEY0: PUSH 12HDEY1: PUSH 12HDEY2: DJNZ R2, DEY2POP 12HDJNZ R2, DEY1 POP 12HDJNZ R2, DEY0 POP 12HDJNZ R2, DEY RETEND。
基于51单片机汇编语言的数字钟课程设计报告(含有闹钟万年历)
单片微型计算机课程设计报告多功能电子数字钟姓 名 许伟敏学 号 060301021124班 级 电气二班指导教师 林卫2009-06-25目录一:概述 (1)二:设计基本原理简介 (2)三:设计要求及说明 (3)四:整体设计方案 (4)系统硬件电路设计 4系统软件总流程设计 5模块划分及分析 6五:单模块流程设计 (8)各模块设计概述、流程图 8模块源程序集合及注释 13六:单模块软件测试 (23)七:系统检测调试 (24)硬件电路调试软件部分烧写调试八:系统优化及拓展 (26)九:心得体会 (28)单片微型计算机课程设计 基于汇编语言的电子数字钟 概述课程设计流程图↑一、概述课程设计题目:电子数字钟应用知识简介:● 51单片机单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。
作为嵌入式系统控制核心的单片机具有其体积小、功能全、性价比高等诸多优点。
51系列单片机是国内目前应用最广泛的单片机之一,随着嵌入式系统、片上系统等概念的提出和普遍接受及应用,51系列单片机的发展又进入了一个新的阶段。
在今后很长一段时间内51系列单片机仍将占据嵌入式系统产品的中低端市场。
● 汇编语言汇编语言是一种面向机器的计算机低级编程语言,通常是为特定的计算机或系列计算机专门设计的。
汇编语言保持了机器语言的优点,具有直接和简捷的特点,其代码具有效率高实时性强等优点。
但是对于复杂的运算或大型程序,用汇编语言编写将非常耗时。
汇编语言可以与高级语言配合使用,应用十分广泛。
● ISPISP (In-System Programming )在系统可编程,是当今流行的单片机编程模式,指电路板上的空白元器件可以编程写入最终用户代码,而不需要从电路板上取下元器件。
已经编程的器件也可以用ISP 方式擦除或再编程。
本次课程设计便使用ISP 方式,直接将编写好的程序下载到连接好的单片机中进行调试。
单片机数字时钟(汇编语言)
单片机课程设计目录前言 (3)一、系统方案选择与论证 (4)1.1数字电子钟设计的要求及技术指标 (4)1.2设计方案论证 (5)1.3元器件清单 (5)1.4电路说明 (6)二、安装与调试 (9)2.1准备元件和工具 (9)2.2 安装元件 (9)2.3测试与调试 (10)三、主程序设计 (14)3.1主程序设计 (14)四、总结 (21)前言20世纪末,电子技术获得了飞速的发展,在其推动下,现代电子产品几乎渗透了社会的各个领域,有力地推动了社会生产力的发展和社会信息化程度的提高,同时也使现代电子产品性能进一步提高,产品更新换代的节奏也越来越快。
时间对人们来说总是那么宝贵,工作的忙碌性和繁杂性容易使人忘记当前的时间。
忘记了要做的事情,当事情不是很重要的时候,这种遗忘无伤大雅。
但是,一旦重要事情,一时的耽误可能酿成大祸。
例如,许多火灾都是由于人们一时忘记了关闭煤气或是忘记充电时间。
尤其在医院,每次护士都会给病人作皮试,测试病人是否对药物过敏。
注射后,一般等待5分钟,一旦超时,所作的皮试试验就会无效。
手表当然是一个好的选择,但是,随着接受皮试的人数增加,到底是哪个人的皮试到时间却难以判断。
所以,要制作一个定时系统。
随时提醒这些容易忘记时间的人。
钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能。
诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、定时启闭电路、定时开关烘箱、通断动力设备,甚至各种定时电气的自动启用等,所有这些,都是以钟表数字化为基础的。
因此,研究数字钟及扩大其应用,有着非常现实的意义。
数字集成电路的出现和飞速发展,以及石英晶体振荡器的广泛应用,使得数字钟的精度稳定度远远超过了老式的机械表,用数字电路实现对“时”、“分”、“秒”数字显示的数字钟在数字显示方面,目前已有集成的计数、译码电路,它可以直接驱动数码显示器件,也可以直接采用才COMS--LED光电组合器件,构成模块式石英晶体数字钟。
单片机汇编程序51电子时钟.doc
单片机汇编程序 51电子时钟电子钟设计实验报告一)实验目的:1、进一步掌握定时器的使用和编程方法。
2、进一步掌握中断处理程序的编程方法。
3、进一步掌握数码显示电路的驱动方法。
4、进一步掌握键盘电路的驱动方法。
5、进一步掌握软件数据处理的方法。
二)内容要求:1、利用CPU的定时器和数码显示电路,设计一个电子时钟。
格式如下:XX XX XX 由左向右分别为:时、分、秒。
2、电子时钟有秒表功能。
3、并能用键盘调整时钟时间。
4、电子时钟能整点报时、整点对时功能。
5、能设定电子时钟的闹铃。
三)主要元件:电阻4.7K 10个 2K 1个四位共阳数码管1个二位共阳数码管1个按钮开关4个万用板(中板)1个 9012PNP 7个排线排阵若干电线一捆蜂鸣器1个最小系统一个四)系统说明:按P1.0键,如果按下的时间小于1秒进入省电模式(数码管不显示,开T0计时器),如果按下的时间大于1秒则进入时间调整.。
在时间调整状态:再按P1.0,如果按下时间大于0.5秒转调小时状态,按下时间小于0.5秒加1分钟操作。
在小时调整状态再按P1.0键,如果按下时间大于0.5秒退出时间调整,如果按下时间小于0.5秒加1小时操作。
按P1.1键,进入闹铃调分状态,按P1.2分加1,按P1.0分减1。
若再按P1.3,则进入调整状态,按P1.2时加1,按P1.0分时。
按P1.1键,闹铃有效,显示式样变为00:00:—0;再按P1.1键,闹铃无效,显示式样变为00:00:—。
按P1.3键,调整闹钟时间结束。
按P1.2键,进入秒表计时功能,按P1.2键暂停或清零,按P1.1键退出秒表回到时钟状态。
而且本系统还有整点报时功能,以及按键伴有声音提示。
五)程序流程图:开始 TO中断初始化保护现场进入功能调用显示定时初值校正程序子程序N Y键按下, 1S到,Y N加1S处理整点到NY恢复现场,中断返回按时间鸣叫次数主程序流程图 T0中断计时程序流程图T1中断保护现场T1中断服务程序流程图秒表/闪烁,时钟调时闪烁加10MS处理闪烁处理恢复现场,中断返回六)电路图七)程序清单:中断入口程序 ;; DISPFIRST EQU 30H BELL EQU P1.4CONBS EQU 2FHOUTPX EQU P2 ;P2位选OUTPY EQU P0 ;P0段选INP0 BIT P1.0INP1 BIT P1.1INP2 BIT P1.2ORG 0000H ;程序执行开始地址LJMP START ;跳到标号START执行ORG 0003H ;外中断0中断程序入口RETI ;外中断0中断返回ORG 000BH ;定时器T0中断程序入口LJMP INTT0 ;跳至INTTO执行ORG 0013H ;外中断1中断程序入口RETI ;外中断1中断返回ORG 001BH ;定时器T1中断程序入口LJMP INTT1 ;跳至INTT1执行ORG 0023H ;串行中断程序入口地址RETI ;串行中断程序返回;QQQQ:MOV A,#10HMOV B,79HMUL ABADD A,78HMOV CONBS,ABSLOOP:LCALL DS20MSLCALL DL1SLCALL DL1SLCALL DL1SDJNZ CONBS,BSLOOPCLR 08HAJMP START;; 主程序 ;;START:MOV R0,#00H ;清70H-7AH共11个内存单元MOV R7,#80H ;CLEARDISP: MOV @R0,#00H ;INC R0 ;DJNZ R7,CLEARDISP ;MOV 20H,#00H ;清20H(标志用)MOV 7AH,#0AH ;放入"熄灭符"数据MOV TMOD,#11H ;设T0、T1为16位定时器MOV TL0,#0B0H ;50MS定时初值(T0计时用) MOV TH0,#3CH ;50MS定时初值MOV TL1,#0B0H ;50MS定时初值(T1闪烁定时用) MOV TH1,#3CH ;50MS定时初值SETB EA ;总中断开放SETB ET0 ;允许T0中断SETB TR0 ;开启T0定时器MOV R4,#14H ;1秒定时用初值(50MS×20)MOV DISPFIRST ,#70HSTART1: LCALL DISPLAY ;调用显示子程序JNB INP0,SETMM1 ;P1.0口为0时转时间调整程序JNB INP1,FUNSS ; 秒表功能,P1.1按键调时时作减1加能JNB INP2,FUNPT ;STOP,PUSE,CLRJNB P1.3,TSFUNSJMP START1 ;P1.0口为1时跳回START1SETMM1: LJMP SETMM ;转到时间调整程序SETMM FUNSS: LCALL DS20MSJB INP1,START1WAIT11: JNB INP1,WAIT11CPL 03HMOV DISPFIRST,#00H :显示秒表数据单元MOV 70H,#00HMOV 71H,#00HMOV 76H,#00HMOV 77H,#00HMOV 78H,#00HMOV 79H,#00HAJMP START1FUNPT: LCALL DS20MSJB INP2,START1WAIT22: JNB INP2,WAIT21CLR ET0CLR TR0WAIT33: JB INP2,WAIT31 LCALL DS20MSJB INP2,WAIT33WAIT66: JNB INP2,WAIT61 MOV R0,#70H ;清70H-79H共10 个内存单元MOV R7,#0AH ;CLEARP: MOV @R0,#00H ;INC R0 ;DJNZ R7,CLEARP ;WAIT44: JB INP2,WAIT41 LCALL DS20MSJB INP2,WAIT44WAIT55: JNB INP2,WAIT51 SETB ET0SETB TR0AJMP START1WAIT21: LCALL DISPLAY AJMP WAIT22WAIT31: LCALL DISPLAY AJMP WAIT33WAIT41: LCALL DISPLAYAJMP WAIT44WAIT51: LCALL DISPLAYAJMP WAIT55WAIT61: LCALL DISPLAYAJMP WAIT66 TSFUN:LCALL DS20MSWAIT113:JNB P1.3,WAIT113JB 05H,CLOSESPMOV DISPFIRST,#50HMOV 50H,#0CHMOV 51H,#0AHDSWAIT:SETB EALCALL DISPLAYJNB P1.2,DSFINCJNB P1.0,DSDECJNB P1.3,DSSFU AJMP DSWAITCLOSESP:CLR 05HCLR BELLAJMP START1 DSSFU:LCALL DS20MS JB P1.3,DSWAIT LJMP DSSFUNN DSFINC:LCALL DS20MS JB P1.2,DSWAIT DSWAIT12:LCALL DISPLAY JNB P1.2,DSWAIT12 CLR EAMOV R0,#53H LCALL ADD1MOV A,R3CLR CCJNE A,#60H,ADDHH22ADDHH22:JC DSWAITACALL CLR0AJMP DSWAITDSDEC:LCALL DS20MSLCALL DISPLAYDSWAITEE:LCALL DISPLAYJNB P1.0,DSWAITEECLR EAMOV R0,#53HLCALL SUB1LJMP DSWAIT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1秒计时程序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;T0中断服务程序INTT0: PUSH ACC ;累加器入栈保护PUSH PSW ;状态字入栈保护CLR ET0 ;关T0中断允许CLR TR0 ;关闭定时器T0JB 03H,FSSMOV A,#0B7H ;中断响应时间同步修正ADD A,TL0 ;低8位初值修正MOV TL0,A ;重装初值(低8位修正值)MOV A,#3CH ;高8位初值修正ADDC A,TH0 ;MOV TH0,A ;重装初值(高8位修正值)SETB TR0 ;开启定时器T0DJNZ R4, OUTT0 ;20次中断未到中断退出ADDSS: MOV R4,#14H ;20次中断到(1秒)重赋初值MOV R0,#71H ;指向秒计时单元(71H-72H)ACALL ADD1 ;调用加1程序(加1秒操作)MOV A,R3 ;秒数据放入A(R3为2位十进制数组合)CLR C ;清进位标志CJNE A,#60H,ADDMM ;ADDMM: JC OUTT0 ;小于60秒时中断退出ACALL CLR0 ;大于或等于60秒时对秒计时单元清0 MOV R0,#77H ;指向分计时单元(76H-77H)ACALL ADD1 ;分计时单元加1分钟MOV A,R3 ;分数据放入ACLR C ;清进位标志CJNE A,#60H,ADDHH ;ADDHH: JC OUTT0 ;小于60分时中断退出ACALL CLR0 ;大于或等于60分时分计时单元清0MOV R0,#79H ;指向小时计时单元(78H-79H)ACALL ADD1 ;小时计时单元加1小时MOV A,R3 ;时数据放入ACLR C ;清进位标志JB 03H,OUTT0 ;秒表时最大数为99CJNE A,#24H,HOUR ;HOUR: JC OUTT0 ;小于24小时中断退出ACALL CLR0 ;大于或等于24小时小时计时单元清0OUTT0: MOV 72H,76H ;中断退出时将分、时计时单元数据移MOV 73H,77H ;入对应显示单元MOV 74H,78H ;MOV 75H,79H ;LCALL BAOJPOP PSW ;恢复状态字(出栈)POP ACC ;恢复累加器SETB ET0 ;开放T0中断RETI ;中断返回 ;秒表计时程序(10MS加1),低2位为0.1、0.01秒,中间2位为秒,最高位为分。
单片机汇编数字时钟
1.前言1.1设计意义近年来随着计算机在社会领域的渗透和大规模集成电路的发展,单片机的应用正在不断地走向深入,由于它具有功能强,体积小,功耗低,价格便宜,工作可靠,使用方便等特点,因此特别适合于与控制有关的系统,越来越广泛地应用于自动控制,智能化仪器,仪表,数据采集,军工产品以及家用电器等各个领域,单片机往往是作为一个核心部件来使用,在根据具体硬件结构,以及针对具体应用对象特点的软件结合,以作完善。
本系统是基于AT89C51单片机设计的一个具有六位LED 显示的数字时实时钟,该系统同时具有硬件设计简单、工作稳定性高、价格低廉等优点。
此次设计电子数字钟是为了了解电子数字钟的原理,从而学会制作电子数字钟。
而且通过电子数字钟的制作进一步的了解各种在制作中用到的中小规模集成电路的作用及实用方法。
通过它可以进一步学习与掌握单片机原理与使用方法。
1.2系统功能数字钟是一个将时分秒在数码管上显示的计时装置,计时方式为24h ,另外还有启动、暂停功能。
1.3使用方法程序运行后始终显示初始值00:00:00。
当按下开始键后开始计时,再按下暂停键后时钟暂停工作,数码管显示暂停时刻的计数数值。
2.硬件电路设计及描述2.1总体设计此次实习的的电子钟由单片机AT89C51、74LS373、8D 锁存器、8255芯片、7407缓冲器、73LS138译码器、数码管组成。
运用汇编语言来控制单片机AT89C51来实现动态数码管显示。
(见下图2-1)图2-1 电路总体设计2.2 硬件电路运行原理单片机烧入HEX 文件后开始工作,通过单片机P0口与8255数据总线相连与8255传送数据,设定8255PB 口送段选码,PC 口送位选码,PC 口接3-8译码器,不停的扫描8单片机 AT89C51 74LS373 锁存地址8255A PB 口 接口控制 PC 口7407段选 74LS138位选七段 数码 管个数码管实现数码管动态扫描功能,P1.0、P1.1接2个独立键盘实现P1.0启动时钟P1.1暂停时钟的功能。
单片机万年历汇编闹钟时间可调程序(LCD1602,DS18B20,DS1302,MAX810L)
片机万年历汇编闹钟时间可调程序(LCD1602,DS18B20,DS1302,MAX810L)说明:0该程序全部是用汇编语言编写1.该程序附带有温度显示,并且带有闹铃功能2.正常时间和闹钟时间都可以用键盘设置3.该程序是使用LCD1602显示年月日,格式为TIME XX-XX-XX XX,由于屏幕的关系,所以就不显示周的数据,其中闹铃调整的上界面是“BELLADJUST”4.该程序的时间是由时钟芯片DS1302提供的,据说很精准,目前看起来确实是这样的,刚开始我是使用定时器计时的,但是不怎么精准,可能是我的汇编技术有限才导致,所以本人就把这个版本呈上,希望诸位多多斧正5.该程序的温度是通过DS18B20提取的,这个模块是我从别人那里COPY过来的,O(∩_∩)O~,显示是肯定没问题的6.该程序也有用MAX810l的复位功能,但是好像这一点还没被体现出来7.烧程序我使用的是MAX232外加几个极性电容,还有一个RS232,不幸的是我的PCB板的RS232的封装画错啦!!~~~~(>_<)~~~~8.该万年历是由五个按键控制的,SW5复位,SW1调时间,调年月日时分秒,除秒可以加减调节之外其余的调节都是只能加不能减(自我觉得如果增加减的功能会觉得程序复杂,所以免!), SW4 是用来调节闹钟的时分秒的,和SW1按键不同的是时分秒都能加减,当闹钟设置的时间和正常显示时间的时分秒相同时,闹铃十秒钟,期间你可以按SW4键终止响铃,SW2 和SW3 分别是用来加减时间的!9.说了这么多,最后说说自我认为的缺陷,行家应该都一眼就看出一些破绽了,那就是按键消抖的问题,这个我觉得有点麻烦所以本人就把这个问题留给阅览资料的你吧!10.废话说了这么多,最后把我的程序,ORCAD电路原理图,PADS软件的PCB图,以及一张实物图献上,希望你能喜欢,页脚有我的Email(prettyboy2009@),欢迎随时交流!程序:;*************************************************************** ;***************************************************************RS BIT P2.5RW BIT P2.6E BIT P2.7SU BIT P1.6 ;1302串行口数据端RST BIT P1.5CLK BIT P1.7ALARM BIT P2.3JIAN BIT P2.2 ;减JIA BIT P2.1 ;加MOSHI BIT P2.0 ;模式DQ BIT P1.0SOUND BIT P1.3NIAN EQU 7FHYUE EQU 7DHDAY EQU 7CHHHH EQU 7EHSHI EQU 7BHFEN EQU 7AHMIAO EQU 79HASHI EQU 78HAFEN EQU 77HAMIAO EQU 76HGEW EQU 75HA_BIT EQU 70H ;18B20B_BIT EQU 6FHFLAG EQU 6EHDS1302_ADDR EQU 6DHDS1302_DATA EQU 6CHORG 0000HLJMP STARTORG 0030H ;***************************************************************; 初始化开机时间 &&&&&&& 初始化闹铃时间;***************************************************************START:MOV DPTR,#TABMOV SHI,#16HMOV ASHI,#17MOV FEN,#58HMOV AFEN,#30MOV MIAO,#00HMOV AMIAO,#00MOV NIAN,#11HMOV YUE,#12HMOV DAY,#13HMOV HHH,#00H;***************************************************************; 初始化LCD1602 &&&&&&& 初始化DS1302 ;***************************************************************MOV P0,#01H ; 显示清屏数据指针清零所有显示清零LCALL WR_CODEMOV P0,#02H ; 显示回车数据指针清零LCALL WR_CODEMOV P0,#38H ;设置16*2显示 5*7 点阵 8位数据接口LCALL WR_CODEMOV P0,#06H ; 当写或写一个数据时地址指针自动加一光标自动加一LCALL WR_CODEMOV P0,#0cH ; 开显示不显光标 0fh开显示开光标光标闪烁LCALL WR_CODELCALL XIAN1;***************************************************************; 主函数(这个大家都懂的);*************************************************************** MAIN:lcall RD_DS1302LCALL XIANSHIlcall keyLCALL AKEYLCALL RE_TEMPLCALL CONVERLCALL DISPLAY_INTLJMP BELLRING;***************************************************************; 读1302子程序;***************************************************************RD_DS1302:MOV DS1302_ADDR,#8DH ;读DS1302中的年LCALL READ ;调用读DS1302子程序MOV NIAN, DS1302_DATA ;把读出的年数据存入年寄存器中MOV DS1302_ADDR,#89H ;读DS1302中的月LCALL READMOV YUE, DS1302_DATA ;把读出的月数据存入月寄存器中MOV DS1302_ADDR,#87H ;读DS1302中的天LCALL READMOV DAY, DS1302_DATA ;把读出的天数据存入天寄存器中MOV DS1302_ADDR,#85H ;读DS1302中的小时LCALL READMOV SHI, DS1302_DATA ;把读出的天数据存入小时寄存器中MOV FEN, DS1302_DATA ;把读出的天数据存入分钟寄存器中MOV DS1302_ADDR,#81H ;读DS1302中的秒钟LCALL READMOV MIAO, DS1302_DATA ;把读出的天数据存入秒钟寄存器中RET ;***************************************************************; 写1302子程序;***************************************************************WR_DS1302:MOV DS1302_ADDR, #8EH ;写DS1302控制指令MOV DS1302_DATA, #00H ;写数据到DS1302的8E控制寄存器中,允许对其进行写操作LCALL WRITE ;调用写DS1302子程序MOV DS1302_ADDR,#8CH ;写DS1302中的年MOV DS1302_DATA , NIAN ;把写出的年数据存入年寄存器中LCALL WRITEMOV DS1302_ADDR,#88H ;写DS1302中的月MOV DS1302_DATA ,YUE ;把写出的月数据存入月寄存器中LCALL WRITEMOV DS1302_ADDR,#86H ;写DS1302中的天MOV DS1302_DATA ,DAY ;把写出的天数据存入天寄存器中LCALL WRITEMOV DS1302_ADDR,#84H ;写DS1302中的小时MOV DS1302_DATA , SHI ;把写出的天数据存入小时寄存器中LCALL WRITEMOV DS1302_ADDR,#82H ;写DS1302中的分钟MOV DS1302_DATA , FEN ;把写出的天数据存入分钟寄存器中LCALL WRITEMOV DS1302_ADDR,#80H ;写DS1302中的秒钟MOV DS1302_DATA , MIAO ;把写出的天数据存入秒钟寄存器中LCALL WRITEMOV DS1302_ADDR, #90H ;写DS1302控制指令MOV DS1302_DATA,#0A6H ;写数据到DS1302的90控制寄存器中,对电池涓流充电,充电电流为1.1mARET;***************************************************************; 写1302程序;***************************************************************WRITE:CLR CLKNOPSETB RSTNOPMOV A,DS1302_ADDRMOV R4,#8 WRITE1:RRC A ;送地址给1302NOPNOPCLR CLKNOPNOPNOPMOV SU,CSETB CLK ;送入地址在时钟上升沿有效NOPNOPNOPNOPDJNZ R4,WRITE1CLR CLKNOPMOV A,DS1302_DATAMOV R4,#8 WRITE2:RRC ANOP ;送数据给1302,时钟上升沿,数据输入CLR CLKNOPNOPMOV SU,CNOPNOPNOPSETB CLKDJNZ R4,WRITE2CLR RSTCLR ARET ;***************************************************************; 读1302程序;***************************************************************READ:CLR CLKNOPNOPSETB RSTNOPMOV A,DS1302_ADDRMOV R4,#8 READ1:RRC ANOPMOV SU,CNOPNOPNOPSETB CLK ;送入地址在时钟上升沿有效NOPNOPNOPCLR CLKNOPNOPDJNZ R4,READ1 ;判断8位数据是否传送完?MOV R4,#8 READ2:CLR CLKNOPNOPNOPMOV C,SUNOPNOPNOPNOPNOP ;从ds1302中读取数据,时钟下降沿有效NOPNOPNOPSETB CLKNOPDJNZ R4,READ2 ;判断8位数据是否传送完?MOV DS1302_DATA,ACLR RSTRET;***************************************************************; 固定显示显示TIME ,'-',:;***************************************************************XIAN1:MOV P0,#84HLCALL WR_CODEMOV A,#'-' ;1602有字库可以直接调用不用查表LCALL WR_DATAMOV P0,#87HLCALL WR_CODEMOV A,#'-'LCALL WR_DATAMOV P0,#80HLCALL WR_CODEMOV A,#'2' ;计时100年所以20XX 20是固定的LCALL WR_DATAMOV P0,#81HLCALL WR_CODEMOV A,#'0'LCALL WR_DATAMOV P0,#0C1HLCALL WR_CODEMOV A,#'T'LCALL WR_DATAMOV P0,#0C2HLCALL WR_CODEMOV A,#'I'LCALL WR_DATAMOV P0,#0C3HLCALL WR_CODEMOV A,#'M'LCALL WR_DATAMOV P0,#0C4HLCALL WR_DATAMOV P0,#0CCHLCALL WR_CODEMOV A,#':'LCALL WR_DATAMOV P0,#0C9HLCALL WR_CODEMOV A,#':'LCALL WR_DATAMOV P0,#08EHLCALL WR_CODEMOV A,#0DFHLCALL WR_DATAMOV P0,#08FHLCALL WR_CODEMOV A,#'C'LCALL WR_DATARET;*************************************************************** ; 显示数据时分秒年月日周地址数据都在变化没用循环体;***************************************************************XIANSHI:MOV HHH,MIAOLCALL HEXMOV P0,#0CDHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#0CEHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV HHH,FENLCALL HEXMOV P0,#0CAHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATALCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATAMOV HHH,SHI LCALL HEXMOV P0,#0C7H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATA MOV A,BMOV P0,#0C8H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATAMOV HHH,DAY LCALL HEXMOV P0,#088H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATA MOV A,BMOV P0,#089H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATAMOV HHH,YUE LCALL HEXMOV P0,#085H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATA MOV A,BMOV P0,#086H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATAMOV HHH,NIAN LCALL HEXMOV P0,#082HMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#083HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATARET;***************************************************************; 判键子程按一次模式键后就一直判断下一次按键是P2.1还是P2.2;判断进入下一模式还是加1(按下模式键第一次加1需要按两次);MO1加分 MO2加时 MO3加月 MO4加日 MO5加年,除秒可以加减调节外,;时间只能通过加分时日月年调节;***************************************************************KEY:JNB MOSHI,MORET MO:JNB MOSHI,$MOV P0,#0DH ; 开显示不显光标 0fh开显示开光标光标闪烁LCALL WR_CODE MO1:MOV P0,#0CBHLCALL WR_CODEJNB JIA,JIAFFJNB JIAN,JIANFFJNB MOSHI,MO11LJMP MO1 MO11:JNB MOSHI,$;MO2:MOV P0,#0C8HLCALL WR_CODEJNB JIA,JIASSJNB MOSHI,MO21LJMP MO2 MO21:JNB MOSHI,$; ;MO4:MOV P0,#089HLCALL WR_CODELJMP MO4 MO41:JNB MOSHI,$MO3:MOV P0,#086HLCALL WR_CODEJNB JIA,JIAMMJNB MOSHI,MO31LJMP MO3 MO31:JNB moshi,$;MO5:MOV P0,#083HLCALL WR_CODEJNB JIA,JIAYYJNB MOSHI,MO51LJMP MO5 MO51:JNB MOSHI,$MOV P0,#0CH ; 开显示不显光标 0fh开显示开光标光标闪烁LCALL WR_CODElcall XIAN1RET;***************************************************************; 跳转出范围中转;***************************************************************JIAFF:LJMP JIAFJIANFF:LJMP JIANFJIADD:LJMP JIADJIAMM:LJMP JIAMJIAYY:LJMP JIAYJIASS:LJMP JIAS;***************************************************************;判断加1 以及跳转到另一模式(模式是指加分还是加时加月等);***************************************************************JIAF:MOV P0,#0CBHLCALL WR_CODEJNB JIAN,JIANFJB JIA,JIAF2JNB JIA,$mov A,FENADD A , #01HDA Amov FEN,ACJNE A , #60H ,JIAF3MOV FEN ,#00H JIAF3:LCALL WR_DS1302LCALL XIANSHILJMP JIAF JIAF1:JNB MOSHI,$LJMP MO11JIANF:MOV P0,#0CBHLCALL WR_CODEJNB MOSHI,JIANF1JNB JIA,JIAFJB JIAN,JIANFJNB JIAN,$MOV A,FENCJNE A,#00,JIANF2MOV FEN,#59HLJMP JIANF3 JIANF2:CLR CSUBB A,#01DA AMOV FEN,A JIANF3:LCALL WR_DS1302LCALL XIANSHILJMP JIANF JIANF1:JNB MOSHI,$LJMP MO11JIAS:MOV P0,#0C8HJIAS2:JNB MOSHI,JIAS1JB JIA,JIAS2JNB JIA,$MOV A,SHIADD A,#01HDA AMOV SHI,ACJNE A,#24H,JIAS3MOV SHI,#00 JIAS3:LCALL WR_DS1302LCALL XIANSHILJMP JIAS JIAS1:JNB MOSHI,$LJMP MO21JIAD:MOV P0,#089HLCALL WR_CODEJIAD2:JNB MOSHI,JIAD1JB JIA,JIAD2JNB JIA,$MOV A,DAYADD A,#01HDA AMOV DAY,AMOV A,YUECJNE A,#01H,SS1LJMP JIAD4 SS1:CJNE A,#03H,SS2 LJMP JIAD4 SS2:CJNE A,#05H,SS3LJMP JIAD4 SS3:CJNE A,#07H,SS4LJMP JIAD4 SS4:SS5:CJNE A,#10H,SS6LJMP JIAD4 SS6:CJNE A,#12H,SSS JIAD4:MOV A,DAYCJNE A,#32H,JIAD3MOV DAY,#01H JIAD3:LCALL WR_DS1302LCALL XIANSHILJMP JIAD JIAD1:JNB MOSHI,$LJMP MO41 SSS:CJNE A,#02H,S30MOV A,NIANANL A,#0FHMOV GEW,AMOV A,NIANANL A,#0F0HSWAP AMOV B,#10MUL ABADD A,GEWMOV B,#04HDIV ABMOV A,BCJNE A,#00H,S29LJMP S28 S30:MOV A,DAYCJNE A,#31H,JIAD3MOV DAY,#01HLJMP JIAD3 S29:MOV A,DAYCJNE A,#29H,JIAD3MOV DAY,#01HLJMP JIAD3 S28:MOV DAY,#01HLJMP JIAD3;***************************************************************;;判断月的天数判断闰年的方法先将年的数据有十六进制BCD码转换成正常的十六进制;再除以4 判断余数是否为0 为零则为闰年不为零不是;***************************************************************JIAM:MOV P0,#086HLCALL WR_CODE JIAM2:JNB MOSHI,JIAM1JB JIA,JIAM2JNB JIA,$MOV A,YUEADD A,#01HDA AMOV YUE,ACJNE A,#13H,JIAM3MOV YUE,#01 JIAM3:LCALL WR_DS1302LCALL XIANSHI JIAM1:JNB MOSHI,$LJMP MO31 JIAY:MOV P0,#083HLCALL WR_CODE JIAY2:JNB MOSHI,JIAY1JB JIA,JIAY2JNB JIA,$MOV A,NIANADD A,#01HDA AMOV NIAN,ACJNE A,#99H,JIAY3MOV NIAN,#00 JIAY3:LCALL WR_DS1302LCALL XIANSHILJMP JIAY;***************************************************************;温度读取;***************************************************************RE_TEMP:SETB DQACALL INIT_18B20JB FLAG, STRET ST:MOV A, #0CCHACALL WRITE_18B20MOV A, #44HACALL WRITE_18B20ACALL INIT_18B20MOV A, #0CCHACALL WRITE_18B20MOV A, #0BEHACALL WRITE_18B20ACALL READ_18B20RET;***************************************************************;初始化DS18B20;***************************************************************INIT_18B20:SETB DQNOPCLR DQMOV R1, #3 DLY:MOV R0, #107DJNZ R0, $DJNZ R1, DLYSETB DQNOPNOPNOPMOV R0, #25H T2:JNB DQ, T3DJNZ R0, T2JMP T4 T3:SETB FLAGJMP T5JMP T7 T5:MOV R0, #117 T6:DJNZ R0, T6 T7:SETB DQRET ;***************************************************************;写DS18B20;***************************************************************WRITE_18B20:MOV R2, #8CLR C WR1:CLR DQMOV R3, #6DJNZ R3, $RRC AMOV DQ, CMOV R3, #23DJNZ R3, $SETB DQNOPDJNZ R2, WR1SETB DQRET;***************************************************************;读DS18B20;***************************************************************READ_18B20:MOV R4, #2MOV R1, #21H RE0:MOV R2, #8 RE1:CLR CSETB DQNOPNOPCLR DQNOPNOPMOV R3, #9 RE2:DJNZ R3, RE2MOV C, DQMOV R3, #23 RE3:DJNZ R3, RE3RRC ADJNZ R2, RE1MOV @R1, ADEC R1DJNZ R4, RE0RET;***************************************************************;温度转换;***************************************************************CONVER:MOV A, 21HMOV C, 20H.0RRC AMOV C, 20H.1RRC AMOV C, 20H.2RRC AMOV C, 20H.3RRC AMOV 21H, ARET;***************************************************************;显示温度整数部分;***************************************************************DISPLAY_INT:MOV A, 21HMOV B, #10DIV ABMOV B_BIT, AMOV A_BIT, BMOV DPTR, #TABMOV P0,#08cHLCALL WR_CODELCALL WR_DATAMOV P0,#08DHLCALL WR_CODEMOV A, A_BITMOVC A, @A+DPTRLCALL WR_DATARET;***************************************************************; 1602的写数据读指令判忙程序;***************************************************************WR_DATA:MOV P0,ASETB RS ;RS=1选择数据寄存器CLR RW ;RW=0 ;准备CLR E ;E=0 ;执行显示命令LCALL BUSY ;判断液晶模块是否忙?SETB E ;E=1 ;显示完成,程序停车RET WR_CODE:CLR RS ;写入控制命令的子程序CLR RWCLR ELCALL BUSYSETB ERET BUSY:MOV P0,#0FFH ;判断液晶显示器是否忙的子程序CLR RSSETB RWCLR ENOP ;nop一定要有SETB EJB P0.7,BUSY ;如果P0.7为高电平表示忙就循环等待RET ;***************************************************************; 判键子程按一次模式键后就一直判断下一次按键是P3.4还是P3.5 判断进入下一模式还是加1(按下模式键第一次加1需要按两次);MO1加分 MO2加时 MO3加月 MO4加日 MO5加年AKEY:JNB ALARM, XIANGUANGRET XIANGUANG:JNB ALARM,$MOV P0,#01H ; 显示清屏数据指针清零所有显示清零LCALL WR_CODEMOV P0,#02H ; 显示回车数据指针清零LCALL WR_CODEMOV P0,#038H ;设置16*2显示 5*7 点阵 8位数据接口LCALL WR_CODEMOV P0,#04H ; 当读或写一个数据时地址指针自动加一光标自动加一LCALL WR_CODEMOV P0,#0DH ; 开显示不显光标 0fh开显示开光标光标闪烁LCALL WR_CODELCALL AXIANLCALL AXIANSHIMOMIAO: MOV P0,#0CBHLCALL WR_CODEJNB JIA,INCMJNB JIAN,DECMJNB ALARM ,BACKMIAOLJMP MOMIAO BACKMIAO:JNB ALARM,$LJMP MOFENINCM:MOV P0,#0CBHLCALL WR_CODE INCM2:JNB ALARM,INCM1JNB JIAN,DECMJB JIA,INCM2JNB JIA,$INC AMIAOMOV A,AMIAOCJNE A,#60,INCM3MOV AMIAO,#00 INCM3:LCALL AXIANSHILJMP INCMINCM1:JNB ALARM ,BACKMIAODECM:MOV P0,#0CBHLCALL WR_CODEJNB ALARM,DECM1JNB JIA,INCMJB JIAN,DECMJNB JIAN,$MOV A,AMIAOCJNE A,#00,DECM2MOV AMIAO,#59LJMP DECM3 DECM2:CLR CSUBB A,#01MOV AMIAO,A DECM3:LCALL AXIANSHILJMP DECM DECM1:JNB ALARM,BACKMIAOMOFEN:MOV P0,#0C8HLCALL WR_CODEJNB JIA,INCFJNB JIAN,DECFJNB ALARM ,BACKFENLJMP MOFEN BACKFEN:JNB ALARM,$LJMP AMOSHIINCF:MOV P0,#0C8HLCALL WR_CODEINCF2:JNB ALARM,INCF1JNB JIAN,DECFJB JIA,INCF2JNB JIA,$INC AFENMOV A,AFENCJNE A,#60,INCF3MOV AFEN,#00INCF3:LCALL AXIANSHILJMP INCFINCF1:JNB ALARM ,BACKFENDECF:MOV P0,#0C8HLCALL WR_CODEJNB ALARM,DECF1JNB JIA,INCFJB JIAN,DECFJNB JIAN,$MOV A,AFENCJNE A,#00,DECF2MOV AFEN,#59LJMP DECF3DECF2:CLR C;DEC ASUBB A,#01;DA AMOV AFEN,ADECF3:LCALL AXIANSHILJMP DECFDECF1:JNB ALARM,BACKFENAMOSHI:MOV P0,#0C5HLCALL WR_CODEJNB JIA,INCSJNB JIAN,DECSJNB ALARM ,BACKSHI LJMP AMOSHIINCS:MOV P0,#0C5HLCALL WR_CODEINCS2:JNB ALARM,INCS1JNB JIAN,DECSJB JIA,INCS2JNB JIA,$INC ASHIMOV A,ASHICJNE A,#24,INCS3MOV ASHI,#00INCS3:LCALL AXIANSHILJMP INCSINCS1:JNB ALARM ,BACKSHIBACKSHI:JNB ALARM,$MOV P0,#01HLCALL WR_CODEMOV P0,#0CHLCALL WR_CODELCALL XIAN1LJMP MAINDECS:MOV P0,#0C5HLCALL WR_CODEJNB ALARM,DECS1JNB JIA,INCSJB JIAN,DECSJNB JIAN,$MOV A,ASHICJNE A,#00,DECS2MOV ASHI,#23LJMP DECS3 DECS2:CLR CSUBB A,#01MOV ASHI,ADECS3:LCALL AXIANSHILJMP DECS DECS1:JNB ALARM,BACKSHI;***************************************************************; 闹钟部分固定显示显示TIME ADJUST;***************************************************************AXIAN:MOV P0,#82HLCALL WR_CODEMOV A,#'B'LCALL WR_DATAMOV P0,#83HLCALL WR_CODEMOV A,#'E'LCALL WR_DATAMOV P0,#84HLCALL WR_CODEMOV A,#'L' ;LCALL WR_DATAMOV P0,#85HLCALL WR_CODEMOV A,#'L'LCALL WR_DATAMOV P0,#088HLCALL WR_CODEMOV A,#'A'LCALL WR_DATAMOV P0,#089HLCALL WR_CODEMOV A,#'D'LCALL WR_DATAMOV P0,#08AHLCALL WR_CODEMOV A,#'J'LCALL WR_DATAMOV P0,#08BHLCALL WR_CODEMOV A,#'U'LCALL WR_DATAMOV P0,#08CHLCALL WR_CODEMOV A,#'S'LCALL WR_DATAMOV P0,#08DHLCALL WR_CODEMOV A,#'T'LCALL WR_DATAMOV P0,#0C6HLCALL WR_CODEMOV A,#':'LCALL WR_DATAMOV P0,#0C9HLCALL WR_CODEMOV A,#':'LCALL WR_DATARET;*************************************************************** ; 显示数据时分秒年月日周地址数据都在变化没用循环体;*************************************************************** AXIANSHI:MOV HHH,AMIAOLCALL AHEXMOV P0,#0CAHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#0CBHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV HHH,AFENLCALL AHEXMOV P0,#0C7HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#0C8HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV HHH,ASHILCALL AHEXMOV P0,#0C4HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#0C5HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATARET;***************************************************************; 分离十进制BCD码中的十位和个位;***************************************************************AHEX: MOV A,HHHMOV B,#10DIV ABRET;***************************************************************; 闹钟模块;***************************************************************;==========================条件符合响铃1分钟============================ BELLRING:MOV HHH,SHILCALL HEXMOV R2,BMOV B,#10MUL ABADD A,R2CJNE A ,ASHI, AAAMOV HHH,FENLCALL HEXMOV R2,BMOV B,#10MUL ABADD A,R2CJNE A ,AFEN,AAAMOV HHH,MIAOLCALL HEXMOV R2,BMOV B,#10MUL ABADD A,R2CJNE A ,AMIAO,AAALCALL BELLRAAA:LJMP MAIN;==========================闹钟响铃10秒钟============================BELLR:MOV COUNT,#10ZZZ:SETB SOUNDLCALL DELAY500MSCLR SOUNDLCALL DELAY500MSlcall RD_DS1302LCALL XIANSHIJNB ALARM ,BBBDJNZ COUNT ,ZZZBBB:JNB ALARM ,$SETB SOUNDRET;==========================设置闹铃延时500MS响一次=================== DELAY500MS:MOV R7,#17HDL1:MOV R6,#98HDL0:MOV R5,#46HDJNZ R5,$DJNZ R6,DL0DJNZ R7,DL1RET;*************************************************************** ; 转换成BCD码;*************************************************************** ZHUAN:MOV A,HHHADD A,#00HDA ARET;*************************************************************** ; 分离BCD码中的十位和个位;*************************************************************** HEX:MOV A,HHHMOV B,#16DIV ABRET;*************************************************************** ; 数据查表;*************************************************************** TAB: DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39HENDORCAD电路原理图PADS软件的PCB图实物图。
单片机电子闹钟的设计汇编语言
ORG 00HAJMP START ;程序开始ORG 0BH ;TimEr0中断向量地址AJMP TimEInt ;跳到中断处理程序ORG 0020HSTART: MOV sp,#70HSETB P3.0 ;输出高电平,闹钟服务程序驱动口SETB P3.5 ;输出高电平,闹钟服务程序驱动口MOV 39H,#40 ;1秒钟中断次数MOV 3AH,#00 ;开机时间MOV 3BH,#00MOV 3CH,#00 ;设置上电时时钟显示的初值MOV 2EH,#06 ;开机时闹钟默认时间MOV 2FH,#00 ;设置上电时闹时时间的初值CLR 20H.1 ;上点复位后闹时功能处于关闭状态CLR 20H.0 ;正常走时模式CLR 20H.2 ;闹钟时间还没有到SETB P3.0; 清闹时输出SETB P3.5; 清闹时输出;************************************; 定时器初始化,定时器0方式1,25ms;TH0=9EH TL0=58H;************************************MOV TMOD ,#01HMOV TH0,#9EHMOV TL0,#58HMOV IE,#82H ;开全局中断SETB TR0 ;开定时中断,启动定时器;*****************************************; 以下为主程序,按键扫描;*****************************************MainLoop:JB P3.2,CheckPP ;闹时设置键按下了吗?没有则转去检测秒设置键篇p3.2 LCALL Delay2JB P3.2,CheckPPSETB 20H.0 ;置为闹时设置模式CALL AlarmSetCheckPP:JB P3.4,CheckPQ ;分设置键按下了吗?没有则转去检测小时设置键CALL Delay2JB P3.4,CheckPQMOV A,3BHADD A,#1 ; 如果按下则将分钟加一MOV 3BH,A;CJNE A,#3CH,NotOver1 ;到60分钟了吗?MOV 3BH,#0NotOver1: ;以下等待按键释放及防抖动JNB P3.4,$CheckPQ:JB P3.3,CheckAlarm ;小时设置键按下了吗?没有则转去闹时状态检测CALL Delay2JB P3.3,CheckAlarm ;按下的时间超过15ms吗?如按下调用蜂鸣器发音程序MOV A,3AHADD A,#1 ;如果按下则将小时加1MOV 3AH,ACJNE A,#18H,NotOver2MOV 3AH,#0 ;到24小时则将小时清0NotOver2: ;以下等待按键释放及防抖动JNB P3.3,$CheckAlarm:JNB 20H.2,ToReturn ;闹钟时间到没有CALL AlarmProcess ;闹钟子程序ToReturn:AJMP MainLoop;**********************************************; 定时器TimEr0中断服务程序(此程序每8ms执行一次);**********************************************TimeInt:MOV TH0,#9EH ;重新加载定时参数MOV TL0,#58HPUSH ACCPUSH PSW ;保护累加器及程序状态字的内容SETB RS0CLR RS1DJNZ 39H,Notone3CH ;中断了40次了吗?即够1秒了吗?MOV 39H,#40 ;如够1秒则重新设置"39H"计数器CALL Clock ;调用将时钟内容加1秒的子程序CALL ConvertoBuffer ;调用将时钟内容转换到显示缓冲区子程序Notone3CH:CALL ScanDisplay ;调用扫描显示子程序POP PSWPOP ACC ;恢复累加器及程序状态字的内容RETI;*********************************************;扫描显示子程序,将缓冲区的数值显示在对应的数码管上;*********************************************ScanDisplay:MOV R1,#30H ;指向显示数据首址,利用c语言指针原理读取缓冲区的数值;子程序ConvErtoBuffEr已经将相应的值存放在30H的缓冲区中MOV R4,#10111111b ;扫描控制字初值,显示右边第一个数码管PLAY: MOV A,R4 ;扫描字放入AMOV P2,A ;从P2口输出,p2口的低六位分别控制对应的六个数码管的显示MOV A,@R1 ;取显示数据到AMOV DPTR,#TAB ;取段码表地址MOVC A,@A+DPTR ;查显示数据对应段码MOV P0,A ;段码放入P0口,具体显示位INC R1 ;指向下一地址MOV A,R4 ;扫描控制字放入A;显示时分秒分隔位JB ACC.1,LPP1 ;显示时分位CLR P0.7CALL DelaySETB P0.7LPP1:JB ACC.3,LPP2 ;显示秒分位CLR P0.7CALL DelaySETB P0.7LPP2: JNB ACC.7,ENDOUT ;扫到第六位时结束RR A ;A中数据循环左移MOV R4,A ;放回R4内LCALL Delay ;每位数码管显示间隔时间为2msSETB P0.7 ;关闭分位显示点AJMP PLAY ;跳回PLAY循环ENDOUT:MOV P0,#0FFH ;P0口复位RETTAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,7FH,0B7H,0FFH;共阳段码表"0""1""2" "3""4""5""6""7" "8""9"".""=""不亮";****************************************************; 时钟内容加1秒的子程序(1秒时间到);****************************************************Clock:MOV A,3CH ;将原秒值送入aADD A,#1 ;加1秒MOV 3CH,aCJNE A,#3CH,NotOverFlowMOV 3CH,#0MOV A,3BHADD A,#1MOV 3BH,A;CJNE A,#3CH,NotOverFlowMOV 3BH,#0MOV A,3AHADD A,#1MOV 3AH,ACJNE A,#18H,NotOverFlowMOV 3AH,#0NotOverFlow:JNB 20H.1,NotAlarm ;闹钟开启了吗?如没有开启则无需理会是否到闹时时间MOV A,3CHJNZ NotAlarm ;秒为零吗?MOV A,3BHCJNE A,2FH,NotAlarm ;时间分钟值和闹时设置分钟值相等吗?MOV A,3AHCJNE A,2EH,NotAlarm ;时间小时值和闹时设置小时值相等吗?SETB 20H.2 ;到了闹时时间则将"闹时时间到"标志设为1NotAlarm:RET;**************************************************************************; 将时钟内容或闹时设置值转换到显示缓冲区子程序;************************************************************************** ConvertoBuffer:MOV R1,#30HJB 20H.0,DispAlarmSet ;判断时钟模式,以决定是显示实时时间还是闹时时间,20H.0,0为正常走时,1为闹钟设定MOV A,3CHMOV 23H,AMOV A,3BHMOV 22H,AMOV A,3AHMOV 21H,AAJMP Convert ;在数码管显示缓冲区的数值DispAlarmSet: ;闹钟设定JB 20H.1,AlarmOn ;闹钟开关,0为关,1为开MOV 23H,#00HAJMP NextAlarmOn:MOV 23H,#1 ;显示闹时时间及显示闹钟状态:显示"00"表示关闭闹钟,NExt: ;"01"表示开启闹钟MOV a,2FH;MOV 22H,A;MOV A,2EH;MOV 21H,A ;将数值显示到数码管Convert:MOV A,23H ;取秒值,将待显示的数值存储到缓冲区MOV B,#10DIV ABMOV @R1,BINC R1 ;缓冲寄存器的地址加1MOV @R1,AINC R1MOV A,22HMOV B,#10DIV ABMOV @R1,B;INC R1 ;缓冲寄存器的地址加1MOV @R1,A ;将秒值的十位值存入缓冲区INC R1MOV A,21HMOV B,#10DIV ABMOV @R1,B;INC R1 ;缓冲寄存器的地址加1MOV @R1,A ;将秒值的十位值存入缓冲区RET;**************************************************; 闹钟时间设置子程序;**************************************************AlarmSet:JNB P3.2,$CALL Delay2 ;等待"P3.2"键释放CheckArmPM: ;JB P3.4,CheckArmPN ;分设置键按下了吗?没有则转去检测小时设置键p3.5 CALL Delay2JB P3.4,CheckArmPNSETB 20H.1 ;闹钟开MOV A,2FHADD A,#1 ;如果按下则将分钟加1,MOV 2FH,ACJNE A,#3CH,ArmNotOver1 ;到60分钟了吗?MOV 2FH,#0 ;到60分钟则将分钟清0ArmNotOver1: ;以下等待按键释放及防抖动JNB P3.4,$ ;等待对应设置时间的按键释放CheckArmPN:JB P3.3,AlarmSetEnd ;小时设置键按下了吗?没有则返回反复检测CALL Delay2JB P3.3,AlarmSetEndSETB 20H.1MOV A ,2EHADD A,#1 ;如果按下则将小时加1MOV 2EH,ACJNE A,#18H,ArmNotOver2MOV 2EH,#0 ;到24小时则将小时清0ArmNotOver2: ;以下等待按键释放及防抖动JNB P3.3,$AlarmSetEnd:JB P3.2,AlarmSet ;闹钟设置完毕了吗?CALL Delay2JB P3.2,AlarmSetJNB P3.2,$CLR 20H.0 ;从设置模式转为走时模式RET;**************************************************; 闹时服务子程序;************************************************** AlarmProcess:MOV R2,#10loop2:CPL P3.0CPL P3.5CALL Delay1JB P3.2,AlarmReturn ;停止闹时键(即闹时设置键)按下了吗?CALL Delay2JB P3.2,AlarmReturnCLR 20H.1 ;关闭闹钟JNB P3.2,$SETB P3.0 ;如停止闹时键按下则停止闹时SETB P3.5CLR 20H.2AJMP loop6AlarmReturn:DEC R2MOV A,R2CJNE A,#00H,loop2SETB P3.0 ;如停止闹时键按下则停止闹时SETB P3.5CLR 20H.1 ;关闭闹钟CLR 20H.2loop6:RET;**************************************************; 延时子程序;**************************************************Delay:MOV R6,#2 ;延时产生1ms,数码管动态显示间隔时间del: MOV R7,#249DJNZ R7,$DJNZ R6,delRETDelay1:MOV R5,#2 ;延时间产生1s,扬声器的震动间隔时间de3:MOV R6,#200de2:MOV R7,#250DJNZ R7,$DJNZ R6,dE2DJNZ R5,dE3RETDelay2:MOV R6,#10 ;延时产生15ms,按键防止抖动时间de4:MOV R7,#245DJNZ R7,$DJNZ r6,de4RETEnd。
单片机数字时钟汇编程序.
单片机数字时钟汇编程序2010-09-30 20:09最近拿汇编程序写了个数字时钟的程序,走时准确,我亲自试验过。
程序设计采用T0方式2工作,有调时功能p1.0 p1.1 p1.2 分别是m键加键减键,p2口出1,p0口出0时数码管点亮,采用共阳数码管,显示方式为23-59-59,上电初始化为00-00-00。
p0.0-p0.6分别接a-gp2.0-2.7分别接时-分-秒的位p2口接74ls244驱动程序如下:;主程序S0 EQU 31HS1 EQU 32HS2 EQU 33HS3 EQU 34HS4 EQU 35HS5 EQU 36HS6 EQU 37HS7 EQU 38HS8 EQU 39HS9 EQU 40HS10 EQU 41HORG 0000HAJMP STARTORG 000BH ;T0入口LJMP ZDNORG 45HSTART:MOV R0,#00HMOV R1,#00HMOV R2,#00HMOV R3,#00HMOV R4,#00HMOV R5,#00HMOV R6,#00HMOV R7,#00HMOV S0,#00HMOV S1,#00HMOV S2,#00HMOV S3,#00HMOV S4,#00HMOV S5,#00HMOV S6,#00HMOV S7,#00HMOV S8,#00HMOV S9,#00HMOV S10,#00HMOV TMOD,#02HMOV TH0,#06HMOV TL0,#06HMOV IE,#82HSETB TR0 ;运行T0MAIN: LCALL DISPLAYLCALL KEYLJMP MAIN;T0中服程序ZDN:PUSH ACCPUSH PSWINC R3CJNE R3,#200,ZD ;不足50mS返回MOV R3,#00HINC S0MOV A,S0CJNE A,#20,ZDMOV S0,#00HINC R0CJNE R0,#60,ZD ;不足60s返回MOV R0,#00HINC R1CJNE R1,#60,ZDMOV R1,#00HINC R2CJNE R2,#24,ZD ;不足24h返回MOV R2,00HZD: POP PSWPOP ACCRETI;显示子程序;秒显示DISPLAY: MOV DPTR,#TABMOV A,R0MOV B,#10DIV ABMOV R4,AMOV R5,BMOV A,R5LCALL CHANGESETB P2.7LCALL DELAY5MSCLR P2.7MOV A,R4LCALL CHANGESETB P2.6LCALL DELAY5MSCLR P2.6MOV A,#10 ;显示-LCALL CHANGESETB P2.5LCALL DELAY5MSCLR P2.5MOV A,R1 ;分显示MOV B,#10DIV ABMOV R4,AMOV R5,BMOV A,R5LCALL CHANGESETB P2.4LCALL DELAY5MSCLR P2.4MOV A,R4LCALL CHANGESETB P2.3LCALL DELAY5MSCLR P2.3MOV A,#10 ;显示-LCALL CHANGESETB P2.2LCALL DELAY5MSCLR P2.2MOV A,R2 ;时显示MOV B,#10DIV ABMOV R4,AMOV R5,BMOV A,R5LCALL CHANGESETB P2.1LCALL DELAY5MSCLR P2.1MOV A,R4LCALL CHANGESETB P2.0LCALL DELAY5MSCLR P2.0RETCHANGE: MOVC A,@A+DPTR ;显示输出MOV P0,ARET;键盘程序KEY:MOV P1,#0FFHMOV A,P1CPL AANL A,#07HJZ RET1LCALL DELAY10MSMOV A,P1CPL AANL A,#07HJZ RET1JB ACC.0,MKEYJB ACC.1,ADDKEYJB ACC.2,DECKEYRET1:RETMKEY: LCALL K1LJMP DISPLAY ADDKEY:LCALL K2LJMP DISPLAY DECKEY:LCALL K3LJMP DISPLAYK1: LCALL DISPLAYLCALL DISPLAYCJNE R6,#4,LOOP1MOV R6,#00HLJMP FHLOOP1:INC R6FH: RETK2: LCALL DISPLAYLCALL DISPLAYCJNE R6,#1,LOOP2CJNE R2,#23,LOOP3MOV R2,#00HLJMP LOOP6LOOP3:INC R2LJMP LOOP6LOOP2:CJNE R6,#2,LOOP4CJNE R1,#59,LOOP5MOV R1,#00HLJMP LOOP6LOOP5:INC R1LJMP LOOP6LOOP4:CJNE R6,#3,LOOP6MOV R0,#00H LOOP6:RETK3: LCALL DISPLAYLCALL DISPLAYCJNE R6,#1,LOOP7CJNE R2,#0,LOOP8MOV R2,#23LJMP LOOP11LOOP8:DEC R2LJMP LOOP11LOOP7:CJNE R6,#2,LOOP9CJNE R1,#0,LOOP10MOV R1,#59LJMP LOOP11 LOOP10:DEC R1LJMP LOOP11 LOOP9:CJNE R6,#3,LOOP11MOV R0,#00HLOOP11:RETDELAY5MS:MOV S1,#5 ;5mS延时D1: MOV S2,#248D2: DJNZ S2,D2DJNZ S1,D1RETDELAY10MS:MOV S3,#25 ;10mS延时D4: MOV S4,#200D3: DJNZ S4,D3DJNZ S3,D4RETTAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0BFHEND电路原理图:照片如下:。
数字钟汇编语言程序
MOV TH0,#3CH ;50MS定时初值
MOV TL1,#0B0H ;50MS定时初值(T1闪烁定时用)
;; 1秒计时程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;T0中断服务程序
INTT0: PUSH ACC ;累加器入栈保护
PUSH PSW ;状态字入栈保护
MOV 73H,77H ;
MOV 74H,78H ;
MOV 75H,79H ;
INTT1OUT: POP PSW ;恢复现场
OUTT0: MOV 72H,76H ;中断退出时将分、时计时单元数据移
MOV 73H,77H ;入对应显示单元
MOV 74H,78H ;
MOV 20H,#00H ;清20H(标志用)
MOV 7AH,#0AH ;放入"熄灭符"数据
MOV TMOD,#11H ;设T0、T1为16位定时器
CPL 02H ;0.3秒定时到对闪烁标志取反
JB 02H,FLASH1 ;02H位为1时显示单元"熄灭"
MOV 72H,76H ;02H位为0时正常显示
CLR ET0 ;关T0中断允许
CLR TR0 ;关闭定时器T0
MOV A,#0B7H ;中断响应时间同步修正
ADD A,TL0 ;低8位初值修正
第一个: ORG 0000H ;程序执行开始地址
LJMP START ;跳到标号START执行
ORG 0003H ;外中断0中断程序入口
RETI ;外中断0中断返回
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
用这个程序吧 C和汇编都有。
数字钟[★]1.实验任务(1.开机时,显示12:00:00的时间开始计时;(2. P0.0/AD0控制“秒”的调整,每按一次加1秒;(3. P0.1/AD1控制“分”的调整,每按一次加1分;(4. P0.2/AD2控制“时”的调整,每按一次加1个小时;2.电路原理图图4.20.13.系统板上硬件连线(1.把“单片机系统”区域中的P1.0-P1.7端口用8芯排线连接到“动态数码显示”区域中的A-H端口上;(2.把“单片机系统:区域中的P3.0-P3.7端口用8芯排线连接到“动态数码显示”区域中的S1-S8端口上;(3.把“单片机系统”区域中的P0.0/AD0、P0.1/AD1、P0.2/AD2端口分别用导线连接到“独立式键盘”区域中的SP3、SP2、SP1端口上;4.相关基本知识(1.动态数码显示的方法(2.独立式按键识别过程(3.“时”,“分”,“秒”数据送出显示处理方法5.程序框图6.汇编源程序SECOND EQU 30HMINITE EQU 31HHOUR EQU 32HHOURK BIT P0.0MINITEK BIT P0.1SECONDK BIT P0.2DISPBUF EQU 40HDISPBIT EQU 48HT2SCNTA EQU 49HT2SCNTB EQU 4AHTEMP EQU 4BHORG 00HLJMP STARTORG 0BHLJMP INT_T0START: MOV SECOND,#00HMOV MINITE,#00HMOV HOUR,#12MOV DISPBIT,#00HMOV T2SCNTA,#00HMOV T2SCNTB,#00HMOV TEMP,#0FEHLCALL DISPMOV TMOD,#01HMOV TH0,#(65536-2000) / 256 MOV TL0,#(65536-2000) MOD 256 SETB TR0SETB ET0SETB EAWT: JB SECONDK,NK1LCALL DELY10MSJB SECONDK,NK1INC SECONDMOV A,SECONDCJNE A,#60,NS60MOV SECOND,#00HNS60: LCALL DISPJNB SECONDK,$NK1: JB MINITEK,NK2LCALL DELY10MSJB MINITEK,NK2INC MINITEMOV A,MINITECJNE A,#60,NM60MOV MINITE,#00HNM60: LCALL DISPJNB MINITEK,$NK2: JB HOURK,NK3LCALL DELY10MSJB HOURK,NK3INC HOURMOV A,HOURCJNE A,#24,NH24MOV HOUR,#00HNH24: LCALL DISPJNB HOURK,$NK3: LJMP WTDELY10MS:MOV R6,#10D1: MOV R7,#248DJNZ R7,$DJNZ R6,D1RETDISP:MOV A,#DISPBUFADD A,#8DEC AMOV R1,AMOV A,HOURMOV B,#10DIV ABMOV @R1,ADEC R1MOV A,BMOV @R1,ADEC R1MOV A,#10MOV@R1,ADEC R1MOV A,MINITEMOV B,#10DIV ABMOV @R1,ADEC R1MOV A,BMOV @R1,ADEC R1MOV A,#10MOV@R1,ADEC R1MOV A,SECONDMOV B,#10DIV ABMOV @R1,ADEC R1MOV A,BMOV @R1,ADEC R1RETINT_T0:MOV TH0,#(65536-2000) / 256 MOV TL0,#(65536-2000) MOD 256 MOV A,#DISPBUFADD A,DISPBITMOV R0,AMOV A,@R0MOV DPTR,#TABLEMOVC A,@A+DPTRMOV P1,AMOV A,DISPBITMOV DPTR,#TABMOVC A,@A+DPTRMOV P3,AINC DISPBITMOV A,DISPBITCJNE A,#08H,KNAMOV DISPBIT,#00HKNA: INC T2SCNTAMOV A,T2SCNTACJNE A,#100,DONEMOV T2SCNTA,#00HINC T2SCNTBMOV A,T2SCNTBCJNE A,#05H,DONEMOV T2SCNTB,#00HINC SECONDMOV A,SECONDCJNE A,#60,NEXTMOV SECOND,#00HINC MINITEMOV A,MINITECJNE A,#60,NEXTMOV MINITE,#00HINC HOURMOV A,HOURCJNE A,#24,NEXTMOV HOUR,#00HNEXT: LCALL DISPDONE: RETITABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H TAB: DB 0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FHEND7. C语言源程序#include <AT89X51.H>unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; unsigned char dispbitcode[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; unsigned char dispbuf[8]={0,0,16,0,0,16,0,0};unsigned char dispbitcnt;unsigned char second;unsigned char minite;unsigned char hour;unsigned int tcnt;unsigned char mstcnt;unsigned char i,j;void main(void){TMOD=0x02;TH0=0x06;TL0=0x06;TR0=1;ET0=1;EA=1;while(1){if(P0_0==0){for(i=5;i>0;i--)for(j=248;j>0;j--);if(P0_0==0){second++;if(second==60){second=0;}dispbuf[0]=second%10; dispbuf[1]=second/10; while(P0_0==0);}}if(P0_1==0){for(i=5;i>0;i--)for(j=248;j>0;j--);if(P0_1==0){minite++;if(minite==60){minite=0;}dispbuf[3]=minite%10; dispbuf[4]=minite/10;while(P0_1==0);}}if(P0_2==0){for(i=5;i>0;i--)for(j=248;j>0;j--);if(P0_2==0){hour++;if(hour==24){hour=0;}dispbuf[6]=hour%10;dispbuf[7]=hour/10;while(P0_2==0);}}}}void t0(void) interrupt 1 using 0{mstcnt++;if(mstcnt==8){mstcnt=0;P1=dispcode[dispbuf[dispbitcnt]]; P3=dispbitcode[dispbitcnt];dispbitcnt++;if(dispbitcnt==8){dispbitcnt=0;}}tcnt++;if(tcnt==4000){tcnt=0;second++;if(second==60){second=0;minite++;if(minite==60){minite=0;hour++;if(hour==24) {hour=0; }}}dispbuf[0]=second%10; dispbuf[1]=second/10; dispbuf[3]=minite%10; dispbuf[4]=minite/10; dispbuf[6]=hour%10; dispbuf[7]=hour/10; }}。