;******************************************************************
;* *
;* 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<<OW_Bit) - (1<<RS_Bit)
#define DataHigh b'11111111' - (1<<RS_Bit)
#define DataBit GPIO,OW_Bit
;--< global vars >-------------------------------------------------
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 <space> 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 <cr> 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 <cr> char
Send232(0x0A) ; send <lf> 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<<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 ;
end
estos son los registros a introducir en el banco 5
LastDiscrep ;registro de ultima discrepancia
LastZero
BitMask
BitIndex
OwTemp
CONT_ROMs ;contador de ROMs recibidas
las definiciones:
#define BANCO_GENERAL 0x05 ;banco donde se hucaran los registros generales (seleccionar el que precisemos)
#define BANCO_ROMs 0x04 ;banco donde se hubicaran las ROMs recibidas (seleccionar el que precisemos)
DS18B20_SEARCH_ROM EQU 0XF0 ;identificacion de todos los dispositivos conectados al bus
y las macros:
GENERAL_BANK MACRO
movlw BANCO_GENERAL ; selecciona el banco indicado en la abezera
movwf BSR ;conmuta el banco
ENDM
ROMs_BANK MACRO
movlw BANCO_ROMs ; selecciona el banco indicado en la abezera
movwf BSR ;conmuta el banco
ENDM
la llamada al programa:
GENERAL_BANK ;selecciona banco de registros generales
CALL SEARCH_ROM
y el programa:
;************************************************* SEARCH_ROM **********************************************************
;Busqueda de ROMs
SEARCH_ROM movlw BANCO_ROMs ;selecciona el banco indicado en la cabezera"banco donde hubicar las ROMs"
movwf FSR2H ;conmuta el indice de direccionamiento indirecto
clrf FSR2L ;borra FSR2L
clrf CONT_ROMs ;borra registro contador de ROMs encontradas
clrf LastDiscrep ;inicializa registro de ultima discrepancia
COP1 incf CONT_ROMs,f ;incrementa contador de ROMs encontradas
call INI_BITS ;inicializa registros de busqueda
call ROM_SEARCH ;comando de busqueda de ROMS
call GetBits ;inicia la busqueda de identidades
clrf WREG ;valor 0x00 para W
xorwf LastDiscrep,W ;comparalo con el registro de ultima discrepancia
btfss STATUS,Z ;si el registro es diferente a 0x00,
goto COP1 ;continua con la busqueda
return ;en caso contrario retorna
;*************************************************** INI_BITS *****************************************************************
INI_BITS clrf BitIndex ;inicializa registro BitIndex = 0
clrf LastZero ;inicializa registro LastZero = 0
movlw b'00000001' ;
movwf BitMask ; setup rom array bit mask
return
;************************************************* GetBits ********************************************************
;Lectura de los bits recibidos
;A=bit1 B=bit0
;AB=11 - ningun dispositivo presente
;AB=01 - todos los dispositivos en el bus tienen un 0 en la hubicacion del bit que se esta leyendo
;AB=10 - todos los dispositivos en el bus tienen un 1 en la hubicacion del bit que se esta leyendo
;AB=00 - algunos dispositivos en el bus
GetBits call OwReadBit ; lectura del primer bit(bit A)leido del sensor y que ha sido introducido en el carry
rlcf OwTemp,F ; desplaza el contenido del carry en OwTemp(bit A)
call OwReadBit ; lectura del segundo bit(bit B)(complemento)
rlcf OwTemp,W ; desplaza el contenido del carry en OwTemp(bit B) y dejas el resultado en W
rrcf OwTemp,F ; desplaza el bit A al carry
andlw 0x03 ; selecciona bit0 y bit1 resto borralos
xorlw 0x03 ; compara bit0 y bit1.
btfsc STATUS,Z ; y si los dos estan a 1, (AB=11)
return ; retorna al no responder ningun dispositivo.
xorlw 0x03 ; compara bit0 y bit1.
bnz SendRomBit ; AB="01 o 10" salta a SendRomBit
; AB="00" si hay algunos dispositivos en la linea,sige.en Discrepency.
Discrepency movf BitIndex,W ; 0..63
subwf LastDiscrep,W ; 0..63
bnc IndexGTLD ; si index > ultima discrepancia, usa '0'
bz SendRomBit ; index = ultima discrepcia, usa '1'
IndexLTLD ; index < ultima discrepancia, usar ROM
movf BitMask,W ; inserta BitMask en W
andwf INDF2,W ; esta el bit de la ROM a 0?
bnz SendRomBit ; no, branch with C = 1, else
bcf STATUS,C ; set C = 0 and
IndexGTLD movf BitIndex,W ; update 'LastZero'
movwf LastZero ;
SendRomBit movf BitMask,W ; set ROM bit to value in Carry
iorwf INDF2,F ; set ROM bit (unconditionally)
btfss STATUS,C ; is bit a '1'? yes, skip, else
xorwf INDF2,F ; clr ROM bit
salt1 call OwSendCarry ; send direction/qualifier bit
rlcf BitMask,W ;
rlcf BitMask,F ; increment rom array bit mask
btfsc STATUS,C ; byte boundary? no, skip, else
incf FSR2L,F ; bump RomBuffer array address
salt2 incf BitIndex,F ; incrementa el registro de bits
btfss BitIndex,6 ; si no se ha llegado al bit 64
goto GetBits ; continua el bucle
movf LastZero,W ; actualizar ultima discrepancia
movwf LastDiscrep ; si LastDiscrep es 0.se ha encontrado la ultima ROM
return ; retorna
OwReadBit call LINE_OUT ;linea como salida
bcf STATUS,C ;borra el carry
call LINE_IN ;linea como entrada
call DEMORA_10uS
btfsc PORTB,5 ;comprueba PB5
bsf STATUS,C ;y si esta a 1,setea el carry
movlw .8 ;retardo de 50uS
call DEMORA_uS ;llamada a retardo
call DEMORA_10uS
return
OwSendCarry call LINE_OUT ;linea como salida
btfsc STATUS,C ;borra el carry
call LINE_IN ;linea como entrada
movlw .8 ;retardo de 50uS
call DEMORA_uS ;llamada a retardo
call DEMORA_10uS ;retardo de 10uS
call LINE_IN ;linea como entrada
return
y librerias:
;**************************************************** ROM_SEARCH *************************************************************
;Busqueda de las ROMs (Identidades) de todos los dispositivos conectados en el bus.(varios dispositivos en el bus)
ROM_SEARCH call DS18B20_RESET ;resetea el sensor
movlw DS18B20_SEARCH_ROM
call WRITE_18B20 ;escribe el comando
return
;*********************************************** DS18b20_RESET ***************************************************
;reset del sensor
DS18B20_RESET
movlw 0xff ;valor para 255 ciclos
movwf CONT_RESET ;introducelo en el contador regresivo
call LINE_IN ;pin del pic como entrada
call LINE_OUT ;pin del pic como salida
call DEMORA_500uS ;retardo de 500uS (solicitud de escucha al 18B20)
call LINE_IN ;pin del pic como entrada(espera de respuesta del 18B20)
call DEMORA_20uS ;retardo para recibir la respusta
espera_lo dcfsnz CONT_RESET ;si no se ha recibido el present del DS18B20 antes de 255 ciclos,
return ;retorna
btfsc PortInOut ;espera a que el 18B20 mande estado bajo
goto espera_lo ;repite hasta que sea estado bajo
espera_hi btfss PortInOut ;espera a que el 18B20 mande estado alto
goto espera_hi ;repite hasta que sea estado alto
return ;retorna
;********************************************* WRITE_18B20 ********************************************************
;Envia el byte cargado en w al sensor.
WRITE_18B20 movwf DATO18B20 ;introduce el contenido del acumulador en el registro DATO18B20
movlw 0x08 ;carga en el acumulador la cantidad de bits a enviar
movwf CONT_BITS ;y metelo en el registro CONT_BITS
call LINE_IN ;pin del pic en modo entrada
send_bit call LINE_OUT ;pin del pic en modo salida
rrcf DATO18B20,F ;rota el registro
btfss STATUS,C ;comprueba si ha habido acarreo
call LINE_OUT ;si no lo ha habido salta a send_cero
btfsc STATUS,C
call LINE_IN ;en caso contrario envia un uno.
movlw .8 ;retardo de 50uS
call DEMORA_uS ;llamad a retardo
call LINE_IN ;flanco de subida
decfsz CONT_BITS,F ;decrementa el contador de bits.
goto send_bit ;repite hasta enviar los 8 bits
btfss PortInOut ;espera a que el 18B20 mande estado alto
goto $-2 ;repite hasta que sea estado alto
return ;retorna
;**************************************************** modo lectura*********************************************
LINE_IN bsf TrisInOut ;pin como entrada(alta impedancia)
return
;**************************************************** modo escritura*********************************************
LINE_OUT bcf TrisInOut
bcf PortInOut ;pin como salida
return