Dallas 1-wire asm code available?

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

Regards

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks you two!

Regards

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

Regards

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

Regards

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My example code for the ATTiny12:

http://www.mikrocontroller.net/a...

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

Regards