导航:首页 > 操作系统 > 单片机数字钟

单片机数字钟

发布时间:2022-04-15 12:55:31

‘壹’ 单片机做数字时钟,求程序

1、解决驱动码。得到显示所有字符的七段码。
2、解决动态扫描问题。在定时中断中顺序扫描其中一个数码管。
3、解决内容——定时的计时表述。Hour,Minute,Second,mS;
4、解决时间的修改设置。

1、通用码表
#define SEGA 1
#define SEGB 2
#define SEGC 4
#define SEGD 8
#define SEGE 0x10
#define SEGF 0x20
#define SEGG 0x40
#define SEGH 0x80
unsigned char code SegCode[11]=

{ ~(SEGA+SEGB+SEGC+SEGD+SEGE+SEGF),//0
~(SEGB+SEGC),//1
~(SEGA+SEGB+SEGD+SEGE+SEGG),//2
~(SEGA+SEGB+SEGC+SEGD+SEGG),//3
~(SEGB+SEGC+SEGF+SEGG),//4
~(SEGA+SEGC+SEGD+SEGF+SEGG),//5
~(SEGA+SEGC+SEGD+SEGE+SEGF+SEGG),//6
~(SEGA+SEGB+SEGC),//7
~(SEGA+SEGB+SEGC+SEGD+SEGE+SEGF+SEGG),//8
~(SEGA+SEGB+SEGC+SEGD+SEGF+SEGG),//9
~(SEGG),//—
};
2、动态扫描,内容放在
unsigned char i, Time[8]={0,0,0xa,0,0,0xa,0,0};
void Disp(unsigned char x)//显示第x个数码管的内容。
{
P0=0xff;
P1=SegCode[Time[x]];
P0=~(1<<x);
}
在定时中断中调用。
3、定时管理并得到50mS时基。按12MHz,定时1方式,定时器0配置中断。
定义unsigned char mS50,Sec,Min,Hour;
void InitialT0(void)//主程序调用一次
{
TMOD=0x1;
ET0=1;EA=1;TR0=1;
}
void ISRForT0(void) interrupt 1
{
TH0=(-50000)>>8;
TL0=(-50000)&0xff;
mS50++;
Disp(i++%8);
if(mS50>19)
{
mS50=0;
Sec++;
if(Sec>59){Sec=0;Min++;if(Min>59){Min=0;Hour++;Hour%=24;}}
Time[0]=Hour/10;
Time[1]=Hour%10;
Time[3]=Min/10;
Time[4]=Min%10;
Time[6]=Sec/10;
Time[7]=Sec%10;
}
}
4、修改时间的问题,还是等你自己忙吧。放到while(1)里面读键,修改Hour,Min,Sec即可。
main函数如下:把上面的代码全部搞到一起,编译通过后调试吧。
main()
{
InitialT0();
while(1);
}

【补充一下,明天数码管会闪的厉害。把中断时间改成2mS,再试一遍。】

‘贰’ 单片机数字时钟比实际时间的慢啊怎么办

单片机是利用定时器实现计时的,根据定时器的定时计算出的时间常数,是理想状态下的数值。
如晶振频率是12M,用定时器T0,按定时20ms 计算的时间常数
TH0=(65536-20000)/256=0XB1
TL0=(65536-20000)%256=0XE0
如果按这个数写程序,电子钟计时的时间肯定就比实际的时间慢。当然了,这需要时间长了,才能体现出来,如果只是计时几个小时是比较不出来的。必须是长时间的计时,比如计时一周以上就体现出来计时的误差了。
这是因为,单片机计时的误差还是比较小的,假如一天慢1秒,那计时一周了,就慢7秒,才会发现的。
为什么会慢呢,是因为定时到,要中断,单片机从响应中断,到在中断程序中重写时间常数,才能重新计时的,这是需要时间,只是这时间只有几个微秒。就产生了计时误差了。可是这向微秒的误差,累计一周后就累计成几秒了。
要计时比较准确的还是有办法的,就是给时间常数的TL0加几个数,来补偿误差。
通常加8就行,不过,还需要长时间的计时来校正。
在中断程序中的时间常数改为
TH0=0XB1;
TL0=0XE8; //这低8位加8,补偿误差
这样补偿后,还有误差,再改这低8位,慢了就加,快了就减

‘叁’ 基于单片机的数字时钟怎么做

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit la=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;
uchar count,s1num;
char miao,shi,fen;
uchar code table[]=" 2007-7-30 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;
lcden=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}

void write_date(uchar date)
{
rs=1;
lcden=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}

void init()
{
uchar num;
la=0;
wela=0;
lcden=0;
// fen=59;
// miao=53;
// shi=23;
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 write_sfm(uchar add,uchar date)
{
uchar shi,ge;
shi=date/10;
ge=date%10;
write_com(0x80+0x40+add);
write_date(0x30+shi);
write_date(0x30+ge);
}

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++;
if(miao==60)
miao=0;
write_sfm(10,miao);
write_com(0x80+0x40+10);

}
if(s1num==2)
{
fen++;
if(fen==60)
fen=0;
write_sfm(7,fen);
write_com(0x80+0x40+7);
}
if(s1num==3)
{
shi++;
if(shi==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)
{
/* if(miao==0)
{
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}*/
miao--;
if(miao==-1)
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}
if(s1num==2)
{
fen--;
if(fen==-1)
fen=59;
write_sfm(7,fen);
write_com(0x80+0x40+7);
}
if(s1num==3)
{
shi--;
if(shi==-1)
shi=23;
write_sfm(4,shi);
write_com(0x80+0x40+4);
}
}
}
}
}
void main()
{
init();
while(1)
{
keyscan();

}
// while(1);
}

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);

}
}

这个是数字时钟的源程序,用12864夜晶显示。

‘肆’ 怎么用单片机制作可调数字时钟

AJMPMAIN

ORG03H

MOVP3,#0FFH

AJMPAJ2

RETI

ORG13H

MOVP3,#0FFH

AJMPAJ1

RETI

ORG1BH

MOVTH1,#0ECH

MOVTL1,#78H

DJNZR6,BACK

MOVR6,#200

AJ:MOVR0,#35H;秒

INC@R0

CJNE@R0,#10,$+3

JCBACK

MOV@R0,#0

MOVR0,#34H

INC@R0

CJNE@R0,#6,$+3

JCBACK

MOV@R0,#0

AJ1:MOVR0,#33H;分

INC@R0

CJNE@R0,#10,$+3

JCBACK

MOV@R0,#0

MOVR0,#32H

INC@R0

CJNE@R0,#6,$+3

JCBACK

MOV@R0,#0

AJ2:MOVR0,#31H;时

INC@R0

CJNE@R0,#4,$+3

JCBACK

CJNE@R0,#5,$+3

JCS24

CJNE@R0,#10,$+3

JCBACK

MOV@R0,#0

MOVR0,#30H

INC@R0

BACK:RETI

S24:DECR0

CJNE@R0,#2,$+3

JCBACK

MOV@R0,#0

MOV31H,#0

RETI

MAIN:MOVR1,#30H

MOV@R1,#0

INCR1

CJNER1,#36H,MAIN+2

MOVP3,#0FFH

MOVP0,#0

MOVDPTR,#SEGPT

MOVR6,#200

MOVTMOD,#10H

MOVTH1,#0ECH

MOVTH1,#78H

SETBIT0

SETBIT1

MOVIP,#15H

MOVIE,#9FH

SETBTR1

LOOPO:MOVR1,#30H

MOVR7,#20H

LOOPI:MOVP2,#0

MOVA,@R1

MOVCA,@A+DPTR

MOVP1,A

MOVP2,R7

INCR1

MOVA,R7

RRA

MOVR7,A

CJNER7,#80H,LOOPI

SJMPLOOPO

SEGPT:DB40H,79H,24H,30H,19H,12H,2,78H,0,18H

‘伍’ 单片机课程设计:简易数字钟

20. 数字钟[★]
1. 实验任务

(1. 开机时,显示12:00:00的时间开始计时;

(2. P0.0/AD0控制“秒”的调整,每按一次加1秒;

(3. P0.1/AD1控制“分”的调整,每按一次加1分;

(4. P0.2/AD2控制“时”的调整,每按一次加1个小时;

#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;

}

}

‘陆’ 单片机数字钟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;//设置定时器工作方式为2,8位定时状态,自动装入初值。
TH0=0x06;//装入初值
TL0=0x06;
TR0=1;//起动定时器
ET0=1;//开启定时器中断
EA=1;//开总中断

while(1)
{//主循环
if(P0_0==0)//如果P0.0位等于0,往下走
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);//延时防抖动
if(P0_0==0)//再次判断P0.0是否等于0,如果是,则设置秒
{
second++;//秒加1
if(second==60)//如果秒等于60,又重0开始,以便开始走时
{
second=0;
}
dispbuf[0]=second%10;//刷新秒个位,并装驱动显示缓冲寄存器
dispbuf[1]=second/10;//刷新秒十位,同上。
while(P0_0==0);//等待P0.0放开。(等待按键放开)
}
}
if(P0_1==0)//如果P0.1位等于0,往下走
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);//延时防抖动
if(P0_1==0)//再次判断P0.1是否等于0,如果是,则设置分钟值
{
minite++;//分钟加1
if(minite==60)//
{
minite=0;
}
dispbuf[3]=minite%10;//刷新分钟个位,并装驱动显示缓冲寄存器
dispbuf[4]=minite/10;//刷新分钟十位,同上
while(P0_1==0);//等待P0.1放开。(等待按键放开)
}
}
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++;//用于刷新所显示的数据,第中断8次显示1位数码管(动态显示)
if(mstcnt==8)//判断中断8次没,如果是,则显示数据
{
mstcnt=0;
P1=dispcode[dispbuf[dispbitcnt]];//段位码送P1口,驱动数码管显示
P3=dispbitcode[dispbitcnt];//选中数码管显示位
dispbitcnt++;//显示索引,用于调哪一位数据
if(dispbitcnt==8)//判断调完没,如果调完了,则又从第一位开始。
{
dispbitcnt=0;
}
}
tcnt++;//第中断一次自动加1,如果中断4000次,则秒自动加1(这里的中断次数可以跟据你所置的定时器初值来改变)
if(tcnt==4000)
{
tcnt=0;
second++;//秒加1
if(second==60)//如果秒等于60,则分钟自动加1,并且秒回0
{
second=0;
minite++;//分钟加1
if(minite==60)//如果分钟等于0,则小时值自动加1,并且分钟回0
{
minite=0;
hour++;//小时值加1
if(hour==24)//如果小时值等于24,则回0
{
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;
}
}

‘柒’ 单片机数字时钟原理

给你个程序看看,主要是看时分显示哪里!这个程序已经调试通过了,在走时的同时流水灯进行流动,时分之间有一个小数点作为分隔。还有整点报时功能,在早上八点到中午十二点以及下午三点到晚上八点两个时间段内逢整点报时,其他时间不报时(是因为考虑到人们要午休及晚间休息),除此之外还有调时、调分功能。整个程序基于单片机AT89S52(可用C51、C52、S51等代替)。

#include <reg52.h>
#define uint unsigned int
sbit P3_0=P3^0;
sbit K1=P3^2;
sbit K2=P3^3;
sbit K3=P3^4;
sbit K4=P3^5;
uint count,min,hour,i,j=0;
uint code tab1[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uint code tab2[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
uint code tab3[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff,
0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,0xff,0x00,0xff,0x00,0xff,
0xfe,0xfb,0xef,0xbf,0xfd,0xf7,0xdf,0x7f,0x7e,0x3c,0x18,0x00,0x81,
0xc3,0xe7,0xff,0xe7,0xdb,0xbd,0x7e,0xff,0x7e,0xbd,0xdb,0xe7,0xff,
0x00,0xff,0x00,0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x80,
0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0x00,0xff,0x00,0xff,0xfe,0xfc,
0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,
0xff,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f,0xff,0x00,0xff,0x00,0xff};//流水灯

void adjust(void)
{
if(!K3) //分调整
{
for(i=0;i<20000;i++);min++;
if(min==60)min=0;
}
if(!K4) //时调整
{
for(i=0;i<20000;i++);hour++;
if(hour==24)hour=0;
}
}

void display(void)
{
P0=tab1[min%10];P2=0xf7;for(i=0;i<5;i++);P2=0xff;//分个位显示
P0=tab1[min/10];P2=0xfb;for(i=0;i<5;i++);P2=0xff;//分十位显示
P0=tab2[hour%10];P2=0xfd;for(i=0;i<5;i++);P2=0xff;//时个位显示
P0=tab1[hour/10];P2=0xfe;for(i=0;i<5;i++);P2=0xff;//时十位显示
}

void ring(void)
{
if(hour/10==0&&(hour%10>=8&&hour%10<=9))P3_0=0;//早上7:00到晚上7:00自动整点报时,其中13、14点不报时
if(hour/10==1&&(hour%10>=0&&hour%10<=2))P3_0=0;
if(hour/10==1&&(hour%10>=5&&hour%10<=9))P3_0=0;
}

void update(void)
{
if(count==1200)
{
count=0;min++;
if(min==60)
{
min=0;hour++;
if(hour==24)hour=0;
ring();
}
}
}

void main(void)
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=1;
EA=1;
ET0=1;
while(1)
{
if(count==120)P3_0=1;//报时六秒后自动关闭蜂鸣器
adjust();
display();
}
}

void timer0_rupt(void) interrupt 1 // 定时器0中断
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count%10==0)
{
P1=tab3[j];
j++;
if(j>99)j=0;
}
update();
}

‘捌’ 利用单片机(STC89C52)设计倒计时数字钟

#include<reg51.h>

#define uchar unsigned char
uchar code ledtab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//0-9
unsigned char sec=0,min=0,hour=24,scanled;
unsigned char key,mode,time;
unsigned char disdat[8];
unsigned char alarm[3]={23,59,0},dly;
sbit keyhu=P1^0;
sbit keyhd=P1^1;
sbit keymu=P1^2;
sbit keymd=P1^3;
sbit keysu=P1^4;
sbit keysd=P1^5;
sbit keyst=P1^6;
sbit fmq=P3^0;
bit flag=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 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)
{
min=0;
hour++;
if(hour>23)hour=0;
}
}
}
break;
case 1:
if(time==20)
{
time=0;
if(sec>0 && flag==0)sec--;
else if(min>0 && flag==0){sec=59;min--;}
else if(hour>0 && flag==0){sec=59;min=59;hour--;}

if((hour == alarm[0]) && (min == alarm[1]) && (sec == alarm[2])){fmq=1;flag=1;dly++;}
}
break;
}
if(dly>=2){fmq=0;flag=0;TR0=0;dly=0;}
dischg();
}
void t1isr() interrupt 3//显示
{
TH1=0xec;
TL1=0x78;
switch(scanled)
{
case 0:
P2=0x20;
P0=~ledtab[disdat[5]];
break;
case 1:
P2=0x10;
P0=~ledtab[disdat[4]]&0x7f;
break;
case 2:
P2=0x08;
P0=~ledtab[disdat[3]];
break;
case 3:
P2=0x04;
P0=~ledtab[disdat[2]]&0x7f;
break;
case 4:
P2=0x02;
P0=~ledtab[disdat[1]];
break;
case 5:
P2=0x01;
P0=~ledtab[disdat[0]];
break;
default:break;
}
scanled++;
scanled%=6;
}
main()
{
TMOD=0x11;
TH0=0x3c;
TL0=0xb0;
TH1=0xec;
TL1=0x78;
TR1=1;
TR0=0;
ET0=1;
ET1=1;
EA=1;
fmq=0;
scanled=0;
time=0;
mode=1;
dischg();
while(1)
{
if(keyhu==0)
{
while(keyhu==0);
TR0=0;
hour++;
hour%=24;
}
if(keyhd==0)
{
while(keyhd==0);
TR0=0;
if(hour>0)hour--;
if(hour==0)hour=23;

}
if(keymu==0)
{
while(keymu==0);
TR0=0;
min++;
min%=60;
}
if(keymd==0)
{
while(keymd==0);
TR0=0;
if(min>0)min--;
if(min==0)min=59;
}
if(keysu==0)
{
while(keysu==0);
TR0=0;
sec++;
sec%=60;
}
if(keysd==0)
{
while(keysd==0);
TR0=0;
if(sec>0)sec--;
if(sec==0)sec=59;
}
if(keyst==0)
{
while(keyst==0);
TR0=~TR0;
}
dischg();
}
}

‘玖’ 基于单片机的数字钟 论文设计

ORG 0000H ;程序入口地址
LJMP START
ORG 000BH ;定时器0中断入口地址
LJMP TIMER_0
ORG 0300H
/*****程序开始,初始化*****/
START:
SETB 48H ;使用一个bit位用于调时闪烁标志
SETB 47H ;使用一个bit位用于产生脉冲用于调时快进时基
MOV R1,#0 ;调整选择键功能标志:0正常走时、1调时、2调分、3调秒
MOV 20H,#00H ;用于控制秒基准时钟源的产生
MOV 21H,#00H ;清零秒寄存器
MOV 22H,#00H ;清零分寄存器
MOV 23H,#00H ;清零时寄存器
MOV 24H,#00H ;用于控制调时闪烁的基准时钟的产生

MOV IP,#02H ;IP,IE初始化
MOV IE,#82H
MOV TMOD,#01H ;设定定时器0工作方式1
MOV TH0,#3CH
MOV TL0,#0B0H ;赋定时初值,定时50ms
SETB TR0 ;启动定时器0
MOV SP,#40H ;重设堆栈指针
/*****主程序*****/
MAIN:
LCALL DISPLAY ;调用显示子程序
LCALL KEY_SCAN ;调用按键检测子程序
JZ MAIN ;无键按下则返回重新循环
LCALL SET_KEY ;调用选择键处理子程序
JB 46H,MAIN ;如果已进行长按调整(调时快进),则不再执行下面的单步调整
LCALL ADD_KEY ;调用增加键处理子程序,加一
LCALL DEC_KEY ;调用减少键处理子程序,减一
LJMP MAIN ;重新循环

/*****定时器中断服务程序*****/
TIMER_0:
PUSH ACC
PUSH PSW ;保护现场
MOV TH0,#3CH
MOV TL0,#0B0H ;重新赋定时初值
CPL 47H ;产生脉冲用于调时快进时基
INC 24H
MOV A,24H
CJNE A,#10,ADD_TIME ;产生0.5秒基准时钟,用于调时闪烁
CPL 48H ;取反调时闪烁标志位
MOV 24H,#00H
ADD_TIME: ;走时
INC 20H
MOV A,20H
CJNE A,#20,RETI1 ;产生1秒基准时钟
MOV 20H,#00H ;一秒钟时间到,清零20H
MOV A,21H
ADD A,#01H
DA A ;作十进制调整
MOV 21H,A
CJNE A,#60H,RETI1
MOV 21H,#00H ;一分钟到
MOV A,22H
ADD A,#01H
DA A
MOV 22H,A
CJNE A,#60H,RETI1
MOV 22H,#00H ;一小时到
MOV A,23H
ADD A,#01H
DA A
MOV 23H,A
CJNE A,#24H,RETI1
MOV 23H,#00H ;到24点,清零小时

RETI1:
POP PSW
POP ACC ;恢复现场
RETI ;中断返回
/*****显示处理*****/
DISPLAY:
MOV A,21H ;秒
ANL A,#0FH
MOV 2FH,A ;转换出秒个位,存入2FH
MOV A,21H
ANL A,#0F0H
SWAP A
MOV 2EH,A ;转换出秒十位,存入2EH
JB 46H,MIN ;如果长按按键(调时快进),则跳过闪烁处理程序
CJNE R1,#3,MIN ;如果R1为3,闪烁秒位待调整
JB 48H,MIN
MOV 2FH,#0AH ;使该位为10,查表得到使该位不显示的输出
MOV 2EH,#0AH
MIN:
MOV A,22H ;分
ANL A,#0FH
MOV 2DH,A ;转换出分个位,存入2DH
MOV A,22H
ANL A,#0F0H
SWAP A
MOV 2CH,A ;转换出分十位,存入2CH
JB 46H,HOUR ;如果长按按键(调时快进),则跳过闪烁处理程序
CJNE R1,#2,HOUR ;如果R1为2,闪烁分位待调整
JB 48H,HOUR
MOV 2DH,#0AH ;使该位为10,查表得到使该位不显示的输出
MOV 2CH,#0AH
HOUR:
MOV A,23H ;时
ANL A,#0FH
MOV 2BH,A ;转换出时个位,存入2BH
MOV A,23H
ANL A,#0F0H
SWAP A
MOV 2AH,A ;转换出时十位,存入2AH
JB 46H,DISP ;如果长按按键(调时快进),则跳过闪烁处理程序
CJNE R1,#1,DISP ;如果R1为1,闪烁时位待调整
JB 48H,DISP
MOV 2BH,#0AH ;使该位为10,查表得到使该位不显示的输出
MOV 2AH,#0AH
/*****数码管动态扫描显示*****/
DISP:
MOV DPTR,#TABLE
MOV A,2FH
MOVC A,@A+DPTR
MOV P0,A
setb P2.7
LCALL DELAY
clr P2.7 ;显示秒个位
MOV A,2EH
MOVC A,@A+DPTR
MOV P0,A
setb P2.6
LCALL DELAY
clr P2.6 ;显示秒十位
MOV A,#0BFH
MOV P0,A
setb P2.5
LCALL DELAY
clr P2.5 ;显示"-"
MOV A,2DH
MOVC A,@A+DPTR
MOV P0,A
setb P2.4
LCALL DELAY
clr P2.4 ;显示分个位
MOV A,2CH
MOVC A,@A+DPTR
MOV P0,A
setb P2.3
LCALL DELAY
clr P2.3 ;显示分十位
MOV A,#0BFH
MOV P0,A
setb P2.2
LCALL DELAY
clr P2.2 ;显示"-"
MOV A,2BH
MOVC A,@A+DPTR
MOV P0,A
setb P2.1
LCALL DELAY
clr P2.1 ;显示时个位
MOV DPTR,#TABLE1 ;该位使用TABLE1以消除前置0
MOV A,2AH
MOVC A,@A+DPTR
MOV P0,A
setb P2.0
LCALL DELAY
clr P2.0 ;显示时十位
RET

/*****按键检测子程序*****/
KEY_SCAN:
CLR 46H ;关闭长按调整(调时快进)标志
MOV P1,#0FFH ;将P1口设置成输入状态
MOV A,P1
CPL A
ANL A,#07H ;P1口低3位连接3个按键,只判断该3位
JZ EXIT_KEY ;无键按下则返回
LCALL DELAY ;延时去抖动
MOV A,P1 ;重新判断
CPL A
ANL A,#07H
JZ EXIT_KEY ;键盘去抖动
MOV R5,A ;临时将键值存入R5
MOV R4,#00H ;用于控制调时快进速度
;设置为00H是为了在进入长按处理前加长延时区分用户的长按与短按,防止误快进

LOOP: ;进入长按处理
LCALL DISPLAY ;使长按时显示正常
MOV A,P1
CPL A
ANL A,#07H
JB 47H,LOOP1
INC R4 ;调时快进间隔时间基准加1
LOOP1:
CJNE R1,#03H,LOOP2 ;如果调秒时长按,则不处理
LJMP LOOP3
LOOP2:
CJNE R4,#99H,LOOP3
MOV R4,#70H ;确认用户长按后,重新设定起始值,加快调时快进速度
SETB 46H ;长按调整(调时快进)标志
LCALL ADD_KEY
LCALL DEC_KEY
LOOP3:
JNZ LOOP ;等待键释放
MOV A,R5 ;输出键值
RET
EXIT_KEY:
RET
/*****延时子程序*****/
DELAY:
MOV R7,#150
DJNZ R7,$
RET

/*****选择键处理子程序*****/
SET_KEY:
CJNE R5,#01H,EXIT ;选择键键值
INC R1 ;调整选择功能标志加一
CJNE R1,#4,EXIT
MOV R1,#0
MOV 24H,#00H ;调时闪烁基准清零
RET
/*****增加键处理子程序*****/
ADD_KEY:
CJNE R5,#02H,EXIT ;增加键键值
CJNE R1,#01H,NEXT1 ;选择键功能标志为1,调时,否则跳出
MOV A,23H
ADD A,#01H
DA A
MOV 23H,A
CJNE A,#24H,EXIT
MOV 23H,#00H
NEXT1:
CJNE R1,#02H,NEXT2 ;选择键功能标志为2,调分,否则跳出
MOV A,22H
ADD A,#01H
DA A
MOV 22H,A
CJNE A,#60H,EXIT
MOV 22H,#00H
NEXT2:
CJNE R1,#03H,EXIT ;选择键功能标志为3,调秒,否则跳出
MOV 21H,#00H ;如增加键按下直接清零秒
RET
/*****减少键处理子程序*****/
DEC_KEY:
CJNE R5,#04H,EXIT ;减少键键值
CJNE R1,#01H,NEXT3 ;选择键功能标志为1,调时,否则跳出
MOV A,23H
ADD A,#99H
DA A
MOV 23H,A
CJNE A,#99H,EXIT
MOV 23H,#23H

NEXT3:
CJNE R1,#02H,NEXT4 ;选择键功能标志为2,调分,否则跳出
MOV A,22H
ADD A,#99H
DA A
MOV 22H,A
CJNE A,#99H,EXIT
MOV 22H,#59H
NEXT4:
CJNE R1,#03H,EXIT ;选择键功能标志为3,调秒,否则跳出
MOV 21H,#00H ;如较少键按下直接清零秒
RET
/*****万用返回子程序*****/
EXIT:
RET
/*****数码管字形编码表*****/
TABLE:
DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH ;字形显示编码
TABLE1:
DB 0FFH,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH ;小时位的十位数编码,该位如果为0则不显示
END ;程序结束

‘拾’ 单片机数字时钟汇编程序设计分析

时钟设计基本上就是通过电子 定时器定时 到1s给一个中断 让单片机去执行中断 跳转至相应的数码管位 然后修改当前显示值 再设置到10进位加一 之后就出来数字时钟的效果 弄懂定时器 一切就顺下来了
这是一个C得时钟程序 你看明白思想 就好说汇编的语句了
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char

sbit la=P3^7;

sbit L1=P2^0;
sbit L2=P2^1;
sbit L3=P2^2;
sbit key1=P3^0;
sbit key2=P3^1;
sbit key3=P3^2;
sbit key4=P3^3;

uchar aa;
uchar code table[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
uchar nummiao,numfen,numshi,t0;

void delayms(uchar xms)
{
uchar i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void init()
{
TMOD=0x11;
TH0=(65536-50000)%256;
TL0=(65536-50000)/256;

EA=1;
ET0=1;

}
void display(uchar nummiao,numfen,numshi)
{
uchar shishi,geshi,shifen,gefen,shimiao,gemiao;
shimiao=nummiao/10;
gemiao=nummiao%10;
shifen=numfen/10;
gefen=numfen%10;
shishi=numshi/10;
geshi=numshi%10;

la=1;
P0=table[shimiao];
la=0;
L1=0;
L2=1;
L3=1;
delayms(5);

la=1;
P0=table[gemiao];
la=0;
L1=1;
L2=1;
L3=1;
delayms(5);

la=1;
P0=0x40;
la=0;
L1=1;
L2=0;
L3=1;
delayms(5);

la=1;
P0=table[gefen];
la=0;
L1=0;
L2=0;
L3=1;
delayms(5);

la=1;
P0=table[shifen];
la=0;
L1=1;
L2=1;
L3=0;
delayms(5);

la=1;
P0=0x40;
la=0;
L1=0;
L2=1;
L3=0;
delayms(5);

la=1;
P0=table[geshi];
la=0;
L1=1;
L2=0;
L3=0;
delayms(5);

la=1;
P0=table[shishi];
la=0;
L1=0;
L2=0;
L3=0;
delayms(5);

}

void keyscan()
{
if(key1==0)
{
delayms(10);
if(key1==0)
{

numshi++;
if(numshi==24)
numshi=0;
while(!key1);

}

}

if(key2==0)
{
delayms(10);
if(key2==0)
{

if(numfen==60)
numfen=0;
numfen++;
while(!key2);

}
}

if(key3==0)
{
delayms(10);

if(key3==0)
{

nummiao=0;
while(!key3);

}
}

if(key4==0)
{
delayms(10);
if(key4==0)
{

while(!key4);
TR0=~TR0;

}
}
}

void main()
{

init();

aa=0xfe;

while(1)
{
P1=aa;

if(nummiao==60)
{
numfen++;
nummiao=0;}
if(numfen==60)
{ numshi++;
numfen=0;}
if(numshi==24)
numshi=0;
keyscan();
display(nummiao,numfen,numshi);

}

}

void t0time()interrupt 1
{

TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
t0++;
if(t0==20)
{
t0=0;

nummiao++;}

aa=_crol_(aa,1);

}

阅读全文

与单片机数字钟相关的资料

热点内容
dbug命令 浏览:349
开逛app如何加好友 浏览:958
ftpdos命令下载文件 浏览:73
华为如何打开语音服务器 浏览:240
python中的idle 浏览:998
五轴联动数控编程 浏览:963
换一台电脑如何远程云服务器 浏览:130
阿里云怎么买云服务器 浏览:662
java提取文字 浏览:95
阿里云服务器同人账号问题 浏览:418
5分钟解压轴题 浏览:339
安卓桌面二级文件夹 浏览:186
eps文档加密 浏览:261
手机怎么做pdf 浏览:162
ug曲面pdf 浏览:279
液化气还是压缩气 浏览:950
阿里云公共ntp服务器地址 浏览:991
金字塔学习机编程 浏览:684
多边形扫描线算法Python 浏览:718
快手app快手粉条在哪里 浏览:256