Does anyone have working sample code for communicating to a 1-wire interface. I need it for a memory but even the DS1820 would work. I see someone has talked about it using C code but I am looking for ASM examples.
Dallas 1-wire asm code available?
Download the Dallas example code from Dallas.. I seem to remeber that there was some example code in there for the AVR, and was all in assembly.
[edit]
Just checked... there indeed is a pure assembly example for the mega103 included in the public domain kit.
Thanks you two!
Thanks everyone. Dallas' Mega103 example is not clear. They are messing around with PortE.6 and PortE.7 which doesn't make sense when I look at PIC examples.
They are using port E.7 to drive a transistor (or some other drive circuitry), and using port E.6 to read the state of the one wire bus.
When PortE.7=1 the bus state will be pulled low, when PortE.7=0 the bus state will be pulled high.
It wouldn't take much to merge the two, and play with DDRE.7 instead.
Yeah, I figured that out later on. There's no need for the transistor depending on your situation. I just left portb.0 hi-z with a 2.2k pullup to VCC and viola!
I am either output driven low or hi-z and it's pulled up. It's working very nicel.
Dallas stinks for their documentation though. The pdf's are not clear.
Here's my routine for a DS2401 silicon serial number on a Mega128. There are three parts: reset and detect presence pulse, one byte command write (0x33 in this case) and 8 byte data read. It should be easy enough to split the sections out to do any one-wire operation.
scratch is R23, acc is R24. You need an external 4.7k pullup on the data line, port B.6 in this example
; Read DS2401 (one-wire) on PORTB.6 ; This takes about 8 milliseonds one_wire_read: cbi PORTB,6 ; port low sbi DDRB,6 ; output, data low ldi scratch,100 ; 500us low call ow_delay_count cbi DDRB,6 ; float data line call ow_delay_5 ; 5us to stabilize set ; set T flag ldi scratch,99 ; 500us wait and check data call ow_delay_count ; T flag is clear if presence pulse detected, set otherwise brtc owire0 sec ; error, return carry ret ; Send byte 33h, read_rom command, LSB first owire0: ldi scratch,0x08 ldi acc,0x33 owire1: push scratch sbi DDRB,6 ; assert data low call ow_delay_5 ; for 5us sbrc acc,0 ; if next LSB is high cbi DDRB,6 ; float the data line ldi scratch,15 ; wait 75us call ow_delay_count cbi DDRB,6 ; then float high anyway call ow_delay_5 ; for 5us lsr acc ; shift data pop scratch dec scratch brne owire1 ; Read 64 bits (8 bytes), save at Y++ ldi scratch,0x40 ; 64 bits ldi acc,0x80 ; stop bit in acc owire2: push scratch sbi DDRB,6 ; assert data low call ow_delay_5 ; for 5us cbi DDRB,6 ; float the data line call ow_delay_5 ; allow 5us to settle set ; set T flag call ow_delay_5 ; sample data this period lsr acc ; shift acc right bld acc,7 ; transfer data bit to MSB brcc owire3 ; stop bit to C on 8th shift st Y+,acc ; store byte ldi acc,0x80 ; reset stop bit owire3: ldi scratch,12 ; wait 60us call ow_delay_count pop scratch dec scratch brne owire2 clc ret ; Delay by 5*[scratch] us ; Return with T clear if port went low during the delay ow_delay_count: call ow_delay_5 dec scratch brne ow_delay_count ret ; Delay for 5us, clear T flag if data line is low ; We want 37 cycles for 7.3728M, 55 for 11.0592, 80 for 16M ow_delay_5: ; 4 for call push scratch ; 2 ; adjust for crystal speed .if XTAL7 ldi scratch,5 ; 1 set N .endif .if XTAL11 ldi scratch,9 .endif .if XTAL16 ldi scratch,14 .endif ow51: sbis PINB,6 ; N clt ; N dec scratch ; N brne ow51 ; 2N-1 pop scratch ; 2 ret ; 4
Thanks, I have my stuff working and it is actually pretty easy. Dallas 1-wire and I2C are two standards that are defined and used but not documented clearly with nice examples, etc.
I ended up translating PIC asm into AVR and it worked ;).
Here are the routines if anyone wants them:
.macro write_0 sbi ddrb, ds_pin ;2 .endmacro .macro hiz_1 cbi ddrb, ds_pin ;2 .endmacro ; Issue reset and check for presense ; Rst_DS: write_0 ; lower io line rcall d480us ; delay ~488us hiz_1 ;;- - - - - - - - - - - - -; rcall d70us ; delay ~70us clc ; clr CY sbis pinb, ds_pin ; if they pulled low, present sec ; else, set CY (present) ;- - - - - - - - - - - - -; rjmp d430us ; delay ~430us ; Rx from Dallas ; RxDS: ldi ix, 8 ;- RxLp: write_0 ; force the line low ;- rcall d7us ; delay 7us ;- hiz_1 ; "input" ;- rcall d2us rcall d2us ; wait 4us ;- in r0, pinb ror r0 ror a ; shift in lsb first ;- rcall d50us ; wait 50us ;- dec ix brne RxLp ;- - - - - - - - - - - - -; ret ; Tx to Dallas ; TxDS: ldi ix, 8 ; shift 8 bits ;- TxLp: write_0 ; force the line low ;- rcall d7us ; delay 7us ;- ror a ; shift a into CY brcc tx0 hiz_1 ; give a '1' ; ;- else do nothign and leave a '0' on the bus ; tx0: rcall d60us hiz_1 ; ;- rcall d2us dec ix brne TxLp ;- ror a ; fix shift so a_in = a_out ;- ret d2us: ret d7us: push a ldi a, 2 rjmp d480lp d50us: push a ldi a, 20 rjmp d480lp d60us: push a ldi a, 24 rjmp d480lp d70us: push a ldi a, 28 rjmp d480lp d430us: push a ldi a, 176 rjmp d480lp ; Delays ~502us including call+ret ; loop is 9 * 205 d480us: push a ;- ldi a, 205 d480lp: nop nop nop nop nop nop dec a brne d480lp ;- pop a ret