Сборка для цикла, повторяющегося 2 раза, хотя предполагается, что это нужно сделать только один раз
Я программирую Arduino Nano, поэтому считаю, что этот вопрос подходит для этого SE.
Я пытаюсь уменьшить яркость светодиода с помощью цикла for в сборке AVR.
Моя проблема в том, что цикл повторяется дважды перед завершением, хотя предполагается, что он закончится после первого цикла.
Цикл — это когда red_loop
повторяется 256 раз (чтобы затемнить светодиод). В этот момент значение должно переполниться, в результате чего переменная вернется к 0. Код должен остановиться на этом, но загадочным образом он выполняет еще один цикл, а затем останавливается.
Кто-нибудь знает почему?
Вот мой код:
.org 0x000
ldi r16, 0b111
out ddrb, r16
ldi r16, 0xff
out portb, r16
ldi r16, 0
; ff00 pin
; ff01 value
; ff02 led
ldi r16, 0b000
sts $ff00, r16
ldi r16, 0
sts $ff01, r16
red:
ldi r16, 0b001
sts $ff00, r16
red_loop:
rcall pwm
lds r16, $ff01
inc r16
sts $ff01, r16
cpi r16, 0
brne red_loop
end:
rjmp end
pwm:
ldi r24, 190
pwm_pre_loop:
ldi r17, 0
pwm_loop:
lds r16, $ff01
cp r17, r16
brge off
cp r17, r16
brlo on
pwm_loop_check:
inc r17
cpi r17, 0
brne pwm_loop
inc r24
cpi r24, 0
brne pwm_pre_loop
ret
on:
lds r16, $ff00
sbrc r16, 0
cbi portb, 0
sbrc r16, 1
cbi portb, 1
sbrc r16, 2
cbi portb, 2
rjmp pwm_loop_check
off:
lds r16, $ff00
sbrc r16, 0
sbi portb, 0
sbrc r16, 1
sbi portb, 1
sbrc r16, 2
sbi portb, 2
rjmp pwm_loop_check
@Dat Ha, 👍1
Обсуждение1 ответ
Лучший ответ:
Проблема в том, что регистр r17
, который вы используете в качестве тайминга ШИМ,
Ramp, переполняется дважды каждый раз, когда вы вводите pwm_pre_loop
:
- когда вы увеличиваете его больше 127, оно переполняется до −128.
- когда вы увеличиваете его больше 255, оно переполняется до 0.
При использовании счетчика так, как вы используете здесь r17
, у вас обычно есть
он переполняется только один раз за цикл: либо вы считаете, что он содержит знак
число, которое переполняется от 127 до −128, или вы считаете, что оно содержит
беззнаковое число, которое переполняется от 255 до 0. Я думаю, последнее
чаще. Ваш код не понимает подписи этого регистра:
Инструкция
brge
(названная «Перейти, если больше или равно (подписано)» в в таблице набора команд) проверяет битS
(знаковый флаг) регистр состояния, который полезен для подписанных сравнений.Инструкция
brlo
(«Перейти, если меньше (без знака)») проверяет перенос флаг, который используется для сравнений без знака.
Следует один раз определиться с подписанностью счетчика, а затем использовать его
последовательно. Поскольку здесь беззнаковый имеет больше смысла, вы можете просто заменить
brge
от brsh
(«Перейти, если то же самое или выше (без знака)»).
Или еще лучше, удалите второй тест, он лишний:
pwm_loop:
lds r16, value
cp r17, r16
brsh off ; if (r17 >= r16) goto off;
rjmp on ; else goto on;
Обратите внимание, что вы можете давать имена переменным оперативной памяти. И вы можете использовать некоторые другие доступные регистры вместо ОЗУ.
- Как создать задержки на языке ассемблера AVR
- Запустить Timer1 в ATmega2560 со сборкой
- Как добавить два сборочных массива в arduino
- Код сборки Arduino Uno R3 для нажатия кнопки и включения светодиода
- Как установить регистр ПК (счетчик программ) на другую функцию (для планировщика)
- Atmega собирает и ретранслирует вызовы прерывания
- В чем разница/связь между Arduino и AVR?
- Разные и самые быстрые способы вычисления синусов и косинусов в Arduino
вы не сказали, что означает
cycle
, поэтому я предполагаю, что это означаетred_loop
..... вы уверены, что red_loop повторяется только два раза?.... я не очень знаком с инструкциями по сборке avr, но похоже, что red_loop повторяется гораздо больше двух раз, @jsotolaСборка AVR - это не Arduino, @Juraj
Что это за ардуино? Если у вас нет памяти вроде 64 КБ,
$ff00
будет вне диапазона., @Edgar BonetЯ предлагаю переписать этот код на C и взглянуть на ассемблерный вывод компилятора в качестве справочного материала. Кроме того, возможно, было бы неплохо передать это в симулятор. Например, http://www.avr-asm-tutorial.net/avr_sim/index_en.html., @ex-punctis
@jsotola цикл — это когда
red_loop
повторяется 256 раз. После этого значение переполнится, что приведет к тому, что значение будет равно 0. В этот момент. Это должно прекратиться, @Dat Ha@Juraj Я программирую Arduino Nano, поэтому этот вопрос должен быть квалифицирован для этого сайта., @Dat Ha
@ЭдгарБонет. Удивительно, но я могу без проблем писать в
$ff00
. Теперь, когда я об этом думаю, немного странно, что это вообще возможно..., @Dat HaАдрес будет просто «зацикливаться», а старшие биты будут отброшены., @Majenko
SRAM начинается с адреса 0x100 — вы должны использовать его в качестве базы для доступа к памяти., @Majenko
Чтобы облегчить себе задачу, вам следует определить свои переменные в
.DSEG
, чтобы вам не приходилось беспокоиться об адресах. (и не забудьте убедиться, что ваш код находится в формате.CSEG
...), @Majenkoвы уверены, что red_loop запускается дважды? .... как вы это определяете?, @jsotola
@jsotola red_loop на самом деле выполняется 512 раз (2 раза по 256). Я хочу, чтобы он запускался только 256 раз. Я знаю это, потому что у меня есть светодиод, подключенный к нему, и предполагается, что он постепенно загорится только один раз. Но вместо этого он один раз постепенно загорается, затем гаснет и повторяет это снова. Потом это прекращается., @Dat Ha
все может быть не так, как вы думаете..... возможно, светодиод циклически переключается на 128 шагов, @jsotola