attiny84 can't escape subroutine...

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

I have an Attiny84 setup to control 4 external shift registers in series.

 

The hardware works and the program does for the most part, however when I call a subroutine from my main program it executes the subroutine but rather than returning to the next instruction it simply loops the subroutine over and over again. When I step through the code in the the atmel studio debugger (simulator) it doesn't do this though and rather acts as I anticipated the code to. Any ideas on what my issue may be?

 

I've tried to change the ret at the end of the subroutines to simply do a relative jump to the other subroutine and this didn't change anything the 1st subroutine called by the main program executes entirely but just loops over without ever jumping to the next subroutine.... 

 

I've tried changing which subroutine gets called first and it simply does the same thing with that subroutine, it executes entirely the way it should but then loops back to itself rather than going back to the  main program.


.NOLIST
.INCLUDE "tn84def.inc"
.LIST

.org 0x00

initialization:
		ldi r17, (1<<DDA3)|(1<<DDA4)|(1<<DDA5)	; setting up outputs on pins A3-A5, PA3 = latch, PA4 = shift clock, PA5 = DATA out
		out DDRA, r17
		ldi r21, 0x00	; zero compare register
		ldi r22, 0x09	; 8 bit counter +1
		ldi r16, 0x05   ; 4 byte counter +1
		; r17 - r20 are being dedicated to store the 32 bits for each sequence
Main:	
		rjmp Chaser
		rjmp Starburst
		rjmp Main

	Starburst:				; this pattern has 8 sequences being sent out to shift registers creating a starburst effect of the images
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x10		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay

		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x05		; Light grid C
		ldi r19, 0x11		; Light grid B
		ldi r20, 0x40		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay

		ldi r17, 0x01		; MSB Light grid D, these are the data bytes
		ldi r18, 0x15		; Light grid C
		ldi r19, 0x11		; Light grid B
		ldi r20, 0x51		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay

		ldi r17, 0x01		; MSB Light grid D, these are the data bytes
		ldi r18, 0x15		; Light grid C
		ldi r19, 0x01		; Light grid B
		ldi r20, 0x51		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay

		ldi r17, 0x01		; MSB Light grid D, these are the data bytes
		ldi r18, 0x10		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x11		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay

		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay

		ldi r17, 0xFF		; MSB Light grid D, these are the data bytes
		ldi r18, 0xff		; Light grid C
		ldi r19, 0xff		; Light grid B
		ldi r20, 0xff		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay

		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay			
		ret

	Chaser:					; this pattern has 28 sequences being sent out to the shift registers to create the effect of 1 moving image
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x01		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay		; need more functional loop
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x02		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x04		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x08		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x10		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x20		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x40		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x80		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x01		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x02		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x04		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x08		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x10		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x20		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x40		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x80		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x01		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x02		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x04		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x08		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x10		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x20		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x40		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x80		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0xFF		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0xFF		; MSB Light grid D, these are the data bytes
		ldi r18, 0xff		; Light grid C
		ldi r19, 0xff		; Light grid B
		ldi r20, 0xff		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ldi r17, 0x00		; MSB Light grid D, these are the data bytes
		ldi r18, 0x00		; Light grid C
		ldi r19, 0x00		; Light grid B
		ldi r20, 0x00		; Light grid A
		rcall Data_transfer
		rcall Latch_outputs
		rcall Delay
		ret

Data_transfer:
		dec r16			; start counting down total bytes 
		cp r16, r21		; if all 4 bytes have been sent execute final ret to sub routine in order to collect the next sequence of data
		brne Bit_send	
		ldi r16, 0x05	; resetting byte counter before returning to main program and grabbing new sequence of data
		ret
	Bit_send:
		dec r22			; remove 1 from the bit counter register
		cp r22, r21		; if all 8 bits have been sent execute the data shift  function
		breq Next_byte
		lsl r17			; shift msb into carry bit
		brcs Data_high	; if carry is set than a 1 shifted out of the data register r17 and the output pin should be set high
		cbi PORTA, PA5	; set data output low
		sbi PORTA, PA4	; set shift clock high
		out PORTA, r21	; clear data line and clock
		rjmp Bit_send	; start sending another bit
	Data_high:
		sbi PORTA, PA5	; set data output high
		sbi PORTA, PA4	; set shift clock high
		out PORTA, r21	; clear data line and clock
		rjmp Bit_send	; start sending another bit

Next_byte:
		ldi r22, 0x09		; this resets the 8 bit counter value
		cpi r16, 0x04		; after 1 pass on the byte counter skip the next command
		brne Byte_check3	; branch if this isnt the first pass
		mov r17, r18		; load contents from r18 into r17 moving bytes forward
		rjmp Data_transfer	; start another byte
	Byte_check3:			; at this point data from r18 has been sent out
		cpi r16, 0x03
		brne Byte_check2
		mov r17, r19
		rjmp Data_transfer
	Byte_check2:			; at this point data from r19 has been sent out
		cpi r16, 0x02
		brne Byte_check1
		mov r17, r20
		rjmp Data_transfer	;
	Byte_check1:			; at this point data from r20 has been sent out
		rjmp Data_transfer

Latch_outputs:
	sbi PORTA, PA3
	nop						; maybe needs delay here instead of NOP		
	cbi PORTA, PA3
	ret

Delay:
    ldi r23, 250    ; One clock cycle;
Delay1:
    ldi r24, 250   ; One clock cycle
Delay2:
    dec r24           ; One clock cycle
    nop                     ; One clock cycle
    brne Delay2          ; Two clock cycles for true 1 clock for false

    dec  r23            ; One clock Cycle
    BRNE Delay1          ; Two clock cycles for true 1 clock for false
    ret



 

This topic has a solution.
Last Edited: Sun. Jan 5, 2020 - 03:45 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you read this?? https://www.avrfreaks.net/forum/...

 

I'll move the thread.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

WHY are you using rjmp to call a subroutine??

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

I modified my code and added 2 pushbuttons to the circuit. now depending on which button I pressed I am able to run each sequence 1 time and return to the main program, this isn't what I am trying to do but I just wanted to make sure that it was something I did wrong in the software. I really must be not understanding something about the way the controller handles the program...

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

WHY have you failed to yet name your registers?...all it takes is accidentally typing r23 instead of r24 somewhere or doing  and r23, r24 when you meant to do and r24, r23.  ...now you have a bug that is almost IMPOSSIBLE to find.

 

.def tons_of_coal =r18

.def pump_seconds=r19

.def bath_gallons=r20

  

A slip of the keyboard (r18 instead of r19) and 200 sec pumping turns into a lot of coal!

 

You may want to set the spl: This Stack space in the data SRAM must be defined by the program before any subroutine calls are executed or interrupts are enabled. The Stack Pointer must be set to point above 0x60

This is taken from the part's datasheet, though for this part the datasheet also says it is automatically set to ram end!!  Since the datasheets are full of cut & paste errors , I'd just take 2 instructions and ensure it is set:

ldi temp, low(ramend)

out SPL, temp

 

 

this whole byte check 1 2 3 etc, is a big mess weaving it's way along.   Have ONE routine that sends a byte & returns

If you want to send five bytes, just rcall it 5 times in a row...no need for a counter & bunch of compares(is it 1 , is it 3, is it 4...)  to determine where to go all over the place

 

ldi val_2send, 100

rcall send_it_now   ;send 1st byte

ldi val_2send, 203

rcall send_it_now   ;send 2nd byte

ldi val_2send, 88

rcall send_it_now   ;send 3rd byte

  

or if the values are in some register , you do:

 

mov val_2send, number_one

rcall send_it_now   ;send 1st byte

mov val_2send, number_two

rcall send_it_now   ;send 2nd byte

mov val_2send, number_three

rcall send_it_now   ;send 3rd byte

 

If you had 200 numbers, this would become too lengthy & you'd use a table

 

Byte_check3:			; at this point data from r18 has been sent out
		cpi r16, 0x03
		brne Byte_check2
		mov r17, r19
		rjmp Data_transfer
	Byte_check2:			; at this point data from r19 has been sent out
		cpi r16, 0x02
		brne Byte_check1
		mov r17, r20
		rjmp Data_transfer	;
	Byte_check1:	

 

 

 

  

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Fri. Jan 3, 2020 - 09:43 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I really must be not understanding

Do you understand the difference between rjmp and rcall?

Main:	
		rjmp Chaser
		rjmp Starburst
		rjmp Main

as it is the program will ALWAYS go to the Chaser subroutine, when that returns the program will crash as the return address is random.

 

Probably you end up back to "initialization" eventually and the cycle repeats.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

To put it another way, rjmp  (or even jmp) does not return, and  it can't, since no return address is saved.  However, rcall (and call) saves the return address, so you can use a ret to go back to (really just after) where you came from. 
If you went back to exactly where you came from that would be bad, since that is the rcall & you'd endlessly bounce back & forth like pong.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

To put it in the context of the thread title... there is no escape from a subroutine you jumped into instead of called.

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

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

Well I suppose you could do some jiggery-pokery with what's on the stack before you jump there ;-)

 

Personally I wonder why write something this complex looking in Asm anyway, surely C would be easier (and it definitely knows how to setup to CALL!)

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

clawson wrote:

Well I suppose you could do some jiggery-pokery with what's on the stack before you jump there ;-)

 

Personally I wonder why write something this complex looking in Asm anyway, surely C would be easier (and it definitely knows how to setup to CALL!)

As unskilled as I am, I do enjoy learning assembly so that's why I am not interested in learning C. Thanks to JS and other posters however that point me in the right direction. I was mistaken on how to use rjmp and the calls. I took the advice from AVRcandies and others and changed my code a lot to make it easier to manage. It is working now on my chip within the circuit.

 

I'm sure there are better practices and ways to write the code which may be obvious to some of you but pointing those things out helps for me who is learning as a hobby. 

Below I post my code please comment. Thanks.

.NOLIST
.INCLUDE "tn84def.inc"
.LIST

 ldi r17, low(ramend)
 out SPL, r17
.def Pattern_length = r18
.def Zero = r21
.def Bit_count = r25
.def Byte_count = r16
.def Shift_complete = r22 
.def Data_out = r17


initialization:
		ldi r17, (1<<DDA3)|(1<<DDA4)|(1<<DDA5)	; setting up outputs on pins A3-A5, PA3 = latch, PA4 = shift clock, PA5 = DATA out
		out DDRA, r17
		ldi Zero, 0x00	; zero compare register
		ldi Bit_count, 0x09	; 8 bit counter +1
		ldi Byte_count, 0x04   ; 4 byte counter +1
		ldi Shift_complete, 0xff ; shift complete should be flagged to get into intial loading from pogram memeory

;=====================================  Main program =========================================================================

Main:

Pattern1_setup:
ldi Pattern_length, 0x05   ; pattern has 20 total bytes in memory. Latch occurs every 4 bytes so i divide total bytes by 4 and use this as the sequence counter
ldi ZH, high (2*Pattern_1)
ldi	ZL, low(2*Pattern_1)
rcall Run_pattern

Pattern2_setup:
ldi Pattern_length, 0x02  ; 8 unique bytes
ldi ZH, high (2*Pattern_2)
ldi ZL, low(2*Pattern_2)
rcall Run_pattern

Pattern3_setup:
ldi Pattern_length, 0xFF  ; there are 1.248Kbytes in total for this pattern 
ldi ZH, high (2*Pattern_2)
ldi ZL, low(2*Pattern_2)
rcall Run_pattern
ldi Pattern_length, 0x39
rcall Run_pattern
rjmp Pattern1_setup			; loop through the 3 patterns again

;====================================  Transfer functions ======================================================

Run_Pattern:
	lpm	Data_out, Z+
	rcall Data_transfer
	dec Byte_count
	cp Byte_count, Zero
	brne Run_pattern
	rcall Latch_out
	dec Pattern_length
	cp Pattern_length, Zero
	brne Run_pattern
	ret


Data_transfer:
		dec Bit_count			; remove 1 from the bit counter register
		cp Bit_count, Zero		; if all 8 bits have been sent execute the data shift  function
		brne Set_data
		ldi Bit_count, 0x09
		ret
		Set_data:
		lsl Data_out			; shift msb into carry bit
		brcs Data_high	; if carry is set than a 1 shifted out of the data register r17 and the output pin should be set high
		cbi PORTA, PA5	; set data output low
		sbi PORTA, PA4	; set shift clock high
		out PORTA, Zero	; clear data line and clock
		rjmp Data_transfer	; start sending another bit
	Data_high:
		sbi PORTA, PA5	; set data output high
		sbi PORTA, PA4	; set shift clock high
		out PORTA, Zero	; clear data line and clock
		rjmp Data_transfer	; start sending another bit
	
Latch_out:
		sbi PORTA, PA3
		nop						; maybe needs delay here instead of NOP		
		cbi PORTA, PA3
		rcall delay
		ldi Byte_count, 0x04
		ret

;=====================================  Delay =============================================================

Delay:
    ldi r23, 120    ; One clock cycle;
Delay1:
    ldi r24, 120 ; One clock cycle
Delay2:
    dec r24           ; One clock cycle
    nop                     ; One clock cycle
    brne Delay2          ; Two clock cycles for true 1 clock for false

    dec  r23            ; One clock Cycle
    BRNE Delay1          ; Two clock cycles for true 1 clock for false
    ret

;======================================== Data ============================================================
	Pattern_1:
		.db 0x85, 0x75, 0x10, 0x00
		.db 0x00, 0x05, 0x11, 0x40
		.db 0x01, 0x15, 0x11, 0x51 
		.db 0x01, 0x15, 0x01, 0x51
		.db 0x01, 0x10, 0x00, 0x11
	Pattern_2:
		.db 0x01, 0x55, 0x55, 0x55
		.db 0x00, 0xAA, 0xAA, 0xAA
	Patern_3:
		.db 0x00, 0x10, 0x00, 0x00
		.db 0x00, 0x20, 0x00, 0x00
		.db 0x00, 0x40, 0x00, 0x00
		.db 0x00, 0x80, 0x00, 0x00
		.db 0x01, 0x00, 0x00, 0x00
		  ; alot more data not shown
		.db 0x00, 0x08, 0x00, 0x00

 

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

Naming registers with global values makes sense, but naming for locals is confusing.  define some rules to pass variables to/from functions - ie R16 for a byte, R16/R17 for a word etc.  Have some rules for registers functions can destroy. If your function needs more registers, then it will need to push/pop the required registers to comply with the rules.

This will make your code more consistent and easier to scale up.

As your programs get larger, the need for naming registers disappears as you will most likely use ram variables and these get named. Having globals in registers works for small programs but becomes a hurdle for larger programs except if you need specific registers for critical speed related code.

 

	dec Bit_count			; remove 1 from the bit counter register
		cp Bit_count, Zero		; if all 8 bits have been sent execute the data shift  function
		brne Set_data
		ldi Bit_count, 0x09

This is a bit clunky. 

 

;
;
; Entry: byte in R16
; Zaps: R17
;
Data_transfer:
        ldi r17,8       ;R17 is the bit counter
dt_lp:
        lsl r16
        brcs dt_1       ;if data bit == 1

        cbi  PORTA,PA5   ;data bit = 0
        sjmp dt_2

dt_1:
        sbi PORTA,PA5    ;data bit = 1
dt_2:
        sbi PORTA,PA4    ;clk hi
        nop
        cbi PORTA,PA4    ;clk low
        dec r17
        brne dt_lp
        ret

 

Manage the byte count in a higher function.

Last Edited: Sun. Jan 5, 2020 - 09:08 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for the advice on how to better manage variables and global values it makes sense. I see what your doing with the modification you made. I don't see djnz as an instruction in the copy of the atmel instruction set I have. I assume that instruction decrements the register if its not 0 and jumps back. I do have a good amount of code I intend on adding to this program so I am sure to be back asking for input again soon.

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

It's been a while for me doing AVR asm - too long it seems. There isn't djnz instruction - I must've been having a 8051 flashback. You can use DEC R17 followed by BRNE to do the same thing.

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

I figured I could do it that way. Will give it a try tomorrow. A lot left for me to figure out and understand. There is something funky going on with my program, I have a feeling I'm not storing my data values in the correct spot in program memory or I'm not handling their addresses very well.

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

I found a defect in the code I posted above , so I've corrected it.