實戰(zhàn)十七《LCD數(shù)字溫度計》
;18B10溫度測量+LCD1602顯示溫度
;實戰(zhàn)目的
;1、學習18B20單總線溫度傳感器的使用。
;2、學習LCD的使用。
;3、學習10進制轉10進制的方法。
;所有資源:
;1、TMRO定時器。產(chǎn)生溫度轉換所需要的延時時間。
;2、PORTA口。即做LCD顯示時可控制端口,RA2同時做18B20的數(shù)據(jù)接口
;3、PORTC口。做LCD顯示時的數(shù)據(jù)口。
;功能說明
;1、通過18B20采集當前環(huán)境
;最高溫度可顯示127.9375,最低溫度可顯示0.0625(無負溫度處理部分)
;2、將溫度在LCD上顯示(3位整數(shù),4位小數(shù))
;硬件連接
;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
#DEFINE RS PORTA,1 ;LCD控制信號
#DEFINE RW PORTA,2 ;LCD控制信號
#DEFINE E PORTA,3 ;LCD控制信號
#DEFINE DAT PORTC ;LCD數(shù)據(jù)線
#DEFINE DQ PORTA,2 ;18B20數(shù)據(jù)口
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的狀態(tài)
BCF RS
BSF RW
BSF E
ENDM
WRITE_COMMAND MACRO ;寫命令
BCF RS
BCF RW
BCF E
ENDM
WRITE_DATA MACRO ;寫數(shù)據(jù)
BSF RS
BCF RW
BCF E
ENDM
;**********************以下是程序的開始************************
ORG 00H
NOP
GOTO MAIN ;入口地址
ORG 04H
RETFIE ;在中斷入口出放置一條中斷返回指令,防止干擾產(chǎn)生中斷
;***************************主程序*******************************
MAIN
CLRF PORTC
CLRF PORTA
BANKSEL TRISA
CLRF TRISA ;A口所有先設置為輸出
CLRF TRISC
MOVLW 01H
MOVWF OPTION_REG ;分頻比1:4,定時器,內(nèi)部時鐘源
MOVLW 06H
MOVWF ADCON1 ;關閉所有A/D口
BCF STATUS,RP0
MOVLW 00H
MOVWF INTCON ;關閉所有中斷,且同時清零T0IF
CLRF TEMP
CLRF TEMP1
CLRF TEMP2 ;清零臨時寄存器
;****************************循環(huán)處理部分************************
;先啟動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 ;調用讀溫度低字節(jié)
MOVFW TEMP
MOVWF TEMP1 ;保存到TEMP1
CALL READ_18B20 ;調用讀溫度高字節(jié)
MOVFW TEMP
MOVWF TEMP2 ;保存到TMEP2
CALL RESET_18B20
CALL TEMP_CHANGE ;調用溫度轉換程序
CALL DISPLAY ;調用LCD顯示程序
GOTO LOOP ;循環(huán)工作
;***************************LCD顯示子程序************************
DISPLAY
;LCD模塊初始化,由廠家提供的資料顯示,其初始化過程為:
;6----寫指令38H,此條指令是將LCD顯示模塊設置為8位數(shù)據(jù)線,雙行,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位數(shù)碼接口
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個數(shù)據(jù)需要顯示
MOVWF COUNT
MOVLW 37H ;取數(shù)地址
MOVWF FSR
DISPLAY1
INCF FSR,1 ;取數(shù)地址加1
MOVFW INDF
CALL DATA_WRITE ;調用寫數(shù)據(jù)子程序
DECFSZ COUNT,1
GOTO DISPLAY1
RETURN
;*****************************寫命令子程序***********************
COMMAND_WRITE
WRITE_COMMAND ;設置寫命令所需要的控制信號
MOVWF DAT ;把命令字送數(shù)據(jù)口
BSF E
NOP
BCF E
CALL BUSY ;判忙
RETURN
;**************************判總線忙子程序************************
BUSY
BSF STATUS,RP0
MOVLW 80H
MOVWF TRISC ;數(shù)據(jù)口最高位置為輸入口
BCF STATUS,RP0
READ_STATE
NOP
BCF E
BTFSC DAT,7 ;是否忙
GOTO BUSY ;是,繼續(xù)判斷
BANKSEL TRISC
CLRF TRISC ;否,數(shù)據(jù)最高位恢復為輸出狀態(tài)
BCF STATUS,RP0
RETURN
;*************************寫數(shù)據(jù)子程序***************************
DATA_WRITE
WRITE_DATA
MOVWF DAT
BSF E
NOP
BCF E
CALL BUSY
RETURN
;*********************復位DS18B20子程序**************************
RESET_18B20
;根據(jù)DATASHEET介紹,寫數(shù)據(jù)時應遵照如下規(guī)定:
;主控制器把總線拉低至少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 ;數(shù)據(jù)線是否為低
GOTO RESET_18B20 ;否則繼續(xù)復位
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
;根據(jù)DATASHEET介紹,寫數(shù)據(jù)時應遵照如下規(guī)定:
;寫數(shù)據(jù)0時,主控制器把總線拉低至少60us
;寫數(shù)據(jù)1時,主控制器把總線拉低,但必須在15us內(nèi)釋放
MOVLW 8H
MOVWF COUNT ;8位數(shù)據(jù)
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 ;判斷寫的數(shù)據(jù)為0還是1
GOTO WRITE_0
BSF DQ ;為1,立即拉高數(shù)據(jù)線
GOTO WRITE_END
WRITE_0
BCF DQ ;繼續(xù)保持數(shù)據(jù)線為低
WRITE_END
MOVLW 0FH
MOVWF COUNT1 ;保持45ms
DECFSZ COUNT1,1
GOTO $-1
BSF DQ ;釋放總線
DECFSZ COUNT,1 ;是否寫完8位數(shù)據(jù)
GOTO WRITE_18B20_1
RETURN
;**********************讀DS18B20子程序****************************
READ_18B20
;根據(jù)DATASHEET介紹,讀數(shù)據(jù)時應遵照如下規(guī)定:
;讀數(shù)據(jù)0時,主控制器把總線拉低后,18B20再把總線拉低60us
;讀數(shù)據(jù)1時,主控制器把總線拉低后,保持總線狀態(tài)不變
;主控制器在數(shù)據(jù)線拉低后15us內(nèi)讀區(qū)數(shù)據(jù)線上的狀態(tài)。
MOVLW 8H ;一次讀8位數(shù)據(jù)
MOVWF COUNT
READ_18B20_1
BANKSEL TRISA
BCF TRISA,2 ;數(shù)據(jù)線先設為輸出
BCF STATUS,RP0
BCF DQ ;先拉低數(shù)據(jù)線
MOVLW 1H
MOVWF COUNT1
DECFSZ COUNT1,1 ;拉低總線3us
GOTO $-1
BSF DQ ;釋放總線
BANKSEL TRISA
BSF TRISA,2 ;數(shù)據(jù)線設為輸入
BCF STATUS,RP0
MOVLW 2H
MOVWF COUNT1
DECFSZ COUNT1,1 ;延時6ms
GOTO $-1
BSF STATUS,C
BTFSS DQ ;判斷數(shù)據(jù)線狀態(tài)
BCF STATUS,C
RRF TEMP,1 ;移位到TEMP中
MOVLW 12H
MOVWF COUNT1
DECFSZ COUNT1,1
GOTO $-1 ;讀一位數(shù)據(jù)至少需要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次方
;結果整數(shù)放在38H開始的存儲器里,小數(shù)部分放在3B開始的單元里
;38H(百位) 39H(十位) 3AH(個位) 3BH(小數(shù)點)3CH(十分位) 3DH(百分位) 3EH(千分位) 3FH(萬分位)
TEMP_CHANGE
;整數(shù)部分
;因為轉換后溫度值位于兩個單元內(nèi),所以必須先把它們組合到一個單元內(nèi)。
;因為最大值為127.9375,所以只需判斷結果是否大于100來決定百位上的結果
;用循環(huán)減0AH的方法得到十位的值,最后剩下的被減數(shù)即為個位的結果
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 ;高低半字節(jié)交換
IORWF 3AH,1 ;組合得到結果的7位整數(shù)部分
MOVLW 64H ;計算整數(shù)部分百位的結果
SUBWF 3AH,W ; -100
BTFSS STATUS,C
GOTO NEXT0 ;溫度小于100
MOVWF 3AH ;減后的結果覆蓋原來的數(shù)據(jù)
MOVLW 1H
MOVWF 38H ;整數(shù)部分最高位為1(不可能大于1)
GOTO