资源描述
实现日期时间温度的显示万年历
———————————————————————————————— 作者:
———————————————————————————————— 日期:
2
个人收集整理 勿做商业用途
; ―――――――――――――――――――――――――――――――
; 温度值存放单元
TEMP_ZH EQU 24H ;实时温度值存放单元
TEMPL EQU 25H ;低温度值存放单元
TEMPH EQU 26H ;高温度值存放单元
TEMP_TH EQU 27H ;高温报警值存放单元
TEMP_TL EQU 28H ;低温报警值存放单元
TEMPHC EQU 29H ;存十位数 BCD码
TEMPLC EQU 2AH ;存个位数 BCD码
;―――――――――――――
;======按键输入引脚定义======
K1 EQU P3.2
K2 EQU P3。3
K3 EQU P3。6
K4 EQU P3。7
;
SPK EQU P3.5
RELAY EQU 2FH
;-----——————-————--————--—-—-—--—--—-
;=====DS1302通信引脚定义=====
RST BIT p1.6
SCLK BIT p1。4
IO BIT p1.5
;=====定义数据存储地址========
DS1302_ADDR DATA 30H ;地址寄存器
DS1302_DATA DATA 31H ;数据寄存器
TIME_YEAR DATA 32H ;年寄存器
TIME_MONT DATA 33H ;月寄存器
TIME_DAY DATA 34H ;天寄存器
WEEK_DATA DATA 35H ;星期寄存器
HOUR DATA 36H ;小时寄存器
MINTUE DATA 37H ;分钟寄存器
SECOND DATA 38H ;秒钟寄存器
;=========显示数据缓冲地址============
YEAR_HBUF DATA 40H
YEAR_LBUF DATA 41H
MONT_HBUF DATA 42H
MONT_LBUF DATA 43H
DAY_HBUF DATA 44H
DAY_LBUF DATA 45H
WEEK_HBUF DATA 46H
WEEK_LBUF DATA 47H
HOUR_HBUF DATA 48H
HOUR_LBUF DATA 49H
MINTUE_HBUF DATA 4AH
MINTUE_LBUF DATA 4BH
SECOND_HBUF DATA 4CH
SECOND_LBUF DATA 4DH
;===============================================
X EQU 2FH ;LCD 地址变量
;―――――――――――――
;LCD控制引脚
RS EQU P2.4
RW EQU P2。5
E EQU P2.6
;―――――――――――――
FLAG EQU 20H.0
KEY_UD EQU 20H.1
DQ EQU p2.7
;============= 主程序 ==============
MAIN:
ACALL SET_LCD ;LCD初始化设置子程序
ACALL SET_1302 ;1302初始化
TOOP: ACALL RESET_1820 ;调用18B20复位子程序
ACALL TEMP_BJ ;显示温度标记”℃"
ACALL MEU_OK ;调用显示”OK”信息子程序
TOOP2:
ACALL RE_TEMP ;调用读取温度数据子程序
ACALL SET_DATA ;调用处理显示温度数据子程序
ACALL TEMP_BJ ;显示温度标记子程序
LCALL RD_DS1302
LCALL DATA_BUF
LCALL DISPLAY
SJMP TOOP2 ;循环
;--------―― 读取温度数据子程序 --------――
RE_TEMP:
ACALL RESET_1820 ;18B20复位子程序
MOV A,#0CCH ;跳过ROM匹配
ACALL WRITE_1820 ;写入子程序
MOV A,#44H ;发出温度转换命令
ACALL WRITE_1820 ;调写入子程序
ACALL RESET_1820 ;调复位子程序
MOV A,#0CCH ;跳过ROM匹配
ACALL WRITE_1820 ;写入子程序
MOV A,#0BEH ;发出读温度命令
ACALL WRITE_1820 ;写入子程序
ACALL READ_1820 ;调用读取子程序
RET
;-------- 温度数据处理显示子程序----------
SET_DATA:
ACALL CONV_TEMP ;处理温度 BCD 码子程序
ACALL DISP_BCD ;显示区 BCD 码温度值刷新子程序
ACALL CONV ;LCD显示子程序
RET
;―――――――――――――
;---------- 处理温度 BCD 码子程序 ----------
CONV_TEMP:
MOV A,TEMPH ;判温度是否零下
ANL A,#80H
JZ TC1 ;温度零转TC1处
CLR C ;C=0
MOV A,TEMPL ;二进制数求补(双字节)
CPL A ;取反加1
ADD A,#01H
MOV TEMPL,A
MOV A,TEMPH
CPL A
ADDC A,#00H
MOV TEMPH,A
JMP TC2
;―――――――――――――
TC1: MOV TEMPHC,#0AH
TC2: MOV A,TEMPHC
SWAP A ;高、低位交换
MOV TEMPHC,A
MOV A,TEMPL
ANL A,#0FH ;乘0。0625
MOV DPTR,#DOTTAB
MOVC A,@A+DPTR
MOV TEMPLC,A ;TEMPLC LOW=小数部分 BCD
;―――――――――――――
MOV A,TEMPL ;整数部分
ANL A,#0F0H ;取出高四位
SWAP A ;高、低位交换
MOV TEMPL,A
MOV A,TEMPH
ANL A,#0FH ;取出低四位
SWAP A ;高、低位交换
ORL A,TEMPL ;重新组合
MOV TEMP_ZH,A
LCALL HEX2BCD1
MOV TEMPL,A
ANL A,#0F0H ;取出高四位
SWAP A ;高、低位交换
ORL A,TEMPHC ;TEMPHC LOW = 十位数 BCD
MOV TEMPHC,A
MOV A,TEMPL
ANL A,#0FH ;取出低四位
SWAP A ;高、低位交换
ORL A,TEMPLC ;TEMPLC HI = 个位数 BCD
MOV TEMPLC,A
MOV A,R4
JZ TC3
ANL A,#0FH ;取出低四位
SWAP A ;高、低位交换
MOV R4,A
MOV A,TEMPHC ;TEMPHC HI = 百位数 BCD
ANL A,#0FH ;取出低四位
ORL A,R4
MOV TEMPHC,A
TC3: RET
;―――――――――――――
HEX2BCD1:
MOV B,#064H ;十六进制-> BCD
DIV AB ;B= A % 100
MOV R4,A ;R4 = 百位数
MOV A,#0AH
XCH A,B
DIV AB ;B = A % B
SWAP A ;高、低位交换
ORL A,B
RET
;―――――――――――――
; 小数部分码表
DOTTAB:
DB 00H,00H,01H,01H,02H,03H,03H,04H
DB 05H,05H,06H,06H,07H,08H,08H,09H
;-------- 显示区BCD 码温度值刷新子程序 --------
DISP_BCD:
MOV A,TEMPLC ;个位数BCD码送入A
ANL A,#0FH ;取低位码
MOV 70H,A ;小数位
MOV A,TEMPLC
SWAP A ;高、低位交换
ANL A,#0FH ;取结果数的高位
MOV 71H,A ;个位
MOV A,TEMPHC
ANL A,#0FH ;取低位码
MOV 72H,A ;十位
MOV A,TEMPHC
SWAP A ;高、低位交换
ANL A,#0FH ;取结果数的高位
MOV 73H,A ;百位
MOV A,TEMPHC
ANL A,#0F0H ;取低位码
CJNE A,#010H,DI0
JMP DI2
;―――――――――――――
DI0: MOV A,TEMPHC
ANL A,#0FH ;取低位码
JNZ DI2 ;十位数是0
MOV A,TEMPHC
SWAP A ;高、低位交换
ANL A,#0FH ;取结果数的高位
MOV 73H,#0AH ;符号位不显示
MOV 72H,A ;十位数显示符号
DI2: RET
;==================================================
;==========读1302子程序=================
RD_DS1302:
MOV DS1302_ADDR,#8DH ;读DS1302中的年
LCALL READ ;调用读DS1302子程序
MOV TIME_YEAR, DS1302_DATA ;把读出的年数据存入年寄存器中
MOV DS1302_ADDR,#8BH ;读DS1302中的星期
LCALL READ
MOV WEEK_DATA, DS1302_DATA ;把读出的星期数据存入星期寄存器中
MOV DS1302_ADDR,#89H ;读DS1302中的月
LCALL READ
MOV TIME_MONT, DS1302_DATA ;把读出的月数据存入月寄存器中
MOV DS1302_ADDR,#87H ;读DS1302中的天
LCALL READ
MOV TIME_DAY, DS1302_DATA ;把读出的天数据存入天寄存器中
MOV DS1302_ADDR,#85H ;读DS1302中的小时
LCALL READ
MOV HOUR, DS1302_DATA ;把读出的天数据存入小时寄存器中
MOV DS1302_ADDR,#83H ;读DS1302中的分钟
LCALL READ
MOV MINTUE, DS1302_DATA ;把读出的天数据存入分钟寄存器中
MOV DS1302_ADDR,#81H ;读DS1302中的秒钟
LCALL READ
MOV SECOND, DS1302_DATA ;把读出的天数据存入秒钟寄存器中
RET
;===========按键子程序=================
;=========数据分离后送显示缓存==================
DATA_BUF:
MOV R0,TIME_YEAR ;年数据分离,送显示缓存
LCALL DIVIDE ;调用数据分离子程序
MOV YEAR_HBUF,R1
MOV YEAR_LBUF,R2
MOV R0,TIME_MONT ;月数据分离,送显示缓存
LCALL DIVIDE
MOV MONT_HBUF,R1
MOV MONT_LBUF,R2
MOV R0,TIME_DAY ;日数据分离,送显示缓存
LCALL DIVIDE
MOV DAY_HBUF,R1
MOV DAY_LBUF,R2
MOV R0,WEEK_DATA ;星期数据分离,送显示缓存
LCALL DIVIDE
MOV WEEK_HBUF,R1
MOV WEEK_LBUF,R2
MOV R0,HOUR ;小时数据分离,送显示缓存
LCALL DIVIDE
MOV HOUR_HBUF,R1
MOV HOUR_LBUF,R2
MOV R0,MINTUE ;分钟数据分离,送显示缓存
LCALL DIVIDE
MOV MINTUE_HBUF,R1
MOV MINTUE_LBUF,R2
MOV R0,SECOND ;秒钟数据分离,送显示缓存
LCALL DIVIDE
MOV SECOND_HBUF,R1
MOV SECOND_LBUF,R2
RET
;=========日历显示子程序==========
;===============年显示===============
DISPLAY:
MOV A,#10000001B ;设定年第1位的显示地址为第1行,第1列
LCALL WR_COMM ;调用写指令到液晶子程序
MOV A, #32H ;数字2的ASCII码
LCALL WR_DATA ;调用写 数据到液晶子程序
MOV A,#10000010B ;设定年第2位的显示地址为第1行,第2列
LCALL WR_COMM
MOV A, #30H ;数字0的ASCII码
LCALL WR_DATA
MOV A,#10000011B ;设定年第3位的显示地址为第1行,第3列
LCALL WR_COMM
MOV A, YEAR_LBUF ;年的低位缓存数据
ADD A,#30H ;加30H修正取ASCII码
LCALL WR_DATA
MOV A,#10000100B ;设定年第4位的显示地址为第1行,第4列
LCALL WR_COMM
MOV A, YEAR_HBUF ;年的高位缓存数据
ADD A,#30H ;加30H修正取ASCII码
LCALL WR_DATA
; =====================斜线显示========================
MOV A,#10000101B ;设定斜线的显示地址为第1行,第5列
LCALL WR_COMM
MOV A,#2FH ;斜线的ASCII码
LCALL WR_DATA
;================显示月============
MOV A,#10000110B ;设定月第1位的显示地址为第1行,第6列
LCALL WR_COMM
MOV A, MONT_LBUF ;月的低位缓存数据
ADD A,#30H ;加30H修正取ASCII码
LCALL WR_DATA
MOV A,#10000111B ;设定月第2位的显示地址为第1行,第7列
LCALL WR_COMM
MOV A, MONT_HBUF ;月的高位缓存数据
ADD A,#30H ;加30H修正取ASCII码
LCALL WR_DATA
;=======================斜线显示============================
MOV A,#10001000B ;设定斜线的显示地址为第1行,第8列
LCALL WR_COMM
MOV A,#2FH ;斜线的ASCII码
LCALL WR_DATA
;==============================天显示=======================
MOV A,#10001001B ;设定天第1位的显示地址为第1行,第9列
LCALL WR_COMM
MOV A, DAY_LBUF ;天的低位缓存数据
ADD A,#30H ;加30H修正取ASCII码
LCALL WR_DATA
MOV A,#10001010B ;设定天第2位的显示地址为第1行,第10列
LCALL WR_COMM
MOV A, DAY_HBUF ;天的高位缓存数据
ADD A,#30H ;加30H修正取ASCII码
LCALL WR_DATA
;========================星期显示======================
MOV A,#10001111B ;设定星期第2位的显示地址为第1行,第13列
LCALL WR_COMM
MOV A, WEEK_DATA ;星期的高位缓存数据
SUBB A,#1
ADD A,#30H ;加30H修正取ASCII码
LCALL WR_DATA
;=======================小时显示============================
MOV A,#11000000B ;设定小时第1位的显示地址为第2行,第0列
LCALL WR_COMM
MOV A, HOUR_LBUF ;小时的低位缓存数据
ADD A,#30H ;加30H修正取ASCII码
LCALL WR_DATA
MOV A,#11000001B ;设定小时第2位的显示地址为第2行,第1列
LCALL WR_COMM
MOV A, HOUR_HBUF ;小时的高位缓存数据
ADD A,#30H ;加30H修正取ASCII码
LCALL WR_DATA
;====================== 冒号的显示==========================
MOV A,#11000010B ;设定冒号的显示地址为第2行,第2列
LCALL WR_COMM
MOV A, #3AH ;冒号的ASCII码
LCALL WR_DATA
;==================== 分钟显示======================
MOV A,#11000011B ;设定分钟第1位的显示地址为第2行,第3列
LCALL WR_COMM
MOV A, MINTUE_LBUF ;分钟的低位缓存数据
ADD A,#30H ;加30H修正取ASCII码
LCALL WR_DATA
MOV A,#11000100B ;设定分钟第2位的显示地址为第2行,第4列
LCALL WR_COMM
MOV A, MINTUE_HBUF ;分钟的高位缓存数据
ADD A,#30H ;加30H修正取ASCII码
LCALL WR_DATA
;====================== 冒号的显示===========================
MOV A,#11000101B ;设定冒号的显示地址为第2行,第5列
LCALL WR_COMM
MOV A, #3AH ;冒号的ASCII码
LCALL WR_DATA
;===================== 秒钟显示=============================
MOV A,#11000110B ;设定秒钟第1位的显示地址为第2行,第6列
LCALL WR_COMM
MOV A, SECOND_LBUF ;秒钟的低位缓存数据
ADD A,#30H ;加30H修正取ASCII码
LCALL WR_DATA
MOV A,#11000111B ;设定秒钟第2位的显示地址为第2行,第7列
LCALL WR_COMM
MOV A, SECOND_HBUF ;秒钟的高位缓存数据
ADD A,#30H ;加30H修正取ASCII码
LCALL WR_DATA
RET
;―――――――― DS18B20复位初始化子程序 ――――――――――
RESET_1820: ;复位(有具体的时序要求)
SETB DQ
NOP
CLR DQ
;―――――――――――――
;主机发出延时537微秒的复位低脉冲
MOV R1,#3
DLY: MOV R0,#107
DJNZ R0,$
DJNZ R1,DLY
;―――――――――――――
;然后拉高数据线
SETB DQ
NOP
NOP
NOP
;―――――――――――――
;等待DS18B20回应
MOV R0,#25H
T2: JNB DQ ,T5
DJNZ R0, T2
;―――――――――――――
;时序要求延时一段时间
T5: MOV R0,#117
T6: DJNZ R0,T6
;――――――――――――――
T7: SETB DQ
RET
;=======================================================
;========DS1302初始化===========
SET_1302:
MOV DS1302_ADDR, #8EH ;写DS1302控制指令
MOV DS1302_DATA, #00H ;写数据到DS1302的8E控制寄存器中,允许对其进行写操作
LCALL WRITE ;调用写DS1302子程序
MOV DS1302_ADDR, #90H ;写DS1302控制指令
MOV DS1302_DATA,#0A6H ;写数据到DS1302的90控制寄存器中,对电池涓流充电,充电电流为1。1mA
LCALL WRITE ;调用写DS1302子程序
RET
;=========查询忙碌标志============
CHECK_BUSY:
PUSH ACC
BUSY_LOOP:
CLR E
SETB RW
CLR RS
SETB E
MOV A, p0
JB p0.7,BUSY_LOOP
POP ACC
LCALL DEL
RET
;--——-—--——--——————----—————-————-—-—————-——-—--—-———-—-——-——--—--—-——--——--——-——--——-—--—-——--
;===========延时程序===================
DEL:
MOV R6,#5
L1:
MOV R7,#248
DJNZ R7,$
DJNZ R6,L1
RET
;―――――――――― 写入DS18B20子程序 ―――――――――――
;写入DS18B20(有具体的时序要求)
WRITE_1820:
MOV R2,#8 ;一共8位数据
CLR C ;C=0
WR1:
CLR DQ ;总线低位,开始写入
MOV R3,#6
DJNZ R3,$ ;保持16微秒以上
RRC A ;把字节DATA分成8个BIT环移给C
MOV DQ, C ;写入一个BIT
MOV R3,#23
DJNZ R3,$ ;等待
SETB DQ ;重新释放总线
NOP
DJNZ R2,WR1 ;写入下一个BIT
SETB DQ ;释放总线
RET
;―――――――――― 读出DS18B20子程序 ―――――――――――
;将温度值从DS18B20中读出(有具体的时序要求)
READ_1820:
MOV R4,#4
MOV R1,#TEMPL ;存入25H、26H、27H、28H
RE0:
MOV R2,#8 ;数据一共有8位
RE1:
CLR C
SETB DQ
NOP
NOP
CLR DQ ;读前总线保持为低位
NOP
NOP
NOP
SETB DQ ;总线释放
;―――――――――――――
MOV R3,#9
DJNZ R3,$ ;延时18微妙
MOV C, DQ ;从总线读到一个BIT
;―――――――――――――
MOV R3,#23 ;
DJNZ R3
展开阅读全文