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.

One Wire Temperature sensor (DS1820) to PC interface.

Status
Not open for further replies.

Pommie

Well-Known Member
Most Helpful Member
Here is a project I worked on a while ago that I’ve finally got around to documenting.

It interfaces Dallas One Wire (OW) temperature devices to a PC using the smallest Pic chip available, the 10f200. The 10f200 can hold 256 instructions and has 16 bytes of RAM so fitting the OW search algorithm in it was rather challenging. It can also use a 12F509.

What the device actually does is to interrogate the Dallas chips one at a time, find their ROM IDs, do a conversion and send a string to the PC containing all the information. It is powered from the RS232 port and works with the 2 USB to RS232 converters that I have.

Here it is with 3 DS13S20s attached. You can attach as many as you like in theory but you will probably have to add an external power supply.
picture.php


And a closer look,
picture.php


The Schematic,
picture.php


Parts list,
A preprogrammed 10F200 or 12F509.
2 x 1K resistors
2 X 10uF electrolitic capacitors
2 x 0.1uF capacitors
1 x 1N4148 diode.
1 x 78L05 voltage regulator

The board,
picture.php

I've attached a monochrome image. See below.

If you run hyperterminal you will get this,
picture.php


Not very useful and so I’ve written a little VB application to demonstrate how to extract the ROM and temperature information. See below. (anyone familiar with the Dallas devices will recognize the above as the ROM ID followed by the scratch pad area.)

This is what the VB app does. This is the 3 ROM Ids and temperatures.
picture.php



The code is rather hard to follow as it uses every trick in the book to minimize ROM and RAM usage. But here it is anyway,
Code:
;*******************************************************************
;	Title	One Wire temperature reader
;	Author	Mike Webb
;	Date	10th January 2009
;	Pic	10F200 or 12F509
;*******************************************************************

	errorlevel	-302,-224
	radix	dec

	#ifdef	__12F509

	include	"p12f509.inc"
	__CONFIG   _MCLRE_ON & _CP_OFF & _WDT_ON & _IntRC_OSC

OW_Bit	equ	4
RS_Bit	equ	2
#define	DataLow		b'11111111' - (1<<OW_Bit) - (1<<RS_Bit)
#define	DataHigh	b'11111111' - (1<<RS_Bit)
#define	DataBit		GPIO,OW_Bit
#define	b_RS232Out	GPIO,RS_Bit

	cblock	0x10
RomBuffer:8	;must be on 16 byte boundary
temp
OwByte:0
Discrepency
OutByte
OwCount
OwFlags
BitIndex
OwTemp
LastDiscrepency
	endc
	endif	


	#ifdef	__10F200

	include	"p10f200.inc"
	__CONFIG   _MCLRE_OFF & _CP_OFF & _WDT_ON

OW_Bit	equ	2
RS_Bit	equ	0
#define	DataLow		b'11111111' - (1<<OW_Bit) - (1<<RS_Bit)
#define	DataHigh	b'11111111' - (1<<RS_Bit)
#define	DataBit		GPIO,OW_Bit
#define	b_RS232Out	GPIO,RS_Bit

	cblock	0x10
RomBuffer:8  	;must be on 16 byte boundary
temp
OwByte:0	;shares same location as Discrepency
Discrepency
OutByte
OwCount
OwFlags
BitIndex
OwTemp
LastDiscrepency	
	endc
	endif	


#define	OwSkipRom	0xcc
#define	OwConvert	0x44
#define	OwReadScratchPad	0xbe
#define	OwSearchRom	0xf0
#define	OwMatchRom	0x55

#define	b_OwPresent	OwFlags,7
#define	b_ClrBit	OwFlags,6
#define	b_Done		OwFlags,5
#define	b_IsGetBit	OwFlags,4
#define	b_SendRom	OwFlags,3


		org	0

		movwf	OSCCAL
		clrf	7		;turn of comparators (10f204/6)
start		movlw	DataHigh	;release line
		tris	GPIO
		movlw	0xdf		;make GPIO2 I/O
		option
First		clrf	LastDiscrepency	;restart search rom
		bcf	b_Done		
Next		bcf	DataBit
		btfsc	b_Done		;Have we completed list
		goto	start		;Yes so restart
		clrf	BitIndex	;start at first bit
		call	OwReset
		movlw	OwSearchRom	;Send search rom command
		call	OwWriteByte
		clrf	Discrepency
GetBits		clrf	OwFlags		;clear all bit variables
		call	OwReadBit	;get bit A
		rlf	OwFlags,f
		call	OwReadBit	;get bit B
		rlf	OwFlags,f
		movlw	0x03
		xorwf	OwFlags,w	;If A=1 && B=1 then no devices present
		btfsc	STATUS,Z	
		goto	start		;Restart
		xorlw	0x03
		btfss	STATUS,Z
		goto	Not00
;A=0 and B=0
		movfw	BitIndex
		subwf	LastDiscrepency,w
		btfsc	STATUS,Z
		goto	RomIndexEqualLD
		btfss	STATUS,C
		goto	RomIndexGTLD
		call	GetBit		;RomIndex < LastDiscrepency
		btfss	STATUS,C
		goto	SetMarker
		goto	SendRomBit
Not00		btfsc	OwFlags,1	;set ROM bit to match Bit A
		call	SetBit
		btfss	OwFlags,1
		call	ClrBit
		goto	SendRomBit
RomIndexGTLD	call	ClrBit		;RomIndex > LastDiscrepency
SetMarker	movfw	BitIndex
		movwf	Discrepency
		goto	SendRomBit
RomIndexEqualLD	call	SetBit		;RomIndex = LastDiscrepency
SendRomBit	call	GetBit
		call	OwSendCarry
		incf	BitIndex,f
		btfss	BitIndex,6
		goto	GetBits
		movfw	Discrepency
		movwf	LastDiscrepency
		btfsc	STATUS,Z
		bsf	b_Done

		bsf	b_SendRom	;this was a subroutine but due to lack of
OwMatch		call	OwReset		;stack space it was put in line and a flag
		movlw	OwMatchRom	;used to indicate the return address
		call	OwWriteByte
		movlw	RomBuffer	;=0x10 = 0001 0000
		movwf	FSR
SendRom		movfw	INDF
		call	OwWriteByte
		incf	FSR,F
		btfss	FSR,3		;bodgey, FSR=0x18
		goto	SendRom
		btfss	b_SendRom
		goto	Continue	;taken 2nd time around

		movlw	OwConvert
		call	OwWriteByte
		bcf	b_SendRom

		bsf	DataBit		;drive data line high by
		movlw	DataLow		;setting to output for
		tris	GPIO		;parasitic power devices
		call	Delay1		;wait for conversion
		movlw	DataHigh	;release data line
		tris	GPIO		;by setting to input

SendSerial	decf	FSR,F		;FSR=0x18 when entering
		btfss	FSR,4		;will be clear when FSR=0x0f
		goto	OwMatch
		swapf	INDF,W
		call	SendNibble
		movfw	INDF
		call	SendNibble
		goto	SendSerial

Continue	movlw	OwReadScratchPad
		call	OwWriteByte
		call	SendSpace
		movlw	0x100-9
		movwf	FSR		;very dodgey - relies on unused bits being 1
ReadLoop	call	OwReadByte	;but no choice as out of RAM!!
		swapf	OwByte,W
		call	SendNibble
		movfw	OwByte
		call	SendNibble
		incfsz	FSR,F		
		goto	ReadLoop
		movlw	0x0d		;send cr/lf
		call	Send
		movlw	0x0a
		call	Send
		goto	Next		;go get next rom ID
		
GetBit		bsf	b_IsGetBit	;Get bit RomBuffer[BitIndex]
		goto	DoBit
ClrBit		bsf	b_ClrBit	;Clear bit RomBuffer[BitIndex]
		btfss	b_ClrBit
SetBit		bcf	b_ClrBit	;Set bit RomBuffer[BitIndex]
		bcf	b_IsGetBit
DoBit		rrf	BitIndex,W
		movwf	OwTemp
		rrf	OwTemp,f
		rrf	OwTemp,W
		andlw	0x07
		iorlw	RomBuffer
		movwf	FSR
		movfw	BitIndex
		andlw	0x07
		clrf	OwTemp
		movwf	OwCount
		bsf	STATUS,C
GetBitLoop	rlf	OwTemp,f	;will clear the carry bit
		decf	OwCount,F
		btfss	OwCount,7
		goto	GetBitLoop
		movfw	OwTemp
		btfsc	b_IsGetBit
		goto	DoGetBit	;carry must be clear
		btfsc	b_ClrBit
		goto	IsClrBit
		iorwf	INDF,f
		retlw	0
IsClrBit	xorlw	0xff
		andwf	INDF,f
		retlw	0
DoGetBit	andwf	INDF,w
		btfss	STATUS,Z
		bsf	STATUS,C
		retlw	0

OwReset		movlw	DataLow		;pull line low
		tris	GPIO
		movlw	.750/4		;delay 750uS
		movwf	temp
		decfsz	temp,W
		goto	$-2
		movlw	DataHigh	;release line
		tris	GPIO
	;	movlw	.68/4		;delay 68uS
	;	movwf	temp
	;	decfsz	temp,W
	;	goto	$-2
	;	bcf	b_OwPresent
	;	btfss	DataBit		;pulled low?
	;	bsf	b_OwPresent	;yes so chip present
	;	movlw	.480/4		;delay 480uS
		movlw	.548/4		;combined times
ExitDelay	movwf	temp
		decfsz	temp,W
		goto	$-2
		retlw	0

OwWriteByte	movwf	OwByte		;store byte to write
		movlw	.8		;send 8 bits
		movwf	OwCount
OwWriteLoop	rrf	OwByte,f	;move bit to carry
		call	OwSendCarry	;send it
		decfsz	OwCount,F	;sent all bits
		goto	OwWriteLoop	;no, so loop
		retlw	0

OwReadByte	movlw	.8		;get 8 bits
		movwf	OwCount
OwReadByteLoop	call	OwReadBit	;returns bit in carry
		rrf	OwByte,F	;move carry into byte
		decfsz	OwCount,F	;finished?
		goto	OwReadByteLoop	;no, so carry on
		retlw	0

OwSendCarry	btfss	STATUS,C	;is carry clear
		goto	OwSend0		;yes, so goto send zero
OwSend1		movlw	DataLow		;pull line low
		tris	GPIO
		goto	$+1		;wait 4uS
		goto	$+1
		movlw	DataHigh	;release line
		tris	GPIO
Exit60		movlw	.60/4		;wait 60uS
		goto	ExitDelay

OwSend0		movlw	DataLow		;pull line low
		tris	GPIO
		movlw	.60/4		;wait 60uS
		movwf	temp
		decfsz	temp,W
		goto	$-2
		movlw	DataHigh	;release line
		tris	GPIO
		movlw	.4/4
		goto	ExitDelay

OwReadBit	movlw	DataLow		;pull line low
		tris	GPIO
		goto	$+1		;wait 4uS
		goto	$+1
		movlw	DataHigh	;release line
		tris	GPIO
		movlw	.12/4		;Wait 12uS
		movwf	temp
		decfsz	temp,W
		goto	$-2
		bcf	STATUS,C
		btfsc	DataBit
		bsf	STATUS,C
	;	movlw	.60/4		;Wait 60uS
		goto	Exit60		;Delay

SendSpace	movlw	' '		;0x20
		goto	Send

SendNibble	andlw	0fh		;keep lower nibble
		movwf	temp		;save for later
		movlw	0x100-10	;test if greater
		addwf	temp,W		;than 10
		movlw	"0"		;add "0"
		btfsc	STATUS,C	;or, if greater than 10
		movlw	"0"+7		;add "A"-10
		addwf	temp,W		;do add and fall through to send it
	
Send		movwf	OutByte		;sends data inverted so no MAX232 needed
		bsf	b_RS232Out	;start bit
		call	BitDelay
		bsf	STATUS,C	;will be first stop bit
SendLoop	rrf	OutByte,F	;move bit to carry
		bsf	b_RS232Out
		btfsc	STATUS,C
		bcf	b_RS232Out
		call	BitDelay
		bcf	STATUS,C	;ensure 0 shifted into outbyte
		movfw	OutByte		;will be zero when 8 bits + 1 stop bit sent
		btfss	STATUS,Z
		goto	SendLoop
		bcf	DataBit		;ensure data line is low

;fall through for second stop bit.

; at 1 meg instructions and 9600 baud
; delay is 1,000,000/9600 = 104 cc
; the calling loop and the call/return = 13
; therefore delay needs to be 91 cycles

BitDelay	movlw	.30
		movwf	temp
DelayLoop	decfsz	temp,F;		(3*30)-1 = 89 + 2 = 91
		goto	DelayLoop
		clrwdt			;kick the dog
		retlw	0

Delay1		clrf	OwTemp		;approx 1 second delay
		movlw	.40
		movwf	OwCount
del		call	BitDelay
		decfsz	OwTemp,F
		goto	del
		decfsz	OwCount,F
		goto	del
		retlw	0



	if	($>0xff)
	messg	"Memory Overflow"
	endif
	end

Note, it is essential that the pic has the correct oscillator calibration value so use a new one or recalibrate it with the Pickit2 software.

The attachments are the VB files, Hex files and board image.

Mike.
 

Attachments

  • VB files.zip
    2.1 KB · Views: 2,172
  • Ow2RS232-10F200.zip
    733 bytes · Views: 1,658
  • Ow2RS232-12F509.zip
    729 bytes · Views: 1,575
  • OWboard.png
    OWboard.png
    12.7 KB · Views: 2,150
Hi Mike,

A very impressive effort. Thank you for sharing.

I've not implemented the ROM Search algorithm and so I'm looking forward to studying your code.

Regards, Mike
 
Hi Mike,

Maxim have a very good explanation of the search ROM algorithm in **broken link removed**. My implementation above is very convoluted (spaghetti like) mainly due to the stack limitations. I also gave up trying to comment the search part as it really needs a whole paragraph per 4 lines of code and it's easier to refer people to the document (which I forgot to do). Anyway, have fun trying to untangle that web of code.:D

Mike.
 
Great job!! Fully documented projects like yours are such a rare commodity, Thanks. There's a lot going on for such a little device.

By coincidence, there are a couple of 10F's from Newark coming my way very soon. Now, to put on my assembly deciphering hat.
 
Mike (Pommie),

Thank you again for sharing your project. I think (hope) I'm getting a handle on the search algorithm thanks to your example and the Maxim application note and I'm taking a stab at optimizing the code a bit and organizing it in a way that's more intuitive for me.

If you get a chance could you take a peek at the following excerpt and tell me if it makes sense? The program is about 45 bytes smaller so far and I was able to eliminate the OwFlags variable and its flag bits as well as the GetBit, SetBit, and ClrBit routines.

Thanks. Take care. Mike

Code:
First
        clrf    LastDiscrepency ; restart search rom
Next
        bcf     DataBit         ; clear 1-wire port latch
        clrf    BitIndex        ; start at first bit
        clrf    LastZero        ;
        movlw   RomBuffer       ;
        movwf   FSR             ; FSR = &RomBuffer
        movlw   1               ;
        movwf   BitMask         ; reset rom array bit mask
        call    OwReset         ;
        OwSend (OwSearchRom)    ; send "search rom" command
GetBits
        clrf    OwTemp          ;
        call    OwReadBit       ; get bit A
        rlf     OwTemp,F        ; F = -------A
        call    OwReadBit       ; get bit B
        rlf     OwTemp,W        ; W = ------AB
        xorlw   0x03            ; AB == 11, no devices present?
        bz      start           ; yes, branch (restart), else
        xorlw   0x03            ; AB == 00, discrepency?
        bnz     SendRomBit      ; no, branch (use 'A' bit), else
Discrepency
        bsf     OwTemp,0        ; set 'A' bit to '1'
        movf    BitIndex,W      ; 0..63
        subwf   LastDiscrepency,W
        bnc     IndexGTLD       ;
        bz      SendRomBit      ; set rom bit to '1'
IndexLTLD
        movf    BitMask,W       ; get ROM bit
        andwf   INDF,W          ; is ROM bit '0'?
        bnz     SendRomBit      ; no, branch, use '1', else
IndexGTLD
        bcf     OwTemp,0        ; set 'A' bit to '0'
        movf    BitIndex,W      ;
        movwf   LastZero        ; update LastZero
SendRomBit
        rrf     OwTemp,F        ; put 'A' bit into Carry
        movf    BitMask,W       ; set ROM bit to bit 'A'
        iorwf   INDF,F          ; set ROM bit (unconditionally)
        skpc                    ; is bit a '1'? yes, skip, else
        xorwf   INDF,F          ; clr ROM bit
        call    OwSendCarry     ; send direction/qualifier bit
        rlf     BitMask,W       ;
        rlf     BitMask,F       ; advance rom array bit mask
        skpnc                   ; all 8 bits done? no, skip, else
        incf    FSR,F           ; bump RomBuffer array address
        incf    BitIndex,F      ; bump bit index, 0..63
        btfss   BitIndex,6      ; BitIndex = 64?  yes, skip, else
        goto    GetBits         ; do next bit
        movf    LastZero,W      ;
        movwf   LastDiscrepency ; update last discrepency
;
;  we now have a qualified 64 bit ROM serial number
;
OwMatch
 
Last edited:
That looks like it should work. I like the way you've kept FSR current rather than recalculating it each bit. I don't have the equipment setup at the moment to test it but can probably try it later. Are you able to test it?

I'm looking forward to seeing the complete code.

Edit, Did you realise that Discrepancy (LastZero) and OWByte share the same RAM location hence why I cleared Discrepancy after sending OWSearchRom.

Mike.
 
Last edited:
I won't be able to test it for a few days but then I'm still workin' on it. There are lots of changes like the SendCarry routine below.

Yes, I think I figured out your local and global variables. I changed them around a bit to fit the new structure.

I can't tell you how geeked I am to try this routine on a couple projects.

Thank you, thank you, thank you...

Mike

Code:
OwSendCarry
        movlw   DataLow         ;
        tris    GPIO            ; initiate write slot
        skpnc                   ; send 0 bit
        movlw   DataHigh        ; send 1 bit
        tris    GPIO            ;
        movlw   .60/4           ; finish 60 usec slot
        movwf   temp            ;
        decfsz  temp,W          ;
        goto    $-2             ;
        movlw   DataHigh        ;
        tris    GPIO            ; release bus
        retlw   0               ;
 
Last edited:
I still had the breadboard with a SOT-23 10F200 on it and just incorporated your code. It worked first time and occupies 0xc4 locations - less than 200.

Mike.
 
Hi Mike (Pommie),

I attached my crude unpolished 168 byte version of your program below just in case you might be interested. It's probably a reasonably good example of optimization and the problems that the subtle dependencies may cause.

Here's my version of your OwMatch code section. I used some macros to hide detail and hopefully make it easier to follow the logic and program flow. I used your flag method to reuse the MatchRom code for both the "Convert" and "Read Scratchpad" operations but I used my BitMask variable for the flag since BitMask always equals '00000001' when we fall out of the "OwSearch" code into the "OwMatch" code.
Code:
;       bsf     BitMask,0       ; do "convert" (bit = 1 already)
OwMatch
        [COLOR=DarkOrchid]OwReset[/COLOR]                 ; reset all 1-wire devices
        [COLOR=DarkOrchid]OwWrite[/COLOR](OwMatchRom)     ; send "match rom" command
        [COLOR=DarkOrchid]OwWriteBuffer[/COLOR]           ; send + print rom serial number
        [COLOR=DarkOrchid]Send232[/COLOR](' ')            ; send <space> char
        btfss   BitMask,0       ; conversion complete?
        goto    OwScratch       ; yes, branch, else
        [COLOR=DarkOrchid]OwWrite[/COLOR](OwConvert)      ; send "convert" command
        [COLOR=DarkOrchid]OwPowerBus[/COLOR]              ; power OW pin during conversion
        [COLOR=DarkOrchid]Send232[/COLOR](0x0D)           ; send <cr> char (htab 0)
        bcf     BitMask,0       ; indicate conversion complete
        goto    OwMatch         ; do "match rom" for OwScratch
OwScratch
        [COLOR=DarkOrchid]OwWrite[/COLOR](OwReadScratch)  ; send "read scratchpad" command
        movlw   -9              ;
        movwf   FSR             ; use FSR as byte counter
RdLoop  [COLOR=DarkOrchid]OwReadByte[/COLOR]              ; read + print scratchpad byte
        incfsz  FSR,F           ; all 9 bytes read + printed?
        goto    RdLoop          ; no, branch, else
        [COLOR=DarkOrchid]Send232[/COLOR](0x0D)           ; send <cr> char
        [COLOR=DarkOrchid]Send232[/COLOR](0x0A)           ; send <lf> char
        goto    OwSearchNext    ; search and process next device
Another subtle dependency is that my Send232() routine always forces the OW pin latch bit in GPIO to '0' so I saved one instruction in my OwPowerBus code by omitting that instruction after powering the bus for 1 second. But this means you have to print something after performing the OwPowerBus operation and before trying to write something else on the OW bus. These kind of dependencies will easily get you into trouble when you try to modify the program.

One program difference worth mentioning is that the OwWriteBuffer code also sends each byte to the serial port. This results in the rom serial number being printed twice but I send a <cr> character after the "OwConvert" operation so the second instance of the rom serial number printout should print on top of the first instance. This should work fine for Hyperterminal but if you're using an application then it will need to ignore the first 17 characters after detecting each <newline> (<cr>+<lf>) sequence.

Now I'm wondering if 88 bytes of free memory might be enough for adding code to print the temperature as a decimal number?

Regards, Mike
 

Attachments

  • 10F200 1-Wire K8LH.ASM.txt
    12 KB · Views: 1,373
Last edited:
Hi Mike,

I've been playing with your code but I can't get it working. I had to add an extra stop bit to the RS232 routine to get sensible data but I don't seem to be getting a correct ROM address.

This is what I'm getting in Hyperterminal,
Code:
0100000000000080 000000000000000000
0100000000000040 000000000000000000
01000000000000C0 000000000000000000
0100000000000020 000000000000000000
01000000000000A0 000000000000000000
0100000000000060 000000000000000000
01000000000000E0 000000000000000000
0100000000000010 000000000000000000
0100000000000090 000000000000000000
0100000000000050 000000000000000000
It looks like it's taking the discrepancy path when there isn't one but I can't figure it out.

Also, I found a problem in the OwScratch routine, FSR has to be -9 and incremented as the unused bits of FSR are set to 1.

I'l have another play later and see if I can figure anything out.

Do you have hardware to test this? Did it work? Have you any ideas why I'm getting strange results?

BTW, some great code saving ideas there. I'm not sure the decimal part will be possible but look forward to trying.

Mike.
 
Thanks for checking it out Mike.

I'll keep working on the code and look for those errors.

Did you notice my serial code was 19200 baud instead of 9600 baud?

I wonder if there's a problem with my modified OwReadBit routine?

I don't have hardware to test this code yet.

Mike
 
Last edited:
Mike,

For a sanity check I just reverted to the code from the first post and I'm getting the same results so I suspect my hardware is at fault.

<edit> one of the outer pins (DS1820) had shorted to the middle pin. No wonder I couldn't get any sense out of it. I'll try your code again and get let you know.</edit>
<edit2> You code works with the mod to OwScratch and the extra stop bit. Extremely nice piece of code. Now for the decimal bit!!</edit2>

Mike.
 
Last edited:
Mike,

The data I was receiving for the scratch area was wrong, I tracked it down to the bsf BitCtr,3 in OwReadByte. It failed because Send232 leaves BitCtr containing 1. Took me a while to spot that ,W on the end of it. Shortening the loop makes the timing better anyway.

Mike.
 
Good catch. One of those darned optimization dependencies. I modified OwReadByte to correct the problem. Program is now 169 bytes.

What do you mean by "shortening the loop makes the timing better"? That Put232 subroutine has perfect 52 usec bit timing with absolutely no jitter. Also wondering why do you need two stop bits?
 
Ok, here's a revised Put232 routine that leaves BitCtr = 0 on exit and still provides perfect 52 usec timing between bit edges.

Code:
;
;  19200 baud, exact 52-usec bit timing (4 MHz)
;
Put232  bsf     GPIO,RS_Bit     ; send start bit
        movwf   OwTemp          ; save Tx data
        movlw   9               ; 8 data bits + 1 stop bit
        movwf   BitCtr          ; update bit counter
PutBit  setc                    ; shift in stop bits
        movlw  (52-8)/4         ; 52 usecs - 8 usec loop time
        movwf   temp            ; a 4 cycle / 4 usec loop
        decfsz  temp,W          ; W == 0? yes, skip, else
        goto    $-2             ; loop
        rrf     OwTemp,F        ; put data bit in C (W = 0)
        skpc                    ; a '1' bit? yes, skip, else
        iorlw   1<<RS_Bit       ; send a '0', W = 1<<RS_Bit
        movwf   GPIO            ; send bit, clear OW DataPin
        decfsz  BitCtr,F        ; all 9 bits? yes, skip, else
        goto    PutBit          ; send next bit
        retlw   0               ;
 
Hi mike,

I should have mentioned that I had already moved the setc into the loop to enable it to send two stop bits and so moving the label down one line brought it back to 52 cycles. If I don't send two stop bits then I get corruption in Hyperterminal.

Mike.
 
Yeah, I should have figured you did that.

Thanks for telling me about how the unused bits behave in the FSR register.

Got the program down to 166 bytes now. I used bit 3 in the BitMask variable for the "conversion complete" flag which leaves BitMask preset to 9 for use as the byte counter in the "Read Scratchpad" section. It saves two bytes. Check it out;

Code:
;       bcf     BitMask,3       ; do "convert" (BitMask=00000001)
OwMatch
        [COLOR=Blue]OwReset[/COLOR]                 ; reset all 1-wire devices
        [COLOR=Blue]OwWrit[/COLOR]e(OwMatchRom)     ; send "match rom" command
        [COLOR=Blue]OwWriteBuffer[/COLOR]           ; send + print rom serial number
        [COLOR=Blue]Send232[/COLOR](' ')            ; send <space> char
        btfsc   BitMask,3       ; conversion complete?
        goto    OwScratch       ; yes, branch, else
        [COLOR=Blue]OwWrite[/COLOR](OwConvert)      ; send "convert" command
        [COLOR=Blue]OwPowerBus[/COLOR]              ; power OW pin during conversion
        [COLOR=Blue]Send232[/COLOR](0x0D)           ; send <cr> char (htab 0)
        bsf     BitMask,3       ; indicate conversion complete
        goto    OwMatch         ; do "match rom" for OwScratch
OwScratch
        [COLOR=Blue]OwWrite[/COLOR](OwReadScratch)  ; send "read scratchpad" command
;       movlw   9               ; instructions not needed
;       movwf   BitMask         ; BitMask = 9 already from above
RdLoop  [COLOR=Blue]OwReadByte[/COLOR]              ; read + print scratchpad byte
        decfsz  BitMask,F       ; all 9 bytes read + printed?
        goto    RdLoop          ; no, branch, else
        [COLOR=Blue]Send232[/COLOR](0x0D)           ; send <cr> char
        [COLOR=Blue]Send232[/COLOR](0x0A)           ; send <lf> char
        goto    OwSearchNext    ; search and process next device
On a newer version of the program I added code to detect DS1820 and DS18S20 devices and to convert their 9 bit temperature word to the DS18B20 12 bit format (1/16th degree resolution);

Code:
OwScratch
        [COLOR=Blue]OwWrite[/COLOR](OwReadScratch)  ; send "read scratchpad" command
        [COLOR=Blue]OwReadByte[/COLOR]              ; read byte 1
        movf    OwByte,W        ;
        movwf   Cels_H          ; save temperature hi
        [COLOR=Blue]OwReadByte[/COLOR]              ; read byte 2
        movf    OwByte,W        ;
        movwf   Cels_L          ; save temperature lo
        movf    RomBuffer,W     ; get Family ID byte
        xorlw   0x28            ; is it 12 bit DS18B20?
        bz      OwTemperature   ; yes, branch, else
        [COLOR=Blue]OwReadByte[/COLOR]              ; read byte 3
        [COLOR=Blue]OwReadByte[/COLOR]              ; read byte 4
        [COLOR=Blue]OwReadByte[/COLOR]              ; read byte 5
        [COLOR=Blue]OwReadByte[/COLOR]              ; read byte 6
        [COLOR=Blue]OwReadByte[/COLOR]              ; read byte 7, Count_Remain
        rlf     Cels_L,F        ;                                 |
        rlf     Cels_H,F        ;
        rlf     Cels_L,F        ;
        rlf     Cels_H,F        ;
        rlf     Cels_L,F        ;
        rlf     Cels_H,F        ;
        movlw   0xF0            ;
        andwf   Cels_L,F        ;
        movlw   16              ;
        movwf   temp            ;
        movf    OwByte,W        ; Count_Remain
        subwf   temp,W          ;
        iorwf   Cels_L,F        ; now DS18B20 12 bit format
OwTemperature
Now I'm trying to add a sign extended 8x16 multiply routine which will produce a 3 byte sign extended binary result of C° * 1000 (3 decimal places with a value ranging from -55000 to 125000); C° * 1000 = 125 * (Celsius16) / 2

Regards, Mike
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top