Hablar por un autobús de 1 cable puede ser doloroso. Ya sea que esté hablando con 1 sensor o 100, deberá pensar en el tiempo. Escribí un código para el DS18B20 hace unos años, pero está en la Asamblea. Si es de alguna utilidad, aquí:
;***************************************************************
;Title: Temperature Logger
;Description: Polls temperature every two seconds and returns a value
; in degC as well as the slope (rising, falling, steady)
;***************************************************************
Screen EQU $F684
;System Equates
PortA EQU $0000
DDRA EQU $0002
;Program Equates
TxPin EQU %00000001
RxPin EQU %00000010
IntPin EQU %10000000
;Commands
SkipROM EQU $CC
Convert EQU $44
ReadPad EQU $BE
;Constants
ASCII_0 EQU 48
Poll_D EQU 2000
;Macros
TxOn macro ; Send the 1-wire line Low
MOVB #TxPin,DDRA
MOVB #$00,PortA
endm
TxOff macro ;Releases the 1-wire line letting it return to High.
MOVB #$00,DDRA
endm
;-------------------------------------
;Main
;-------------------------------------
ORG $0D00
; Clear registers and initialise ports
Start: MOVB #$00, DDRA
Main: LDD #$00
JSR Init
LDAA #SkipROM
JSR Write
LDAA #Convert
JSR Write
JSR Wait
JSR Init
LDAA #SkipROM
JSR Write
LDAA #ReadPad
JSR Write
JSR Read ; read first 8 bits
TFR A, B
JSR Read ; read second 8 bits
; Convert bytes to BCD
LSRB
LSRB
LSRB
LSRB
STD TempNew
PSHA
PSHB
LDAB #6
MUL
TBA
PULB
ABA
CLRB
Conv_Lp:SUBA #10
BMI Conv_Dn
INCB
BRA Conv_Lp
Conv_Dn:ADDA #10
TFR A, Y
PULA
ABA
TFR Y, B
; convert BCD bytes to ASCII and store in temp register
LDX #Temp
ADDA #ASCII_0
STAA 0, X
INX
ADDB #ASCII_0
STAB 0, X
LDX #OutUp ; print 'The current temp is '
JSR Echo
LDX #Temp ; print ASCII bytes
JSR Echo
; compare stored temp with previously stored and print 'rising', 'falling' or 'steady'
LDD TempNew
SUBD TempOld
BGT Rising
BEQ Same
LDX #Fall
BRA EchDir
Rising: LDX #Rise
BRA EchDir
Same: LDX #Steady
EchDir: JSR Echo
; wait 2 seconds
LDX #Poll_D
Bla_Lp: JSR Del1ms
DBNE X, Bla_Lp
; set new temp as old temp and loop
LDD TempNew
STD TempOld
JMP Main
SWI
;-------------------------------------
;Subroutines
;-------------------------------------
Init: TxOn ; turn pin on
uDelay 500 ; for 480us
TxOff ; turn pin off
uDelay 70 ; wait 100us before reading presence pulse
JSR Wait
RTS
Wait: LDX #120
Wait_Lp:JSR Del1ms
DBNE X, Wait_Lp
RTS
Write: PSHX
PSHA
LDX #8 ; 8 bits in a byte
Wr_Loop:BITA #%00000001
BNE Wr_S1 ; bit is set, send a 1
BEQ Wr_S0 ; bit is clear, send a 0
Wr_Cont:LSRA ; shift input byte
uDelay 100
DBNE X, Wr_Loop ; shifted < 8 times? loop else end
BRA Wr_End
Wr_S1: TxOn ; on for 6, off for 64
uDelay 6
TxOff
uDelay 64
BRA Wr_Cont
Wr_S0: TxOn ; on for 60, off for 10
uDelay 60
TxOff
uDelay 10
BRA Wr_Cont
Wr_End: PULA
PULX
RTS
Read: PSHB
LDAB #%00000001
CLRA
Rd_Loop:TxOn ; on for 6, off for 10
uDelay 6
TxOff
uDelay 10
BRSET PortA, #RxPin, Rd_Sub1 ; high? add current bit to output byte
Rd_Cont:uDelay 155 ; delay and shift.. 0? shifted 8 times, end
LSLB
BNE Rd_Loop
BRA Rd_End
Rd_Sub1:ABA
BRA Rd_Cont
Rd_End: PULB
RTS
uDelay macro ;Delay a mutliple of 1us (works exactly for elays > 1us)
PSHD
LDD #\1
SUBD #1
LSLD
\@LOOP NOP
DBNE D, \@LOOP
PULD
endm
;-------------------------------------
;General Functions
;-------------------------------------
; delays
Del1us: RTS
Del1ms: PSHA
LDAA #252
Del_ms: JSR Del1us
JSR Del1us
JSR Del1us
CMPA $0000
CMPA $0000
NOP
DECA
BNE Del_ms
CMPA $0000
NOP
PULA
RTS
; display text from address of X to \0
Echo: PSHY
PSHB
LDAB 0, X
Ech_Lp: LDY Screen
JSR 0, Y
INX
LDAB 0, X
CMPB #0
BNE Ech_Lp
PULB
PULY
RTS
Interrupt:
SWI
RTI
;-------------------------------------
;Variables
;-------------------------------------
ORG $0800
OutUp: DC.B 'The current temperature is ', 0
Rise: DC.B ' and Rising', $0D, $0A, 0
Steady: DC.B ' and Steady', $0D, $0A, 0
Fall: DC.B ' and Falling', $0D, $0A, 0
Temp: DS 2
DC.B 0
TempOld:DS 2
TempNew:DS 2