Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

1 wire Help on PIC16F628A

Status
Not open for further replies.

mihaiBB

New Member
Hi! Can anybody help me ? I'am having some issues with a DS18B20 1 wire temperature sensor. I tryed to write a firmware for PIC16F628, starting from MAXIM application notes, but the problem is that on my serial port (with Hyperterminal) I receive "#$" characters. When i try to approach the sensor to lower or higher temperatures this values does not change :( . This sensor is conected at RB0. Also i use an external 11.0592 MHZ oscilator.

I'm attaching my asm code and the 1 wire header from MAXIM.
Any help, ideea would be greatfull.

Regards, Mihai.
 

Attachments

  • 1-wire.inc.asm
    2.9 KB · Views: 293
  • ProjectSI.asm
    4.8 KB · Views: 260
Do you need to issue a convert command (0x44) before reading. Edit, Whoops, missed that as your comment says "; Send Read Data Command (0x69)" even though you send 0x44. After a convert command you have to wait (100-750mS) for the convertion to take place.

Mike.
 
Last edited:
Still a problem

Yes, I tried with a delay routine to wait for a conversion (750 ms) and I get the same results : #$. I tried to use the built-in 4 MHz oscillator without any good results. I also replaced the sensor and still getting that #$ value. I don't know where is the problem. All I know is that is coming from my firmware.
 
As Pommie mentioned you need to provide a delay or do a "read slot" loop after sending the "start temperature conversion" command and before reading the temperature data. Here's how I do it (using simple macros);

Code:
;******************************************************************
;
;  get new DS18B20 temperature reading
;
GetTemp
        owReset                 ; reset one-wire devices          |B0
        btfss   owByte,0        ; DS18x20 device found?           |B0
        return                  ; no, return, else                |B0
        owSend (h'CC')          ; DS1820 'skip rom' command       |B0
        owSend (h'44')          ; start temperature conversion    |B0
ReadSlot
        DelayUS(56)             ; wait 56-usecs                   |B0
        owRdBit                 ; conversion complete (C=1)?      |B0
        bnc     ReadSlot        ; no, branch, else                |B0
        DelayUS(56)             ; finish slot period              |B0
        owReset                 ; reset one-wire devices          |B0
        owSend (h'CC')          ; DS1820 'skip rom' command       |B0
        owSend (h'BE')          ; DS1820 'read scratchpad' cmd    |B0
        movlw   9               ;                                 |B0
        goto    owRdBuff        ; read 9 byte scratchpad buffer   |B0
You seem to be sending the raw 16 bit temperature data through the serial port which very well could come out as the characters you're seeing on Hyperterminal. I use a simple formula and a few subroutines to convert the raw data into 6 digit (3 decimal places) BCD data and convert that BCD data to ASCII before sending it out the serial port;

Code:
;******************************************************************
;
;  BC2DC - binary °C*16 to decimal °C*1000 (3 decimal places)
;
;  °C*1000 = 1000 * 16 * (Celsius*16) / 256
;          = 16000 * TempH:TempL / 256
;          =   125 * TempH:TempL / 2
;
;  Bcd2:0 packed bcd output -055000 to +125000 (°C*1000)
;
        radix   dec
BC2DC
        movlw   d'125'          ; multiplier = 125                |B0
        movwf   Mul1L           ;                                 |B0
        clrf    Mul1H           ;                                 |B0
        call    Mult8x16        ; sign extended 8x16 multiply     |B0
        call    DivBy2          ; divide result by 2              |B0
        call    AbsFunc         ; set/clr NegFlag, make positive  |B0
        goto    Bin2bcd         ; bin Prod3:1 -> packed Bcd2:0    |B0
Code:
;******************************************************************
;
;  BC2DF - binary °C*16 to decimal °F*1000 (3 decimal places)
;
;  °F*1000 = ( 9/5*1000*16*(Celsius*16)+32*1000*256)/256
;          = ( 28800 * TempH:TempL + 8192000) / 256
;          =   28800 * TempH:TempL / 256 + 819200 / 256
;          =   28800 * TempH:TempL / 256 + 32000
;          =   ( 225 * TempH:TempL / 2)  + 32000
;
;  Bcd2:0 packed bcd output -067000 to +257000 (°F*1000)
;
;                  TempH:L Neg Output   Display
;     ==========================================
;     125.0000°C   h'07D0'  0  257000  257.000°F
;      25.0000°C   h'0190'  0  077000   77.000°F
;      22.0000°C   h'0160'  0  071600   71.600°F
;       0.5000°C   h'0008'  0  032900   32.900°F
;       0.0625°C   h'0001'  0  032112   32.112°F
;       0.0000°C   h'0000'  0  032000   32.000°F
;     - 0.0625°C   h'FFFF'  0  031887   31.887°F
;     - 0.1250°C   h'FFFE'  0  031775   31.775°F
;     - 5.0000°C   h'FFB0'  0  023000   23.000°F
;     -10.0000°C   h'FF60'  0  014000   14.000°F
;     -17.0625°C   h'FEEF'  0  001287    1.287°F
;     -17.6875°C   h'FEE5'  0  000162    0.162°F
;     -17.7500°C   h'FEE4'  1  000005  - 0.005°F
;     -17.8125°C   h'FEE3'  1  000062  - 0.062°F
;     -25.0000°C   h'FE70'  1  013000  -13.000°F
;     -55.0000°C   h'FC90'  1  067000  -67.000°F
;
 
Last edited:
Help

The problem is not the conversion of the Raw data. The problem is that the raw data is not changing while I approach the DS18B20 to high temperature, or to low temperature, or just a simple touch of it. I've bin trying almost everything: using internal oscillator 4 MHz to avoid the delay problems, I also provided a delay routine without any results. Weird is that I still no longer receive that #$. Now I receive "⌂⌂". I checked the firmware twice and I see no problems. This is my firmware:

list p=16F628A, r=DEC ; Use the PIC16F628 and decimal system

#include <p16f628a.inc> ; Include header file

errorlevel -302 ; Suppress "Register not in bank 0." message

__config _INTOSC_OSC_NOCLKOUT & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_ON

;---------------------------------------------------------
; Macros
;---------------------------------------------------------
BANK0:macro ; Select bank 0
bcf STATUS,RP0
bcf STATUS,RP1
endm

BANK1:macro ; Select bank 1
bsf STATUS,RP0
bcf STATUS,RP1
endm
;---------------------------------------------------------
; Select PORTB pin number for 1-Wire
;---------------------------------------------------------
constant DQ=0 ; Use RB0 for TMP
;--------------------------------------------------------
; These constants are standard 1-Wire ROM commands
;---------------------------------------------------------
constant SRCHROM=0xF0
constant RDROM=0x33
constant MTCHROM=0x55
constant SKPROM=0xCC
constant CONV=0x44
constant RDPAD=0xBE
;---------------------------------------------------------
; Constants used in code for 1-Wire, RS232 and Delay
;---------------------------------------------------------
cblock 0x20
IOBYTE
TMP0 ; Address 0x23
COUNT ; Keep track of bits
PDBYTE ; Presence Detect Pulse
TP ; Used for Delay routine
TP1 ; Used for Delay routine
TP2 ; Used for Delay routine
DATAL ; RS232 data
endc

org 0x000 ; Program starts at 0x000

movlw 7
movwf CMCON ; Set comperators off

;---------------------------------------------------------
; Initialize ports
;---------------------------------------------------------
movlw B'00000100' ; Set up port A (RA2 is output)
movwf PORTA

movlw B'00000100' ; RB2(TX)=1 others are 0
movwf PORTB

BANK1 ; Select Bank 1 of data memory

movlw B'11110010' ; RB7-RB4 and RB1(RX)=input, others output
movwf TRISB
;---------------------------------------------------------
; Set baud rate to communicate with PC
;---------------------------------------------------------
; Boot Baud Rate = 9600, No Parity, 1 Stop Bit
movlw 0x19 ; 0x19=9600 bps (0x0C=19200 bps)
movwf SPBRG
movlw B'00100100' ; BRGH = 1
movwf TXSTA ; Enable asynchron transmission, set BRGH
BANK0 ; Select Bank 0 of data memory
movlw B'10010000' ; Enable Asynchron reception
movwf RCSTA
;---------------------------------------------------------
; Provide a settling time for start up
;---------------------------------------------------------
clrf DATAL
SETTLE
decfsz DATAL,F
goto SETTLE
movf RCREG,W
movf RCREG,W
movf RCREG,W ; Flush receive buffer
;---------------------------------------------------------
; 1-Wire initializations
;---------------------------------------------------------
BANK1 ; Select Bank 1 of data memory
movlw 0xD7
movwf OPTION_REG
BANK0 ; Select Bank 0 of data memory
bsf INTCON,PEIE ; Enable all un-masked peripheral interrupts



; ---------
; MAIN LOOP
; ---------
LOOP
call START_TMP ; Call 1 wire routine
goto LOOP ; Once again




;---------------------------------------------------------
; SEND CHARACTER IN W VIA RS232 AND WAIT UNTIL FINISHED SENDING
;---------------------------------------------------------
SEND_232
movwf TXREG ; Put data in W
SEND_WAIT
BANK1 ; Select Bank 1 of data memory
WAIT_HERE
btfss TXSTA,TRMT ; Transmission is complete if 1
goto WAIT_HERE
BANK0 ; Select Bank 0 of data memory

return
;---------------------------------------------------------
; 1-Wire
;---------------------------------------------------------

#include <1-wire.inc>

;---------------------------------------------------------
START_TMP
call OW_RESET ; Reset

movlw SKPROM
call DSTXBYTE ; Send 'Skip ROM' command (0xCC)

movlw CONV
call DSTXBYTE ; Send 'Convert T' command (0x44)

call Delay ; Wait for coversion

movlw RDPAD
call DSTXBYTE ; Send 'Read Scratchpad' command (0xBE)

call DSRXBYTE ; Read Current Register MSB
movf IOBYTE,W ; The contents of IOBYTE goes to W
call SEND_232 ; Send the content of W to RS232

call DSRXBYTE ; Read Current Register LSB
movf IOBYTE,W ; The contents of IOBYTE goes to W
call SEND_232 ; Send the content of W to RS232

call OW_RESET

return
;---------------------------------------------------------
; Delay Routine
;---------------------------------------------------------
Delay
movlw 0X10
movwf TP
L2 movlw 0XFF
movwf TP1
L3 movlw 0XFF
movwf TP2
L4 decfsz TP2,F
goto L4
decfsz TP1,F
goto L3
decfsz TP,F
goto L2

return

END


Regards, Mihai.
 
You're not using the correct sequence. Please take a look at my first code sequence again.

owReset
owSend (h'CC') ; send "skip rom" cmd
owSend (h'44') ; send "start temp' conversion" cmd

DelayUS or ReadSlot

owReset
owSend (h'CC') ; send "skip rom" cmd
owSend (h'BE') ; send "read scratchpad" cmd

owRdByte ; read temp' MSB
owRdByte ; read temp' LSB
 
Ty Mike. I've tried to use the corect code sequence and I get the same result. There is my sequence :

list p=16F628A, r=DEC ; Use the PIC16F628 and decimal system

#include <p16f628a.inc> ; Include header file

errorlevel -302 ; Suppress "Register not in bank 0." message

__config _INTOSC_OSC_NOCLKOUT & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_ON

;---------------------------------------------------------
; Macros
;---------------------------------------------------------
BANK0:macro ; Select bank 0
bcf STATUS,RP0
bcf STATUS,RP1
endm

BANK1:macro ; Select bank 1
bsf STATUS,RP0
bcf STATUS,RP1
endm
;---------------------------------------------------------
; Select PORTB pin number for 1-Wire
;---------------------------------------------------------
constant DQ=0 ; Use RB0 for TMP
;--------------------------------------------------------
; These constants are standard 1-Wire ROM commands
;---------------------------------------------------------
constant SRCHROM=0xF0
constant RDROM=0x33
constant MTCHROM=0x55
constant SKPROM=0xCC
constant CONV=0x44
constant RDPAD=0xBE
;---------------------------------------------------------
; Constants used in code for 1-Wire, RS232 and Delay
;---------------------------------------------------------
cblock 0x20
IOBYTE
TMP0 ; Address 0x23
COUNT ; Keep track of bits
PDBYTE ; Presence Detect Pulse
TP ; Used for Delay routine
TP1 ; Used for Delay routine
TP2 ; Used for Delay routine
DATAL ; RS232 data
endc

org 0x000 ; Program starts at 0x000

movlw 7
movwf CMCON ; Set comperators off

;---------------------------------------------------------
; Initialize ports
;---------------------------------------------------------
movlw B'00000100' ; Set up port A (RA2 is output)
movwf PORTA

movlw B'00000100' ; RB2(TX)=1 others are 0
movwf PORTB

BANK1 ; Select Bank 1 of data memory

movlw B'11110010' ; RB7-RB4 and RB1(RX)=input, others output
movwf TRISB
;---------------------------------------------------------
; Set baud rate to communicate with PC
;---------------------------------------------------------
; Boot Baud Rate = 9600, No Parity, 1 Stop Bit
movlw 0x19 ; 0x19=9600 bps (0x0C=19200 bps)
movwf SPBRG
movlw B'00100100' ; BRGH = 1
movwf TXSTA ; Enable asynchron transmission, set BRGH
BANK0 ; Select Bank 0 of data memory
movlw B'10010000' ; Enable Asynchron reception
movwf RCSTA
;---------------------------------------------------------
; Provide a settling time for start up
;---------------------------------------------------------
clrf DATAL
SETTLE
decfsz DATAL,F
goto SETTLE
movf RCREG,W
movf RCREG,W
movf RCREG,W ; Flush receive buffer
;---------------------------------------------------------
; 1-Wire initializations
;---------------------------------------------------------
BANK1 ; Select Bank 1 of data memory
movlw 0xD7
movwf OPTION_REG
BANK0 ; Select Bank 0 of data memory
bcf INTCON,7 ; Enable all un-masked peripheral interrupts



; ---------
; MAIN LOOP
; ---------
LOOP
call START_TMP ; Call 1 wire routine
goto LOOP ; Once again




;---------------------------------------------------------
; SEND CHARACTER IN W VIA RS232 AND WAIT UNTIL FINISHED SENDING
;---------------------------------------------------------
SEND_232
movwf TXREG ; Put data in W
SEND_WAIT
BANK1 ; Select Bank 1 of data memory
WAIT_HERE
btfss TXSTA,TRMT ; Transmission is complete if 1
goto WAIT_HERE
BANK0 ; Select Bank 0 of data memory

return
;---------------------------------------------------------
; 1-Wire
;---------------------------------------------------------

#include <1-wire.inc>

;---------------------------------------------------------
START_TMP
call OW_RESET ; Reset

movlw SKPROM
call DSTXBYTE ; Send 'Skip ROM' command (0xCC)

movlw CONV
call DSTXBYTE ; Send 'Convert T' command (0x44)

call Delay ; Wait for conversion

call OW_RESET ; Reset​


movlw SKPROM
call DSTXBYTE ; Send 'Skip ROM' command (0xCC)

movlw RDPAD
call DSTXBYTE ; Send 'Read Scratchpad' command (0xBE)

call DSRXBYTE ; Read Current Register MSB
movf IOBYTE,W ; The contents of IOBYTE goes to W
call SEND_232 ; Send the content of W to RS232

call DSRXBYTE ; Read Current Register LSB
movf IOBYTE,W ; The contents of IOBYTE goes to W
call SEND_232 ; Send the content of W to RS232

return

;---------------------------------------------------------
; Delay Routine
;---------------------------------------------------------
Delay
movlw 0X10
movwf TP
L2 movlw 0XFF
movwf TP1
L3 movlw 0XFF
movwf TP2
L4 decfsz TP2,F
goto L4
decfsz TP1,F
goto L3
decfsz TP,F
goto L2

return

END

Is there a problem that I conected DQ via RB0/INT pin? Otherwise I don't see where is the "bug".
 
Mike said:
...

DelayUS or ReadSlot

...
I've noticed that you use a macro called 'owRdBit'. I'd like to try that method instead of a delay routine, after the ConvertT command. Is the code already available on this forum? Thanks


p.s.: I use a DS18S20 but there shouldn't be any difference.
From the datasheet of the DS18S20:
If the DS18S20 is powered by an external supply, the master can issue read-time slots after the Convert T command and the DS18S20 will respond by transmitting 0 while the temperature conversion is in progress and 1 when the conversion is done.
 
I'm developing macros and subroutines which will support 'cardinal' clock frequencies from 4-MHz up to 48-MHz. My owRdBit macro is just a combination of macros from the Dallas/Maxim application note (OW_LO, OW_HIZ, and the pin test portion of DSRXBYTE).

Code:
;******************************************************************
;
owRdBit macro
        bcf     owPin           ; clr pin (output latch = 0)      |B0
        bsf     STATUS,RP0      ; bank 1                          |B0
        bcf     owPin           ; clr TRIS bit (output '0')       |B0
        DelayCy(tClk)           ; delay 2 usecs                   |B0
        bsf     owPin           ; set TRIS pin (hi-z input)       |B0
        bcf     STATUS,RP0      ; bank 0                          |B0
        DelayCy(tRd-1)          ; delay 2 usecs minus 1 cycle     |B0
        movf    owPort,W        ; read port                       |B0
        andlw   owMask          ; apply ow pin mask               |B0
        addlw   d'255'          ; set Carry = data bit            |B0
        endm
I use the 'ReadSlot' method in my GetTemp routine so that I can use DS18S20 or DS18B20 devices which have different conversion times and read the 9 byte scratchpad from them as soon as the temperature conversion is complete.

Code:
;******************************************************************
;
;  get new DS18x20 temperature reading
;
GetTemp
        owReset                 ; reset one-wire devices          |B0
        owSend (h'CC')          ; DS18x20 'skip rom' command      |B0
        owSend (h'44')          ; start temperature conversion    |B0 [COLOR=Blue]
ReadSlot
        DelayUS(56)             ; wait 56-usecs                   |B0
        owRdBit                 ; conversion complete (C=1)?      |B0
        bnc     ReadSlot        ; no, branch, else                |B0
[/COLOR]        owReset                 ; reset one-wire devices          |B0
        owSend (h'CC')          ; DS18x20 'skip rom' command      |B0
        owSend (h'BE')          ; DS18x20 'read scratchpad' cmd   |B0
        owRead  owBuf,9         ; read 9 byte scratchpad -> owBuf |B0
        return                  ; exit (done)                     |B0
 
Last edited:
owRdBit

Mike said:
I use the 'ReadSlot' method in my GetTemp routine so that I can use DS18S20 or DS18B20 devices which have different conversion times and read the 9 byte scratchpad from them as soon as the temperature conversion is complete.
Thank you, I'm using your method instead of the delay ruotine.
It will allow me to use the DS1820 (obsolete and more expensive now, but you still find it!) or the DS18S20 indifferently (The primary specification difference between the two parts is the temperature conversion time...)

Are you writing a general routine for both the DS18S20 and the DS18B20? Besides the different timing requirements, the data format is different, isn't it? Are you going to read the 8-bit family code of the chip in order to find out which sensor is used and make the specific conversion?
 
Last edited:
eng1 said:
Are you writing a general routine for both the DS18S20 and the DS18B20?
Yes, I'm supporting DS1820, DS18S20, and DS18B20.

Besides the different timing requirements, the data format is different, isn't it?
Yes, the 16 bit temperature data is different but one byte in the 9 byte 'scratchpad' buffer is a "remainder" byte which can be used to provide 1/16th degree resolution like the DS18B20.

B_format_temp = (S_format_temp / 2) * 16 + (16 - S_remainder)

Are you going to read the 8-bit family code of the chip in order to find out which sensor is used and make the specific conversion?
Yes, I use the above formula for a DS1820 or DS18S20 family code ID to convert the temperature word into the DS18B20 format before performing math routines.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top