|
;18B10溫度測量+LCD1602顯示溫度 ;實戰目的 ;1、學習18B20單總線溫度傳感器的使用。 ;2、學習LCD的使用。 ;3、學習10進制轉10進制的方法。 ;所有資源: ;1、TMRO定時器。產生溫度轉換所需要的延時時間。 ;2、PORTA口。即做LCD顯示時可控制端口,RA2同時做18B20的數據接口 ;3、PORTC口。做LCD顯示時的數據口。 ;功能說明 ;1、通過18B20采集當前環境 ;最高溫度可顯示127.9375,最低溫度可顯示0.0625(無負溫度處理部分) ;2、將溫度在LCD上顯示(3位整數,4位小數) ;硬件連接 ;1,在18B20按DEMO板上的標識插在插座U8上 ;2,撥碼開關S13第4位置ON ;3,其他所有撥碼開關都置OFF ;源程序如下: LIST P=PIC16F877 TITLE="LCD DISPLAY" ERRORLEVEl -302 ;去掉編譯時的302號提示信息 ;__CONFIG B'000010010101' ;代碼保護開啟;WRT_ENABLE;CPD_ENABLE;LVP_DISABLE;BODEN_ENABLE ;PWRTE_ENABLE;WDT_ENABLE;OSC_XT ;*****************以下是暫存器的定義***************************** #INCLUDE<P16F877A.INC> #DEFINE RS PORTA,1 ;LCD控制信號 #DEFINE RW PORTA,2 ;LCD控制信號 #DEFINE E PORTA,3 ;LCD控制信號 #DEFINE DAT PORTC ;LCD數據線 #DEFINE DQ PORTA,2 ;18B20數據口 CBLOCK 20H DQ_DELAY1 DQ_DELAY2 TEMP TEMP1 TEMP2 ;存放采樣到的溫度值 COUNT COUNT1 ENDC TMR0_VALUE EQU 0AH ;寄存器初值為6,預分頻比1:4,中斷一次時間為4*(256-6)=1000us DQ_DELAY_VALUE1 EQU 0FAH DQ_DELAY_VALUE2 EQU 4H ;***********************以下是宏定義**************************** READ_STATE MACRO ;讀18B20的狀態 BCF RS BSF RW BSF E ENDM WRITE_COMMAND MACRO ;寫命令 BCF RS BCF RW BCF E ENDM WRITE_DATA MACRO ;寫數據 BSF RS BCF RW BCF E ENDM ;**********************以下是程序的開始************************ ORG 00H NOP GOTO MAIN ;入口地址 ORG 04H RETFIE ;在中斷入口出放置一條中斷返回指令,防止干擾產生中斷 ;***************************主程序******************************* MAIN CLRF PORTC CLRF PORTA BANKSEL TRISA CLRF TRISA ;A口所有先設置為輸出 CLRF TRISC MOVLW 01H MOVWF OPTION_REG ;分頻比1:4,定時器,內部時鐘源 MOVLW 06H MOVWF ADCON1 ;關閉所有A/D口 BCF STATUS,RP0 MOVLW 00H MOVWF INTCON ;關閉所有中斷,且同時清零T0IF CLRF TEMP CLRF TEMP1 CLRF TEMP2 ;清零臨時寄存器 ;****************************循環處理部分************************ ;先啟動18B20溫度轉換程序,在判斷溫度轉換是否完成(需750us) ;未完成則調用顯示子程序,直到完成溫度轉換 ;完成后讀取溫度值 ;送LCD顯示 LOOP CALL RESET_18B20 ;調用復位18B20子程序 MOVLW 0CCH MOVWF TEMP CALL WRITE_18B20 ;SKIP ROM命令 MOVLW 44H MOVWF TEMP CALL WRITE_18B20 ;溫度轉換命令 CLRF STATUS BCF INTCON,T0IF CALL DELAY_750MS ;調用溫度轉換所需要的750MS延時 NOP CALL RESET_18B20 MOVLW 0CCH MOVWF TEMP CALL WRITE_18B20 ;SKIP ROM命令 MOVLW 0BEH MOVWF TEMP CALL WRITE_18B20 ;讀溫度命令 CALL READ_18B20 ;調用讀溫度低字節 MOVFW TEMP MOVWF TEMP1 ;保存到TEMP1 CALL READ_18B20 ;調用讀溫度高字節 MOVFW TEMP MOVWF TEMP2 ;保存到TMEP2 CALL RESET_18B20 CALL TEMP_CHANGE ;調用溫度轉換程序 CALL DISPLAY ;調用LCD顯示程序 GOTO LOOP ;循環工作 ;***************************LCD顯示子程序************************ DISPLAY ;LCD模塊初始化,由廠家提供的資料顯示,其初始化過程為: ;6----寫指令38H,此條指令是將LCD顯示模塊設置為8位數據線,雙行,5X7點陣顯示 ;7----檢測Busy信號; ;8----寫指令08H,關閉顯示 ;9----檢測Busy信號; ;10---寫指令01H,顯示清屏 ;以后寫入光標等的控制指令. BANKSEL TRISA CLRF TRISA ;A口為LCD控制信號,全輸出 BANKSEL PORTA NOP MOVLW 38H CALL COMMAND_WRITE ;顯示模式設置:16*2顯示,5*7點陣,8位數碼接口 MOVLW 08H CALL COMMAND_WRITE ;顯示關閉,不顯示光標 MOVLW 01H CALL COMMAND_WRITE ;顯示清屏 MOVLW 06H CALL COMMAND_WRITE ;顯示光標移動設置(右移),整屏顯示不移動 MOVLW 0CH CALL COMMAND_WRITE ;顯示開及光標設置,不顯示光標 DISPLAY0 MOVLW 84H CALL COMMAND_WRITE ;設置顯示起始位置 CALL BUSY ;判忙 MOVLW 8H ;共8個數據需要顯示 MOVWF COUNT MOVLW 37H ;取數地址 MOVWF FSR DISPLAY1 INCF FSR,1 ;取數地址加1 MOVFW INDF CALL DATA_WRITE ;調用寫數據子程序 DECFSZ COUNT,1 GOTO DISPLAY1 RETURN ;*****************************寫命令子程序*********************** COMMAND_WRITE WRITE_COMMAND ;設置寫命令所需要的控制信號 MOVWF DAT ;把命令字送數據口 BSF E NOP BCF E CALL BUSY ;判忙 RETURN ;**************************判總線忙子程序************************ BUSY BSF STATUS,RP0 MOVLW 80H MOVWF TRISC ;數據口最高位置為輸入口 BCF STATUS,RP0 READ_STATE NOP BCF E BTFSC DAT,7 ;是否忙 GOTO BUSY ;是,繼續判斷 BANKSEL TRISC CLRF TRISC ;否,數據最高位恢復為輸出狀態 BCF STATUS,RP0 RETURN ;*************************寫數據子程序*************************** DATA_WRITE WRITE_DATA MOVWF DAT BSF E NOP BCF E CALL BUSY RETURN ;*********************復位DS18B20子程序************************** RESET_18B20 ;根據DATASHEET介紹,寫數據時應遵照如下規定: ;主控制器把總線拉低至少480us, ;18B20等待15-60us后,把總線拉低做為返回給控制器的應答信號 BANKSEL TRISA BCF TRISA,2 BCF STATUS,RP0 BCF DQ MOVLW 0A0H MOVWF COUNT ;160US DECFSZ COUNT,1 GOTO $-1 ;拉低480us BSF DQ ;釋放總線 MOVLW 14H MOVWF COUNT DECFSZ COUNT,1 GOTO $-1 ;等待60us BANKSEL TRISA BSF TRISA,2 ;DQ設置為輸入 BCF STATUS,RP0 BTFSC DQ ;數據線是否為低 GOTO RESET_18B20 ;否則繼續復位 MOVLW 4H MOVWF COUNT DECFSZ COUNT,1 ;延時一段時間后再次判斷 GOTO $-1 BTFSC DQ GOTO RESET_18B20 MOVLW 4BH MOVWF COUNT DECFSZ COUNT,1 GOTO $-1 BANKSEL TRISA BCF TRISA,2 ;DQ設置為輸出 BCF STATUS,RP0 RETURN ;*********************寫DS18B20子程序**************************** WRITE_18B20 ;根據DATASHEET介紹,寫數據時應遵照如下規定: ;寫數據0時,主控制器把總線拉低至少60us ;寫數據1時,主控制器把總線拉低,但必須在15us內釋放 MOVLW 8H MOVWF COUNT ;8位數據 BANKSEL TRISA BCF TRISA,2 BCF STATUS,RP0 BCF STATUS,C WRITE_18B20_1 BSF DQ ;先保持DQ為高 MOVLW 5H MOVWF COUNT1 BCF DQ ;拉低DQ15us DECFSZ COUNT1,1 GOTO $-1 RRF TEMP,1 BTFSS STATUS,C ;判斷寫的數據為0還是1 GOTO WRITE_0 BSF DQ ;為1,立即拉高數據線 GOTO WRITE_END WRITE_0 BCF DQ ;繼續保持數據線為低 WRITE_END MOVLW 0FH MOVWF COUNT1 ;保持45ms DECFSZ COUNT1,1 GOTO $-1 BSF DQ ;釋放總線 DECFSZ COUNT,1 ;是否寫完8位數據 GOTO WRITE_18B20_1 RETURN ;**********************讀DS18B20子程序**************************** READ_18B20 ;根據DATASHEET介紹,讀數據時應遵照如下規定: ;讀數據0時,主控制器把總線拉低后,18B20再把總線拉低60us ;讀數據1時,主控制器把總線拉低后,保持總線狀態不變 ;主控制器在數據線拉低后15us內讀區數據線上的狀態。 MOVLW 8H ;一次讀8位數據 MOVWF COUNT READ_18B20_1 BANKSEL TRISA BCF TRISA,2 ;數據線先設為輸出 BCF STATUS,RP0 BCF DQ ;先拉低數據線 MOVLW 1H MOVWF COUNT1 DECFSZ COUNT1,1 ;拉低總線3us GOTO $-1 BSF DQ ;釋放總線 BANKSEL TRISA BSF TRISA,2 ;數據線設為輸入 BCF STATUS,RP0 MOVLW 2H MOVWF COUNT1 DECFSZ COUNT1,1 ;延時6ms GOTO $-1 BSF STATUS,C BTFSS DQ ;判斷數據線狀態 BCF STATUS,C RRF TEMP,1 ;移位到TEMP中 MOVLW 12H MOVWF COUNT1 DECFSZ COUNT1,1 GOTO $-1 ;讀一位數據至少需要60us DECFSZ COUNT,1 ;是否讀完8位 GOTO READ_18B20_1 RETURN ;*******************溫度表示形式轉換程序************************** ;因為從18B20中讀出的溫度值是二進制形式,必須把它轉換成對象ASCII才能在LCD上顯示 ;18B20中溫度的表示為:S S S S S 2的6次方 2的5次方 2的4次方 2的3次方 2的2次方 。。。。2的負4次方 ;結果整數放在38H開始的存儲器里,小數部分放在3B開始的單元里 ;38H(百位) 39H(十位) 3AH(個位) 3BH(小數點)3CH(十分位) 3DH(百分位) 3EH(千分位) 3FH(萬分位) TEMP_CHANGE ;整數部分 ;因為轉換后溫度值位于兩個單元內,所以必須先把它們組合到一個單元內。 ;因為最大值為127.9375,所以只需判斷結果是否大于100來決定百位上的結果 ;用循環減0AH的方法得到十位的值,最后剩下的被減數即為個位的結果 MOVLW 7H ANDWF TEMP2,1 ;只保留低3位 SWAPF TEMP2,0 MOVWF 3AH ;轉存3AH MOVFW TEMP1 MOVWF TEMP2 ;轉存TEMP2 MOVLW 0F0H ANDWF TEMP2,1 ;清除低4位 SWAPF TEMP2,0 ;高低半字節交換 IORWF 3AH,1 ;組合得到結果的7位整數部分 MOVLW 64H ;計算整數部分百位的結果 SUBWF 3AH,W ; -100 BTFSS STATUS,C GOTO NEXT0 ;溫度小于100 MOVWF 3AH ;減后的結果覆蓋原來的數據 MOVLW 1H MOVWF 38H ;整數部分最高位為1(不可能大于1) GOTO $+2 NEXT0 CLRF 38H ;溫度小于100,最高位為0 CLRF 39H ;計算整數部分十位的結果 MOVLW 0AH ; -10 SUBWF 3AH,1 BTFSS STATUS,C GOTO NEXT1 INCF 39H,1 ;夠減 十位上加1 GOTO $-5 NEXT1 MOVLW 0AH ADDWF 3AH,1 ;多減一次再加回來,剩下的值即為個位上的值 MOVLW '.' MOVWF 3BH ;小數點 ;小數部分 ;取四位精度 ;計算方法為從最低位開始依次判斷是否為1 ,若為1則分別加上: ;0.0625、0.125、0.25、0.5,而且只有百分位相加時有可能結果大于0AH CLRF 3CH CLRF 3DH CLRF 3EH CLRF 3FH BTFSS TEMP1,0 GOTO NEXT2 MOVLW 5H MOVWF 3FH MOVLW 2H MOVWF 3EH MOVLW 6H MOVWF 3DH ;萬分位 NEXT2 BTFSS TEMP1,1 GOTO NEXT3 MOVLW 5H ADDWF 3EH,1 MOVLW 2H ADDWF 3DH,1 MOVLW 1H MOVWF 3CH ;千分位 NEXT3 BTFSS TEMP1,2 GOTO NEXT5 MOVLW 5H ADDWF 3DH,1 MOVLW 0AH SUBWF 3DH,1 BTFSS STATUS,C GOTO NEXT4 INCF 3CH,1 GOTO $+3 NEXT4 MOVLW 0AH ADDWF 3DH,1 MOVLW 2H ADDWF 3CH,1 ;百分位 NEXT5 BTFSS TEMP1,3 GOTO NEXT6 MOVLW 5H ADDWF 3CH,1 ;十分位 NEXT6 MOVLW 30H ;各位加上30H,轉換成對應的ASCII碼,以便能在LCD上顯示 ADDWF 38H,1 ADDWF 39H,1 ADDWF 3AH,1 ADDWF 3CH,1 ADDWF 3DH,1 ADDWF 3EH,1 ADDWF 3FH,1 RETURN ;**************************延時750ms****************************** DELAY_750MS MOVLW DQ_DELAY_VALUE2 MOVWF DQ_DELAY2 DELAY_750MS_2 MOVLW DQ_DELAY_VALUE1 MOVWF DQ_DELAY1 DELAY_750MS_1 MOVLW TMR0_VALUE MOVWF TMR0 ;開啟定時器 BTFSS INTCON,T0IF GOTO $-1 BCF INTCON,T0IF DECFSZ DQ_DELAY1,1 GOTO DELAY_750MS_1 DECFSZ DQ_DELAY2,1 GOTO DELAY_750MS_2 RETURN ;**************************程序結束****************************** END |