求单片机程序:汇编语言数字钟

求单片机程序:汇编语言数字钟,第1张

用DS1302+单片机比较简单 ;DS1302程序(51汇编)

;推荐

;1每次上电,必须把秒寄存器高位(第7位)设置为0,时钟才能走时。

;2如果需要写入数据和时钟日历信息,必须把“写保护”寄存器设置成为0

;内存数据定义

BitCnt data 3Ch ; 数据位计数器

ByteCnt data 3Dh ; 数据字节计数器

Command data 3Eh ; 命令字节地址

RcvDat DATA 40H ; 接收数据缓冲区

XmtDat DATA 50H ; 发送数据缓冲区

;端口位定义

IO_DATA bit P16 ; 数据传送总线

SCLK bit P15; 时钟控制总线

RST bit P17 ; 复位总线

RS BIT P35

RW BIT P36

EN BIT P37

ORG 0000H

ORG 0013H

LCALL JKS

AJMP KS

; ;main program

ORG 0030H

KS: CLR RST

MOV SP,#2AH

;----LCD初始化----

CLR EN ;使能端为0,液晶执行命令

INIT_LCD:

MOV A,#38H ;双列显示,字形57点阵

ACALL WCOM

ACALL DELAY1

MOV A,#38H ;双列显示,字形57点阵

ACALL WCOM

ACALL DELAY1

MOV A,#38H ;双列显示,字形57点阵

ACALL WCOM

ACALL DELAY1

MOV A,#0CH ;开显示,关光标

ACALL WCOM

ACALL DELAY1

MOV A,#01H ;清除 LCD 显示屏

ACALL WCOM

ACALL DELAY1

MOV A,#06H ;地址加1

ACALL WCOM

ACALL DELAY1

;------------------------------------初始化1302-------------------------

SET1302:

LCALL Write_Enable;写允许

LCALL Osc_Disable

LCALL Write_Multiplebyte;初始化1302,将我们要设定的数据写入

LCALL Read_Multiplebyte;将我们设定的数据读出来

LCALL Osc_Enable

START:

ACALL LCD

LCALL Read_Multiplebyte

AJMP START

;---------------------LCD显示-------------------------

LCD:

MOV A,#11001000B

LCALL WCOM

MOV A,#0;显示时间

MOV A,42H

LCALL SSH2

MOV A,#00111010B

LCALL WDATA

MOV A,41H

LCALL SSH2

MOV A,#00111010B

LCALL WDATA

MOV A,40H

LCALL SSH2

MOV A,#11000000B

LCALL WCOM

MOV A,#0;显示日期字符

MOV A,46H

LCALL SSH2

MOV A,#00101101B

LCALL WDATA

MOV A,44H

LCALL SSH2

MOV A,#00101101B

LCALL WDATA

MOV A,43H

LCALL SSH2

RET

SSH2:

MOV B,#16

DIV AB

MOV 58H,B

MOV 59H,A

MOV A,59H

MOV DPTR,#TAB

MOVC A,@A+DPTR

ACALL WDATA

MOV A,58H

MOV DPTR,#TAB

MOVC A,@A+DPTR

ACALL WDATA

RET

;-----------------------------------------------------

; 写指令、数据使能子程序

;-----------------------------------------------------

WCOM: ;写指令使能

ACALL DELAY0

MOV P0,A

CLR RS

CLR RW

CLR EN

CLR EN

CLR EN

SETB EN

RET

WDATA: ;写数据使能

ACALL DELAY0

MOV P0,A

SETB RS ;RS=H,RW=L,D0-D7=数据,E=高脉冲

CLR RW

CLR EN

CLR EN

CLR EN

SETB EN

RET

;判忙音

DELAY0:

MOV P0,#0FFH

CLR RS

SETB RW

CLR EN

NOP

SETB EN

JB P07,DELAY0

RET

TAB:DB 00110000B,00110001B,00110010B,00110011B

DB 00110100B,00110101B,00110110B,00110111B

DB 00111000B,00111001B

;

;发送数据程序

;名称:Send_Byte

;描述:发送ByteCnt 个字节给被控器DS1302

;命令字节地址在Command 中

;所发送数据的字节数在ByteCnt 中发送的数据在XmtDat 缓冲区中

;

Send_Byte:

CLR RST ;复位引脚为低电平所有数据传送终止

NOP

CLR SCLK; 清时钟总线

NOP

SETB RST ;复位引脚为高电平逻辑控制有效

NOP

MOV A,Command; 准备发送命令字节

MOV BitCnt,#08h ;传送位数为8

S_Byte0:

RRC A ;将最低位传送给进位位C

MOV IO_DATA,C ;位传送至数据总线

NOP

SETB SCLK ;时钟上升沿发送数据有效

NOP

CLR SCLK ;清时钟总线

DJNZ BitCnt,S_Byte0 ;位传送未完毕则继续

NOP

S_Byte1: ;准备发送数据

MOV A,@R0 ;传送数据过程与传送命令相同

MOV BitCnt,#08h

S_Byte2:

RRC A

MOV IO_DATA,C

NOP

SETB SCLK

NOP

CLR SCLK

DJNZ BitCnt,S_Byte2

INC R0 ;发送数据的内存地址加1

DJNZ ByteCnt,S_Byte1 ;字节传送未完毕则继续

NOP

CLR RST ;逻辑 *** 作完毕清RST

RET

;

;接收数据程序;

;名称:Receive_Byte

;描述:从被控器DS1302 接收ByteCnt 个字节数据

;命令字节地址在Command 中

;所接收数据的字节数在ByteCnt 中接收的数据在RcvDat 缓冲区中

;

Receive_Byte:

CLR RST ;复位引脚为低电平所有数据传送终止

NOP

CLR SCLK ;清时钟总线

NOP

SETB RST ;复位引脚为高电平逻辑控制有效

MOV A,Command ;准备发送命令字节

MOV BitCnt,#08h ;传送位数为8

R_Byte0:

RRC A ;将最低位传送给进位位C

MOV IO_DATA,C ;位传送至数据总线

NOP

SETB SCLK ;时钟上升沿发送数据有效

NOP

CLR SCLK ;清时钟总线

DJNZ BitCnt,R_Byte0 ;位传送未完毕则继续

NOP

R_Byte1: ;准备接收数据

CLR A ;清类加器

CLR C ;清进位位C

MOV BitCnt,#08h ;接收位数为8

R_Byte2:

NOP

MOV C,IO_DATA ;数据总线上的数据传送给C

RRC A ;从最低位接收数据

SETB SCLK ;时钟总线置高

NOP

CLR SCLK ;时钟下降沿接收数据有效

DJNZ BitCnt,R_Byte2 ;位接收未完毕则继续

MOV @R1,A ;接收到的完整数据字节放入接收内存缓冲区

INC R1 ;接收数据的内存地址加1

DJNZ ByteCnt,R_Byte1 ;字节接收未完毕则继续

NOP

CLR RST ;逻辑 *** 作完毕清RST

RET

;--写保护寄存器 *** 作------------------------------------------

Write_Enable:

MOV Command,#8Eh ;命令字节为8E

MOV ByteCnt,#1 ;单字节传送模式

MOV R0,#XmtDat ;数据地址覆给R0

MOV XmtDat,#00h ;数据内容为0 写入允许

ACALL Send_Byte ;调用写入数据子程序

RET

;当写保护寄存器的最高位为1 时禁止数据写入寄存器---------------

Write_Disable:

MOV Command,#8Eh ;命令字节为8E

MOV ByteCnt,#1 ;单字节传送模式

MOV R0,#XmtDat ;数据地址覆给R0

MOV XmtDat,#80h ;数据内容为80h 禁止写入

ACALL Send_Byte ;调用写入数据子程序

RET ;返回调用本子程序处

;当把秒寄存器的第7 位时钟停止位设置为0 时起动时钟开始---------

Osc_Enable:

MOV Command,#80h ; 命令字节为80

MOV ByteCnt,#1 ; 单字节传送模式

MOV R0,#XmtDat ;数据地址覆给R0

MOV XmtDat,#00h ;数据内容为0 振荡器工作允许

ACALL Send_Byte ;调用写入数据子程序

RET ;返回调用本子程序处

;当把秒寄存器的第7 位时钟停止位设置为1 时时钟振荡器停止HT1380 进入低功耗方式---------------

Osc_Disable:

MOV Command,#80h ;命令字节为80

MOV ByteCnt,#1 ;单字节传送模式

MOV R0,#XmtDat ;数据地址覆给R0

MOV XmtDat,#80h ;数据内容为80h 振荡器停止

ACALL Send_Byte ;调用写入数据子程序

RET ;返回调用本子程序处

;写入00 年6 月21 日星期三13 时59 分59---------------------

Write_Multiplebyte:

MOV Command,#0BEh ;命令字节为BEh

MOV ByteCnt,#8 ;多字节写入模式此模块为8 个

MOV R0,#XmtDat ;数据地址覆给R0

MOV XmtDat,#59h ;秒单元内容为59h

MOV XmtDat+1,#59h ;分单元内容为59h

MOV XmtDat+2,#13h ;时单元内容为13h

MOV XmtDat+3,#21h ;日期单元内容为21h

MOV XmtDat+4,#06h ;月单元内容为06h

MOV XmtDat+5,#03h ;星期单元内容为03h

MOV XmtDat+6,#0 ;年单元内容为00h

MOV XmtDat+7,#0 ;写保护单元内容为00h

ACALL Send_Byte ;调用写入数据子程序

RET ;返回调用本子程序处

;读出寄存器0-7 的内容程序设置如下

Read_Multiplebyte:

MOV Command,#0BFh ;命令字节为BFh

MOV ByteCnt,#8 ;多字节读出模式此模块为8 个

MOV R1,#RcvDat ;数据地址覆给R1

ACALL Receive_Byte; 调用读出数据子程序

RET; 返回调用本子程序处

DELAY1: ;延时10MS

MOV 21H,#75

D2: MOV 22H,#100

DJNZ 22H,$

DJNZ 21H,D2

RET

;=============================================================================================

END

哈哈,你有福了 我也想了好久这程序 这不 刚写好 研究研究

#include <reg52h>

#include <intrinsh>

#include <stringh>

#define uint unsigned int

#define uchar unsigned char

sbit IO = P1^0;

sbit SCLK = P1^1;

sbit RST = P1^2;

sbit RS = P2^0;

sbit RW = P2^1;

sbit EN = P2^2;

sbit KEY1=P3^4;

sbit KEY2=P3^5;

sbit KEY3=P3^6;

uchar WEEK[]={"SUN","","MON","TUS","WEN","THU","FRI","SAT"};

uchar LCD_DSY_BUFFER1[]={"DATE 00-00-00 "};

uchar LCD_DSY_BUFFER2[]={"TIME 00:00:00 "};

uchar DateTime[7]; //秒,分,时,日,月,周,年

uchar flag,flag_1,i,miao,fen,shi,ri,yue,zhou,nian;

void DelayMS(uint ms)

{

uchar i;

while(ms--)

{

for(i=0;i<120;i++);

}

}

//

//函数名称: Write_A_Byte_TO_DS1302(uchar x)

//函数功能: 向1302写入一个字节

//入口参数: x

//出口参数: 无

//调用子程序: 无

//

void Write_A_Byte_TO_DS1302(uchar x)

{

uchar i;

for(i=0;i<8;i++)

{

IO=x&0x01;

SCLK=1;

SCLK=0;

x>>=1;

}

}

void Write_DS1302(uchar add,uchar num)

{

SCLK=0;

RST=0;

RST=1;

Write_A_Byte_TO_DS1302(add);

Write_A_Byte_TO_DS1302(num);

RST=0;

SCLK=1;

}

//

//函数名称: Get_A_Byte_FROM_DS1302()

//函数功能: 从1302读一个字节

//入口参数: 无

//出口参数: b/1610+b%16

//调用子程序: 无

//

uchar Get_A_Byte_FROM_DS1302()

{

uchar i,b=0x00;

for(i=0;i<8;i++)

{

b |= _crol_((uchar)IO,i);

SCLK=1;SCLK=0;

}

return b/1610+b%16;

}

//

//函数名称: Read_Data(uchar addr)

//函数功能: 指定位置读数据

//入口参数: addr

//出口参数: dat

//调用子程序: Write_Abyte_1302(addr)

//

uchar Read_Data(uchar addr)

{

uchar dat;

RST = 0;SCLK=0;RST=1;

Write_A_Byte_TO_DS1302(addr);

dat = Get_A_Byte_FROM_DS1302();

SCLK=1;RST=0;

return dat;

}

//

//函数名称: GetTime()

//函数功能: 读取时间

//入口参数: 无

//出口参数: 无

//调用子程序: 无

//

void GetTime()

{

uchar i,addr = 0x81;

for(i=0;i<7;i++)

{

DateTime[i]=Read_Data(addr);addr+=2;

}

}

uchar Read_LCD_State()

{

uchar state;

RS=0;RW=1;EN=1;DelayMS(1);

state=P0;

EN = 0;DelayMS(1);

return state;

}

void LCD_Busy_Wait()

{

while((Read_LCD_State()&0x80)==0x80);

DelayMS(5);

}

void Write_LCD_Data(uchar dat) //写数据到1602

{

LCD_Busy_Wait();

RS=1;RW=0;EN=0;P0=dat;EN=1;DelayMS(1);EN=0;

}

void Write_LCD_Command(uchar cmd) //写命令

{

LCD_Busy_Wait();

RS=0;RW=0;EN=0;P0=cmd;EN=1;DelayMS(1);EN=0;

}

void Init_LCD() //1602 初始化

{

Write_LCD_Command(0x38);

DelayMS(1);

Write_LCD_Command(0x01);

DelayMS(1);

Write_LCD_Command(0x06);

DelayMS(1);

Write_LCD_Command(0x0c);

DelayMS(1);

}

void Set_LCD_POS(uchar p)

{

Write_LCD_Command(p|0x80);

}

void Display_LCD_String(uchar p,uchar s) //1602显示

{

uchar i;

Set_LCD_POS(p);

for(i=0;i<16;i++)

{

Write_LCD_Data(s[i]);

DelayMS(1);

}

}

void write_com(uchar com)

{

RS=0;

P0=com;

DelayMS(5);

EN=1;

DelayMS(5);

EN=0;

}

void write_date(uchar date)

{

RS=1;

P0=date;

DelayMS(5);

EN=1;

DelayMS(5);

EN=0;

}

void display(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 display1(uchar add,uchar date)

{

uchar shi,ge;

shi=date/10;

ge=date%10;

write_com(0x80+add);

write_date(0x30+shi);

write_date(0x30+ge);

}

void Format_DateTime(uchar d,uchar a)

{

a[0]=d/10+'0';

a[1]=d%10+'0';

}

uchar ZH(uchar dat)

{

uchar tmp;

tmp=dat/10;

dat=dat%10;

dat=dat+tmp16;

return dat;

}

void Keyscan()

{

flag_1=1;

while(flag_1)

{

if(KEY1==0)

{

DelayMS(5);

while(!KEY1);

flag=(flag+1)%8;

switch(flag)

{

case(1): Write_LCD_Command(0x0f);

Write_LCD_Command(0x80+0x40+11);

break;

case(2): Write_LCD_Command(0x80+0x40+8);

break;

case(3): Write_LCD_Command(0x80+0x40+5);

break;

case(4): Write_LCD_Command(0x80+13);

break;

case(5): Write_LCD_Command(0x80+11);

break;

case(6): Write_LCD_Command(0x80+8);

break;

case(7): Write_LCD_Command(0x80+5);

break;

case(0): flag_1=0;

Write_LCD_Command(0x0c);

//miao

Write_DS1302(0x8e,0x00);

Write_DS1302(0x80,ZH(DateTime[0]));

Write_DS1302(0x8e,0x80);

//fen

Write_DS1302(0x8e,0x00);

Write_DS1302(0x82,ZH(DateTime[1]));

Write_DS1302(0x8e,0x80);

//shi

Write_DS1302(0x8e,0x00);

Write_DS1302(0x84,ZH(DateTime[2]));

Write_DS1302(0x8e,0x80);

//ri

Write_DS1302(0x8e,0x00);

Write_DS1302(0x86,ZH(DateTime[3]));

Write_DS1302(0x8e,0x80);

// yue

Write_DS1302(0x8e,0x00);

Write_DS1302(0x88,ZH(DateTime[4]));

Write_DS1302(0x8e,0x80);

//nian

Write_DS1302(0x8e,0x00);

Write_DS1302(0x8c,ZH(DateTime[6]));

Write_DS1302(0x8e,0x80);

break;

}

}

if(flag!=0)

{

if(KEY2==0)

{

DelayMS(5);

if(KEY2==0)

while(!KEY2);

if(flag==1) //miao

{

DateTime[0]++;

if(DateTime[0]==60)

DateTime[0]=0;

write_com(0x80+0x40+11);

display(11,DateTime[0]);

}

if(flag==2) //fen

{

DateTime[1]++;

if(DateTime[1]==60)

DateTime[1]=0;

write_com(0x80+0x40+8);

display(8,DateTime[1]);

}

if(flag==3) //shi

{

DateTime[2]++;

if(DateTime[2]==24)

DateTime[2]=0;

write_com(0x80+0x40+5);

display(5,DateTime[2]);

}

/ if(flag==4) //zhou

{

DateTime[0]++;

if(DateTime[0]==60)

DateTime[0]=0;

write_com(0x80+0x40+11);

display(11,DateTime[0]);

} /

if(flag==5) // ri

{

DateTime[3]++;

if(DateTime[3]==30)

DateTime[3]=0;

write_com(0x80+11);

display1(11,DateTime[3]);

}

if(flag==6) //yue

{

DateTime[4]++;

if(DateTime[4]==13)

DateTime[4]=0;

write_com(0x80+8);

display1(8,DateTime[4]);

}

if(flag==7) //nian

{

DateTime[6]++;

if(DateTime[6]==100)

DateTime[6]=0;

write_com(0x80+5);

display1(5,DateTime[6]);

}

}

}

if(flag!=0)

{

if(KEY3==0)

{

DelayMS(5);

if(KEY3==0)

while(!KEY3);

if(flag==1) //miao

{

DateTime[0]--;

if(DateTime[0]==-1)

DateTime[0]=0;

write_com(0x80+0x40+11);

display(11,DateTime[0]);

}

if(flag==2) //fen

{

DateTime[1]--;

if(DateTime[1]==-1)

DateTime[1]=0;

write_com(0x80+0x40+8);

display(8,DateTime[1]);

}

if(flag==3) //shi

{

DateTime[2]--;

if(DateTime[2]==-1)

DateTime[2]=0;

write_com(0x80+0x40+5);

display(5,DateTime[2]);

}

/ if(flag==4) //zhou

{

DateTime[0]++;

if(DateTime[0]==60)

DateTime[0]=0;

write_com(0x80+0x40+11);

display(11,DateTime[0]);

} /

if(flag==5) // ri

{

DateTime[3]--;

if(DateTime[3]==-1)

DateTime[3]=0;

write_com(0x80+11);

display1(11,DateTime[3]);

}

if(flag==6) //yue

{

DateTime[4]--;

if(DateTime[4]==-1)

DateTime[4]=0;

write_com(0x80+8);

display1(8,DateTime[4]);

}

if(flag==7) //nian

{

DateTime[6]--;

if(DateTime[6]==-1)

DateTime[6]=0;

write_com(0x80+5);

display1(5,DateTime[6]);

}

}

}

}

}

void main()

{

Init_LCD();

while(1)

{

EA=1;

EX0=1;

GetTime();

Format_DateTime(DateTime[6],LCD_DSY_BUFFER1+5); //年

Format_DateTime(DateTime[4],LCD_DSY_BUFFER1+8); //月

Format_DateTime(DateTime[3],LCD_DSY_BUFFER1+11); //日

strcpy(LCD_DSY_BUFFER1+13,WEEK[DateTime[5]]); //周 串拷贝 包含于STRINGH

Format_DateTime(DateTime[2],LCD_DSY_BUFFER2+5); //时

Format_DateTime(DateTime[1],LCD_DSY_BUFFER2+8); //分

Format_DateTime(DateTime[0],LCD_DSY_BUFFER2+11); //秒

Display_LCD_String(0x00,LCD_DSY_BUFFER1);

Display_LCD_String(0x40,LCD_DSY_BUFFER2);

}

}

void int0() interrupt 0

{

Keyscan();

}

;

; 带有时间设置和秒显示的数字闹钟

; Date : 20071026 12MHZ晶振

; Create by :星星 缘木求鱼

; P32设置键 P33小时调整键 P35分钟调整键 P37定时输出指示

;

;

; 变量地址分配

;

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 20h0; 模式(正常走时/闹时)设置寄存器地址,值为0时正常走时,为1时闹时设定

AlarmOnOff equ 20h1; 闹钟开启/关闭标志,为0关闭,为1开启

AlarmTimeOn equ 20h2; 此位为1时表示闹时时间到

DataMode equ 20h3

DispHour equ 21h; 设置小时显示寄存器的地址

DispMinute equ 22h; 设置分钟显示寄存器的地址

DispSecond equ 23h; 设置秒显示寄存器的地址

Dnum equ 24h

AlarmHour equ 2eh; 设置闹时小时计数器的地址

AlarmMinute equ 2fh; 设置闹时分钟计数器的地址

AlarmSetKey bit P32; 闹钟设置键

MinuteKey bit P33; 定义分设置键

HourKey bit P34; 定义小时设置键

DataSetKey bit p35;

RelayOut equ P37; 定义输出引脚

;

; 程序开始

;

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 ACC7,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

以上就是关于求单片机程序:汇编语言数字钟全部的内容,包括:求单片机程序:汇编语言数字钟、(急!!!)用DS1302与1602LCD设计的可调式电子日历与时钟 我要C程序啊。、用汇编语言编写一个时钟程序,在微机屏幕上显示当前时间的时、分、秒。等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10636615.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-10
下一篇 2023-05-10

发表评论

登录后才能评论

评论列表(0条)

保存