3

I've been trying this for days without success...

I need to turn on a LED on portb when a button in portd is pushed. Cabling works, I've tested it with Arduino IDE and it works like a charm.

This is what I got so far:

.global main
.equ LED, PB5
.equ BUTTON, PD3
main:
 ldi r22,0xff ;all bits in portb are output
 out _SFR_IO_ADDR(DDRB),r22 
 ldi r21,0x00 ;all bits in portd are input
 out _SFR_IO_ADDR(DDRD),r21
 ldi r19, 0b00000000 ;unpushed button
 ldi r18, 0b00100000 ;pushed button
 eor r16, r16
loop:
 out BUTTON, r16 ;read button to r16
 cp r16, r18 ;compare r16 with r19 (button on)
 cbi _SFR_IO_ADDR(PORTB),LED
 breq loop ;go back to loop
 sbi _SFR_IO_ADDR(PORTB),LED ;if z=1, turn led on turn led on
 rjmp loop ;back to loop

It is much easier with sbis, if I got it right...

#include <avr/io.h>
.equ LED, PB5
.global main
ldi r16,0xff
out _SFR_IO_ADDR(DDRB),r16
ldi r16,0x00
out _SFR_IO_ADDR(DDRD),r16
main:
 sbis portd, 3
 rjmp ledoff
 ldi r16,0xff
 sbi _SFR_IO_ADDR(PORTB),LED ; turn on led
 rjmp main
ledoff:
 ldi r16,0x00
 cbi _SFR_IO_ADDR(PORTB),LED ; turn off led
 rjmp main

But I got this error compiling:

.pio\build\uno\src\main.o: In function `main':
(.text+0x8): undefined reference to `portd'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\uno\firmware.elf] Error 1
asked Jun 16, 2023 at 17:46
0

1 Answer 1

5

This line:

 ldi r18, 0b00100000 ;pushed button

does not match the definition of BUTTON. You are setting bit 5 of the register, whereas the button is on bit 3. In order to avoid this kind of error, I would rather write

 ldi r18, _BV(BUTTON) ;pushed button

Then, here:

 out BUTTON, r16 ;read button to r16

you are not reading anything: you are writing somewhere. I guess you mean:

 in r16, _SFR_IO_ADDR(PIND) ;read button to r16

Note that this reads the whole port at once. If you are only interested in one bit, you should then

 andi r16, _BV(BUTTON) ;keep only the relevant bit

before the comparison.

One last thing: you may want to read about the sbis and sbic instructions: they could simplify the code you have here.


Edit: answering the updated question.

undefined reference to `portd'

This is because there is no such thing as "portd". You mean _SFR_IO_ADDR(PORTD). Well, no, you should actually use _SFR_IO_ADDR(PIND), as this is the port input register, whereas PORTD is the output register.

A couple of extra notes:

  • Do not put code before main: it will not be executed, as the C runtime jumps to main after its initialization.
  • The instructions ldi r16, ... within the main loop serve no purpose: you are not using this register after the program initialization.
answered Jun 16, 2023 at 19:11

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.