2
\$\begingroup\$

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 :D

\$\endgroup\$
  • \$\begingroup\$ Why do your comments not match your code? \$\endgroup\$ – Ignacio Vazquez-Abrams Mar 2 '14 at 8:16
  • \$\begingroup\$ I thought they did. Can you point to what comment does not match? \$\endgroup\$ – DrOnline Mar 2 '14 at 10:47
  • \$\begingroup\$ in r18,PORTA0 ; Copies PINA0 to r18 \$\endgroup\$ – Ignacio Vazquez-Abrams Mar 2 '14 at 17:21
  • \$\begingroup\$ @IgnacioVazquez-Abrams Ah ok. Well you see I figured if a Port was '1', and the pin is for reading the value of the Port, then reading the Pin is equivalent with reading the Port. Am I wrong in this understanding? \$\endgroup\$ – DrOnline Mar 2 '14 at 19:05
1
\$\begingroup\$

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.

|improve this answer|||||
\$\endgroup\$
  • 1
    \$\begingroup\$ While writing to PINx like this may work by accident (since writing to PINx inverts the bits in PORTx), I agree that you should not do it this way. \$\endgroup\$ – Ignacio Vazquez-Abrams Mar 2 '14 at 8:23
  • 1
    \$\begingroup\$ @IgnacioVazquez-Abrams Added a related quote from the datasheet. \$\endgroup\$ – jippie Mar 2 '14 at 8:37
  • 1
    \$\begingroup\$ @DrOnline How do you know it doesn't work? Your code doesn't do anything useful after the brne \$\endgroup\$ – jippie Mar 2 '14 at 11:04
  • 1
    \$\begingroup\$ You have to read the whole byte from PORTA, then test bit0, for example with AND R18,0x01. You cannot read a single bit from a port directly. \$\endgroup\$ – jippie Mar 2 '14 at 15:48
  • 1
    \$\begingroup\$ An alternative for testing with AND are the SBRC and SBRS instructions. \$\endgroup\$ – jippie Mar 2 '14 at 16:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.