PDA

View Full Version : 16F887 giao tiếp với 18B20 (one_wire)


duc thang
11-04-2013, 12:30 PM
Chạy mô phỏng với Protues, kết quả nhận được toàn là FFH (Low) FFH (high).
Không biết sai chổ nào, các giúp đở .
Pic 16F887, thạch anh 4MHz. như vậy mỗi chu kỳ lệnh = 1us.
Khả năng sai là ở WRITE_TIME_SLOT và READ_TIME_SLOT; thay đổi tới lui cũng không được. Nhờ giúp đở.
;==============================
Code Main:
MAIN
call RESET_18B20
movlw 0CCH
movwf TEMP
call WRITE_18B20 ;SKIP ROM command
movlw 44H
movwf TEMP
call WRITE_18B20 ;temperature convert command
;====
call delay_750ms
;====
call RESET_18B20
movlw 0CCH
movwf TEMP
call WRITE_18B20 ;SKIP ROM command
movlw 0BEH
movwf TEMP
call WRITE_18B20 ;READ temperature command
call READ_18B20 ;READ temperature low byte
movfw TEMP
movwf PORTC
movwf TEMP1 ;keep in TEMP1
call READ_18B20 ;READ temperature high byte
movfw TEMP
movwf PORTD
movwf TEMP2 ;keep in TEMP2
goto MAIN

;==========
RESET_18B20
banksel TRISB
bcf Tris_DQ
banksel PORTB
bcf DQ
movlw 0A4H ;500us
movwf COUNT
decfsz COUNT,1
goto $-1
banksel TRISB
bsf Tris_DQ
banksel PORTB
movlw 0F4H
movwf COUNT
loop_reset_18B20
btfss DQ
goto OK_RESET_18B20
decfsz COUNT,1
goto loop_reset_18B20 ;otherwise continue reset
bsf DQ
nop
nop
goto RESET_18B20
OK_RESET_18B20
btfss DQ
goto $-1
banksel TRISA
bcf Tris_DQ
banksel PORTB
bsf DQ
return
;===========
WRITE_18B20
movlw 08H
movwf COUNT1
WRITE_18B20_1
rrf TEMP,1
call WRITE_TIME_SLOT
decfsz COUNT1,1 ;if finish 8 bit data
goto WRITE_18B20_1
movlw 23H ;106us
movwf COUNT
decfsz COUNT,1
goto $-1
return
;=============
WRITE_TIME_SLOT ;viet 1 bit
bcf DQ
nop
nop
bsf DQ ;3us
movlw 04H ;17us
movwf COUNT
decfsz COUNT,1
goto $-1
btfss STATUS,C ;judge the write data is 0 or 1
goto WRITE_END
bsf DQ
WRITE_END
movlw 13H ;58us
movwf COUNT
decfsz COUNT,1
goto $-1
bsf DQ
nop
return
;================
READ_18B20
movlw 08H
movwf COUNT1
READ_18B20_1
call READ_TIME_SLOT
decfsz COUNT1,1 ;if finish reading 8 bit
goto READ_18B20_1
movlw 1FH
movwf COUNT
decfsz COUNT,1
goto $-1
return
;==================
READ_TIME_SLOT
bcf DQ
nop
nop
bsf DQ ;3us
banksel TRISA
bsf Tris_DQ
banksel PORTA
movlw 04H ;16us
movwf COUNT ;
decfsz COUNT,1
goto $-1
bsf STATUS,C
btfss DQ
bcf STATUS,C
rrf TEMP,1
movlw 11H
movwf COUNT ;
decfsz COUNT,1
goto $-1 ;pull low 56us
banksel TRISA
bcf DQ
banksel PORTA
bsf DQ
nop
nop
return
;==================
delay_750ms
movlw 04H
movwf DQ_DELAY3
DELAY_750MS_3
movlw 0FFH
movwf DQ_DELAY2
DELAY_750MS_2
movlw 0FFH
movwf DQ_DELAY1
DELAY_750MS_1
decfsz DQ_DELAY1,1
goto DELAY_750MS_1
decfsz DQ_DELAY2,1
goto DELAY_750MS_2
decfsz DQ_DELAY3,1
goto DELAY_750MS_3
return
;=============

tdm
12-04-2013, 10:48 AM
Chạy mô phỏng với Protues, kết quả nhận được toàn là FFH (Low) FFH (high).
Không biết sai chổ nào, các giúp đở .
Pic 16F887, thạch anh 4MHz. như vậy mỗi chu kỳ lệnh = 1us.
Khả năng sai là ở WRITE_TIME_SLOT và READ_TIME_SLOT; thay đổi tới lui cũng không được. Nhờ giúp đở.
;==============================
Code Main:
MAIN
call RESET_18B20
movlw 0CCH
movwf TEMP
call WRITE_18B20 ;SKIP ROM command
movlw 44H
movwf TEMP
call WRITE_18B20 ;temperature convert command
;====
call delay_750ms
;====
call RESET_18B20
movlw 0CCH
movwf TEMP
call WRITE_18B20 ;SKIP ROM command
movlw 0BEH
movwf TEMP
call WRITE_18B20 ;READ temperature command
call READ_18B20 ;READ temperature low byte
movfw TEMP
movwf PORTC
movwf TEMP1 ;keep in TEMP1
call READ_18B20 ;READ temperature high byte
movfw TEMP
movwf PORTD
movwf TEMP2 ;keep in TEMP2
goto MAIN

;==========
RESET_18B20
banksel TRISB
bcf Tris_DQ
banksel PORTB
bcf DQ
movlw 0A4H ;500us
movwf COUNT
decfsz COUNT,1
goto $-1
banksel TRISB
bsf Tris_DQ
banksel PORTB
movlw 0F4H
movwf COUNT
loop_reset_18B20
btfss DQ
goto OK_RESET_18B20
decfsz COUNT,1
goto loop_reset_18B20 ;otherwise continue reset
bsf DQ
nop
nop
goto RESET_18B20
OK_RESET_18B20
btfss DQ
goto $-1
banksel TRISA
bcf Tris_DQ
banksel PORTB
bsf DQ
return
;===========
WRITE_18B20
movlw 08H
movwf COUNT1
WRITE_18B20_1
rrf TEMP,1
call WRITE_TIME_SLOT
decfsz COUNT1,1 ;if finish 8 bit data
goto WRITE_18B20_1
movlw 23H ;106us
movwf COUNT
decfsz COUNT,1
goto $-1
return
;=============
WRITE_TIME_SLOT ;viet 1 bit
bcf DQ
nop
nop
bsf DQ ;3us
movlw 04H ;17us
movwf COUNT
decfsz COUNT,1
goto $-1
btfss STATUS,C ;judge the write data is 0 or 1
goto WRITE_END
bsf DQ
WRITE_END
movlw 13H ;58us
movwf COUNT
decfsz COUNT,1
goto $-1
bsf DQ
nop
return
;================
READ_18B20
movlw 08H
movwf COUNT1
READ_18B20_1
call READ_TIME_SLOT
decfsz COUNT1,1 ;if finish reading 8 bit
goto READ_18B20_1
movlw 1FH
movwf COUNT
decfsz COUNT,1
goto $-1
return
;==================
READ_TIME_SLOT
bcf DQ
nop
nop
bsf DQ ;3us
banksel TRISA
bsf Tris_DQ
banksel PORTA
movlw 04H ;16us
movwf COUNT ;
decfsz COUNT,1
goto $-1
bsf STATUS,C
btfss DQ
bcf STATUS,C
rrf TEMP,1
movlw 11H
movwf COUNT ;
decfsz COUNT,1
goto $-1 ;pull low 56us
banksel TRISA
bcf DQ
banksel PORTA
bsf DQ
nop
nop
return
;==================
delay_750ms
movlw 04H
movwf DQ_DELAY3
DELAY_750MS_3
movlw 0FFH
movwf DQ_DELAY2
DELAY_750MS_2
movlw 0FFH
movwf DQ_DELAY1
DELAY_750MS_1
decfsz DQ_DELAY1,1
goto DELAY_750MS_1
decfsz DQ_DELAY2,1
goto DELAY_750MS_2
decfsz DQ_DELAY3,1
goto DELAY_750MS_3
return
;=============
em tham khảo code sau.

duc thang
12-04-2013, 06:58 PM
Cám ơn bạn gửi đường link, nhưng không down được.
Bạm xem lại giùm.

tdm
13-04-2013, 11:51 AM
Cám ơn bạn gửi đường link, nhưng không down được.
Bạm xem lại giùm.
vẫn down bình thường.


;************************************************* **********************
LIST P = 16F877A; definitions used in this program for the PIC16F877A chip
#include "P16F877A.INC"; the definition of this program contains the file

__CONFIG 3F72H; crystal configuration HS, watchdog banned, power-on delay enabled, the brown-out reset enable
; Low-voltage programming prohibited, the code does not protect
#define DQ PORTC, 7
#define DIR TRISC,7
E EQU H'0005'
RW EQU H'0004'
SR EQU H'0006'
XUAT_LCD EQU PORTB
XUAT_DIEU_KHIEN EQU PORTD
CBLOCK 20H
Y1
Y2
COUNT1
COUNT2
COMD
DATE
BIN_L; to convert the byte
GE; converted bits
SHI; converted 10
DATE_L
DATE_H
NUM1
NUM2
NUM3
DATA1
TAM_H
TAM_L
TAM10
TAM_11
CHUA_DAU
LUU_GIA_TRI_CU_H
LUU_GIA_TRI_CU_L
CHO_HIEN_THI
TAM_BANG
HET_BANG
LUU
TAM
ENDC

;************************************************* **********************
; Reset vector definition (for the 16F877A)
;************************************************* **********************
ORG 0000H; reset vector address
GOTO MAIN; program jump to the main program MAIN
;------------------------------------------------- ---------------------
TRA_BANG
ADDWF PCL ,1
DT" NHIET DO PHONG ",0x00
;************************************************* **********************
; The main program areas
;************************************************* **********************
MAIN
NOP
;CALL INTIAL
BSF STATUS, RP0; the definition of the current body is the body 1, in the right direction to modify register
MOVLW 06H
MOVWF ADCON1; off A mouth of the analog channel
MOVLW 00H
MOVWF TRISB; Segment display port as an output port
MOVWF TRISD; Segment display port as an output port
MOVWF TRISE; Segment display port as an output port
BSF DIR; make the data line is input
BCF STATUS, RP0; so that the current body is the body 0
;MOVLW 00H; close Segment
;MOVWF PORTC
MOVLW 00H; closed-bit code
MOVWF PORTD
BCF XUAT_DIEU_KHIEN,E
BCF XUAT_DIEU_KHIEN,RW
BCF XUAT_DIEU_KHIEN,SR
CLRF LUU_GIA_TRI_CU_H
CLRF LUU_GIA_TRI_CU_L
CALL CAI_DAT_LCD
START BTFSS DQ; data line idle state is high
GOTO $ -1
CALL RESET; reset DS18B20
MOVLW 0CCH; skip read ROM command
CALL WR18B20
MOVLW 44H; Temperature Conversion
CALL WR18B20
CALL DELAY_750US; delay 750us
CALL RESET; reset DS18B20
MOVLW 0CCH; skip read ROM command
CALL WR18B20
MOVLW 0BEH; reading the 9 bytes of internal RAM contents
CALL WR18B20
NOP
CALL RE18B20; reading data
CALL NHIET_DO_CO_THAY_DOI_KHONG
MOVLW 0xFF
SUBWF CHO_HIEN_THI,0
BTFSC STATUS,Z
GOTO KHONG_THAY_DOI_HIEN_THI
CALL gia_tri_am_hay_duong
CALL BIN_BCD
CALL HIEN_THI_LCD
KHONG_THAY_DOI_HIEN_THI
CALL DELAY
CALL DELAY
CALL DELAY
CALL DELAY
;------------------------ Display processing ----------------------- ---------------
GOTO START
;************************************************* **********************
; Initialization and consumer video
;************************************************* **********************
INTIAL
BSF STATUS, RP0; the definition of the current body is the body 1, in the right direction to modify register
MOVLW 06H
MOVWF ADCON1; off A mouth of the analog channel
MOVLW 00H
MOVWF TRISB; Segment display port as an output port
MOVWF TRISD; Segment display port as an output port
MOVWF TRISE; Segment display port as an output port
BSF DIR; make the data line is input
BCF STATUS, RP0; so that the current body is the body 0
;MOVLW 00H; close Segment
;MOVWF PORTC
MOVLW 00H; closed-bit code
MOVWF PORTD
BTFSS DQ; data line idle state is high
GOTO $ -1
CALL RESET; reset DS18B20
MOVLW 0CCH; skip read ROM command
CALL WR18B20
MOVLW 44H; Temperature Conversion
CALL WR18B20
CALL DELAY_750US; delay 750us
CALL RESET; reset DS18B20
MOVLW 0CCH; skip read ROM command
CALL WR18B20
MOVLW 0BEH; reading the 9 bytes of internal RAM contents
CALL WR18B20
NOP
NOP
CALL RE18B20; reading data
CALL DELAY_MAX; delay 600ms
CALL DELAY_MAX
CALL DELAY_MAX
RETLW 00H
;================================================= ======================

;************************************************* **********************
; Delay 200ms
;************************************************* **********************
DELAY_MAX
MOVLW 0FFH
MOVWF Y1
MOVLW 0FFH
MOVWF Y2
DECFSZ Y2
GOTO $ -1
DECFSZ Y1
GOTO $ -5
RETLW 00H
;************************************************* **********************
; Delay 6ms
;************************************************* **********************
DELAY
MOVLW 03FH
MOVWF Y1
MOVLW 020H
MOVWF Y2
DECFSZ Y2
GOTO $ -1
DECFSZ Y1
GOTO $ -5
RETLW 00H
;************************************************* **********************
; Delay 750us subroutine
;************************************************* **********************
DELAY_750US
MOVLW 09H
MOVWF Y1
MOVLW 01AH
MOVWF Y2
DECFSZ Y2
GOTO $ -1
DECFSZ Y1
GOTO $ -5
RETLW 00H
;************************************************* **********************
; DS18B20 reset and respond to routine
;************************************************* **********************
RESET
BSF STATUS, RP0; so that the current body is the body a
BCF DIR; so that the output data bit
BCF STATUS, RP0; so that the current body is the body 0
BSF DQ; pulled data bits
NOP; air circulation
BCF DQ; pull down data bits
MOVLW .200 ; delay 600us
MOVWF Y1
DECFSZ Y1
GOTO $ -1
BSF STATUS, RP0; so that the current body is the body a
BSF DIR; make the data bits as input
BCF STATUS, RP0; so that the current body is the body 0
MOVLW .30; Delay 90us
MOVWF Y1
DECFSZ Y1
GOTO $ -1
BTFSC DQ; the host receives a low pulse, jump to the next one
GOTO RESET
MOVLW .80; delay 240us
MOVWF Y1
DECFSZ Y1
GOTO $ -1
BTFSS DQ; the host receives a high pulse, jump to the next one
GOTO RESET
RETLW 00H; return to 00H, the end of reset response
;************************************************* **********************
; Write DS18B20 subroutine
;************************************************* **********************
WR18B20
MOVWF COMD; to write the data in write COMD
MOVLW .8
MOVWF COUNT2; large circle 8 times
WR0 BSF STATUS, RP0; so that the current body is the body a
BCF DIR; so that the output data bit
BCF STATUS, RP0; so that the current body is the body 0
BCF DQ; pull down the data line
NOP
NOP
MOVLW .2
MOVWF COUNT1; delay 9us
WR1 DECFSZ COUNT1, 1
GOTO WR1
BTFSC COMD, 0; COMD the lowest level of 0 Jump to the next one
BSF DQ; pulled the data cable
BTFSC COMD, 0; COMD the lowest level of 0 Jump to the next one
NOP
BCF STATUS, C; into the bit position 0
RRF COMD, 1; into the bit-bit, COMD to the right one
MOVLW .20; Delay 60us
MOVWF COUNT1
WR2 DECFSZ COUNT1, 1
GOTO WR2
BSF DQ; pulled the data cable, idle state
BSF STATUS, RP0; so that the current body is the body a
BSF DIR; make the data bits as input
BCF STATUS, RP0; so that the current body is the body 0
DECFSZ COUNT2, 1; 8 cycles then jump out to a
GOTO WR0
RETLW 00H
;************************************************* **********************
; Read 18B20 subroutine
;************************************************* **********************
RE18B20
CLRF DATE_H
CLRF DATE_L
MOVLW .16
MOVWF COUNT2
RE0 BSF STATUS, RP0; so that the current body is the body a
BCF DIR; so that the output data bit
BCF STATUS, RP0; so that the current body is the body 0
BCF DQ
MOVLW .2
MOVWF COUNT1
RE1 DECFSZ COUNT1, 1
GOTO RE1
BSF STATUS, RP0; so that the current body is the body a
BSF DIR; make the data bits as input
BCF STATUS, RP0; so that the current body is the body 0
NOP
BTFSS DQ; if the data line is high, then C = 1
BCF STATUS, C
BTFSC DQ; if the data line is low, then C = 0
BSF STATUS, C
RRF DATE_H, 1; These data on the existence DATE
RRF DATE_L, 1
MOVLW .20 ; Delay 60us
MOVWF COUNT1
RE2 DECFSZ COUNT1, 1
GOTO RE2
DECFSZ COUNT2, 1
GOTO RE0
BSF DQ
RETLW 00H
;))))))))))))))))))))))))))))))))))))))))))))))))) ))))))))))))
NHIET_DO_CO_THAY_DOI_KHONG
MOVF DATE_L,0
SUBWF LUU_GIA_TRI_CU_L,0
BTFSS STATUS,Z
GOTO CO_THAY_DOI
GOTO KHONG_THAY_DOI
CO_THAY_DOI
MOVF DATE_L,0
MOVWF LUU_GIA_TRI_CU_L
CLRF CHO_HIEN_THI
GOTO THOAT
KHONG_THAY_DOI
MOVLW 0xFF
MOVWF CHO_HIEN_THI
THOAT
RETURN
;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""'
gia_tri_am_hay_duong
MOVF DATE_H,0
MOVWF TAM_H
SWAPF TAM_H,1
MOVLW B'01110000'
ANDWF TAM_H,1
MOVF DATE_L,0
MOVWF TAM_L
SWAPF TAM_L,1
MOVLW B'00001111'
ANDWF TAM_L,0
IORWF TAM_H,1
XAC_DINH_GIA_TRI_AM_HAY_DUONG
BTFSS DATE_H,7
GOTO GIA_TRI_DUONG
BTFSS DATE_H,6
GOTO GIA_TRI_DUONG
BTFSS DATE_H,5
GOTO GIA_TRI_DUONG
BTFSS DATE_H,4
GOTO GIA_TRI_DUONG
BTFSS DATE_H,3
GOTO GIA_TRI_DUONG
GIA_TRI_AM
COMF TAM_H,1
BCF TAM_H,7
INCF TAM_H,1
MOVLW '-'
MOVWF CHUA_DAU
MOVF TAM_H,0
MOVWF DATA1
GOTO HET
GIA_TRI_DUONG
MOVF TAM_H,0
MOVWF DATA1
MOVLW ' '
MOVWF CHUA_DAU
HET
RETURN


;================================================= =============
BIN_BCD
clrf NUM2 ; Clear register of 10's unit
Check movlw 0x0A ; Subtract with 10 until the result lower 10
subwf DATA1,w ; Fisrt subtraction < 10 ?
btfss STATUS,C
goto Less1 ; If < 10 then return
incf NUM2,f ; If > 10 then increase 10's unit
movlw 0x0A ; Subtract with 10
subwf DATA1,f ; Test Again. Is it lower 10 ?
goto Check

Less1 movf DATA1,w ; If < 10, send data to 1's unit
movwf NUM1 ;
clrf NUM3 ; Clear 100's unit
Check2 movlw 0x0A
subwf NUM2,w ; 10's unit > 10 ?
btfss STATUS,C
return ; If < 10 then return
incf NUM3,f
movlw 0x0A ; If > 10 then subtraction again
subwf NUM2,f ; and check until the result is lower 10
goto Check2
RETURN
XUAT_DU_LIEU
MOVWF XUAT_LCD
CALL LENH
RETLW .0
;*****LENH*******
LENH
BSF PORTD,E
CALL DL
BCF PORTD,E
RETURN
;**CAI_DAT_LCD***
CAI_DAT_LCD
MOVLW 0x01;XOA MAN HINH
MOVWF XUAT_LCD
CALL LENH
;***************
MOVLW 0x38;8BIT,2 DONG,5*7 DOT
MOVWF XUAT_LCD
CALL LENH
;***************
MOVLW 0x0C
MOVWF XUAT_LCD
CALL LENH
;****************
MOVLW 0x06;TANG CON TRO
MOVWF XUAT_LCD
CALL LENH
;CHO HIEN THI DONG_1
BSF XUAT_DIEU_KHIEN,SR
MOVLW .0
MOVWF LUU
BSF XUAT_DIEU_KHIEN,SR;SR=1 HIEU LA DU LIEU
TIEP
MOVF LUU,0
CALL TRA_BANG
MOVWF TAM;DU LIEU SAU KHI TRA BANG LUU TAI DAY
CLRW ;XOA W
SUBWF TAM ,0
BTFSS STATUS,Z;NEU DU LIEU SAU KHI TRA BANG =0 THI KET THUC BANG TRA
GOTO TRA_TIEP
RETURN
TRA_TIEP
MOVF TAM,0;DUA DU LIEU RA LCD
CALL XUAT_DU_LIEU
INCF LUU,1
GOTO TIEP
RETURN
;*****DL*******
DL MOVLW .4
MOVWF TAM_11
LOPP
MOVLW .250
MOVWF TAM10
LOP DECFSZ TAM10,1
GOTO LOP
DECFSZ TAM_11,1
GOTO LOPP
RETURN
HIEN_THI_LCD
BCF XUAT_DIEU_KHIEN,SR
MOVLW B'11000100';DONG 2
MOVWF XUAT_LCD
CALL LENH
BSF XUAT_DIEU_KHIEN,SR
MOVF CHUA_DAU,0
CALL XUAT_DU_LIEU
MOVLW .0
SUBWF NUM3,0
BTFSC STATUS,Z
GOTO HANG_CHUC
MOVF NUM3,0
ADDLW 0x30
CALL XUAT_DU_LIEU
GOTO HIEN_THI_HANG_CHUC
HANG_CHUC
MOVLW .0
SUBWF NUM2,0
BTFSC STATUS,Z
GOTO HANG_DVI
HIEN_THI_HANG_CHUC
MOVF NUM2,0
ADDLW 0x30
CALL XUAT_DU_LIEU
HANG_DVI
MOVF NUM1,0
ADDLW 0x30
CALL XUAT_DU_LIEU
MOVLW '.'
CALL XUAT_DU_LIEU
MOVLW 'O'
CALL XUAT_DU_LIEU
MOVLW 'C'
CALL XUAT_DU_LIEU
RETURN
END; end of the process