;****************************************************************** ;* * ;* Filename: 10F200 1-Wire K8LH.asm * ;* Author: Mike McLaren, K8LH (k8lh@arrl.net) * ;* Date: 20-Jan-09 * ;* * ;* Variation of Mike Webb's 10F200 Serial DS1820 Sensor Program * ;* * ;* MPLab: 8.14 (tabs=8) * ;* MPAsm: 5.21 * ;* * ;****************************************************************** ;****************************************************************** ; Title One Wire temperature reader ; Author Mike Webb ; Date 10th January 2009 ; Pic 10F200 or 12F509 ;****************************************************************** errorlevel -302 include "p10f200.inc" __CONFIG _MCLRE_OFF & _CP_OFF & _WDT_OFF radix dec OW_Bit equ 2 ; GP2 RS_Bit equ 0 ; GP0 #define DataLow b'11111111' - (1<------------------------------------------------- cblock 0x10 RomBuffer:8 ; must be on 16 byte boundary LastDiscrep ; ;--< local vars >-------------------------------------------------- LastZero ; Search BitMask ; Search, OwMatch flag bit (BitMask,0) BitIndex ; Search OwByte ; OwReadByte, OwWriteByte BitCtr ; OwReadByte, OwWriteByte, Put232 temp ; all delay routines & PutNybble OwTemp ; GetBits, Put232 endc TimerH equ LastZero ; OwPowerBus 1 second delay TimerL equ BitIndex ; OwPowerBus 1 second delay ;--< one wire command constants >---------------------------------- #define OwSkipRom 0xCC #define OwConvert 0x44 #define OwReadScratch 0xBE #define OwSearchRom 0xF0 #define OwMatchRom 0x55 ;--< macros >------------------------------------------------------ OwReset macro call Ow.Reset endm OwWrite macro pByte movlw pByte call Ow.WriteByte endm OwReadByte macro call Ow.ReadByte endm OwReadBit macro call Ow.ReadBit endm OwSendCarry macro call Ow.SendCarry endm OwPowerBus macro bsf DataBit ; setup OW pin to output a '1' movlw DataLow ; to power parisitic devices tris GPIO ; during the 'convert' command movlw ~(high(1000000/768)) movwf TimerH ; dly1 decfsz temp,F ; 768 usec loop goto dly1 ; decfsz TimerL,F ; goto dly1 ; incfsz TimerH,F ; goto dly1 ; call Release ; release data line endm OwWriteBuffer macro local loop bcf FSR,3 ; reset FSR = &RomBuffer (0x10) loop movf INDF,W ; call Ow.WriteByte ; send rom serial number byte call PutHex ; print byte as hex incf FSR,F ; btfss FSR,3 ; goto loop ; endm Send232 macro pByte ; movlw pByte ; call Put232 ; endm ;****************************************************************** ; ; main program ; org 0x00 movwf OSCCAL ; Restart clrf GPIO ; set OW and serial pins '0' movlw DataHigh ; 1-wire pin hi-z, '1' tris GPIO ; serial pin output '0' movlw b'11011111' ; 11011111 ; 1-------, IOC off ; -1------, weak pullups off ; --0-----, tmr0 source Fosc/4 ; ---1----, tmr0 edge hi>lo ; ----1---, wdt gets prescaler ; -----111, wdt prescale 128:1 option ; clrf LastDiscrep ; init Last Discrepency var' OwSearchNext clrf BitIndex ; BitIndex = 0 clrf LastZero ; LastZero = 0 movlw b'00000001' ; movwf BitMask ; setup rom array bit mask OwReset ; reset all 1-wire devices OwWrite(OwSearchRom) ; send "search rom" command ; movlw RomBuffer ; OwWrite() returns W = &RomBuffer movwf FSR ; FSR = &RomBuffer (0x10) GetBits OwReadBit ; read bit A rlf OwTemp,F ; F = -------A OwReadBit ; read bit B (compliment) rlf OwTemp,W ; W = ------AB rrf OwTemp,F ; put 'A' bit back into Carry andlw 0x03 ; filter out unused bits xorlw 0x03 ; AB == 11, no response? bz Restart ; yes, branch (restart), else xorlw 0x03 ; AB == 00, a discrepency? bnz SendRomBit ; no, branch, use 'A' bit, else Discrepency movf BitIndex,W ; 0..63 subwf LastDiscrep,W ; 0..63 bnc IndexGTLD ; index > last discrepency, use '0' bz SendRomBit ; index = last discrepency, use '1' IndexLTLD ; index < last discrepency, use ROM movf BitMask,W ; get ROM bit andwf INDF,W ; is ROM bit '0'? bnz SendRomBit ; no, branch with C = 1, else clrc ; set C = 0 and IndexGTLD movf BitIndex,W ; update 'LastZero' movwf LastZero ; SendRomBit movf BitMask,W ; set ROM bit to value in Carry iorwf INDF,F ; set ROM bit (unconditionally) skpc ; is bit a '1'? yes, skip, else xorwf INDF,F ; clr ROM bit OwSendCarry ; send direction/qualifier bit rlf BitMask,W ; rlf BitMask,F ; increment rom array bit mask skpnc ; byte boundary? 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 ; update last discrepency movwf LastDiscrep ; a 0 value indicates end-of-list ; bsf BitMask,0 ; do "convert" (bit = 1 already) OwMatch OwReset ; reset all 1-wire devices OwWrite(OwMatchRom) ; send "match rom" command OwWriteBuffer ; send + print rom serial number Send232(' ') ; send char btfss BitMask,0 ; conversion complete? goto OwScratch ; yes, branch, else OwWrite(OwConvert) ; send "convert" command OwPowerBus ; power OW pin during conversion Send232(0x0D) ; send char (htab 0) bcf BitMask,0 ; indicate conversion complete goto OwMatch ; do "match rom" for OwScratch OwScratch OwWrite(OwReadScratch) ; send "read scratchpad" command movlw -9 ; movwf FSR ; use FSR as byte counter RdLoop OwReadByte ; read + print scratchpad byte incfsz FSR,F ; all 9 bytes read + printed? goto RdLoop ; no, branch, else Send232(0x0D) ; send char Send232(0x0A) ; send char goto OwSearchNext ; search and process next device ;****************************************************************** ; ; subroutines ; Ow.Reset movlw DataLow ; output a '0' tris GPIO ; movlw (750/4)-1 ; delay 750 usecs & release bus call Delay ; returns W = (548/4)-1 goto Delay ; delay 548 usecs Ow.WriteByte movwf OwByte ; store byte to write movlw 8 ; send 8 bits movwf BitCtr ; wrloop rrf OwByte,F ; move bit to carry call Ow.SendCarry ; send it decfsz BitCtr,F ; sent all bits goto wrloop ; no, so loop rrf OwByte,F ; leave OwByte intact retlw RomBuffer ; for OwSearch routine Ow.SendCarry movlw DataLow ; tris GPIO ; initiate write slot skpnc ; send 0 bit movlw DataHigh ; send 1 bit tris GPIO ; movlw 56/4 ; finish 60 usec slot Delay movwf temp ; decfsz temp,W ; goto Delay ; Release movlw DataHigh ; tris GPIO ; release data line retlw (548/4)-1 ; for Ow.Reset routine Ow.ReadBit movlw DataLow ; pull line low tris GPIO ; falling edge 0 usecs clrc ; assume bit = 0 1 usecs movlw DataHigh ; 2 usecs tris GPIO ; release line at 3 usecs movlw 3 ; delay 10 usecs movwf temp ; decfsz temp,F ; goto $-1 ; sample between 13-14 usecs btfsc DataBit ; a '0'? yes, skip (C=0), else setc ; indicate a '1' (C=1) goto Delay-1 ; delay 60 usecs Ow.ReadByte movlw 8 ; movwf BitCtr ; BitCtr = 8 rdloop call Ow.ReadBit ; returns C = bit rrf OwByte,F ; move Carry into byte decfsz BitCtr,F ; built a full byte? goto rdloop ; no, branch, else PutHex swapf OwByte,W ; print hi nybble call PutNybble ; movf OwByte,W ; print lo nybble PutNybble andlw 0x0F ; keep lower nibble movwf temp ; save for later movlw -10 ; test if greater addwf temp,W ; than 10 movlw "0" ; add "0" skpnc ; or, if greater than 10 movlw "0"+7 ; add "A"-10 addwf temp,W ; fall through to send it ; ; 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<