?? shuiwen.asm
字號:
TEMPER_L EQU 29H ;用于保存讀出溫度的低8位
TEMPER_H EQU 28H ;用于保存讀出溫度的高8位
FLAG1 EQU 38H ;是否檢測到DS18B20標志位
FLAG2 EQU 39H ;存放設定的溫度
FLAG3 EQU 40H ;存放當前的溫度
a_bit EQU 20H ;數碼管個位數存放內存位置
b_bit EQU 21H ;數碼管十位數存放內存位置
K_OLD EQU 30H ;存放按鍵未按下時的按鍵端口值
K_NEW EQU 31H ;存放按鍵按下時的按鍵端口值
;------------------------------------------------------
ORG 0000H
AJMP MAIN
ORG 0030H
;------------------------------------------------------
MAIN: ACALL CHUSHI ;初始化
LCALL DS1820 ;顯示當前溫度
LCALL DS1820
MOV FLAG3,R5
MOV 29H,FLAG3
LCALL DISPLAY
LCALL LOSS ;判斷是否缺水
LCALL KEY ;判斷是否有按鍵
MAIN1: LCALL KEY00 ;溫度設定
MAIN2: LCALL WENBI ;當前溫度與設定溫度比較
MAIN3: LCALL DS1820
AJMP MAIN
;---------- 初始化 -----------------------------------
CHUSHI: MOV P0,#78H
MOV P2,#1CH
RET
;---------- 當前溫度與設定溫度比較 -------------------
WENBI: CLR C ;標志位清零
MOV A,FLAG3 ;當前溫度存入A
MOV FLAG2,R2 ;設定溫度存入FLAG2
SUBB A,FLAG2 ;設定溫度減去當前溫度
JNC MAIN ;設定溫度小于當前溫度則跳回主程序
WENBI1: MOV P0,#7FH ;判斷是否缺水
LCALL LOSS ;缺水報警
MOV P2,#12H ;亮燈,接通繼電器,加熱
LCALL DS1820
MOV A,R5
SUBB A,FLAG2 ;設定溫度減去當前溫度
JC WENBI1 ;設定溫度大于當前溫度,繼續加熱
MOV P2,#01H
LCALL DS1820
LCALL DS1820
LCALL DS1820
LCALL DS1820
;---------------- 保持溫度不變 -----------------------
CLR C ;標志位清零
WENBI2: MOV P2,#00H
LCALL DS1820
MOV P0,#7FH ;判斷是否缺水
LCALL LOSS
MOV A,R5 ;當前溫度存入A
SUBB A,FLAG2
JNC WENBI2 ;設定溫度小于當前溫度,則繼續測試,否則加熱
WENBI3: MOV P2,#12H ;亮燈,接通繼電器,加熱
LCALL DS1820
MOV P0,#7FH ;判斷是否缺水
LCALL LOSS
MOV A,R5
SUBB A,FLAG2
JC WENBI3 ;設定溫度大于當前溫度,則繼續加熱
JMP WENBI2
;--------------- 3號鍵十位設置 -----------------------
KEY11: ACALL K_SCAN2
MOV A,K_NEW
CJNE A,K_OLD,KEY21
JMP KEY11
KEY21: CALL K_DELAY
CALL K_SCAN2
MOV A,K_NEW
CJNE A,K_OLD,KEY31
JMP KEY11
KEY31: MOV A,R3 ;90跳轉
SUBB A,#5AH
JZ KEY00
MOV A,R3 ;91跳轉
SUBB A,#5BH
JZ KEY00
MOV A,R3 ;92跳轉
SUBB A,#5CH
JZ KEY00
MOV A,R3 ;93跳轉
SUBB A,#5DH
JZ KEY00
MOV A,R3 ;94跳轉
SUBB A,#5EH
JZ KEY00
MOV A,R3 ;95跳轉
SUBB A,#5FH
JZ KEY00
MOV A,R3 ;96跳轉
SUBB A,#60H
JZ KEY00
MOV A,R3 ;97跳轉
SUBB A,#61H
JZ KEY00
MOV A,R3 ;98跳轉
SUBB A,#62H
JZ KEY00
MOV A,R3 ;99跳轉
SUBB A,#63H
JZ KEY00
MOV A,R3
ADD A,#0AH
MOV 29H,A
CALL DISPLAY
JMP KEY01
K_SCAN2:MOV K_NEW,#00H
MOV A,P0.4
MOV K_NEW,A
RET
;----------------- 中轉 --------------------------
MIDDLE1:;JMP MAIN2
RET
;----------------- KEY判斷 -----------------------
KEY00: MOV R2,#00H
MOV 29H,#00H
LCALL DISPLAY
CALL KEY01
RET
KEY01: LCALL DISPLAY
MOV K_OLD,#00H ;保存初始值
JNB P0.5,KEY10 ;2號鍵個位有按下則跳轉
JNB P0.4,KEY11 ;3號鍵十位有按下則跳轉
JNB P0.6,MIDDLE1
JMP KEY01
;---------------- 2號鍵個位設置 --------------------------
KEY10: ACALL K_SCAN1
MOV A,K_NEW
CJNE A,K_OLD,KEY20
JMP KEY10
KEY20: CALL K_DELAY
CALL K_SCAN1
MOV A,K_NEW
CJNE A,K_OLD,KEY30
JMP KEY10
KEY30: MOV A,#63H
SUBB A,R2
JZ KEY00
INC R2
MOV 29H,R2
CALL DISPLAY
JMP KEY01
K_SCAN1:
MOV K_NEW,#00H
MOV A,P0.5
MOV K_NEW,A
RET
;--------------------- 按鍵判斷 ---------------------------
KEY: MOV P0,#07FH ;按鍵端口初始化
MOV K_OLD,#70H ;存儲按鍵未按時的按鍵端口值
KEY1: LCALL DS1820
LCALL LOSS
ACALL K_SCAN ;掃描鍵盤
MOV A,K_NEW
CJNE A,K_OLD,KEY2
JMP KEY1 ;沒有按鍵按下,則繼續掃描
KEY2: CALL K_DELAY ;按鍵延時
CALL K_SCAN ;再次掃描
MOV A,K_NEW
CJNE A,K_OLD,KEY3 ;有按鍵按下,跳轉運行
JMP KEY1 ;沒有按鍵按下,則繼續掃描
KEY3: MOV P2,#18H
RET
K_SCAN:
MOV K_NEW,#00H
MOV A,P0
MOV K_NEW,A
RET
K_DELAY:
MOV R6,#200
K_DEL:
MOV R7,#0FFH
DJNZ R7,$
DJNZ R6,k_DEL
RET
;-------------- 缺水報警子程序 --------------------------
LOSS: MOV A,P0
MOV R1,#08H
ANL A,R1
ANL A,R1
CJNE A,#00H,BAOJING
RET
BAOJING:LCALL DS1820
CLR P2.1
SETB P2.0
Nop
LCALL DELAY
CLR P2.0
Nop
LCALL DELAY
LJMP LOSS
DELAY: MOV R1,#10 ;延時0.5s子程序,使用參數R0,R7和R6
DELY0: MOV R2,#100 ;延時0.05s
DELY1: MOV R3,#250 ;延時0.5ms
DJNZ R3,$
DJNZ R2,DELY1
DJNZ R1,DELY0
RET
;---------------- DS1820子程序 ------------------------------------
DS1820: LCALL GET_TEMPER;調用讀溫度子程序
;進行溫度顯示,這里我們考慮用網站提供的兩位數碼管來顯示溫度
;顯示范圍00到99度,顯示精度為1度
;因為12位轉化時每一位的精度為0.0625度,我們不要求顯示小數所以可以拋棄29H的低4位
;將28H中的低4位移入29H中的高4位,這樣獲得一個新字節,這個字節就是實際測量獲得的溫度
;這個轉化溫度的方法非常簡潔無需乘于0.0625系數
MOV A,29H
MOV C,40H ;將28H中的最低位移入C
RRC A
MOV C,41H
RRC A
MOV C,42H
RRC A
MOV C,43H
RRC A
MOV 29H,A
MOV R5,29H
LCALL DISPLAY ;調用數碼管顯示子程序
;CPL P2.2
RET
; 這是DS18B20復位初始化子程序
INIT_1820:
SETB P1.0
NOP
CLR P1.0
;主機發出延時537微秒的復位低脈沖
MOV R1,#3
TSR1: MOV R0,#107
DJNZ R0,$
DJNZ R1,TSR1
SETB P1.0 ;然后拉高數據線
NOP
NOP
NOP
MOV R0,#25H
TSR2: JNB P1.0,TSR3;等待DS18B20回應
DJNZ R0,TSR2
LJMP TSR4 ;延時
TSR3: SETB FLAG1 ;置標志位,表示DS1820存在
;CLR P2.3 ;檢查到DS18B20就點亮P1.7LED
LJMP TSR5
TSR4: CLR FLAG1 ;清標志位,表示DS1820不存在
;CLR P2.4
LJMP TSR7
TSR5: MOV R0,#117
TSR6: DJNZ R0,TSR6 ;時序要求延時一段時間
TSR7: SETB P1.0
RET
; 讀出轉換后的溫度值
GET_TEMPER:
SETB P1.0
LCALL INIT_1820;先復位DS18B20
JB FLAG1,TSS2
RET ;判斷DS1820是否存在?若DS18B20不存在則返回
TSS2: ;CLR P2.4 ;DS18B20已經被檢測到!!!!!!!!!!!!!!!!!!
MOV A,#0CCH ;跳過ROM匹配
LCALL WRITE_1820
MOV A,#44H ;發出溫度轉換命令
LCALL WRITE_1820
;這里通過調用顯示子程序實現延時一段時間,等待AD轉換結束,12位的話750微秒
LCALL DISPLAY
LCALL INIT_1820 ;準備讀溫度前先復位
MOV A,#0CCH ;跳過ROM匹配
LCALL WRITE_1820
MOV A,#0BEH ;發出讀溫度命令
LCALL WRITE_1820
LCALL READ_18200;將讀出的溫度數據保存到35H/36H
RET
;寫DS18B20的子程序(有具體的時序要求)
WRITE_1820:
MOV R2,#8 ;一共8位數據
CLR C
WR1: CLR P1.0
MOV R3,#6
DJNZ R3,$
RRC A
MOV P1.0,C
MOV R3,#23
DJNZ R3,$
SETB P1.0
NOP
DJNZ R2,WR1
SETB P1.0
RET
; 讀DS18B20的程序,從DS18B20中讀出兩個字節的溫度數據
READ_18200:
MOV R4,#2 ;將溫度高位和低位從DS18B20中讀出
MOV R1,#29H ;低位存入29H(TEMPER_L),高位存入28H(TEMPER_H)
RE00: MOV R2,#8 ;數據一共有8位
RE01: CLR C
SETB P1.0
NOP
NOP
CLR P1.0
NOP
NOP
NOP
SETB P1.0
MOV R3,#9
RE10: DJNZ R3,RE10
MOV C,P1.0
MOV R3,#23
RE20:
DJNZ R3,RE20
RRC A
DJNZ R2,RE01
MOV @R1,A
DEC R1
DJNZ R4,RE00
RET
;--------------- 顯示子程序 ------------------------------------
display:mov a,29H ;將29H中的十六進制數轉換成10進制
MOV R3,29H
MOV R2,29H
mov b,#10 ;10進制/10=10進制
div ab
mov b_bit,a ;十位在a
mov a_bit,b ;個位在b
mov dptr,#numtab ;指定查表啟始地址
mov r0,#4
dpl1: mov r1,#250 ;顯示1000次
dplop: mov a,a_bit ;取個位數
MOVC A,@A+DPTR ;查個位數的7段代碼
mov p1,a ;送出個位的7段代碼
clr p3.7 ;開個位顯示
acall d1ms ;顯示1ms
setb p3.7
mov a,b_bit ;取十位數
MOVC A,@A+DPTR ;查十位數的7段代碼
mov p1,a ;送出十位的7段代碼
clr p3.6 ;開十位顯示
acall d1ms ;顯示1ms
setb p3.6
djnz r1,dplop ;100次沒完循環
djnz r0,dpl1 ;4個100次沒完循環
ret
;1MS延時(按12MHZ算)
D1MS: MOV R7,#80
DJNZ R7,$
RET
;實驗板上的7段數碼管0~9數字的共陰顯示代碼
numtab: DB 002H,9EH,024H,0CH,98H,48H,041H,1EH,00H,08H
; 0 1 2 3 4 5 6 7 8 9
END
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -