|
Использование команды ijmp |
|
|
|
Jul 13 2008, 16:45
|

Частый гость
 
Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414

|
Доброго времени суток, товарищи! Программирую я на 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 такта  А как быть если t = 513? Добить NOP-ами просто не получится, поскольку t постоянно меняется каждые 1000 тактов. Товарищ посоветовал использовать команду ijmp, но как ей пользоваться я не разобрался. Помогите!
|
|
|
|
|
 |
Ответов
|
Jul 14 2008, 07:35
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(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 - на два такта.
|
|
|
|
|
Jul 14 2008, 11:09
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(Палыч @ 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 считаю очевидными :-)
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jul 14 2008, 12:50
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(ReAl @ Jul 14 2008, 14:09)  Если использовать пару R25:R24, то увеличивается максимальная задержка и естественным образом цикл становится 4 такта, легче вычислять счётчик. Что-то в духе: Код delay: sbiw r24, 1 brne delay макросы lsrw, ldiw, subw считаю очевидными :-) Последнюю команду (brne) необходимо заменить на brnew  (а, иначе оно и работать не будет). Но, как демонстрация использования ijmp, Ваш пример - самое то.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|