Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Использование команды ijmp
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
Sprite
Доброго времени суток, товарищи! Программирую я на atmega8535.
Задача такая:
Имеется промежуток времени - 1000 тактов. Через время t [~0;1000] должно наступить событие S(скажем должен податься уровень 1 на ногу PB7) с точностью до 1 такта. Вначале промежутка время события t известно. Наступление этого события требуется сгенерировать программно, не используя какие-либо прерывания.
По логике вещей нужно после преобразования значения t в значение счетчика декрементировать его до наступления этого события, т.е. примерно так:
Код
        ldi    R16,    200   ; Считаем, что 200  - уже преобразованное значение счетчика, соответствующее t = 800
Decrement:
        dec R16    ; Вычитаем 1
        cpi R16,    0; Сравниваем с 0
        brne Decrement; Перейти если не равно 0    

                                sbi  PORTB,   7          ; Событие S - подаем уровень 1 на ногу PB7

Все бы хорошо, но вышеописанный подход позволяет генерировать событие S через время t кратное 4, т.е. 16, 20, 24 и т.д., поскольку код в операциях dec, cpi и brne занимает 4 тактаsad.gif А как быть если t = 513? Добить NOP-ами просто не получится, поскольку t постоянно меняется каждые 1000 тактов. Товарищ посоветовал использовать команду ijmp, но как ей пользоваться я не разобрался.
Помогите!
aaarrr
Забейте 1000 nop'ов и используйте ijmp.
Палыч
Цитата(Sprite @ Jul 13 2008, 19:45) *
...позволяет генерировать событие S через время t кратное 4, т.е. 16, 20, 24 и т.д., поскольку код в операциях dec, cpi и brne занимает 4 такта. А как быть если t = 513? Добить NOP-ами просто не получится, поскольку t постоянно меняется каждые 1000 тактов. Товарищ посоветовал использовать команду ijmp

Команда cpi в Вашем примере - явно лишняя (команда dec сама устанавливает флаг z), поэтому время - кратно 3. Можно, конечно, поставить много-много nop'ов подряд и переходить на нужный командой ijmp (как посоветовал aaarrr), а можно модифицировать ваш цикл (добавить nop'ы)

Код
Decrement_2: nop
Decrement_1: nop
Decrement: dec R16
      brne Decrement

При одном и том же значении r16, переход на Decrement_1 даст на 1 такт задержку больше чем переход на Decrement, а, переход на Decrement_2 - на два такта.
ReAl
Цитата(Палыч @ Jul 14 2008, 10:35) *
Код
Decrement_2: nop
Decrement_1: nop
Decrement: dec R16
      brne Decrement

При одном и том же значении r16, переход на Decrement_1 даст на 1 такт задержку больше чем переход на Decrement, а, переход на Decrement_2 - на два такта.
Да, именно так.
Только тут на 3 делить надо и максимальное время задержки меньше заявленной тысячи тактов.
Если использовать пару R25:R24, то увеличивается максимальная задержка и естественным образом цикл становится 4 такта, легче вычислять счётчик. Что-то в духе:
Код
; тут в r25:r24 время в тактах на задержку, 17..65536
; r17:r16 рабочие
    sbiw    r24, 14; 2; накладные расходы на организацию процесса
    movw    r16,r24; 1;
    lsrw    r24; 2;
    lsrw    r24; 2;
    andi    r16, 0x03; 1;
    clr    r17; 1;
    ldiw    ZL, pm(delay); 2;
    subw    r30,r16; 2;
    ijmp    ; 2;
    nop
    nop
    nop
delay:
    sbiw  r24, 1
    brne delay

макросы lsrw, ldiw, subw считаю очевидными :-)
Sprite
Цитата(Палыч @ Jul 14 2008, 14:35) *
Команда cpi в Вашем примере - явно лишняя (команда dec сама устанавливает флаг z), поэтому время - кратно 3. Можно, конечно, поставить много-много nop'ов подряд и переходить на нужный командой ijmp (как посоветовал aaarrr), а можно модифицировать ваш цикл (добавить nop'ы)

Код
Decrement_2: nop
Decrement_1: nop
Decrement: dec R16
      brne Decrement

При одном и том же значении r16, переход на Decrement_1 даст на 1 такт задержку больше чем переход на Decrement, а, переход на Decrement_2 - на два такта.


Спасибо, обязательно попробую.
Палыч
Цитата(ReAl @ Jul 14 2008, 14:09) *
Если использовать пару R25:R24, то увеличивается максимальная задержка и естественным образом цикл становится 4 такта, легче вычислять счётчик. Что-то в духе:
Код
delay:
    sbiw  r24, 1
    brne delay

макросы lsrw, ldiw, subw считаю очевидными :-)
Последнюю команду (brne) необходимо заменить на brnew smile.gif (а, иначе оно и работать не будет). Но, как демонстрация использования ijmp, Ваш пример - самое то.
aaarrr
Цитата(Палыч @ Jul 14 2008, 16:50) *
Последнюю команду (brne) необходимо заменить на brnew smile.gif (а, иначе оно и работать не будет).

Это шутка? sbiw ставит флаг Z.
Палыч
Цитата(aaarrr @ Jul 14 2008, 15:54) *
Это шутка? sbiw ставит флаг Z.
Конечно - шутка (я, и смайлик соответствующий поставил). Просто в первый раз вижу как активно используются макросы типа lsrw, ldiw, subw (сам пишу соответствующую пару команд). Автор вопроса, наверное, - новичок (судя по названию подфорума) - может и не понять сути макросов.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.