I posted a kind of similar question recently, but it was not that organized, so here I am trying again :) I wrote this short assembly code to blink an LED at different intervals depending on the state a 2-pin dip switch. The code is working perfectly in simulation but in real world the controller is just stuck at mode1 and randomly visits other modes for a couple of cycles then go back to mode1 even through mode1 is supposed to blink nothing and just keep checking for changes on the DIP switch. Also I say strange behaviors as it works with C code with no problems, so I guess maybe it is not a hardware issue? please advice. here is my code:
.include "m32def.inc"
.cseg ; indicates that what follows is code
.org 0x00
.def delayMultiplier = r25
.def Mode = r31
ldi r21,LOW(RAMEND) ; initialize
out SPL,r21 ; stack pointer ;do not need to save r21
ldi r21,HIGH(RAMEND) ; to RAMEND
out SPH,r21 ; " ;do not need to save r21
ser r16
out DDRD, r16
clr r16
out PORTD, r16
out DDRB, r16
sbi PORTB, 0
sbi PORTB, 1
start:
clr r16
out PORTD, r16
in Mode, PINB ; Read PortB actual values in Mode
ldi r30, 0
cp Mode, r30 ; Subtract 0 from mode to compare with 0
breq mode3 ; if Sw == 00 jump to mode 3
ldi r30, 1
cp Mode, r30
breq mode2 ; if Sw == 01 jump to mode 2
ldi r30, 2
cp Mode, r30
breq mode1 ; if Sw == 10 jump to mode 1
ldi r30, 3
cp Mode, r30
breq start ; if Sw == 11 jump to mode 0
mode1:
sbi PORTD, 7
ldi delayMultiplier, 25
rcall delay
cbi PORTD, 7
ldi delayMultiplier, 25
rcall delay
rjmp start
mode2:
sbi PORTD, 7
ldi delayMultiplier, 100
rcall delay
cbi PORTD, 7
ldi delayMultiplier, 100
rcall delay
rjmp start
mode3:
sbi PORTD, 7
ldi delayMultiplier, 250
rcall delay
cbi PORTD, 7
ldi delayMultiplier, 250
rcall delay
rjmp start
.include "delay.asm"
here is delay sub routine:
.equ l1 = 20000
delay:
push r27
push r26
push r25
loop2:
ldi r26, LOW(l1)
ldi r27, HIGH(l1)
loop1:
sbiw r26, 1
brne loop1
dec delayMultiplier
brne loop2
pop r25
pop r26
pop r27
ret
and here is the schematic
Please be gentle I am kind of a beginner :)
UPDATE: I tried using a mask to read only bits 0, 1 from PINB and it worked for a while, but suddenly every thing stopped working and I went down to trying to blink an LED and it just do not work, here is the code:
.include "m32def.inc" ;load the ATmega32 directory which include rigsters' & bits' named and addresses
.cseg ; indicates that what follows is code
.org 0x00 ; indicates orgin address in flash to start
ldi r21,LOW(RAMEND) ; initialize
out SPL,r21 ; stack pointer ;do not need to save r21
ldi r21,HIGH(RAMEND) ; to RAMEND
out SPH,r21 ; " ;do not need to save r21
ser r16 ;
out DDRD, r16 ; Set PORTD as an ouput
start:
sbi PORTD, 7 ; turn on LED on PORTD pin7
ldi delayMultiplier, 100 ; do nothing for 1 sec
rcall delay
cbi PORTD, 7 ; turn off LED on PORTD pin7
ldi delayMultiplier, 100 ; do nothing for 1sec
rcall delay
rjmp start ; start over
.include "delay.asm"
I tried light another LED at other parts of the code to try and debug and found out that it stops working at the "ret" instruction in the first "delay" call, even though it works in simulation. and this C code (I suppose it does the same) thing works without a problem
#include <avr/io.h>
#define F_CPU 8000000L
#include <util/delay.h>
int main(void)
{
DDRD = 0xff;
while (1)
{
PORTD = (1<<7);
_delay_ms(1000);
PORTD = 0;
_delay_ms(1000);
}
}