;以下程式之讀取寫入時序是針對笙泉82G516,工作於12MHz設計,如要在其他單晶片工作,請自行調整時序, 否則可能無法正常工作 ;將讀取到的溫度顯示在七段顯示器上 DQ EQU P3.3 ;DS18B20資料線 LCD_RS EQU P1.0 ;定義LCD接線位置 LCD_RW EQU P1.1 LCD_E EQU P1.2 LCD_DATA EQU P2 TEMP_H EQU 20H ;讀到的溫度,高位元組 TEMP_L EQU 21H ;讀到的溫度,低位元組 ORG 00H JMP MAIN MAIN: ; MOV R5,#1 ;如果電源關掉重開時,LCD無法正常顯示 ; CALL DELAY ;請加上此延遲程式 CLR LCD_RW ;習慣上直接將LCD的RW接腳直接接地, MOV A,#00111000B ;設定LCD介面為8位元, 2行, 5x7字型 CALL WRIR MOV A,#00001100B ;設定要LCD顯示, 不要有游標 CALL WRIR MOV A,#00000110B ;設定寫資料進入LCD時, 顯示器不要動, 游標向右移一格 CALL WRIR MOV A,#1 ;清除LCD CALL WRIR MOV R5,#1 ;延遲等清除LCD命令處理完畢 CALL DELAY MOV A,#10000101B ;游標移到第五格 CALL WRIR MOV A,#11011111B ;先顯示。C符號 CALL WRDR MOV A,#'C' ; CALL WRDR READ_T: CALL INIT_18B20 MOV A,#0CCH CALL WR_BYTE MOV A,#044H CALL WR_BYTE MOV R5,#80 ;等溫度轉換完畢,要750 ms CALL DELAY CALL INIT_18B20 MOV A,#0CCH CALL WR_BYTE MOV A,#0BEH CALL WR_BYTE CALL RD_BYTE MOV TEMP_L,A ;將讀到的溫度, 存到TMP_L CALL RD_BYTE MOV TEMP_H,A ;將讀到的溫度, 存到TMP_H MOV A,#10000000B ;游標移到開頭 CALL WRIR MOV A,#' ' ; CALL WRDR JNB TEMP_H.7,PLUS ;如果最高位元為0,代表溫度為正 MOV A,TEMP_L CPL A ;如果溫度為負, ADD A,#1 ;取補數再加1 MOV TEMP_L,A MOV A,TEMP_H CPL A ADDC A,#0 MOV TEMP_H,A MOV A,#10000000B ;游標移到開頭 CALL WRIR MOV A,#'-' ; CALL WRDR PLUS: MOV A,TEMP_L ANL A,#0F0H MOV B,A MOV A,TEMP_H ;將高位元組的後4位元與低位元組的前4位元 ANL A,#0FH ;組合成溫度的整數值 ORL A,B SWAP A MOV B,#10 DIV AB ADD A,#30H CALL WRDR MOV A,B ADD A,#30H CALL WRDR MOV A,#'.' CALL WRDR MOV A,TEMP_L ;小數點以下佔4位元,每格代表0.0625度 ANL A,#0FH ;直接用查表比較快 MOV DPTR,#DIGIT ;數值0~15對應到0.0~0.9度 MOVC A,@A+DPTR CALL WRDR ; MOV R5,#250 ;測試用,休息一下再讀下一次溫度 ; CALL DELAY ;好像連續轉換讀到的溫度會高一些? JMP READ_T DIGIT: DB '0112334456678899' ;數值0~15對應到0.0~0.9度 WRIR: CLR LCD_RS ;寫命令到LCD副程式 SETB LCD_E MOV LCD_DATA,A MOV R7,#50 ;延遲等訊號穩定 DJNZ R7,$ CLR LCD_E ;讓Enable接腳產生負緣訊號 MOV R7,#80 ;延遲等訊號處裡完畢 DJNZ R7,$ RET WRDR: SETB LCD_RS ;寫資料到LCD副程式 SETB LCD_E MOV LCD_DATA,A MOV R7,#50 ;延遲等訊號穩定 DJNZ R7,$ CLR LCD_E ;讓Enable接腳產生負緣訊號 MOV R7,#80 ;延遲等訊號處裡完畢 DJNZ R7,$ RET WR_BYTE: ;寫入一位元組訊號 MOV R6,#8 WR_1BIT: RRC A CLR DQ MOV R7,#45 ;持續至多15 us,起始訊號 DJNZ R7,$ MOV DQ,C ;將要寫入DS18B20的資料送出 MOV R7,#60 ;持續20 us,等待ds18b20讀取 DJNZ R7,$ SETB DQ MOV R7,#100 ;持續35 us,等待ds18b20回復 DJNZ R7,$ DJNZ R6,WR_1BIT RET RD_BYTE: ;讀取一位元組訊號 MOV R6,#8 RD_1BIT: CLR DQ MOV R7,#2 ;起始訊號, 持續 2 us DJNZ R7,$ SETB DQ MOV R7,#30 ;等待10 us後再讀訊號訊號 DJNZ R7,$ MOV C,DQ RRC A MOV R7,#150 ;持續50 us,等待ds18b20回復 DJNZ R7,$ DJNZ R6,RD_1BIT RET INIT_18B20: ;喚醒DS18B20 CLR DQ MOV R5,#50 ;起始訊號, 持續 500 us CALL DELAY10 SETB DQ MOV R5,#8 ;持續 80 us,等待DS18B20回應 CALL DELAY10 ; JNB DQ,OK_18B20 ; MOV P2,#55H ;DS18B20不存在時,P2顯示01010101 ; JMP $ ;OK_18B20: MOV R5,#42 CALL DELAY10 RET DELAY: ;延遲時間 = R5 * 10 ms MOV R6,#200 DEL: MOV R7,#150 DJNZ R7,$ DJNZ R6,DEL DJNZ R5,DELAY RET DELAY10: ;延遲時間 = R5 * 10 us MOV R7,#30 DJNZ R7,$ DJNZ R5,DELAY10 RET END