在做課程設計,其中有一條是需要時間與溫度交替顯示。
我寫好了溫度顯示和時間顯示,分別測試都已經可以實現功能了。
但是,一旦把溫度顯示和時間顯示合并在一個程序中,時間顯示是正常的,但是溫度顯示為“FE”了。
測試了一下,發現沒有加進時間中斷程序的時候,溫度顯示是正常的,加進來時間中斷程序之后,溫度顯示就變成了“EF”。
弄了一天都沒有找到哪里錯了,請大家指出程序的錯誤,謝謝啦!
下面是代碼
- FLAG1 BIT 00H ;FLAG1:標志位,為"1"時表示檢測到DS18B20
- TEMPER_NUM EQU 38H ;TEMPER_NUM:保存讀出的溫度數據
- TEMPER_L EQU 5BH ;溫度的低位
- TEMPER_H EQU 5AH ;溫度的高位
- TEMP EQU 5DH ;臨時存放溫度數據的單元
- DIS_TEMP EQU 58H ;58H存放顯示溫度的個位數,59H存放顯示溫度的十位數
- DIS_C EQU 5CH
- DQ BIT P1.3 ; DQ:DS18B20的數據總線接腳
- ;DS18B20初始化程序
- ;//*****************************************//
- ;定義區
- ;//===============================
- ;//時間計數緩沖區
- DIS_MIN EQU 50H ;50H,51H
- DIS_HOUR EQU 52H ;52H,53H
- DIS_DAY EQU 54H ;54H,55H
- DIS_MON EQU 56H ;56H,57H
- ;//===============================
- ;//時間儲存單元
- MONTH EQU 30H
- DAY EQU 31H
- HOUR EQU 32H
- MINUTE EQU 33H
- COUNT_MIN EQU 4FH
- DL_2S EQU 41H
- ORG 0000H
- LJMP MAIN
- ORG 000BH
- LJMP TIMER_T0
- ORG 0030H
-
- MAIN: MOV R0,#50H
- MOV R2,#8
- CLEAR: MOV @R0,#00
- INC R0
- DJNZ R2,CLEAR ;緩沖區清0
- ACALL INT_TO ;定時器T0初始化
- MOV MONTH,#01H
- MOV DAY,#01H
- MOV HOUR,#00
- MOV MINUTE,#00
- MOV DL_2S,#64H
- MOV A,#00
- MOV TEMPER_NUM,A
- MOV TEMPER_L,#00
- MOV TEMPER_H,#00
- MOV DIS_C,#0CH
- ACALL INIT_1820
- LOOP1: NOP
- CALL DISPLY_CLOCK
- CALL DL10MS
- DJNZ DL_2S,LOOP1
- MOV DL_2S,#64H
- LOOP2: CALL DISPLY_DATE
- CALL DL10MS
- DJNZ DL_2S,LOOP2
- MOV DL_2S,#64H
-
- LOOP3: CALL TEMPER
- CALL DISPLY_TEMP
- CALL DL10MS
- DJNZ DL_2S,LOOP3
- MOV DL_2S,#64H
- LJMP LOOP1
- ;初始化程序
- INIT_1820: SETB DQ
- NOP
- CLR DQ ;主機發出延時540us的復位低脈沖
- MOV R0,#36
- LCALL DELAY
- SETB DQ ;然后拉高數據線
- NOP
- NOP
- MOV R0,#36
- TSR2: JNB DQ,TSR3 ;等待DS18B20的回應
- DJNZ R0,TSR2
- LJMP TSR4; 延時
- TSR3: SETB FLAG1; 置標志位,表示DS1820存在
- LJMP TSR5
- TSR4: CLR FLAG1; 清標志位,表示DS1820不存在
- LJMP TSR7
- TSR5: MOV R0,#06BH; 200us
- TSR6: DJNZ R0,TSR6; 復位成功!時序要求延時一段時間
- TSR7: SETB DQ
- RET
- ;//定時器初始化
- INT_TO: MOV COUNT_MIN,#20
- MOV TMOD,#01H
- MOV TH0,#0FFH ;延時50MS,常數3CB0H
- MOV TL0,#0B0H
- SETB EA
- SETB ET0
- SETB TR0
- RET
- ;//================================時鐘中斷程序
- ORG 0200H
- TIMER_T0:PUSH ACC
- PUSH PSW
- MOV TH0,#0FFH
- MOV TL0,#0B0H
- DJNZ COUNT_MIN,TINEXT
- MOV COUNT_MIN,#20
- MOV A,MINUTE ;分處理
- ADD A,#01H
- DA A
- MOV MINUTE, A
- CJNE A, #60H,TINEXT;分處理結束
- MOV MINUTE,#00 ;分清零
- MOV A,HOUR ;時處理
- ADD A,#01H
- DA A
- MOV HOUR, A
- CJNE A, #24H,TINEXT;時處理結束
- MOV HOUR,#00 ;時清零
- MOV A,DAY ;日處理
- ADD A,#01H
- DA A
- MOV DAY, A
- CJNE A, #31H,TINEXT;日處理結束
- MOV DAY,#01 ;日清零
- MOV A,MONTH ;月處理
- ADD A,#01H
- DA A
- MOV MONTH,A
- CJNE A, #13,TINEXT ;月處理結束
- MOV MONTH,#01 ;月清零
- TINEXT: POP PSW
- POP ACC
- RETI
-
- TEMPER: ACALL RE_CONFIG
- ACALL GET_TEMPER
- CALL TEMPER_COV
- RET
- ;//*****************************************//
- ; 重新寫DS18B20暫存存儲器設定值
- ;//*****************************************//
- RE_CONFIG: JB FLAG1,RE_CONFIG1; 若DS18B20存在,轉RE_CONFIG1
- RET
- RE_CONFIG1:MOV A,#0CCH; 發SKIP ROM命令
- LCALL WRITE_1820
- MOV A,#4EH; 發寫暫存存儲器命令
- LCALL WRITE_1820
- MOV A,#00H; 不 TH(報警上限)中寫入00H
- LCALL WRITE_1820
- MOV A,#00H; TL(報警下限)中寫入00H
- LCALL WRITE_1820
- MOV A,#1FH; 選擇9位溫度分辨率
- LCALL WRITE_1820
- RET
- ;//*****************************************//
- ; 讀出轉換后的溫度值
- ;//*****************************************//
- GET_TEMPER: SETB DQ; 定時入口
- LCALL INIT_1820
- JB FLAG1,TSS2
- RET; 若DS18B20不存在則返回
- TSS2: MOV A,#0CCH; 跳過ROM匹配
- LCALL WRITE_1820
- MOV A,#44H; 發出溫度轉換命令
- LCALL WRITE_1820
- MOV R0,#50;等待A/D轉換結束,12位的話750us
- LCALL DELAY
- LCALL INIT_1820
- MOV A,#0CCH; 跳過ROM匹配
- LCALL WRITE_1820
- MOV A,#0BEH; 發出讀溫度命令
- LCALL WRITE_1820
- LCALL READ_18200
- MOV TEMPER_NUM,A; 將讀出的溫度數據保存
- RET
- ;//*****************************************//
- ; 讀DS18B20的程序,從DS18B20中讀出一個字節的數據
- ;//*****************************************//
- READ_1820: MOV R2,#8
- RE1: CLR C
- SETB DQ
- NOP
- NOP
- CLR DQ
- NOP
- NOP
- NOP
- SETB DQ
- MOV R3,#7
- DJNZ R3,$
- MOV C,DQ
- MOV R3,#23
- DJNZ R3,$
- RRC A
- DJNZ R2,RE1
- RET
- ;//*****************************************//
- ; 寫DS18B20的程序
- ;//*****************************************//
- WRITE_1820: MOV R2,#8
- CLR C
- WR1: CLR DQ
- MOV R3,#6
- DJNZ R3,$
- RRC A
- MOV DQ,C
- MOV R3,#23
- DJNZ R3,$
- SETB DQ
- NOP
- DJNZ R2,WR1
- SETB DQ
- RET
- ;//*****************************************//
- ; 讀DS18B20的程序,從DS18B20中讀出兩個字節的溫度數據
- ;//*****************************************//
- READ_18200:MOV R4,#2; 將溫度高位和低位從DS18B20中讀出
- MOV R1,#5BH; 低位存入5BH(TEMPER_L),高位存入5AH(TEMPER_H)
- RE00:MOV R2,#8
- RE01:CLR C
- SETB DQ
- NOP
- NOP
- CLR DQ
- NOP
- NOP
- NOP
- SETB DQ
- MOV R3,#7
- DJNZ R3,$
- MOV C,DQ
- MOV R3,#23
- DJNZ R3,$
- RRC A
- DJNZ R2,RE01
- MOV @R1,A
- DEC R1
- DJNZ R4,RE00
- RET
- ;//*****************************************//
- ; 將從DS18B20中讀出的溫度數據進行轉換
- ;//*****************************************//
- TEMPER_COV: MOV A,#0F0H
- ANL A,TEMPER_L; 舍去溫度低位中小數點后的四位溫度數值
- SWAP A
- MOV TEMPER_NUM,A
- MOV A,TEMPER_L
- JNB ACC.3,TEMPER_COV1; 四舍五入去溫度值
- INC TEMPER_NUM
- TEMPER_COV1: MOV A,TEMPER_H
- ANL A,#07H
- SWAP A
- ORL A,TEMPER_NUM
- MOV TEMPER_NUM,A; 保存變換后的溫度數據
- LCALL BIN_BCD
- RET
- ;//*****************************************//
- ; 將16進制的溫度數據轉換成壓縮BCD碼
- ;//*****************************************//
- BIN_BCD: MOV DPTR,#TEMP_TAB
- MOV A,TEMPER_NUM
- MOVC A,@A+DPTR
- MOV TEMPER_NUM,A
- RET
- TEMP_TAB: DB 00H,01H,02H,03H,04H,05H,06H,07H
- DB 08H,09H,10H,11H,12H,13H,14H,15H
- DB 16H,17H,18H,19H,20H,21H,22H,23H
- DB 24H,25H,26H,27H,28H,29H,30H,31H
- DB 32H,33H,34H,35H,36H,37H,38H,39H
- DB 40H,41H,42H,43H,44H,45H,46H,47H
- DB 48H,49H,50H,51H,52H,53H,54H,55H
- DB 56H,57H,58H,59H,60H,61H,62H,63H
- DB 64H,65H,66H,67H,68H,69H,70H,71H
- DB 72H,73H,74H,75H,76H,77H,78H,79H
- DB 80H,81H,82H,83H,84H,85H,86H,87H
- DB 88H,89H,90H,91H,92H,93H,94H,95H
- DB 96H,97H,98H,99H
- ;//*****************************************//
- ; 延時子程序
- ;為保證DS18B20的嚴格I/O時序,需做較精確的延時
- ;在DS18B20操作中,用到的延時有15us、90us、270us、540us、750us
- ;因為這些延時均為15us的倍數,因此可編寫一個DELAY15(n)函數
- ;//*****************************************//
- DELAY:
- TEMP_LOOP:MOV R1,#06H
- TEMP_LOOP1:DJNZ R1,TEMP_LOOP1
- DJNZ R0,TEMP_LOOP
- RET
- ;//*****************************************//
- ;500毫秒延時子程序和10毫秒延時子程序
- ;//*****************************************//
- DELAY500:MOV R4,#248
- DA222: MOV R5,#248
- DJNZ R5,$
- DJNZ R4,DA222
- RET
-
- DL10MS: MOV R5,#10
- DL1: MOV R6,#20
- DL: NOP
- NOP
- NOP
- DJNZ R6,DL
- DJNZ R5,DL1
- RET
- ;=================================顯示一位子程序
- ;顯示子程序
- ;顯示緩沖區地址:(R0)
- ;位控(R2)
- DIS: MOV DPTR, #SEG_TAB
- MOV A,@R0
- MOVC A,@A+DPTR
- MOV P0,A ;輸出
- NOP
- NOP
- MOV A,R2
- MOV P1,A
- NOP
- NOP
- RET
-
- SEG_TAB: DB 3FH,06H,5BH,4FH
- DB 66H,6DH,7DH,07H
- DB 7FH,6FH,77H,7CH
- DB 39H,5EH,79H,71H
- ;=================================BCD分離子程序
- ; 待轉換的數放在(R2)中
- ; 轉換結果放在(R0)指出的單元中
- BCDS: MOV A, R2
- ANL A,#00001111B
- MOV @R0,A
- INC R0
- MOV A,R2
- ANL A,#11110000B
- SWAP A
- MOV @R0,A
- RET
- ;================================顯示程序
- DISPLY_TEMP:
- MOV R2, TEMPER_NUM; 取溫度
- MOV R0, #DIS_TEMP
- CALL BCDS
-
- NOP
- MOV R0,#DIS_C
- MOV R2,#00000101B
- CALL DIS
- CALL DL10MS
- MOV R0,#DIS_TEMP
- MOV R2,#00000100B ;溫度個位
- CALL DIS
- CALL DL10MS
- INC R0
- MOV R2,#00000011B ;溫度十位
- CALL DIS
- CALL DL10MS
- RET
- DISPLY_CLOCK:
- MOV R2, MINUTE; 取分值
- MOV R0, #DIS_MIN
- CALL BCDS
- MOV R2, HOUR; 取時值
- MOV R0, #DIS_HOUR
- CALL BCDS
-
- NOP
- MOV R0,#DIS_MIN
- MOV R2,#00000101B ;分個位
- CALL DIS
- CALL DL10MS
- INC R0
- MOV R2,#00000100B ;分十位
- CALL DIS
- CALL DL10MS
- INC R0
- MOV R2,#00000010B ;時個位
- CALL DIS
- CALL DL10MS
- INC R0
- MOV R2,#00000001B ;時十位
- CALL DIS
- CALL DL10MS
- RET
- DISPLY_DATE:
- MOV R2, DAY; 取日值
- MOV R0, #DIS_DAY
- CALL BCDS
- MOV R2,MONTH; 取月值
- MOV R0, #DIS_MON
- CALL BCDS
-
- NOP
- MOV R0,#DIS_DAY
- MOV R2,#00000101B ;日個位
- CALL DIS
- CALL DL10MS
- INC R0
- MOV R2,#00000100B ;日十位
- CALL DIS
- CALL DL10MS
- INC R0
- MOV R2,#00000010B ;月個位
- CALL DIS
- CALL DL10MS
- INC R0
- MOV R2,#00000001B ;月十位
- CALL DIS
- CALL DL10MS
- INC R0
- RET
- END
復制代碼
|