㈠ 请问如何使用单片机定时器制作一个以00-00-00为初始的24小时制时钟
程序比较长,可用定时器定时50mS,累积20次,即1S,秒加1,60S后分加1,秒清0,60分后,小时加1,分清0 ,24小时后小时清0,这些都在定时器中断程序中完成,主程序只管显示时 分 秒即可。
㈡ 单片机电子时钟怎么调星期
按键控制电路中共有4个按键,按键1的功能是进行日期,时间的设置。
按下1次,进入“秒”设置;按下2次,进入“分”设置;按下3次,进入“时”设置;按下4次,进入“星期”设置;按下5次,进入“日”设计;按下6次;进入“月”设置;按下7次,进入“年”设置。按键2的功能是增加时间或日期。按键3的功能是减少时间或日期。按键4的功能是数码管显示的相应时间进行加或减。
系统上电首先初始化LCD1602和定时器,设置定时器模式、开启定时器中断,然后循环执行更新显示时间,实时扫描按键状态。当单片机上电以后,LCD上会立即显示出2021. 12.12 SUN 7 21:42:00即2021年12月12号,周日,21 时 42 分 0 秒,通过与实时扫描单片机 IO 口相连接的按键的控制可以实现对时间以及模式的调整,以调整到正确的时间和模式。
㈢ 求一个简单的单片机时钟程序
#include<reg51.h>
#defineucharunsignedchar
ucharcodeledtab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0-9
unsignedcharsec=0,min=0,hour=0,scanled;
unsignedcharkey,time;
unsignedchardisdat[6];
sbitK=P1^0;
voiddischg()
{
disdat[0]=sec%10;
disdat[1]=sec/10;
disdat[2]=min%10;
disdat[3]=min/10;
disdat[4]=hour%10;
disdat[5]=hour/10;
}
voidt0isr()interrupt1 //秒计时
{
TR0=0;
TH0=0x3c;
TL0=0xb0;
TR0=1;
time++;
if(time==20)
{
time=0;
sec++;
if(sec>59)
{
sec=0;
min++;
if(min>59)
{
min=0;
hour++;
if(hour>23)hour=0;
}
}
}
dischg();
}
voidt1isr()interrupt3 //显示
{
TH1=0xec;
TL1=0x78;
switch(scanled)
{
case0:
P2=0x01;
P0=~ledtab[disdat[5]];
break;
case1:
P2=0x02;
P0=~ledtab[disdat[4]]&0x7f;
break;
case2:
P2=0x04;
P0=~ledtab[disdat[3]];
break;
case3:
P2=0x08;
P0=~ledtab[disdat[2]]&0x7f;
break;
case4:
P2=0x10;
P0=~ledtab[disdat[1]];
break;
case5:
P2=0x20;
P0=~ledtab[disdat[0]];
break;
default:break;
}
scanled++;
scanled%=6;
}
main()
{
TMOD=0x11;
TH0=0x3c;
TL0=0xb0;
TH1=0xec;
TL1=0x78;
EA=1;
TR1=1;
ET0=1;
ET1=1;
sec=0;
min=0;
hour=0;
scanled=0;
time=0;
key=0;
dischg();
while(1)
{
if(K==0)
{
while(K==0);
key++;
key%=2;
}
switch(key)
{
case0:
TR0=1;
break;
case1:
TR0=0;
break;
}
}
}
㈣ 51单片机定时器定时时间t的影响因素有哪些
单片机的定时器,是对系统时钟脉冲进行计数的,因此定时器的最小定时时间,即响应时间,受制于系统时钟频率。
定时器的响应,大都是通过中断例程来实现,因此,运行起来就包括进入退出中断例程的基本耗时,以及用户的应用耗时,都在现实中影响到定时器的最小时间设定。
看见,影响定时器的根本是系统时钟频率,可操作的机会不大,在中断例程中抠点时间吧,主要还是在用户应用目的上,因此,代码效率很重要。
不要什么都放在中断例程中运行,可通过设置标记,让大部分代码在中断例程外运行。
㈤ 单片机电子时钟直接设置定时时间,并实时显示剩余时间
#include<reg51.h>
#defineucharunsignedchar
#defineuintunsignedint
#defineu8unsignedchar
#defineu16unsignedint
sbitk1=P3^1;//第一个按键,选择设置
ucharcodedistab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//共阴数码管段码表
uchardisbuf[8];//声明显示缓冲区8个单元
ucharhour=12;//声明小时变量,初值为12
ucharminute=59;//声明分变量,初值为59
ucharsecond;//声明秒变量
uchart0n;//定时器T0中断计数,定时50ms,中断20次为1秒
uchardis;//调时状态下,显示小数点位
voiddelay()//延时子程序,用于显示子程序
{
uintj;
for(j=300;j>0;j--);
}
//显示子程序,参数dis为显示小数点位
voiddisplay(uchardis)
{
ucharj,disbit=0x01;//位码
for(j=0;j<8;j++)
{
P2=~disbit;//P2口输出位码
if(dis>0&&dis==j)//调时状态下,显示小数点
P0=distab[disbuf[j]]+0x80;//在小时,分,秒位上显示小数点
else
P0=distab[disbuf[j]];//其它位正常显示
disbit<<=1;//取下一个位码
delay();//延时
}
}
#defineRxBUFSIZE10
u8RxBuf[RxBUFSIZE];
u8Rxcount=0;
u8Rxtime=0;
voidUartInit(){
SCON=0x50;
TMOD&=0x0f;
TMOD|=0x20;
TH1=TL1=0xfd;//11.059269600
TR1=1;
ES=1;
EA=1;
}
//格式Txx:xx:xx
//解析时间
voidJX1(){
u8a;
a=(RxBuf[1]-'0')*10+(RxBuf[2]-'0');
if(a>23)return;
hour=a; //时
a=(RxBuf[4]-'0')*10+(RxBuf[5]-'0');
if(a>59)return;
minute=a; //分
a=(RxBuf[7]-'0')*10+(RxBuf[8]-'0');
if(a>59)return;
second=a; //秒
}
voidUartCl(){
if((Rxtime>4)&&(Rxcount>=9)){
if(RxBuf[0]=='T'){
JX1();
}
Rxcount=0;
}
}
voidUartInterrupt()interrupt4
{
if(RI){
RI=0;
Rxtime=0;
if(Rxcount<RxBUFSIZE){
RxBuf[Rxcount++]=SBUF;
}
}
}
voidmain()
{
disbuf[2]=disbuf[5]=10;//数码管第3,6位显示-
TMOD=0x01;
TH0=0x3C;//单片机晶振频率=12M,定时50ms,时间常数=3CB0
TL0=0xB0;
IE=0x82;//开定时器T0中断
TR0=1;//启动定时器T0
IT0=1;//设置外部中断为下降沿有效
IT1=1;
UartInit();
while(1)
{
display(dis);//调显示子程序
UartCl();
if(k1==0)//选择设置
{
dis++;//停止计时,进入调时状态
EX0=1;//调时状态下,允许外部INT0,INT1中断
EX1=1;//用来调小时,分,秒
if(dis>7)//调小时,在小时位显示小数点
{
dis=0;//灭小数点
t0n=0;//调时结束,开始计时
TR0=1;
EX0=0;//关外部中断
EX1=0;
}
elseif(dis==2)dis=4;//调分,在分位显示小数点
elseif(dis==5)dis=7;//调秒,在秒位显示小数点
while(k1==0)display(dis);//等待按键释放
}
if(t0n>=20&&dis==0)//中断20次,1秒到,计时状态下时钟计时
{
t0n=0;
second++;//秒加1
if(second>=60)//到60秒
{
second=0;
minute++;//分加1
if(minute>=60)//到60分
{
minute=0;
hour++;//小时加1
if(hour>=24)
hour=0;
}
}
}
disbuf[0]=hour/10;//显示小时十位
disbuf[1]=hour%10;//显示小时个位
disbuf[3]=minute/10;//显示分十位
disbuf[4]=minute%10;//显示分个位
disbuf[6]=second/10;//显示秒十位
disbuf[7]=second%10;//显示秒个位
}
}
//定时器T0中断服务子程序
voidT0_isr()interrupt1
{
TH0=0x3C;//重写时间常数
TL0=0xb0;
t0n++;//中断次加1
if(++Rxtime>(20*5)){//超时处理
Rxtime=0;
Rxcount=0;
}
}
//外部中断INT0服务程序,调时状态下,加1
voidINT0_ISR()interrupt0
{
if(dis==1)//调小时
{
hour++;//小时加1
if(hour>=24)
hour=0;
}
if(dis==4)//调分
{
minute++;//分加1
if(minute>=60)
minute=0;
}
if(dis==7)//调秒
{
second++;//秒加1
if(second>=60)
second=0;
}
}
//外部中断INT1服务程序,调时状态下,减1
voidINT1_ISR()interrupt2
{
if(dis==1)//调小时
{
hour--;//小时减1
if(hour==0xff)
hour=23;
}
if(dis==4)//调分
{
minute--;//分减1
if(minute==0xff)
minute=59;
}
if(dis==7)//调秒
{
second--;//秒减1
if(second==0xff)
second=59;
}
}
㈥ 用51单片机实现时钟功能程序
anEQUP0;
weiEQUP2;
keyBITP3.7;
ORG0000H
AJMPMAIN;绝对转移指令,2kb范围(11位)内跳转LJMP16位64kb范围内跳转
;短转移指令的功能是先使程序计数器PC加1两次(即:取出指令码),然后把加2后的地址和rel相加作为目标转移地址。因此,短转移指令是一条相对转移指令,是一条双字节双周期指令
ORG0030H;指明后面的程序从程序存储器的0030H单元开始存放
DELAY200US:;@11.0592MHz
NOP
NOP
NOP
PUSH30H
PUSH31H
MOV30H,#2
MOV31H,#179
NEXT:
DJNZ31H,NEXT
DJNZ30H,NEXT
POP31H
POP30H
RET
ORG0060H
;DISPLAY子程序
DISPLAY:
PUSHACC;不能写A,此处ACC代表地址,push后跟地址,代表把地址内的内容压入栈中
PUSH00H;R0
PUSH06H;R6
PUSH07H;R7
PUSH83H;DPH
PUSH82H;DPL
MOVR6,#01H;位选数据,01指的是缓冲区最低位数据
MOVR7,#08H;循环次数
FLAG:
MOVan,#0x00;消影
MOVA,R6
CPLA;取反
MOVwei,A;位选
MOVA,#disBufDat
ADDA,R7
SUBBA,#0X08
MOVR0,A
MOVA,@R0;读出要显示的数据到A
MOVDPTR,#disTab
MOVCA,@A+DPTR;从rom取数据,取出要显示的数据对应的段码
MOVan,A;段选
MOVA,R6
RLA
MOVR6,A;更新下一次位选
LCALLDELAY200US
DJNZR7,FLAG
POP82H;DPL
POP83H;DPH
POP07H
POP06H
POP00H
POPACC
RET
ORG0100H
;定时器中断0初始化
T0_INIT:
MOVTMOD,#0X01
MOVTH0,#0X3C
MOVTL0,#0XB0
SETBEA
SETBTR0
SETBET0
RET
ORG0130H
;T0中断处理程序
INT_TIMERE0:
PUSHACC
SETBRS0
MOVTH0,#0X3C
MOVTL0,#0XB0
INCR0
MOVA,R0
SUBBA,#0X14
JBCY,SECFLAG
MOVR0,#0x00
INCsec
SECFLAG:
CLRRS0
POPACC
RETI
ORG000BH;定时器/计数器T0入口地址
LJMPINT_TIMERE0;跳转到定时器/计数器中断服务程序中去
disTab:DB0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x40;0-f,空白,横杠的段选数据
disBufDatEQU47H;定义显示缓冲数据变量区,8个
disBufDatHeadEQU40H//单片机上显示在最左边
secEQU48H
;主程序
ORG0180H
MAIN:
MOVSP,#0X60;将0x60到0x7f设为堆栈区
LCALLT0_INIT
MOVdisBufDatHead,#0X00
MOVdisBufDatHead+1,#0X00
MOVdisBufDatHead+2,#0X11
MOVdisBufDatHead+3,#0X11
MOVdisBufDatHead+4,#0X11
MOVdisBufDatHead+5,#0X11
MOVdisBufDatHead+6,#0X11
MOVdisBufDatHead+7,#0X11
MOVsec,#0X3A
WHILE:
JBkey,KEYSCAN
MOVsec,0x00
KEYSCAN:
MOVA,sec
SUBBA,#3CH;超过60s归零
JBCY,CLEAR
MOVsec,#0X00;clr加ram地址无效
CLEAR:
MOVA,sec
MOVB,#0AH
DIVAB;A/B,商存到A中,余数存B中
MOVdisBufDatHead,A
MOVdisBufDatHead+1,B
LCALLDISPLAY
LJMPWHILE;循环
END;
(6)单片机定时时钟扩展阅读
51机器周期和指令周期
1、机器周期是指单片机完成一个基本操作所花费的时间,一般使用微秒来计量单片机的运行速度,51单片机的一个机器周期包括12个时钟振荡周期,也就是说如果51单片机采用12MHz晶振,那么执行一个机器周期就只需要1μs;如果采用的是6MHz的晶振,那么执行一个机器周期就需要2μs。
2、指令周期是指单片机执行一条指令所需要的时间,一般利用单片机的机器周期来计量指令周期。在51单片机里有单周期指令(执行这条指令只需一个机器周期),双周期指令(执行这条指令只需要两个机器周期),四周期指令(执行这条指令需要四个机器周期)。
除了乘、除两条指令是四周期指令,其余均为单周期或双周期指令。也就是说,如果51单片机采用的是12MHz晶振,那么它执行一条指令一般只需1~2微秒的时间;如果采用的是6MH晶振,执行一条指令一般就需2~4微秒的时间。
㈦ 如何做一个单片机电子时钟
这个很简单啊,两种思路:1,用单片机定时器来做,优点是外围电路简单,只需要一个单片机最小系统,和一个显示模块(1602液晶比较好);缺点是:定时不是很准,跑的时间长了会有误差,而且主要是程序,要写很多,不过程序不是很难。2,用时钟芯片,一般都用DS1302,还需要单片机最小系统和显示模块,优点是:定时准确,误差很小,在有备用电池的情况下,即使单片机掉电,也可以维持很长时间,程序相对简单。缺点是:外围电路比前者相对复杂一点。如果想做个实际的东西拿来用,建议使用第二种方法,如果是想锻炼自己的编程能力的话,选第一种吧。祝成功!
㈧ 单片机定时器时钟设计程序,急求
#include<reg51.h>
#define uchar unsigned char
uchar code ledtab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0-9
unsigned char sec=0,min=0,hour=12,scanled;
unsigned char key,flashbit,mode,time;
unsigned char disdat[6];
sbit led=P1^0;
void delay(unsigned int x)
{
unsigned int i,j;
for(i=0;i<x;i++)
for(j=0;j<120;j++);
}
void dischg()
{
disdat[0]=sec%10;
disdat[1]=sec/10;
disdat[2]=min%10;
disdat[3]=min/10;
disdat[4]=hour%10;
disdat[5]=hour/10;
}
void flash()
{
switch(flashbit)
{
case 0:break;
case 1:
disdat[4]=0x10;
disdat[5]=0x10;
delay(50);
dischg();
delay(80);
break;
case 2:
disdat[2]=0x10;
disdat[3]=0x10;
delay(50);
dischg();
delay(80);
break;
case 3:
disdat[0]=0x10;
disdat[1]=0x10;
delay(50);
dischg();
delay(80);
break;
default:break;
}
}
void t0isr() interrupt 1 //秒计时
{
TH0=0x3c;
TL0=0xb0;
time++;
switch(mode)
{
case 0:
if(time==20)
{
time=0;
sec++;
if(sec>59)
{
sec=0;
min++;
if(min>59)
{
hour++;
if(hour>23)hour=0;
}
}
}
break;
case 1:
if(time==20)
{
time=0;
if(sec>0)sec--;
else if(min>0){sec=59;min--;}
else if(hour>0){sec=59;min=59;hour--;}
else {hour=0;min=0;sec=0;}
}
break;
}
dischg();
}
void t1isr() interrupt 3 //显示
{
TH1=0xec;
TL1=0x78;
switch(scanled)
{
case 0:
P2=0x01;
P0=~ledtab[disdat[5]];
break;
case 1:
P2=0x02;
P0=~ledtab[disdat[4]];
break;
case 2:
P2=0x04;
P0=~ledtab[disdat[3]];
break;
case 3:
P2=0x08;
P0=~ledtab[disdat[2]];
break;
case 4:
P2=0x10;
P0=~ledtab[disdat[1]];
break;
case 5:
P2=0x20;
P0=~ledtab[disdat[0]];
break;
default:break;
}
scanled++;
scanled%=6;
}
main()
{
TMOD=0x11;
TH0=0x3c;
TL0=0xb0;
TH1=0xec;
TL1=0x78;
EA=1;
TR1=1;
ET0=1;
ET1=1;
sec=0;
min=0;
hour=12;
flashbit=0;
scanled=0;
time=0;
mode=0;
dischg();
while(1)
{
flash();//闪烁
// led=1;
if((P3&0x0f)!=0x0f){
key=P3&0x0f;
while((P3&0x0f)!=0x0f);
led=0;
delay(10);
key|=0xf0;
switch(~key)
{
case 0x01: //p3.1选择调时、分、秒
TR0=0;
flashbit+=1;
if(flashbit>3){flashbit=0;TR0=1;}
break;
case 0x02: //p3.2调数
if(flashbit==0)break;
if(flashbit==1)
{
hour++;
if(hour>23)hour=0;
}
if(flashbit==2)
{
min++;
if(min>59)min=0;
}
if(flashbit==3)
{
sec++;
if(sec>59)sec=0;
}
break;
case 0x04: //选择正/倒
TR0=0;
mode++;
mode&=0x01;
if(mode==0){sec=0;min=0;hour=0;}
dischg();
break;
case 0x08: //启动/暂停
TR0=~TR0;
break;
default:break;
}
}
}
}