用51单片机实现时钟功能程序???

用四位显示管要实现秒表、时钟、闹钟1、闹钟2功能。由按键控制。按键数3个。。

duanEQUP0;

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:

MOVduan,#0x00;消影

MOVA,R6

CPLA;取反

MOVwei,A;位选

MOVA,#disBufDat

ADDA,R7

SUBBA,#0X08

MOVR0,A

MOVA,@R0;读出要显示的数据到A

MOVDPTR,#disTab

MOVCA,@A+DPTR;从rom取数据,取出要显示的数据对应的段码

MOVduan,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;

扩展资料

51机器周期和指令周期

1、机器周期是指单片机完成一个基本操作所花费的时间,一般使用微秒来计量单片机的运行速度,51单片机的一个机器周期包括12个时钟振荡周期,也就是说如果51单片机采用12MHz晶振,那么执行一个机器周期就只需要1μs;如果采用的是6MHz的晶振,那么执行一个机器周期就需要2μs。

2、指令周期是指单片机执行一条指令所需要的时间,一般利用单片机的机器周期来计量指令周期。在51单片机里有单周期指令(执行这条指令只需一个机器周期),双周期指令(执行这条指令只需要两个机器周期),四周期指令(执行这条指令需要四个机器周期)。

除了乘、除两条指令是四周期指令,其余均为单周期或双周期指令。也就是说,如果51单片机采用的是12MHz晶振,那么它执行一条指令一般只需1~2微秒的时间;如果采用的是6MH晶振,执行一条指令一般就需2~4微秒的时间。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2013-08-28
这个功能建议你用DS1302时钟芯片实现!编程就容易多了,至于程序就自己编写吧,这样才有意义!
第2个回答  推荐于2017-12-16
#define uchar unsigned char //定义一下方便使用
#define uint unsigned int
#define ulong unsigned long
#include <reg52.h> //包括一个52标准内核的头文件

uchar code zixing[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar code ziwei[]={0x10,0x20,0x40,0x80};
uchar *h,*m;
uchar hour=12,min=0,sec=0,h_ding,m_ding,count=0,ms_50,ms_10,miaobiao_sec;
sbit dp=P0^7;
sbit k1=P3^2;
sbit k2=P3^3;
sbit k3=P3^4;
sbit sound=P2^3;
sfr ZIXING=0x80; //p0口输出字形
sfr ZIWEI=0xa0; //P2口输出字位

typedef enum //枚举类型:4种状态//
{
CLOCK,
SET_RING1,
SET_RING2,
MIAOBIAO_RUN,
}STATE;
STATE status;

typedef struct //定时时间的数据结构//
{
uchar hour;
uchar min;
}DINGSHI_TIME;
DINGSHI_TIME dingshi_time[2];

#define NO_KEY -1 //定义一下方便使用
#define KEY_1 1
#define KEY_2 2
#define KEY_3 3

bit show_on_flag;

//#######定时器T0中断服务程序########//
Timer0() interrupt 1
{
TH0=0x3c;TL0=0xb4; //50ms
ms_50++;
if(ms_50==20) {sec++;ms_50=0;}
if(sec==60) {sec=0;min++;}
if(min==60) {min=0;hour++;}
if(hour==24) {hour=0;}
}

//#######定时器T1中断服务程序########//
Timer1() interrupt 3
{
TH1=0xd8;TL1=0xf4; //10ms
ms_10++;
if(ms_10==100)
{
miaobiao_sec++;
ms_10=0;
}
if(miaobiao_sec==60)
miaobiao_sec=0;
}

//##############数码管显示#####################//
show(uchar time_high,uchar time_low)
{
uchar m;
uint n,k;
k=time_high*1000/10+time_low;
for(m=0;m<4;m++)
{
ZIXING=zixing[k%10];
if(ms_50<10)
dp=0;
ZIWEI=~ziwei[m];
for(n=0;n<500;n++);
ZIXING=0xff;
for(n=0;n<100;n++);
k=k/10;
}
}
//显示 on 定时编号//
show_on(uchar id) //id:定时编号//
{
uchar m;
uint n;

for(m=0;m<2;m++)
{
ZIXING=zixing[id%10];
dp=0;
ZIWEI=~ziwei[m];
for(n=0;n<500;n++);
ZIXING=0xff;
for(n=0;n<80;n++);
id=id/10;
}
ZIXING=0xc8; //字母n//
ZIWEI=~ziwei[2];
for(n=0;n<500;n++);
ZIXING=0xff;
for(n=0;n<200;n++);

ZIXING=0xc0; //字母0//
ZIWEI=~ziwei[3];
for(n=0;n<500;n++);
ZIXING=0xff;
for(n=0;n<200;n++);
}

/*************启动秒表***************/
void run_miaobiao()
{
ms_10=0;
miaobiao_sec=0;
TH1=0xd8; //标准是0xd8e4
TL1=0xf4;
// TR1=1; //启动定时器1
}

/*************显示秒表***************/
void show_miaobiao()
{
show(miaobiao_sec,ms_10);
}

/*********** 检测按键动作函数 *************/
int get_key()
{
uchar d;
if(!k1)
{
for(d=0;d<50;d++);
if(!k1)
{
while(!k1);
return(KEY_1);
}
}
if(!k2)
{
for(d=0;d<50;d++);
if(!k2)
{
while(!k2);
return(KEY_2);
}
}
if(!k3)
{
for(d=0;d<50;d++);
if(!k3)
{
while(!k3);
return(KEY_3);
}
}
else return NO_KEY;
}
/*****************************************

各状态下按键处理函数

******************************************/

void key_process_clock() // 处理时钟状态下的按键和显示//
{
switch(get_key())
{
case KEY_1:
status=SET_RING1; ;//切换状态
show_on_flag=1;
show_on(1);
break;
case KEY_2:
hour++;
if(hour==24) hour=0;
show(hour,min);
break;
case KEY_3:
min++;
if(min==60) min=0;
show(hour,min);
break;
case NO_KEY: //没有按键操作//
show(hour,min);
break;
}

}

/****************设定时1或2状态下的按键处理及显示*****************/
void key_process_set_dingshi()
{
switch(get_key())
{
case KEY_1:
if(status==SET_RING1)
{
status=SET_RING2; //切换设第二段定时状态
show_on_flag=1;
show_on(2);
}
else if(status==SET_RING2)
{
status=MIAOBIAO_RUN; //切换到秒表运行状态
run_miaobiao();
show_miaobiao();
}
break;
case KEY_2:
dingshi_time[status-1].hour++;
if(dingshi_time[status-1].hour==24)
dingshi_time[status-1].hour=0;
show(dingshi_time[status-1].hour,dingshi_time[status-1].min);
show_on_flag=0;
break;
case KEY_3:
dingshi_time[status-1].min++;
if(dingshi_time[status-1].min==60)
dingshi_time[status-1].min=0;
show(dingshi_time[status-1].hour,dingshi_time[status-1].min);
show_on_flag=0;
break;
case NO_KEY: //没有按键操作//
if(show_on_flag)
show_on(status);
else
show(dingshi_time[status-1].hour,dingshi_time[status-1].min);
break;
}
}

/********秒表运行状态按键处理及显示*********/
void key_process_miaobiao_run()
{
switch(get_key())
{
case KEY_1:
TR1=0;
status=CLOCK; //回到时钟显示状态
break;

case KEY_2:
TR1=!TR1; //定时器1暂停、继续
break;

case KEY_3:
TR1=0; //秒表复位
miaobiao_sec=0;
ms_10=0;
break;

case NO_KEY: //无按键操作//
show_miaobiao();
break;
}
}

//############主程序#######################//
void main(void)
{ sound=1;
TH0=0x3c;
TL0=0xb4;
TMOD=0x11;
TR0=1;
ET0=1;

TR1=0;
ET1=1;

EA=1;
status=CLOCK;

dingshi_time[0].hour=0;
dingshi_time[0].min=0;
dingshi_time[1].hour=0;
dingshi_time[1].min=0;

while(1) //程序循环
{
switch(status)
{
case CLOCK:
key_process_clock(); // 处理时钟状态下的按键和显示//
break;

case SET_RING1:

case SET_RING2:
key_process_set_dingshi(); //处理设置定时状态下的按键和显示//
break;

case MIAOBIAO_RUN:
key_process_miaobiao_run(); //处理秒表状态下的按键和显示//
break;
}
if(
((hour==dingshi_time[0].hour) //定时响铃//
&&(min==dingshi_time[0].min)
&&(sec<5))
||
((hour==dingshi_time[1].hour) //定时响铃//
&&(min==dingshi_time[1].min)
&&(sec<5))
)
sound=0;
else sound=1;
}
}本回答被网友采纳
相似回答