时钟程序汇编程序
㈠ 单片机数字时钟汇编程序设计分析
时钟设计基本上就是通过电子 定时器定时 到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);
}
㈡ 用汇编语言编写一个时钟程序,在微机屏幕上显示当前时间的时、分、秒。
;*********************************************************
; 带有时间设置和秒显示的数字闹钟
; Date : 2007.10.26 12MHZ晶振
; Create by :星星 缘木求鱼
; P3.2设置键 P3.3小时调整键 P3.5分钟调整键 P3.7定时输出指示
;**************************************************************
;*********************************************************
; 变量地址分配
;*********************************************************
SwDelay equ 2; 设置按键时去抖动时间
DisplayBuffer equ 30h; 设置显示缓冲区的地址为30h-35h共6个字节
BeepVal equ 38h; 蜂鸣时间长短存储器地址
OneSecondCounter equ 39h; 设置1秒计数器的地址,1秒计数器是用来计数1秒内计时器的中断次数
Hour equ 3ah; 设置小时计数器的地址
Minute equ 3bh; 设置分钟计数器的地址
Second equ 3ch; 设置秒计数器的地址
Year equ 3dh; 设置月日年计数器的地址
Month equ 3eh;
Day equ 3fh;
P1Val equ 40h; 设置数码管位驱动值的地址
ClockMode equ 20h.0; 模式(正常走时/闹时)设置寄存器地址,值为0时正常走时,为1时闹时设定
AlarmOnOff equ 20h.1; 闹钟开启/关闭标志,为0关闭,为1开启
AlarmTimeOn equ 20h.2; 此位为1时表示闹时时间到
DataMode equ 20h.3
DispHour equ 21h; 设置小时显示寄存器的地址
DispMinute equ 22h; 设置分钟显示寄存器的地址
DispSecond equ 23h; 设置秒显示寄存器的地址
Dnum equ 24h
AlarmHour equ 2eh; 设置闹时小时计数器的地址
AlarmMinute equ 2fh; 设置闹时分钟计数器的地址
AlarmSetKey bit P3.2; 闹钟设置键
MinuteKey bit P3.3; 定义分设置键
HourKey bit P3.4; 定义小时设置键
DataSetKey bit p3.5;
RelayOut equ P3.7; 定义输出引脚
;**********************************************************************
; 程序开始
;**********************************************************************
org 00h
ajmp Reset ;程序开始
org 0bh ;Timer0中断向量地址
ajmp TimeInt ;跳到中断处理程序
org 0020h
Reset: ;以下为初始化程序,为各个变量赋初值
mov sp,#70h;
setb RelayOut
mov OneSecondCounter,#125
;
mov Hour,#23
mov Minute,#59
mov Second,#30 ;设置上电时时钟显示的初值
;
mov Year,#07
mov Month,#12
mov Day,#27
;
mov AlarmHour,#00
mov AlarmMinute,#00 ;设置上电时闹时时间的初值
;
clr AlarmOnOff ;上点复位后闹时功能处于关闭状态
clr ClockMode ;正常走时模式
clr AlarmTimeOn
setb RelayOut ;清闹时输出
clr DataMode
;
mov 36h,#10
mov 37h,#11
;
;************************************
; Use Timer 0 Mode 1
; 400us interrupt
;************************************
mov tmod,#00000001b
mov th0,#0E3h
mov tl0,#5Dh
mov ie, #82h ;开全局中断
SETB EA
SETB ET0
setb tr0 ;开定时中断
;*****************************************
; 以下为主程序
;*****************************************
MainLoop:
jb AlarmSetKey,CheckMinuteKey ;闹时设置键按下了吗?没有则转去检测秒设置键
call Delay
jb AlarmSetKey,CheckMinuteKey ;按下的时间超过500ms吗?
setb ClockMode ;置为闹时设置模式
call AlarmSet
CheckMinuteKey:
jb MinuteKey,CheckHourKey ;分设置键按下了吗?没有则转去检测小时设置键
;如按下调用蜂鸣器发音程序
mov a,Minute
add a,#1; 如果按下则将分钟加一 十进制调整
mov Minute,a;
cjne a,#3ch,NotOver1; 到60分钟了吗?
mov Minute,#0; 到60分钟则将分钟清0
NotOver1: ;以下等待按键释放及防抖动
jnb MinuteKey,$
CheckHourKey:
jb HourKey,CheckDataKey;
; 如按下调用蜂鸣器发音程序
mov a,Hour
add a,#1; 如果按下则将小时加1
mov Hour,a
cjne a,#18h,NotOver2
mov Hour,#0; 到24小时则将小时清0
NotOver2: ;以下等待按键释放及防抖动
jnb HourKey,$
CheckDataKey:
jb DataSetKey,CheckAlarm
call Delay
jb DataSetKey,CheckAlarm
setb DataMode
call Dataset
CheckAlarm:
jnb AlarmTimeOn,ToReturn
call AlarmProcess
ToReturn:
ajmp MainLoop
;**********************************************
; 定时器Timer0中断服务程序(此程序每8ms执行一次)
;**********************************************
TimeInt:
mov th0,#0E3h; 重新加载定时参数
mov tl0,#5Dh;
push acc
push psw; 保护累加器及程序状态字的内容
setb rs0; 选择工作寄存器组1,
clr rs1; 这样可保护原工作寄存器组(0组)的内容
djnz OneSecondCounter,NotoneSecond; 中断了125次了吗?即够1秒了吗?
mov OneSecondCounter,#125; 如够1秒则重新设置"OneSecondCounter"计数器
call Clock ; 调用将时钟内容加1秒的子程序
call Daynum
call ConvertoBuffer ; 调用将时钟内容转换到显示缓冲区子程序
NotoneSecond:
call ScanDisplay ; 调用扫描显示子程序
pop psw
pop acc ; 恢复累加器及程序状态字的内容
reti ; 中断返回
;*********************************************
; 扫描显示子程序
;*********************************************
ScanDisplay:
MOV R1,#DisplayBuffer ;指向显示数据首址
MOV R5,#0FEH ;扫描控制字初值
PLAY:
MOV A,R5 ;扫描字放入A
MOV P2,A ;从P2口输出
MOV A,@R1 ;取显示数据到A
MOV DPTR,#TAB ;取段码表地址
MOVC A,@A+DPTR ;查显示数据对应段码
MOV P1,A ;段码放入P1口
LCALL Delay
INC R1 ;指向下一地址
MOV A,R5 ;扫描控制字放入A
JNB ACC.7,ENDOUT ;扫到第六位时结束
RL A ;A中数据循环左移
MOV R5,A ;放回R5内
AJMP PLAY ;跳回PLAY循环
ENDOUT: MOV P2,#0FFH ;一次显示结束,P2口复位
MOV P1,#00H ;P1口复位
RET ;子程序返回
TAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H,39h
;共阴段码表 "0""1""2" "3""4""5""6""7" "8""9""-""c"
;****************************************************
; 时钟内容加1秒的子程序
;****************************************************
Clock:
mov a,Second; 将原秒值送入a
add a,#1; 加1秒
mov Second,a
cjne a,#3cH,NotOverFlow; 够60秒了吗?
mov Second,#0; 够了则将秒值清0
;
mov a,Minute
add a,#1
mov Minute,a; 分钟加1
cjne a,#3cH,NotOverFlow; 够60分了吗?
mov Minute,#0; 够了则将分值清0
;
mov a,Hour
add a,#1
mov Hour,a; 小时加1
cjne a,#18H,NotOverFlow; 够24小时吗?
mov Hour,#0; 够了则将小时值清0
;
mov a,Day
add a,#1
mov Day,a
cjne a,Dnum,NotAlarm
mov Day,#1
;
mov a,Month
add a,#1
mov Month,a
cjne a,#13,NotAlarm
mov Month,#1
;
mov a,Year
add a,#1
mov Year,a
cjne a,#11,NotAlarm
mov Year,#0
NotOverFlow:
jnb AlarmOnOff,NotAlarm; 闹钟开启了吗?如没有开启则无需理会是否到闹时时间
mov a,Second
jnz NotAlarm; 秒为零吗?
mov a,Minute
cjne a,AlarmMinute,NotAlarm; 时间分钟值和闹时设置分钟值相等吗?
mov a,Hour
cjne a,AlarmHour,NotAlarm; 时间小时值和闹时设置小时值相等吗?
setb AlarmTimeOn; 到了闹时时间则将“闹时时间到”标志设为1
NotAlarm:
ret
;**************************************************************************
; 将时钟内容或闹时设置值转换到显示缓冲区子程序
;**************************************************************************
ConvertoBuffer:
mov r1,#DisplayBuffer
jnb dataMode,TimeDisp
mov a,Day
mov DispSecond,a
mov a,Month
mov DispMinute,a
mov a,Year
mov DispHour,a
ajmp Convert
TimeDisp: jb ClockMode,DispAlarmSet; 判断时钟模式,以决定是显示实时时间还是闹时时间
mov a,Second;
mov DispSecond,a;
mov a,Minute;
mov Dispminute,a;
mov a,Hour;
mov DispHour,a; 显示实时时间
;
ajmp Convert
DispAlarmSet:
jb AlarmOnOff,AlarmOn
mov DispSecond,#00h
ajmp Next
AlarmOn:
mov DispSecond,#11; 显示闹时时间及显示闹钟状态:显示“00”表示关闭闹钟,
Next: ;“11”表示开启闹钟
mov a,AlarmMinute;
mov Dispminute,a;
mov a,AlarmHour;
mov DispHour,a;
;
Convert:
mov a,DispSecond; 取秒值
mov b,#10
div ab
mov @r1,b;
inc r1; 缓冲寄存器的地址加1
mov @r1,a; 将秒值的十位值存入缓冲区
;
inc r1
mov a,DispMinute
mov b,#10
div ab
mov @r1,b;
inc r1; 缓冲寄存器的地址加1
mov @r1,a; 将秒值的十位值存入缓冲区
;
inc r1
mov a,DispHour
mov b,#10
div ab
mov @r1,b;
inc r1; 缓冲寄存器的地址加1
mov @r1,a; 将秒值的十位值存入缓冲区
ret;
;*******************************************************
;天数判断,平年,闰年
;*******************************************************
Daynum: mov a,Month
mov dptr,#TABL
movc a,@a+dptr
mov Dnum,a
mov a,Year
mov b,#4
div ab
mov a,b
cjne a,#0,BB
mov a,Month
cjne a,#2,BB
inc Dnum
BB: RET
TABL: DB 31,32,29,32,31,32,31,32,32,31,32,31,32
;**************************************************
; 闹时设置子程序
;**************************************************
AlarmSet:
jnb AlarmSetKey,$
call Delay; 等待“AlarmSetKey”键释放
CheckArmMinuteKey: ;
jb MinuteKey,CheckArmHourKey; 分设置键按下了吗?没有则转去检测小时设置键
setb AlarmOnOff
mov 37h,#0
mov a,AlarmMinute
add a,#1; 如果按下则将分钟加1 十进制调整
mov AlarmMinute,a;
cjne a,#3ch,ArmNotOver1; 到60分钟了吗?
mov AlarmMinute,#0; 到60分钟则将分钟清0
ArmNotOver1: ;以下等待按键释放及防抖动
jnb MinuteKey,$
CheckArmHourKey:
jb HourKey,AlarmSetEnd; 小时设置键按下了吗?没有则返回反复检测
setb AlarmOnOff
mov a,AlarmHour
add a,#1; 如果按下则将小时加1
mov AlarmHour,a
cjne a,#18h,ArmNotOver2
mov AlarmHour,#0; 到24小时则将小时清0
ArmNotOver2: ;以下等待按键释放及防抖动
jnb HourKey,$
AlarmSetEnd:
jb AlarmSetKey,AlarmSet; 设置完毕了吗?
jnb AlarmSetKey,$;
clr ClockMode; 从设置模式转为走时模式
ret
;*********************************************
; 日期调整
;*********************************************
DataSet:
jnb DataSetKey,$
call Delay
CheckDataYearKey:
jb HourKey,CheckDataMonthKey
mov a,Year
add a,#1
mov Year,a
cjne a,#11,DataNotOver1
mov Year,#0
DataNotOver1:
jnb HourKey,$
CheckDataMonthKey:
jb MinuteKey,CheckDataDayKey
mov a,Month
add a,#1
mov Month,a
cjne a,#13,DataNotOver2
mov Month,#1
DataNotOver2:
jnb MinuteKey,$
CheckDataDayKey:
jb AlarmSetKey,DataSetEnd
mov a,day
add a,#1
mov Day ,a
cjne a,Dnum,DataNotOver3
mov Day,#1
DataNotOver3:
jnb AlarmSetKey,$
DataSetEnd:
jb DataSetKey,DataSet
jnb DataSetKey,$
clr DataMode
ret
;**************************************************
; 闹时服务子程序
;**************************************************
AlarmProcess:
clr RelayOut;
jb AlarmSetKey,AlarmReturn; 停止闹时键(即闹时设置键)按下了吗?
clr AlarmOnOff
jnb AlarmSetKey,$;
setb RelayOut; 如停止闹时键按下则停止闹时
clr AlarmTimeOn;
mov 37h,#11
mov AlarmMinute,#00
mov AlarmHour,#00
AlarmReturn:
ret
;**************************************************
; 延时子程序
;**************************************************
Delay:
mov r6,#2
Del:
mov r7,#124
djnz r7,$
djnz r6,Del
ret
DL1s: mov r3,#4
dd: call Delay
djnz r3,dd
ret
end
㈢ 这段汇编程序是一个时钟加一个闹钟 现在我想在这段程序里面加10组闹钟,请问各位高手应该如何操作。。
以下是剩余代码
SWADD: MOV A,37H
CJNE A,#2,SWADDX
JNB 2FH.3,MK3
JNB P1.2,SD_1
SETB 2FH.3
RET
MK3: JNB P1.2,SD_EXT1
SETB 2FH.3
SD_EXT1:RET
SD_1: ACALL DELAY
JB P1.2,SD_EXT2
CLR 2FH.3
MOV A,30H
CJNE A,#1,SD_2
INC 50H
MOV A,50H
CJNE A,#10,SD_EXT2
MOV 50H,#0
SD_EXT2:
RET
SD_2: MOV A,30H
CJNE A,#2,SD_3
INC 51H
MOV A,51H
CJNE A,#6,SD_EXT3
MOV 51H,#0
SD_EXT3:
RET
SD_3: MOV A,30H
CJNE A,#3,SD_4
INC 52H
MOV A,52H
CJNE A,#10,SD_EXT4
MOV 52H,#0
SD_EXT4:
RET
SD_4: MOV A,30H
CJNE A,#4,SD_EXT5
INC 53H
MOV A,53H
CJNE A,#3,SD_EXT5
MOV 53H,#0
SD_EXT5:RET
SWADDX: RET
ALARM: MOV A,20H
CJNE A,50H,AEX
MOV A,21H
CJNE A,51H,AEX
MOV A,22H
CJNE A,52H,AEX
MOV A,23H
CJNE A,53H,AEX
CLR P1.7
RET
AEX: SETB P1.7
RET
CODESE: MOV DPTR,#TABLE ;7段码格式
MOV R1,#20H ;将R1指向地址20H
MOV R0,#40H ;将R0指向地址40H
MOV R2,#4 ;将立即数4传递给R2,用于循环
ZP: MOV A,@R1 ;间接寻址,R1指向20H,所以将地址20H的内容传递给A
MOVC A,@A+DPTR ;7段码格式
MOV @R0,A ;间接寻址,R0指向地址40H,所以将A中的内容传递到地址40H中
INC R0
INC R1
DJNZ R2,ZP
MOV R1,#50H
MOV R0,#60H
MOV R3,#4
ZP1: MOV A,@R1
MOVC A,@A+DPTR
MOV @R0,A
INC R0
INC R1
DJNZ R3,ZP1
RET
SHOW: MOV A,37H
CJNE A,#1,SHOW_2
MOV A,30H
CJNE A,#1,L1
JNB 2FH.7,L2
L1: MOV A,#80H
ADD A,40H
MOV P2,A
CLR P0.3
ACALL DELAY
SETB P0.3
L2: MOV A,30H
CJNE A,#2,L3
JNB 2FH.7,L4
L3: MOV P2,41H
CLR P0.2
ACALL DELAY
SETB P0.2
L4: MOV A,30H
CJNE A,#3,L5
JNB 2FH.7,L6
L5: MOV P2,42H
CLR P0.1
ACALL DELAY
SETB P0.1
L6: MOV A,30H
CJNE A,#4,L7
JNB 2FH.7,L8
L7: MOV P2,43H
CLR P0.0
ACALL DELAY
SETB P0.0
L8: RET
SHOW_2: MOV A,37H
CJNE A,#2,SHOW
MOV A,30H
CJNE A,#1,S1
JNB 2FH.7,S2
S1: MOV P2,60H
CLR P0.3
ACALL DELAY
SETB P0.3
S2: MOV A,30H
CJNE A,#2,S3
JNB 2FH.7,S4
S3: MOV P2,61H
CLR P0.2
ACALL DELAY
SETB P0.2
S4: MOV A,30H
CJNE A,#3,S5
JNB 2FH.7,S6
S5: MOV P2,62H
CLR P0.1
ACALL DELAY
SETB P0.1
S6: MOV A,30H
CJNE A,#4,S7
JNB 2FH.7,S8
S7: MOV P2,63H
CLR P0.0
ACALL DELAY
SETB P0.0
S8: RET
ZD: PUSH ACC
PUSH PSW
SETB RS1
SETB RS0
INC R7
CJNE R7,#0C8H,ZD1
MOV R7,#00H
INC R6
CJNE R6,#0AH,ZD1
MOV R6,#00H
INC 08H
CPL 2FH.7
ZD1: CLR RS1
CLR RS0
POP PSW
POP ACC
RETI
DELAY: MOV 2CH,#200
DJNZ 2CH,$
RET
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
END