Код сборки Arduino Uno R3 для нажатия кнопки и включения светодиода
Я пытался это сделать уже несколько дней, но безуспешно...
Мне нужно включить светодиод на порте при нажатии кнопки в порте. Кабель работает, я тестировал его с помощью Arduino IDE, и он работает просто великолепно.
Вот что у меня получилось:
.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
С sbis
гораздо проще, если я все правильно понял...
#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
Но при компиляции я получил вот такую ошибку:
.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
@mcflurry, 👍3
1 ответ
Лучший ответ:
Эта строка:
ldi r18, 0b00100000 ;pushed button
не соответствует определению BUTTON
. Вы устанавливаете бит 5
регистре, тогда как кнопка находится на бите 3. Во избежание
такого рода ошибка, я бы лучше написал
ldi r18, _BV(BUTTON) ;pushed button
Тогда вот:
out BUTTON, r16 ;read button to r16
вы ничего не читаете: вы куда-то пишете. я думаю, вы имею в виду:
in r16, _SFR_IO_ADDR(PIND) ;read button to r16
Обратите внимание, что при этом считывается весь порт одновременно. Если вам интересно только в один момент, тогда вам следует
andi r16, _BV(BUTTON) ;keep only the relevant bit
перед сравнением.
И последнее: возможно, вам захочется прочитать о sbis
и sbic
инструкции: они могли бы упростить ваш код.
Обновлено: ответ на обновленный вопрос.
неопределенная ссылка на `portd'
Это потому, что не существует такого понятия, как «portd». Ты имеешь в виду
_SFR_IO_ADDR(PORTD)
. Ну нет, на самом деле вам следует использовать
_SFR_IO_ADDR(PIND)
, так как это регистр входного порта, тогда как
PORTD
— это выходной регистр.
Несколько дополнительных примечаний:
- Не помещайте код перед
main
: он не будет выполнен, так как C среда выполнения переходит кmain
после инициализации. - Инструкции
ldi r16, …
внутри основного цикла бесполезны: вы не используете этот регистр после инициализации программы.
- Как создать задержки на языке ассемблера AVR
- Запустить Timer1 в ATmega2560 со сборкой
- Как добавить два сборочных массива в arduino
- Сборка для цикла, повторяющегося 2 раза, хотя предполагается, что это нужно сделать только один раз
- Как установить регистр ПК (счетчик программ) на другую функцию (для планировщика)
- Atmega собирает и ретранслирует вызовы прерывания
- esp32, platformio A fatal error occurred: Packet content transfer stopped (received 8 bytes) *** [upload] Error 2
- В чем разница/связь между Arduino и AVR?