Electronic – ATmega2560 assembly pin read and compare logic problem

assemblyatmegaatmelatmel-studio

I apologize if my question was vague.

Program: Atmel Studio 6

I am trying to make a program that enters an loop which it will only break out of when a pin goes low.

;Set PA0 high before entering loop checking for low
CBI DDRA,DDA0       ;PA0 to input
SBI PINA0,0         ;PA0 pull-up enable
;PA0 is now input & high

chklow: inc r16     ; Increase r16
in r18,PORTA0       ; Copies PINA0 to r18
cpi r18,0           ; Compares r18 to 0
brne chklow         ; Branch if PA0 is not low
nop             ; Loop exit (do nothing)

What happens is that when I set PINA0, PORTA0 goes high. I guess this is good, it's like I pressed a button attached to PINA0.

Now I enter the loop, and I have my I/O view box up, so I see that PORTA0 is set. This is the rightmost box in PORTA.

But "in r18,PORTA" doesn't make r18 become '1'… it remains 0.

And so the Z-bit is set to 1 because the compare succeeded, and the branch doesn't occur.

What's wrong? I want the loop to continue indefinitely until I make PORTA0 low.

EDIT: I changed it now, using your advice:

CBI DDRA,DDA0           ;PA0 to input
SBI PORTA0,0            ;PA0 pull-up enable


chklow:
in r18,PORTA        ; Copies PINA0 to r18
cpi r18,0x00        ; Compares r18 to 0
brne chklow         ; Branch if PA0 is not low
nop             ; Loop exit (do nothing)

So what I changed was I copied the entire PORTA byte, instead of trying to copy the PORTA0 bit, which isn't possible (at least using my method), and now it works. Thanks 😉

Also, I know this is a dirty solution, because it fails if ANY bit in Pin A is set, but I can refine that later, this is a working prototype 😀

Best Answer

Couple things that make me frown:

SBI PINA0,0         ;PA0 pull-up enable

According to the datasheet:

Three I/O memory address locations are allocated for each port, one each for the Data Register – PORTx, Data Direction Register – DDRx, and the Port Input Pins – PINx. The Port Input Pins I/O location is read only, while the Data Register and the Data Direction Register are read/write. However, writing a logic one to a bit in the PINx Register, will result in a toggle in the corresponding bit in the Data Register. In addition, the Pull-up Disable – PUD bit in MCUCR disables the pull-up function for all pins in all ports when set.

To enable the pull-up you should write to PORTA not to PINA0. Also notice the difference PINA0 and PINA in your code. You cannot read a single bit from an IO port, you must read the whole byte. Then you can check one or more bits in the byte read using AND, SBRC or SBRS.

nop             ; Loop exit (do nothing)

Don't use nop to "do nothing", because the microcontroller will go forward to the next instruction in flash which can be anything, including an instruction from a previous program that was in flash if it wasn't overwritten. Anything can happen from there.