- 北有云溪
-
* 回复内容中包含的链接未经审核,可能存在风险,暂不予完整展示!http://www.b***.com/s?wd=89c51%B5%A5%C6%AC%BB%FA%CD%F2%C4%EA%C0%FA%BB%E3%B1%E0%B3%CC%D0%F2DS1302&ch=&tn=site888_pg&bar=
http://www.p**.com/downloads135/sourcecode/asm/detail575062.html
http://www.e******.com/article/87/82/2009/2009091791650.html
基于单片机的万年历汇编语言程序
;真正的万年历: 84 bytes 的 51 ASM
;==SUB_WNL=== 万年历 ==* Deng Miao * 2004-06-01 ***** GuangZhou ******
SJ DATA 30H ; 世纪 BCD 00 TO 99
NH DATA 31H ; 年号 BCD 00 TO 99 0000 TO 9999 年
YF DATA 32H ; 月份 BCD 01 TO 12
org 000h
MOV SP, #40H
MOV SJ, #21H ;2004-05
MOV NH, #01H
MOV YF, #4H
ACALL SUB_WNL
SJMP $
;===============SUB_WNL===================
; 入口:
; SJ DATA 30H ; 世纪 BCD 00 TO 99
; NH DATA 31H ; 年号 BCD 00 TO 99 0000 TO 9999 年
; YF DATA 32H ; 月份 BCD 01 TO 12
; 出口
; ACC -- 本月天数 BCD 28 to 31
; B -- 本月1日的星期数 1 to 6 == 星期1 to 星期6
; 0 -- 星期日
; 使用: ACC, B, R5, R6
; STACK: 3 bytes (不包括调用)
ORG 50H
SUB_WNL:
PUSH PSW
MOV A, SJ
ACALL BCD2BIN_MOD4
; x 400年: (大周期)
; =146097天 = 7 * 20871 + 0 天
; x 100年:
; 000年 = 7 * 0 + 0 + 1 - 1 1 = 0 * 2 + 1 ****
; 100年 = 7 * 5217 + 7 + 1 - 2 2 = 1 * 2
; 200年 = 7 * 10435 + 7 + 1 - 4 4 = 2 * 2
; 300年 = 7 * 15653 + 7 + 1 - 6 6 = 3 * 2
; {1,2,4,6}
MOV A, R6 ; A=R6= SJ_BIN MOD 4
RLC A ; A=A*2+C A = {1,2,4,6} ****
XRL A, #10000111B ; A = 87H - A ; 边界调整
MOV R5, A ; A = {86H, 85H, 83H, 81H} ; R5: 星期
MOV A, NH
JZ WNL_1
ACALL BCD2BIN_MOD4
XCH A, R5
SUBB A, R5 ; 0 年 ; 0 = 0 + 0 + 1 + (-1) ***
MOV R5, A
WNL_1:
MOV A, YF
ADD A, #(WNL_TAB-$-4)
MOVC A, @A+PC
MOV R6, A
SWAP A
ACALL WNL_F0; 大年对>=3月调整准备
ADDC A, R5 ; 月调整
MOV B, #7
DIV AB ; B = A MOD 7
MOV A, R6
ACALL WNL_F0; 大年调整准备
ADDC A, #28
POP PSW
RET
WNL_TAB:
DB 3*2 + 5 * 32+0 ;1 BIT 0 : "2月" 标志
DB 0*2+1+1 * 32+0 ;2 ** BIT 1..2: 月大小
DB 3*2 + 1 * 32+16 ;3 00:28 天
DB 2*2 + 4 * 32+16 ;4 01:----
DB 3*2 + 6 * 32+16 ;5 10: 30 天
DB 2*2 + 2 * 32+16 ;6 11: 31 天
DB 3*2 + 4 * 32+16 ;7 BIT 3: 0 -----
DB 3*2 + 7 * 32+16 ;8 BIT 4: 0: 1/2月
DB 2*2 + 3 * 32+16 ;9 1: >=3月
WNL_F0: ; 6 BYTES ; 大年调整准备
RRC A ;0AH
ANL A, #07H ;0BH
;0CH
ANL C, F0 ;0DH
;0EH
RET ;0FH
DB 3*2 + 5 * 32+16 ;10H BIT 5..7: 星期调整数
DB 2*2 + 1 * 32+16 ;11H 0:---
DB 3*2 + 3 * 32+16 ;12H 1-7: 调整数
BCD2BIN_MOD4:
; 功能:A. 1 BYTES BCD TO BIN
; B. MOD 4
; C. MUL 2
; 入口:
; A : SJ OR NH
; F0 : 大世纪
; 出口
; ACC -- (BIN(A) 4) * 2 - (BIN(A) MOD 4) - F0
; R6 -- BIN(A) MOD 4
; C -- IIF( (BIN(A) MOD 4)=0, 1, 0 )
; 使用: ACC, B, R6, PSW
; STACK: 0 bytes (不包括调用)
MOV R6, A ; BCD ==> BIN
ANL A, #0F0H ; 16X+Y ==> 10X+Y
SWAP A
MOV B, #(256-6) ; (256-6)*X + (16X+Y)
MUL AB ;
ADD A, R6 ; = 256X + (10X+Y)
MOV R6, A ; MOD4
ANL A, #3
XCH A, R6 ; R6 = BIN MOD 4 = {0,1,2,3}
; X 4年:3 * 365 + 366 = 7*209 + (-2) **
XRL A, R6 ; A = (BIN 4)
RR A ; A = (BIN 4 ) * 2 **
MOV C, F0 ; 大世纪调整
SUBB A, R6
;X 1 年:
;0 年 0 = 0 + 0 + 1 + (-1) ***
;1 年 366 = 7*52 + 1 + 1
;2 年 366 + 365 = 7*104 + 2 + 1
;3 年 366 + 365 + 365 = 7*156+3 + 1
; {-1,1,2,3}
CJNE R6, #1, $ + 3 ; C = IIF(R6>=1, 0, 1)
MOV F0, C ; C=1 为大年/大世纪
RET
;-----------------------------
END ;======== END OF FILE
- 西柚不是西游
-
;======================================
;DS1302显示时间程序
;本课重点为DS1302的时序
;======================================
SCLK BIT P2.3 ;时钟线(当SCLK为1时,数据被写入,为0数据被输出)
IO_K BIT P2.4 ;数据线
RST BIT P2.5 ;所有数据传送在RST为1进行,为0停止任何数据的传送。
YS1 DATA 30H
YS2 DATA 31H
IR DATA 32H ;送指令寄存器
BUF DATA 40H
WSJQ DATA 50H ;写时间寄存区
RSJQ DATA 58H ;读时间寄存区
ORG 0000H
MAIN: MOV SP,#80H
LCALL CS1302
LOOP: LCALL DU1302
LCALL BCD
LCALL YHDTSM
SJMP LOOP
;初始化1302
CS1302: MOV R4,#8
MOV IR,#0BEH
MOV R1,#WSJQ
MOV WSJQ,#12H ;给秒参数(这个参数值必须要16进制)
MOV WSJQ+1,#30H ;定义30分
MOV WSJQ+2,#09H ;09时
MOV WSJQ+3,#11H ;11日
MOV WSJQ+4,#01H ;01月
MOV WSJQ+5,#01H ;星期1
MOV WSJQ+6,#10H ;2010年
MOV WSJQ+7,#00H ;打开写允许寄存器(0为允许,1禁止)
ACALL WRSX
RET
;读出1302
DU1302: MOV R4,#7
MOV IR,#0BFH
MOV R1,#RSJQ
ACALL RDSX
RET
;对读出的数据进行显示程序
;============================
BCD: MOV A,RSJQ
MOV B,#16
DIV AB
MOV BUF,B
MOV BUF+1,A
MOV A,RSJQ+1
MOV B,#16
DIV AB
MOV BUF+2,B
MOV BUF+3,A
MOV A,RSJQ+2
MOV B,#16
DIV AB
MOV BUF+4,B
MOV BUF+5,A
RET
YHDTSM: MOV R5,#0
MOV R0,#BUF
LYH1: MOV P2,R5
LCALL CB
INC R5
CJNE R0,#BUF+6,LYH1
RET
CB: MOV DPTR,#TABLE
MOV A,@R0
MOVC A,@A+DPTR
MOV P0,A
LCALL D5MS
INC R0
RET
;============================
;DS1302协议
WRSX: ACALL ZBCL
LWR2: MOV R3,#8 ;传送位寄存器(8位共1字节)
MOV A,@R1
LWR1: RRC A
MOV IO_K,C
SETB SCLK
NOP
CLR SCLK
DJNZ R3,LWR1
INC R1
DJNZ R4,LWR2 ;传送字节个数控制寄存器
CLR RST
RET
RDSX: ACALL ZBCL
LRD2: MOV R3,#8
LRD1: MOV C,IO_K
SETB SCLK
NOP
CLR SCLK
RRC A
DJNZ R3,LRD1
MOV @R1,A
INC R1
DJNZ R4,LRD2
CLR RST
RET
ZBCL: CLR RST ;要通信的准备1:先告诉单片机准备通信
NOP
CLR SCLK ;准备2:把RST置1(开通信)前须先将SCLK(时钟电平)拉低
NOP
SETB RST ;拉高RST做通信传送(开始通信)
MOV R3,#8
MOV A,IR ;这条告诉DS1302任务(任务命令下达为IR控制)
LZB1: RRC A
MOV IO_K,C
SETB SCLK
NOP
CLR SCLK
DJNZ R3,LZB1
RET
;======================================
;延时子程序
D5MS: MOV YS1,#5
D1: MOV YS2,#250
DJNZ YS2,$
DJNZ YS1,D1
RET
TABLE:
DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
END
- tt白
-
typedef struct __SYSTEMTIME__
{
unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
unsigned char DateString[11];
unsigned char TimeString[9];
}SYSTEMTIME; //定义的时间类型
SYSTEMTIME CurrentTime;
#define AM(X) X
#define PM(X) (X+12) // 转成24小时制
#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时间
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_WEEK 0x8A
#define DS1302_DAY 0x86
#define DS1302_MONTH 0x88
#define DS1302_YEAR 0x8C
void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数)
{
unsigned char i;
ACC = d;
for(i=8; i>0; i--)
{
DS1302_IO = ACC0; //相当于汇编中的 RRC
DS1302_CLK = 1;
DS1302_CLK = 0;
ACC = ACC >> 1;
}
}
unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数)
{
unsigned char i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; //相当于汇编中的 RRC
ACC7 = DS1302_IO;
DS1302_CLK = 1;
DS1302_CLK = 0;
}
return(ACC);
}
void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据
{
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr); // 地址,命令
DS1302InputByte(ucDa); // 写1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
}
unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据
{
unsigned char ucData;
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr|0x01); // 地址,命令
ucData = DS1302OutputByte(); // 读1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
return(ucData);
}
void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组
{
unsigned char ReadValue;
ReadValue = Read1302(DS1302_SECOND);
Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MINUTE);
Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_HOUR);
Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_DAY);
Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_WEEK);
Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MONTH);
Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_YEAR);
Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
}
void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]
{ if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22
{
Time->DateString[0] = "2";
Time->DateString[1] = "0";
Time->DateString[2] = Time->Year/10 + "0";
Time->DateString[3] = Time->Year%10 + "0";
}
else
{
Time->DateString[0] = " ";
Time->DateString[1] = " ";
Time->DateString[2] = " ";
Time->DateString[3] = " ";
}
Time->DateString[4] = "/";
if(hide_month<2)
{
Time->DateString[5] = Time->Month/10 + "0";
Time->DateString[6] = Time->Month%10 + "0";
}
else
{
Time->DateString[5] = " ";
Time->DateString[6] = " ";
}
Time->DateString[7] = "/";
if(hide_day<2)
{
Time->DateString[8] = Time->Day/10 + "0";
Time->DateString[9] = Time->Day%10 + "0";
}
else
{
Time->DateString[8] = " ";
Time->DateString[9] = " ";
}
if(hide_week<2)
{
week_value[0] = Time->Week%10 + "0"; //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示
}
else
{
week_value[0] = " ";
}
week_value[1] = " ";
Time->DateString[10] = " "; //字符串末尾加 " " ,判断结束字符
}
void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];
{ if(hide_hour<2)
{
Time->TimeString[0] = Time->Hour/10 + "0";
Time->TimeString[1] = Time->Hour%10 + "0";
}
else
{
Time->TimeString[0] = " ";
Time->TimeString[1] = " ";
}
Time->TimeString[2] = ":";
if(hide_min<2)
{
Time->TimeString[3] = Time->Minute/10 + "0";
Time->TimeString[4] = Time->Minute%10 + "0";
}
else
{
Time->TimeString[3] = " ";
Time->TimeString[4] = " ";
}
Time->TimeString[5] = ":";
if(hide_sec<2)
{
Time->TimeString[6] = Time->Second/10 + "0";
Time->TimeString[7] = Time->Second%10 + "0";
}
else
{
Time->TimeString[6] = " ";
Time->TimeString[7] = " ";
}
Time->DateString[8] = " ";
}
void Initial_DS1302(void) //时钟芯片初始化
{
unsigned char Second=Read1302(DS1302_SECOND);
if(Second&0x80) //判断时钟芯片是否关闭
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x8c,0x07); //以下写入初始化时间 日期:07/07/25.星期: 3. 时间: 23:59:55
Write1302(0x88,0x07);
Write1302(0x86,0x25);
Write1302(0x8a,0x07);
Write1302(0x84,0x23);
Write1302(0x82,0x59);
Write1302(0x80,0x55);
Write1302(0x8e,0x80); //禁止写入
}
}