ATTiny85 assembly code noobe problem

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

Please help, this code doesn't work.

Using the ADC to give me a 8 bit value, left justified so the result is in ADCH
This value is placed into a delay subroutine.

I send out a 2 ms pulse, null delay for the ADC value stored, then decrement the stored ADCH value by one and send out another pulse.

When it reaches a value of 3 I increment the ADCH stored value back up to it's max value.

When at max I re-read the ADC and store the new number.

A simple sweep of a 2 ms pulse that gets closer and farther away, the speed of this sweep adjusted with the ADCH value.

Here is my code, why do I only get a 2 ms pulse spaced 500 ms apart no matter where I set the ADC DC voltage level?

The code shows futile attempts at renaming defined values back to their register numbers to see if that was the problem.

;
;****************************
; AFTER ONE SWEEP ALL VALUES
; ARE RELOADED
;****************************
;
MAIN_J:
	rcall READ_ADC			;read input voltage and store as a 8 bit value at ADCH
	ldi r20, ADCH			;set the top limit
	ldi r24, ADCH			;store same value to compare later (TOP_COMPARE)
;
;
;
;*******************
; DO THE PULSE SWEEP
;*******************
;
DO_SPEED_UP:
;
	rcall MOSFETON			;turn MOSFET driving load on
;
	sbis pinb, 2			;(Skip next instruction If port is 5V) is the switch off?
	rjmp SWCK1				;no it is on, do switch routine
;
;
TEST_TOP1:
;
	ldi TEMP, 3				;see if TOPSET (r20) is at fastest sweep speed
	cp r20, TEMP			;time to sweep back up to TOPSET
	breq DO_SLOW_DOWN
	dec r20
	rcall PULSE_GEN
	rcall DELAY_TOP
	rjmp DO_SPEED_UP			;no match, continue increasing sweep speed
;
;
;
DO_SLOW_DOWN:
;
	rcall MOSFETON
;
	sbis pinb, 2			;(Skip next instruction If port is 5V) is the switch off?
	rjmp SWCK1				;no it is on, do switch routine
;
;
TEST_TOP2:
;
	mov TEMP, R24			;r16  << r24 see if TOPSET is at ADC value, slowest sweep speed
	cp r20, TEMP
	breq MAIN_J 			;limits match, read ADC again
	inc r20
	rcall PULSE_GEN
	rcall DELAY_TOP
	rjmp DO_SLOW_DOWN		;no match, continue increasing sweep speed
;
;
PULSE_GEN:
;
	cbi PORTB, PWM			;pulse goes low, turning on the opto triac
	rcall DELAY1			;1 ms delay
	rcall DELAY1			;** for a wider pulse add more delays **
	sbi PORTB, PWM			;pulse goes hi
	ret
;
;
;
;===================================
;READ THE ADC INPUT AND CONVERT TO
;A 8 BIT VALUE. 00000000 = 0V
;11111111 = 5v
;RESULTS ARE AUTOMATICALLY STORED
;IN ADCH REGISTER
;===================================
;
;
READ_ADC:
	sbi ADCSRA, ADSC  		;start conversion ADSC to 1 (zeros when done)
loopX:   
	sbic ADCSRA, ADSC  		;ADSC bit goes low when conversion complete
 	rjmp loopX         		;not complete, keep checking
	ret
;
;
;
;
DELAY_TOP:
	ldi r26,8			;load 16 bit counter
	mov r27,r20			;load TOPSET value into timer
;
delt:
	sbiw r27:r26,1		;decrement 16 bit counter by one
	brne delt
	ret
;
;======================
;1MS DELAY SUBROUTINE
;======================
;
DELAY1:
	ldi r26,8			;load 16 bit counter
	ldi r27,1
;
del0:
	sbiw r27:r26,1		;decrement 16 bit counter by one
	brne del0
	ret
;
;
;

BADBAUD

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

Quote:

ldi r20, ADCH ;set the top limit
ldi r24, ADCH ;store same value to compare later

Why read twice? I'd read once then MOV.

The code calls a MOSFETON: function that is not shown.

Similarly there's mention of SWCK1: without showing it.

The decision to go there is based on PINB input - how can we know whether it takes that path or not?

The key thing determining whether the inter pulse gap is 500ms or whatever would appear to be R20 on entry to DELAY_TOP: so I'd be doing something to observe what is in that register. Maybe store the value to successive EERPOM locations each time DELAY_TOP is called and then read out after with ISP and see whether it has values you expect?

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

Both ldi r20/r24 ADCH read whatever else but not ADCH. Guess why :lol:

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.

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

Oh God bless your eyesight!

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

What concerned me was if I was actually creating a 8 bit ADC value so I used the following subroutine and read the EEPROM value with my programmer to verify a voltage to 8 bit value relationship.

;
;***************************************
; A SOFTWARE TEST TO ALLOW VIEWING 
; OF THE ADC 8 BIT RESULT IN THE EEPROM
; "rjmp TEST_ADC" USED
;***************************************
;
;**** TEST ****
TEST_ADC:
	rcall READ_ADC
	in TO_EE_0, ADCH		;r21   <<  r16
	rcall EEPROM_write		;store the number at location 00 of the EEPROM
NULLWAIT:
	rcall DELAY10
	rjmp NULLWAIT
;**** TEST ****

This does not use r20 or r24.

But I had assumed a register was a register.

What's different about those two?

BADBAUD

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

LDI loads a constant value to a general purpose register. In your case LDI R20,ADCH loads a value of 5 to R20 (5 is an ADCH i/o address as defined in tn85def.inc header file). To read the ADCH (or whatever else i/o register - timer, port etc.) contents you need to use the IN R20,ADCH instruction.

Go read the datasheet and instruction set document.

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.

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

Thanks, that one has bit me in the arse in the past. Just need more practice.

BADBAUD