A non-working program is boggling my mind

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

Hello all.

I am somewhat of a newbie at programming AVR’s, I am currently in school for electrical engineering. In an effort to become better at programming I decided to start writing a simple program every couple days or so for practice.

This is my third one, it is supposed to be a game where you try to stop the light by pressing the button that is currently lit up. I am having a problem I have no idea how to deal with at the moment. Even removing all the tests for button press conditions it still does not work. The below program runs perfectly on the AVR Studio simulator but it only completes all the left shift operations and than appears to stop. The only thing I can think of is that my carry is getting modified to a 1 when it should stay 0. I have not tested this by saving the SREG simply because I do not know the point in which I should save it.

4Mhz clock on the STK 500

.include "m16def.inc"
.def rmp = R16
.org 0x0000
rjmp Reset

.org 0x002A
Reset:
ldi rmp, high(RAMEND)
out SPH, rmp
ldi rmp, low(RAMEND)
out SPL, rmp

ser rmp
out DDRB, rmp

ldi rmp, 0xFE
out PortB, rmp

sec

Left:
rcall Delay

rol rmp
out PortB, rmp

brcc Right

rjmp Left

Right:
rcall Delay

ror rmp
out Portb, rmp

brcc Left

rjmp Right

Delay:
clr r24
clr r25
DelayLoop:
adiw r24, 1
brne DelayLoop
ret

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

You do a set carry instruction then call the delay, this will leave the carry cleared.

Keep it simple it will not bite as hard

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

I have a slightly different take on the problem. I am also new to AVRs, so looking at your code is helping me get used to AVR assembly.

Because your delay routine always overflows the 16 bit register pair, delay always returns with the Zero and Carry flags set (when ADIW increments to zero, it also overflows setting Carry). Your left: routine ROL puts the Carry in the r16 LSB, filling r16's LSB with one values, one shift at a time. When the original r16 LSB zero value finally gets shifted into the Carry, you go the the right: routine and call delay, which immediately sets the carry bit to 1. Now all 8 r16 bits and the Carry are all one values. So, the BRCC left branch can never happen. End of game.

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

I gave it some more thought. Pick an unused general purpose register and save SREG in it as soon as you enter the delay routine. Then restore SREG just before the return instruction. That will protect the carry flag and your program should start working.

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

Thanks for the help

However I did end up solving the problem myself. I did not think my delay routine was affecting the carry flag in my program because it was working fine on the simulator. I forgot one habit of mine though, I usually comment out my delay calls during simulation because I do not like the couple second wait it causes when you step through them.

I fixed the problem by throwing the SREG into the stack, however I found out I cannot simply use push SREG to save it like the in the 8051. This seems odd that I first must throw it into a general purpose register than onto the stack.