单片机基于c语言编写时钟
- 格式:doc
- 大小:24.54 KB
- 文档页数:6
单片机时钟程序设计代码好的,由于你没有给出具体的单片机型号,下面是一个基于 51 单片机的时钟程序设计示例:```c#include <reg52.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>// 定义变量char str[20];int i=0;int j=0;int k=0;int time=0;int flag=0;int h=0,m=0,s=0;void delay(int xms){int i,j;for(i=xms;i>0;i--)for(j=110;j>0;j--);}void time0() interrupt 1{TH0=(65536-50000)/256;TL0=(65536-50000)%256;time++;if(time==20){time=0;s++;if(s==60){s=0;m++;if(m==60){m=0;h++;}}}// 将时间数据转换为字符串sprintf(str," %02d:%02d:%02d",h,m,s);// 输出时间字符串for(i=0;i<16;i++){P0=str[i];delay(1000);}}void main(){// 初始化定时器 0 为 16 位定时器模式,计数初值为 50000 TMOD=0x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;ET0=1;TR0=1;while(1);}```该程序利用 51 单片机的定时器 0 来产生定时中断,每 20 次中断为 1 秒,通过对秒、分、时的累计来实现时钟功能。
在中断服务函数中,将当前时间转换为字符串,并通过循环输出到 P0 口。
#include<reg52.h>typedef unsigned intuint;typedef unsigned char uchar;sbit LED_Bit1 = P2^4;sbit LED_Bit2 = P2^5;sbit LED_Bit3 = P2^6;sbit LED_Bit4 = P2^7;sbit Key0=P3^4;sbit Key1=P3^5;sbit Key2=P3^6;sbit Key3=P3^7;sbit Buzzer=P2^3;int point;intnum=0;int alarm=1;uint count=0;uint second=0;uint min=0;uint hour=6;uint count1=0;uint second1=0;uint year=2011;uint month=1;uint day=1;uint hour1=6;uint min1=0;uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};void Delay(uint m){uintx,y;for(x = m;x> 0;x--)for(y = 110;y > 0;y--);}voidLED_DynamicDisplay(uchar Bit1,uchar Bit2,uchar Bit3,uchar Bit4) {LED_Bit1 = 0;LED_Bit2 = 1;LED_Bit4 = 1;if(point==2||point==7||point==9){if(count<50)P0 = table[Bit1]&0x7f;elseP0=table[Bit1];}elseP0=table[Bit1];Delay(1);P0 = 0xFF;LED_Bit1 = 1;LED_Bit2 = 0;LED_Bit3 = 1;LED_Bit4 = 1;if(point>=1&point<=10&point!=5&point!=9&point!=10) P0=table[Bit2]&0x7f;else{if (count<50)P0 = table[Bit2] & 0x7f;elseP0=table[Bit2];}Delay(1);P0 = 0xFF;LED_Bit1 = 1;LED_Bit2 = 1;LED_Bit3 = 0;LED_Bit4 = 1;if(point==3||point==8||point==10){if(count<50)P0 = table[Bit3]&0x7f;elseP0=table[Bit3];}elseP0=table[Bit3];Delay(1);P0 = 0xFF;LED_Bit2 = 1;LED_Bit3 = 1;LED_Bit4 = 0;P0 = table[Bit4];Delay(1);P0 = 0xFF;}voidTimer_Init(void){TMOD=0x11;TH1=(65536-10000)/256;TL1=(65536-10000)%256;TH0=(65536-10000)/256;TL0=(65536-10000)%256;TR0=1;TR1=1;ET1=1;ET0=1;EA=1;}uchar LED=0x00;void timer0(void) interrupt 3 using 1 {count++;TH1=(65536-10000)/256;TL1=(65536-10000)%256;if(Buzzer==0){if(count%50 == 0)LED =~LED;}if(Buzzer==1)LED=0x00;}void timer1(void) interrupt 1 using 1 {if(point==1)count1++;TH0 = (65536 - 10000)/256;TL0 = (65536 - 10000)%256;}{if(Key0 == 0){Delay(5);if(Key0 == 0){//alarm=~alarm; while(!Key0);}}if(Key1 == 0){Delay(5);if(Key1 == 0){second1=0;count1=0;TH0= (65536 - 10000)/256; TL0= (65536 - 10000)%256; while(!Key1);}}if(Key2==0){Delay(5);if(Key2==0){point++;/*if(point==1){ET0=0;}*/if(point==11)point=0;}while(!Key2);}if(Key3==0){Delay(5);if(Key3==0){if(point==0) alarm=~alarm; if(point==9) hour1++;if(point==10) min1++;if(point==2) hour++;if(point==3) min++;if(point==1) ET0=~ET0; if(point==5) year++;if(point==7) month++;if(point==8) day++;while(!Key3); }}}void time() {if(count>=100) {second++; count=0;}if(second>=60) {min++; second=0;}if(min>=60) {hour++;min=0;}if(hour>=24) {hour=0;day++;}if(month<=7&month%2==1||month>=8&month%2==0) {if(day>=32){month++;day=0;}}else if(year%4==0&year%400!=0&month==2){if(day>=30){month++;day=0;}}else if(year%4!=0&month==2){if(day>=29){month++;day=0;}}else{if(day>=31){month++;day=0;}}if(month>=12){year++;month=0;}if(year>=9999)year=0;if(count1>=100){second1++;count1=0;}if(second1>=60){second1=0;}if(hour1>=24)hour1=0;if(min1>=60)min1=0;if(alarm>=2)alarm=0;}int main(){Timer_Init();while(1){P1=~LED;Keyscan();time();if(point==1){time();LED_DynamicDisplay(second1/10,second1%10,count1/10,count1%10); }else if(point==4||point==5){time();LED_DynamicDisplay(year/1000,year/100%10,year/10%10,year%10);}else if(point==6||point==7||point==8){time();LED_DynamicDisplay(month/10,month%10,day/10,day%10);}else if(point==9||point==10)。
一、功能要求整体上要考虑:结构简单大方、布局美观合理、操作方便易懂、尽量避免各元器件之间的相互影响。
1、以AT89C51单片机进行实现秒分时上的正常显示和进位,其中显示功能由单片机控制共阴极数码管来实现,数码管进行动态显示。
2、具有校时功能,按键控制电路其中时键、分键、秒键三个键分别控制时分秒时间的调整。
按秒键秒加1;按分键分加1;按时键时加1.二、硬件设计1、整体设计框图2、管脚功能描述(1) XTAL1(19 脚)和XTAL2(18 脚):振荡器输入输出端口,外接晶振电路。
(2)RST/Vpd(9 脚)为复位输入端口,外接电阻电容组成的复位电路。
(3)P0口8个端口依次和LED显示器的A、B、C、D、E、F、G和Dp端口对应连接,实现对显示器的片选功能。
(4)P2.0~P2.5依次与LED显示器的1、2、3、4、5、6一一连接,实现对显示器的为选功能。
(5)P3.0~P3.2依次与按键电路的秒、分、时三个按键相连接。
通过按键实现对时间的调试功能。
3、整体原理设计其计时周期为24小时,显示满刻度为23时59分59秒,另外还有校时功能。
整个设计图由晶振电路、复位电路、AT89C51单片机、键盘控制电路组成。
显示电路将“时”、“分”、“秒”通过七段显示器显示出来,6个数码管的段选接到单片机的P0口,位选接到单片机的P2口。
数码管按照数码管动态显示的工作原理工作。
把定时器定时时间设为50ms,则计数溢出20次即得时钟计时最小单位秒,而20次计数可用软件方法实现,每累计60秒进1分,每累计60分钟,进1小时。
时采用24进制计时器,可实现对一天24小时的累计。
校时电路时用来对“时”、“分”、“秒”显示数字进行校对调整,时分秒三个控制键分别接单片机的p3.2、p3.1、p3.0进行控制。
按一下秒键秒单元就加1 ,按一下分键分就加1,按一下时键时就加1。
4、晶振电路单片机的时钟产生方法有两种:内部时钟方式和外部时钟方式。
#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit dula=P2^6;sbit wela=P2^7;sbit rs=P3^5;sbit lcden=P3^4;sbit s1=P3^0;sbit s2=P3^1;sbit s3=P3^2;sbit rd=P3^7;sbit rw=P3^6;uchar count,s1num;char miao,fen,shi;uchar code table[]=" 2011-5-23 MON";uchar code table1[]=" 00:00:00";void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void write_com(uchar com){ rs=0;P0=com;lcden=0;delay(5);lcden=1;delay(5);lcden=0;}void write_date(uchar date){rs=1;P0=date;lcden=0;delay(5);lcden=1;delay(5);lcden=0;}void write_sfm(uchar add,uchar date)//写时分秒函数{uchar shi,ge;shi=date/10;//分解一个2位数的十位和个位ge=date%10;write_com(0x80+0x40+add);//设置显示位置write_date(0x30+shi);//送去液晶显示十位write_date(0x30+ge); //送去液晶显示个位}void init()//初始化函数{uchar num;dula=0;wela=0;lcden=1;fen=0;miao=0;shi=0;count=0;s1num=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80);for(num=0;num<15;num++){write_date(table[num]);delay(5);}write_com(0x80+0x40);for(num=0;num<12;num++){write_date(table1[num]);delay(5);}TMOD=0x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;ET0=1;TR0=1;}void keyscan()//按键扫描函数{rd=0;if(s1==0){delay(5);if(s1==0)//确认功能键被按下{ s1num++;//功能键按下次数记录while(!s1);//释放确认if(s1num==1)//第一次被按下时{TR0=0; //关闭定时器write_com(0x80+0x40+10);//光标定位到秒位置write_com(0x0f); //光标开始闪烁}if(s1num==2)//第二次按下光标闪烁定位到分钟位置{write_com(0x80+0x40+7);}if(s1num==3)//第三次按下光标闪烁定位到小时位置{write_com(0x80+0x40+4);}if(s1num==4)//第四次按下{s1num=0;//记录按键数清零write_com(0x0c);//取消光标闪烁TR0=1; //启动定时器使时钟开始走}}}if(s1num!=0)//只有功能键被按下后,增加和减小键才有效{if(s2==0){delay(5);if(s2==0)//增加键确认被按下{while(!s2);//按键释放if(s1num==1)//若功能键第一次按下{miao++; //则调整秒加1if(miao==60)//若满60后将清零miao=0;write_sfm(10,miao);//每调节一次送液晶显示一下write_com(0x80+0x40+10);//显示位置重新回到调节处}if(s1num==2)//若功能键第二次按下{fen++;//则调整分钟加1if(fen==60)//若满60后将清零fen=0;write_sfm(7,fen);//每调节一次送液晶显示一下write_com(0x80+0x40+7);//显示位置重新回到调节处}if(s1num==3)//若功能键第三次按下{shi++;//则调整小时加1if(shi==24)//若满24后将清零shi=0;write_sfm(4,shi);;//每调节一次送液晶显示一下write_com(0x80+0x40+4);//显示位置重新回到调节处}}}if(s3==0){delay(5);if(s3==0)//确认减小键被按下{while(!s3);//按键释放if(s1num==1)//若功能键第一次按下{miao--;//则调整秒减1if(miao==-1)//若减到负数则将其重新设置为59miao=59;write_sfm(10,miao);//每调节一次送液晶显示一下write_com(0x80+0x40+10);//显示位置重新回到调节处}if(s1num==2)//若功能键第二次按下{fen--;//则调整分钟减1if(fen==-1)//若减到负数则将其重新设置为59fen=59;write_sfm(7,fen);//每调节一次送液晶显示一下write_com(0x80+0x40+7);//显示位置重新回到调节处}if(s1num==3)//若功能键第二次按下{shi--;//则调整小时减1if(shi==-1)//若减到负数则将其重新设置为23shi=23;write_sfm(4,shi);//每调节一次送液晶显示一下write_com(0x80+0x40+4);//显示位置重新回到调节处}}}}}void main(){rw=0;init();while(1){keyscan();}}void timer0() interrupt 1{TH0=(65536-50000)/256;TL0=(65536-50000)%256;count++;if(count==18){count=0;miao++;if(miao==60){miao=0;fen++;if(fen==60){fen=0;shi++;if(shi==24){shi=0;}write_sfm(4,shi);}write_sfm(7,fen);}write_sfm(10,miao);}}。
/*这是一个真正有意义的时钟key1功能键选择可调位,短按,每按一下有一位闪烁长按闪烁不断向下一位推移key2 加键短按相应闪烁的位加1,长按连续加1;key3 减键短按相应闪烁的位减1,长按连续减一;key4 确定键按下退出调时,正常显示;*/#include<reg52.h>#define uint unsigned int#define uchar unsigned char#define LED P0#define KEY_1 0x0e#define KEY_2 0x0d#define KEY_3 0x0b#define KEY_4 0x07#define KEY_NULL 0x0f#define KEY_PRESS 0x80#define KEY_LONG 0x40#define KEY_STATE_INIT 0#define KEY_STATE_PRESS 1#define KEY_STATE_LONG 2#define KEY_STATE_UP 3#define KEY_LONG_PERIOD 20#define KEY_CONTINUE_PERIOD 10bit set;bit dao1S=0;bit dao2MS=0;bit dao10MS;sbit dula=P2^6;sbit wela=P2^7;sbit key1=P3^4;sbit key2=P3^5;sbit key3=P3^6;sbit key4=P3^7;int main_flag,exit_flag,up_flag,down_flag;int tab[]={0,0,0,0,0,0};uchar weitable[]={0x01,0x02,0x04,0x08,0x10,0x20};uchar tab1[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; void nint(){ TMOD=0X01;TH0=0XF8;TL0=0XCC;TR0=1;ET0=1;}uchar KeyScan(){if(key1==0) return KEY_1;if(key2==0) return KEY_2;if(key3==0) return KEY_3;if(key4==0) return KEY_4;return KEY_NULL;}uchar GetKey(){uchar keyRetu=0,keyTemp=KEY_NULL;static uchar s_keyState=KEY_STATE_INIT,keyTime=0,keyLast=KEY_NULL;keyTemp=KeyScan();switch (s_keyState){case KEY_STA TE_INIT:if(keyTemp!=KEY_NULL){s_keyState=KEY_STA TE_PRESS;}break;case KEY_STA TE_PRESS:if(keyTemp!=KEY_NULL){s_keyState=KEY_STA TE_LONG;keyTime=0;keyLast=keyTemp;}else{s_keyState=KEY_STA TE_INIT;}break;case KEY_STA TE_LONG:if(keyTemp==KEY_NULL){s_keyState=KEY_STA TE_INIT;keyRetu=(keyLast|KEY_PRESS);}else{if(++keyTime>=KEY_LONG_PERIOD) //按下时间>1s{s_keyState=KEY_STATE_UP;keyTime=0;}}break;case KEY_STA TE_UP:if(keyTemp==KEY_NULL){s_keyState=KEY_STA TE_INIT;}else{if(++keyTime>=KEY_CONTINUE_PERIOD) //按下时间>0.5s {keyTime=0;keyRetu=(keyLast|KEY_LONG);}}break;}return keyRetu;}void updatetime(){if(dao1S){dao1S=0;if(++tab[5]==10){ tab[5]=0;if(++tab[4]==6){tab[4]=0;if(++tab[3]==10){ tab[3]=0;if(++tab[2]==6){ tab[2]=0;if(tab[0]<2){if(++tab[1]==10){ tab[1]=0;tab[0]++;}}else{ if(tab[1]==4){ tab[1]=0;tab[0]=0;}} }}}}}}void display(){ static uchar k=0;dula=1;LED=tab1[tab[k]];if(set&&((k==main_flag-1))){LED=0XFF;}dula=0;LED=0Xff;wela=1;LED=weitable[k];wela=0;if(++k>5) k=0;}void sittime(uchar hour,uchar minute,uchar second ) { uchar a1,a2,b1,b2,c1,c2;a1=hour/10;a2=hour%10;b1=minute/10;b2=minute%10;c1=second/10;c2=second%10;tab[0]=a1;tab[1]=a2;tab[2]=b1;tab[3]=b2;tab[4]=c1;tab[5]=c2;}void main(){ nint();EA=1;sittime(15,20,15);while(1){updatetime();if(dao2MS){dao2MS=0;display();}if(dao10MS){dao10MS=0;switch (GetKey()){case (KEY_1|KEY_PRESS):if(++main_flag>=7)main_flag=0;break;case (KEY_1|KEY_LONG):if(++main_flag>=7)main_flag=0;break;case (KEY_2|KEY_PRESS):switch(main_flag){case 1:{if(++tab[0]>=3)tab[0]=0;}break;case 2:{if(++tab[1]>4)tab[1]=0;}break;case 3:{if(++tab[2]>5)tab[2]=0;}break;case 4:{if(++tab[3]>9)tab[3]=0;}break;case 5:{if(++tab[4]>5)tab[4]=0;}break;case 6:if(++tab[5]>9)tab[5]=0;}break;case (KEY_2|KEY_LONG): switch(main_flag) {case 1:{if(++tab[0]>=3)tab[0]=0;}break;case 2:{if(++tab[1]>4)tab[1]=0;}break;case 3:{if(++tab[2]>5)tab[2]=0;}break;case 4:{if(++tab[3]>9)tab[3]=0;}break;case 5:{if(++tab[4]>5)tab[4]=0;}break;case 6:if(++tab[5]>9)tab[5]=0;}break;case (KEY_3|KEY_PRESS):switch(main_flag){case 1:{if(--tab[0]<0)tab[0]=2;}break;case 2:{if(--tab[1]<0)tab[1]=4;}break;case 3:{if(--tab[2]<0)tab[2]=5;}break;case 4:{if(--tab[3]<0)tab[3]=9;}break;case 5:{if(--tab[4]<0)tab[4]=5;}break;case 6:if(--tab[5]<0)tab[5]=9;}break;case (KEY_3|KEY_LONG): switch(main_flag){case 1:{if(--tab[0]<0)tab[0]=2;}break;case 2:{if(--tab[1]<0)tab[1]=4;}break;case 3:{if(--tab[2]<0)tab[2]=5;}break;case 4:{if(--tab[3]<0)tab[3]=9;}break;case 5:{if(--tab[4]<0)tab[4]=5;}break;case 6:if(--tab[5]<0)tab[5]=9;}break;case (KEY_4|KEY_PRESS):main_flag=0;display();}}}}void timer() interrupt 1{ static count=0;static count1=0;TH0=0XF8;TL0=0XCC;dao2MS=1;count++;if(++count1==10){ c ount1=0;dao10MS=1;}if(!(count%25)) set = !set;if(count==500) {count=0;dao1S=1; }}。
<>[]{}共阴数码管数字码资料个人收集整理,勿做商业用途为数码管地段选^; 移位时钟^; 锁存时钟^; 串行数据输入^;^;^;^;^; ^为"调时"按键^; ^为"选择时分秒"按键^; ^为"增加"按键^; ^为"完成"按键;; 定义秒,分,时,秒地个位,十位,分地个位,十位,时地个位,十位资料个人收集整理,勿做商业用途; 按下"选择时分秒"按键地次数; 定义"调时"按键地标志位资料个人收集整理,勿做商业用途();();( );();( );();资料个人收集整理,勿做商业用途(){();(){;();();}}资料个人收集整理,勿做商业用途(){;;资料个人收集整理,勿做商业用途; 定义定时器工作与方式(); 定时器赋初值();; 开总中断和中断;}资料个人收集整理,勿做商业用途( ) 数据发送{设置循环变量;;(<){((>>));;;;};;}延时子函数资料个人收集整理,勿做商业用途( ){;(<)(<);}显示子函数资料个人收集整理,勿做商业用途(){;() 如果定时器溢出{; 清中断标志位;(){;; 秒加() 如果秒为,则清零,分加{;;}() 如果分为,则清零,时加{;;}() 如果时为,则清零{;}}}; 秒地个位和十位;; 分地个位和十位;; 时地个位和十位;; 口为([]); 显示第一位时; 口为();; 消影([]); 显示第二位时; 口为();; 消影(); 显示第三位; 口为();; 消影([]); 显示第四位分; 口为();; 消影([]); 显示第位分; 口为();; 消影(); 显示第位; 口为();; 消影([]); 显示第位秒; 口为();; 消影([]); 显示第位秒; 口为();; 消影}调时子程序资料个人收集整理,勿做商业用途(){() 如果"调时"按键按下{(); 延时去抖(){; 标志位置() 当标志位为时才能进行时间调整{; 定时器停止(); 显示停止时地时间() 如果"完成"按键按下{(); 延时去抖(){; 标志位清零;;;}}() 如果"时分秒选择"按键按下{(); 延时去抖(){();; 按下地次数增加() 如果次数达到次{; 次数清零}() 如果次数为,秒指示灯亮{;;;}() 如果次数为,分指示灯亮{;;;}() 如果次数为,时指示灯亮{;;;}}}() 如果"增加"按键按下{(); 延时去抖(){() 分支结构,根据地值来判断哪一位加{: 如果为,秒加,到清零{();;();;}: 如果为,分加,到清零{();;();;}: 如果为,时加,到清零{();;();;};}}}}}}}。
堆栈栈底80H;;******************************************************************** **;;LED数码管显示器设定;;P0.7---P0.0段控线,接LED的显示段dp,g,f,e,d,c,b,a;P2.0---P2.7位控线,从左至右(LED7,LED6,LED5,LED4,LED3,LED2,LED1,LED0) ;显示缓冲区设定从左至右依次为78H,79H,7AH,7BH,7CH,7DH,7EH,7FH;******************************************************************** **;;独立式键盘设定;;8个按键S2至S9分别依次接在P1.0至P1.7口线;;******************************************************************** **;;20H字节单元:十六进制,S2键键值01H,S3键键值02H,S4键键值04H,S5键键值08H,S6键键值10H,S7键键值20H,S8键键值40H,S9键键值80H;******************************************************************** **;;定时器/计数器资源:;T/C0:工作模式;功能;定时时间;查询或中断;******************************************************************** **;;中断系统资源;;T/C0;******************************************************************** **;;键功能程序;;KEYA (S2键键功能程序);KEYB (S3键键功能程序);KEYC (S4键键功能程序);KEYD (S5键键功能程序);******************************************************************** **;;中断服务程序;;**********************************************************************;;常数表格;;DISBH(系统提示符P.字型代码序号表);DISBI(00-00-00字符的代码序号);TAB(共阳数码管字型代码表);******************************************************************** **;;子程序;;DL(2毫秒延时子程序);DISP(数码管显示子程序);KEY(键扫描子程序);;KEYCHULI(P1口数据处理子程序);加1子程序;******************************************************************** **;;伪指令定义SEC EQU 30HMIN EQU 31HHOUR EQU 32HSECGE EQU 7FHSECSHI EQU 7EHMINGE EQU 7CHMINSHI EQU 7BHHOURGE EQU 79HHOURSHI EQU 78H;******************************************************************** **;;系统起始程序区ORG 0000HSTART: LJMP MAINORG 000BHLJMP TC0;******************************************************************** **;;系统监控程序区ORG 0030HMAIN: MOV SP, #80H ;初始化数据MOV PSW, #00HMOV TMOD, #01H ;定时器0工作方式1MOV TH0, #0D8H ;10MSMOV TL0, #0F0HSETB EASETB ET0MOV R0, #20H ;RAM区首地址MOV R7, #5FH ;RAM区单元个数 95个CHUSHI:MOV @R0, #00HINC R0 ;将RAM全部清零,初始化DJNZ R7, CHUSHITSF: MOV DPTR, #DISBH ;系统初始化“P.”字符代码表首地址MOV R5, #08HMOV R0, #78HDISPTSF:CLR AMOVC A, @A+DPTRMOV @R0, AINC R0INC DPTRDJNZ R5, DISPTSFD: LCALL DISP ;调显示子程序显示提示符“P.”LCALL KEYJB 20H.0, KEYALJMP D;******************************************************************** **;;键功能程序区;S2键功能程序KEYA: MOV SEC, #0 ;寄存器初始化,秒寄存器MOV MIN, #0 ;分寄存器MOV HOUR, #0 ;时寄存器MOV DPTR, #DISBI ;“00-00-00”字符代码表首地址 MOV R5, #08HMOV R0, #78HDISPTSG:CLR AMOVC A, @A+DPTRMOV @R0, AINC R0INC DPTRDJNZ R5, DISPTSGKEYAS: SETB TR0 ;开定时器DI: LCALL DISPLCALL KEYJB 20H.0, CPLJMP DICP: CLR TR0 ;S2键按下,进入调整状态DD: LCALL DISPLCALL KEYJB 20H.0, KEYASJB 20H.1, KEYBJB 20H.2, KEYCJB 20H.3, KEYDLJMP DD;S3键功能程序KEYB: LCALL HOUR_ ;调时LC: LCALL DISPLCALL KEYJB 20H.0, KEYASJB 20H.1, KEYBJB 20H.2, KEYCJB 20H.3, KEYDLJMP LC;S4键功能程序KEYC: LCALL MIN_ ;调分DIIS: LCALL DISPLCALL KEYJB 20H.0, KEYASJB 20H.1, KEYBJB 20H.2, KEYCJB 20H.3, KEYDLJMP DIIS;S5键功能程序KEYD: LCALL SEC_ ;调秒DISS: LCALL DISPLCALL KEYJB 20H.0, KEYASJB 20H.1, KEYBJB 20H.2, KEYCJB 20H.3, KEYDLJMP DISS;中断服务程序TC0: PUSH ACCPUSH BPUSH PSWSETB RS1CLR RS0MOV TH0, #0D8HMOV TL0, #0F0HINC 33HMOV A, 33HCJNE A, #100, REMOV 33H, #0INC SECMOV A, SECMOV B, #10DIV ABMOV SECSHI,AMOV SECGE, BMOV A, SECCJNE A, #60, REINC MINMOV SEC, #00HMOV SECGE, #0MOV SECSHI,#0MOV A, MINMOV B, #10DIV ABMOV MINSHI, AMOV MINGE, BMOV A, MINCJNE A, #60, REINC HOURMOV MIN, #00HMOV MINGE, #0MOV MINSHI,#0MOV A, HOURMOV B, #10DIV ABMOV HOURSHI,AMOV HOURGE, BMOV A, HOURCJNE A, #24, REMOV HOUR, #0MOV HOURGE,#0MOV HOURSHI,#0RE: POP PSWPOP BPOP ACCRETI;延时1毫秒子程序DL: PUSH PSWSETB RS1SETB RS0MOV R7, #02HDL1: MOV R6, #0FFHDL2: DJNZ R6, DL2DJNZ R7, DL1POP PSWRET;显示子程序;入口: 77H,78H,79H,7AH,7BH,7CH,7DH,7EH,7FH,DISP: PUSH DPHPUSH DPLPUSH ACCPUSH PSWCLR RS1 ;改变当前寄存器组为组1SETB RS0MOV R1, #78H ;显示缓冲存储单元首地址MOV R2, #0FEH ;从右至左显示,共阳极DISP1:MOV A, @R1MOV DPTR, #TABMOVC A, @A+DPTRMOV P0, A ;送段控MOV P2, R2 ;送位控LCALL DL ;延时2毫秒为什么这里要延时MOV A, R2JNB ACC.7, DISP2 ;为0转移;RL AINC R1MOV R2, ALJMP DISP1DISP2: POP PSW ;恢复当前寄存器组的组号POP ACCPOP DPLPOP DPHRET;键扫描子程序KEY: LCALL KEYCHULI ;调P1口数据处理子程序 JZ EXIT ;没有键按下,转返回LCALL DISP ;调显示子程序去抖动LCALL DISPLCALL KEYCHULI ;调P1口数据处理子程序 JZ EXIT ;没有键按下,转返回MOV B, 20H ;保存取反后的键值KEYSF: LCALL KEYCHULI ;调P1口数据处理子程序JZ KEY1 ;键释放,转恢复键值LCALL DISP ;调显示子程序延时LJMP KEYSF ;等待释放KEY1: MOV 20H, B ;键值送20H保存EXIT: RET ;子程序返回;P1口数据处理子程序KEYCHULI:PUSH PSW ;保护现场CLR RS1 ;改变当前寄存器组为组1SETB RS0MOV P1, #0FFH ;先向P1口写1MOV A, P1 ;读P1口数据CPL A ;P1口数据取反MOV 20H, A ;保存取反后的键值CLR RS1 ;恢复当前寄存器组为组0CLR RS0POP PSW ;恢复现场RET ;子程序返回;加1子程序SEC_: INC SECMOV A, SECMOV B, #10DIV ABMOV SECSHI, AMOV SECGE, BMOV A, SECCJNE A, #60, EXIMOV SEC, #0MOV SECGE, #0MOV SECSHI, #0LJMP EXIMIN_: INC MINMOV A, MINMOV B, #10DIV ABMOV MINSHI, AMOV MINGE, BMOV A, MINCJNE A, #60, EXIMOV MIN, #0MOV MINGE, #0MOV MINSHI, #0LJMP EXIHOUR_: INC HOURMOV A, HOURMOV B, #10DIV ABMOV HOURSHI, AMOV HOURGE, BMOV A, HOURCJNE A, #24, EXIMOV HOUR, #0MOV HOURGE, #0MOV HOURSHI, #0EXI: RET;常数表格区------------------------------------------------------------;系统初始化后提示符“P.”字符代码表DISBH: DB 11H,10H,10H,10H,10H,10H,10H,10H ;“P.”字符序号DISBI: DB 00H,00H,12H,00H,00H,12H,00H,00H;显示字符段选码表(共阳极代码)TAB: DB 0C0H, 0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H ;0-8DB 90H,88H,83H,0C6H,0A1H,86H,8EH,0FFH,0CH,0BFH;9,A,B,C,D,E,F,灭,p. END。
单片机基于c语言编写时钟#include <REGX51.H>#define uint unsigned int#define uchar unsigned charchar led[10]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xe6};//共阴数码管数字码#define weixuan P0 //P0为数码管的段选sbit sck=P2^7; //移位时钟sbit tck=P2^6; //锁存时钟sbit data1=P2^5; //串行数据输入sbit x1=P1^0;sbit x2=P1^1;sbit x3=P1^2;sbit bee=P3^5;sbit time_change=P1^5; //P3^0为"调时"按键sbit time_choose=P1^6; //P3^1为"选择时分秒"按键sbit time_inc=P1^7; //P3^2为"增加"按键sbit time_ok=P3^3; //P3^3为"完成"按键uint t;uchar sec,min,hour,sec_ge,sec_shi,min_ge,min_shi,hour_ge,hour_shi; //定义秒,分,时,秒的个位,十位,分的个位,十位,时的个位,十位int choose_n; //按下"选择时分秒"按键的次数int flag; //定义"调时"按键的标志位//---------------------------------------------------------------------void init();void display();void delay(int x);void time_modify();void send(uchar data8);void naozhong();//---------------------------------------------------------------------void main(){init();while(1){TR0=1;display();time_modify();}}//---------------------------------------------------------------------void init(){t=choose_n=0;sec_ge,sec_shi,min_ge,min_shi,hour_ge,hour_shi,sec=min=hour=flag=0;TMOD=0x01; //定义定时器0工作与方式1TH0=(65536-60000)/256; //定时器赋初值TL0=(65536-60000)%256;EA=1; //开总中断和T0中断ET0=1;}//---------------------------------------------------------------------void send(uchar data8) // 数据发送{uchar i;//设置循环变量sck=1;tck=1;for(i=0;i<=7;i++){if((data8>>i)&0x01)data1=1;elsedata1=0;sck=0;sck=1;}tck=0;tck=1;}//--------------------------------延时子函数------------------------------------void delay(int x){int i,j;for(i=0;i<=x;i++)for(j=0;j<=100;j++);}//-------------------------------显示子函数---------------------------------------void display(){int i=0;if(TF0==1) //如果定时器溢出{TF0=0; //清中断标志位t++;if(t==18){t=0;sec++; //秒加1if(sec==60) //如果秒为60,则清零,分加1{sec=0;min++;}if(min==60) //如果分为60,则清零,时加1{min=0;hour++;}if(hour==24) //如果时为24,则清零{hour=0;}}}sec_ge=sec%10; //秒的个位和十位sec_shi=sec/10;min_ge=min%10; //分的个位和十位min_shi=min/10;hour_ge=hour%10; //时的个位和十位hour_shi=hour/10;weixuan = 0xff; // p0口为1111 1111send(led[hour_shi]); // 显示第一位时weixuan= 0xfe; // p0口为1111 1110delay(1);weixuan=0xff; // 消影send(led[hour_ge]); // 显示第二位时weixuan= 0xfd; // p0口为1111 1101delay(1);weixuan=0xff; // 消影send(0x02); // 显示第三位weixuan= 0xfb; // p0口为1111 1011delay(1);weixuan=0xff; // 消影send(led[min_shi]); // 显示第四位分weixuan= 0xf7; // p0口为1111 0111delay(1);weixuan=0xff; // 消影send(led[min_ge]); // 显示第5位分weixuan= 0xef; // p0口为1110 1111delay(1);weixuan=0xff; // 消影send(0x02); // 显示第6位weixuan= 0xdf; // p0口为1101 1111delay(1);weixuan=0xff; // 消影send(led[sec_shi]); // 显示第7位秒weixuan= 0xbf; // p0口为1011 1111delay(1);weixuan=0xff; // 消影send(led[sec_ge]); // 显示第8位秒weixuan= 0x7f; // p0口为0111 1111delay(1);weixuan=0xff; // 消影}//----------------------------调时子程序-------------------------------void time_modify(){if(time_change==0) //如果"调时"按键按下{delay(5); //延时去抖if(time_change==0){flag=1; //标志位置1while(flag) //当标志位为1时才能进行时间调整{TR0=0; //定时器停止display(); //显示停止时的时间if(time_ok==0) //如果"完成"按键按下{delay(15); //延时去抖if(time_ok==0){flag=0; //标志位清零x1=1;x2=1;x3=1;}}if(time_choose==0) //如果"时分秒选择"按键按下{delay(30); //延时去抖if(time_choose==0){while(!time_choose);choose_n++; //按下的次数增加if(choose_n==4) //如果次数达到4次{choose_n=1; //次数清零}if(choose_n==1) //如果次数为1,秒指示灯亮{x1=0;x2=1;x3=1;}else if(choose_n==2) //如果次数为2,分指示灯亮{x1=1;x2=0;x3=1;}else if(choose_n==3) //如果次数为3,时指示灯亮{x1=1;x2=1;x3=0;}}}if(time_inc==0) //如果"增加"按键按下{delay(30); //延时去抖if(time_inc==0){switch(choose_n) //分支结构,根据choose_n的值来判断哪一位加1 {case 1: //如果choose_n为1,秒加1,到60清零{while(!time_inc);sec++;if(sec==60)sec=0;break;}case 2: //如果choose_n为2,分加1,到60清零{while(!time_inc);min++;if(min==60)min=0;break;}case 3: //如果choose_n为3,时加1,到24清零{while(!time_inc);hour++;if(hour==24)hour=0;break;}default:break;}}}}}}}。