DS18S20 on PIC16F628 - helpppp!

LK/ELK/VK/PK/OK/MX/GLK/EGLK/GVK/GLT Series

Moderators: Henry, Mods

Post Reply
ChriX
ICEHW.net
ICEHW.net
Posts: 18
Joined: Tue Dec 18, 2001 4:00 pm
Location: North Cornwall, UK
Contact:

DS18S20 on PIC16F628 - helpppp!

Post by ChriX »

I've been trying (unsuccessfully) for the past couple of days to detect the presence pulse given by the DS18S20 when using the reset routine. I just can't detect when it pulls the data line low, i'm pretty sure it's my timing that's at fault and hence i'm missing it.

Would appreciate it if someone could take a look at this code and help me out. I'm using 20Mhz external oscillator. DQ line from DS18S20 connected to PORTB,5 with a 5k pullup on there.

Code: Select all

 LIST  R=DEC ; Sets number base to decimal
 INCLUDE "p16f628.inc" ; Includes microchip configuration for this processor
 __CONFIG _CP_OFF & _WDT_OFF & _HS_OSC & _PWRTE_ON & _LVP_OFF & _MCLRE_ON
 
 ; CP - Copy protection (off)
 ; WDT - Watchdog timer (off)
 ; HS_OSC - I'm using a high speed oscillator (20Mhz)
 ; PWRTE - Power up timer delay (on), leaves a delay for voltages to stabilise
 ; LVP - Low voltage programming (off)
 ; MCLRE - Holds MCLR pin high if on (on)

  CBLOCK 0x20             ; Declare variable addresses starting at 0x20 
  DELAY,DELAYTMP,CONTRAST,ORIGCONTRAST,RECTEMP,PDBYTE
  ENDC 

;##### Macros #####
BANK0 macro 
  bcf STATUS,RP1
  bcf STATUS,RP0
  endm

BANK1 macro
  bcf STATUS,RP1
  bsf STATUS,RP0
  endm

DELAY_MILLI macro TIME
  movlw TIME
  movwf DELAY
  call DELAY_MS
  endm

DELAY_MICRO macro TIME
  movlw TIME
  movwf DELAY
  call DELAY_US
  endm

SENDDATA macro DATA
  movlw DATA
  call TRANSMIT
  endm

CLEARSCREEN macro
  movlw 0xFE
  call TRANSMIT
  movlw 0x58
  call TRANSMIT
  endm
  
HOMECURSOR macro
  movlw 0xFE
  call TRANSMIT
  movlw 0x48
  call TRANSMIT
  endm
  
HOMECURSOR2 macro
  movlw 0xFE
  call TRANSMIT
  movlw 0x47
  call TRANSMIT
  movlw 0x01
  call TRANSMIT
  movlw 0x02
  call TRANSMIT
  endm
  
SETCONTRAST macro CONTRAST
  movlw 0xFE
  call TRANSMIT
  movlw 0x50
  call TRANSMIT
  movlw CONTRAST
  call TRANSMIT
  endm

OW_HIZ macro
  bsf STATUS,RP0
  bsf TRISB,5
  bcf STATUS,RP0
  endm

OW_LO macro
  bcf STATUS,RP0
  bcf PORTB,5
  bsf STATUS,RP0
  bcf TRISB,5
  bcf STATUS,RP0
  endm


;##### Program Code #####
        ORG    0
  goto MAIN        
        
;##### Subroutines #####
OW_RESET
  OW_HIZ
  clrf PDBYTE
  OW_LO
  DELAY_MICRO 250
  DELAY_MICRO 250
  OW_HIZ
  DELAY_MICRO 70
  btfss PORTB,5
  incf PDBYTE,F
  DELAY_MICRO 400
  retlw 0
  

NO_OW_DETECT
  CLEARSCREEN
  SENDDATA 'N'
  SENDDATA 'o'
  SENDDATA ' '
  SENDDATA '1'
  SENDDATA '-'
  SENDDATA 'W'
  SENDDATA 'i'
  SENDDATA 'r'
  SENDDATA 'e'
  SENDDATA ' '
  SENDDATA 'D'
  SENDDATA 'e'
  SENDDATA 'v'
  SENDDATA 'i'
  SENDDATA 'c'
  SENDDATA 'e'
  SENDDATA 's'
  SENDDATA '!'
  return

SECDELAY
  DELAY_MILLI 250
  DELAY_MILLI 250
  DELAY_MILLI 250
  DELAY_MILLI 250
  return

DELAY_US					; busy wait of DELAY us
  nop						; (1)
  nop						; (2)
  decfsz DELAY,f			; test DELAY count (3)
  goto DELAY_US				; loop if not done (4,5)
  return					; gtfo (4,5)

DELAY_MS					; busy wait of DELAY ms
  movf DELAY,w
  movwf DELAYTMP			; save DELAY time
DELAY_MS_LOOP				; inner loop
  movlw 245					; load 245 (1)
  movwf DELAY				; into DELAY (2)
  call DELAY_US				; wait 245us (3-249)
  movlw 245					; load 245 (250)
  movwf DELAY				; into DELAY (251)
  call DELAY_US				; wait 245us (252-498)
  movlw 245					; load 245 (499)
  movwf DELAY				; into DELAY (500)
  call DELAY_US				; wait 245us (501-747)
  movlw 246					; load 246 (748)
  movwf DELAY				; into DELAY (749)
  call DELAY_US				; wait 246us (750-997)
  decfsz DELAYTMP,f			; test DELAYTMP count (998)
  goto DELAY_MS_LOOP		; loop if not done (999,1000)
  return					; gtfo (999,1000)
  
INIT
  bsf STATUS,RP0          ; RAM PAGE 1 
  movlw b'00000010'       ; RB1(RX)=input, others output 
  movwf TRISB 
  movlw 0x40              ; 0x40 = 19.2kbps
  movwf SPBRG 
  movlw b'00100100'       ; brgh = high (2) 
  movwf TXSTA             ; enable Async Transmission, set brgh 
  bcf STATUS,RP0          ; RAM PAGE 0 
  movlw b'10010000'       ; enable Async Reception 
  movwf RCSTA
  call SECDELAY
  movlw 0x5B
  movwf ORIGCONTRAST
  CLEARSCREEN
  return
  
TRANSMIT
  movwf TXREG             ; send data in W  
  bsf STATUS,RP0          ; RAM PAGE 1 
TRANSMITTEST
  btfss TXSTA,TRMT        ; (1) transmission is complete if hi 
  goto TRANSMITTEST 
  bcf STATUS,RP0          ; RAM PAGE 0 
  return 
  
RECEIVE 
  btfss PIR1,RCIF         ; check for received data 
  goto RECEIVE 
  movf RCREG,W            ; save received data in W
  movwf RECTEMP			  ; save received data in RECTEMP
  return

MAIN
  call INIT
  call SPLASH
  call SECDELAY
  call SECDELAY
  CLEARSCREEN
  call OW_RESET
  decfsz PDBYTE,0
  call NO_OW_DETECT

ENDLOOP
  goto ENDLOOP
  END 
Cheers!

ChriX
ICEHW.net
ICEHW.net
Posts: 18
Joined: Tue Dec 18, 2001 4:00 pm
Location: North Cornwall, UK
Contact:

Post by ChriX »

Doh, I meant PORTB,5 not PORTA,0 :nono:

Paradigm
Matrix Orbital
Matrix Orbital
Posts: 255
Joined: Thu Sep 13, 2001 6:00 pm
Location: Calgary, Alberta, Canada

Post by Paradigm »

Ok, B.5 makes a heck of a lot more sense than A.0 :lol:

Well your code looks sane. The reset does look right. The only thing that jumps to mind is that the 1-wire protocol is VERY picky about timing. When I wrote the MX code, the 1-wire timing was one of the trickiest parts to get working. Only two suggestions come to mind:

1) Turn off intertupts while talking to the bus. Interrupts triggering will really mess up your timing. So during reset and writing or reading, turn them off. For writing or reading you can re-enable them between bits as the time between bits doesn't matter (as long as it is over 1 or 2us)

2) Verify your delay routines. This is a biggie. I'm looking at the MX code and I see a comment "delay for 500us" and the next line is DELAY_US(300). Delay routines are next to impossible to get correct. Usually they will delay for a lot longer than you expect. For example, if you use a loop, the loop overhead will get you. The critical one to check is your delay between releasing the bus (after reset) and sampling the bus to check for the presence pulse. According to the spec you need it between 60 and 75us. That is a very tight timing spec. I would find some way to verify your delays.

I would really try to get access to an oscilloscope. In embedding timing situations like this, it can realy be your best friend.

One kludge I could suggest is to not just sample the bus once looking for the presence pulse. Sample it, then delay by 1us, then sample again.... Just keep ANDing all the results together.

Hope this helps. But without having it in front of me with a scope on it, I really can't say more than your're going in the right direction.
James McTavish, P.Eng
Director of Engineering
Matrix Orbital

Post Reply