Двигаем! Бегущий огонек v1.2

Ура! Попытка №1 оптимизации программы прошла успешно. Теперь - попытка номер 2.
Посмотрите, как изменяется содержимое регистра Temp в процессе выполнения программы:
00000001
00000010
00000100
00001000
00010000
00100000
01000000
10000000

То есть, мы постоянно двигаем единичку влево. А нельзя ли как-нибудь сделать так, чтобы она "сама" двигалась влево?
Можно! А можно и вправо! Итак, две новые команды:
lsl - Logical Shift Left - логический сдвиг влево
lsr - Logical Shift Right - логический сдвиг вправо

Пример:
lsl Temp
lsr Temp

При этом, в освободившиеся биты вдвигаются нули
Значит, нам достаточно в начале записать в Temp число 00000001, а потом двигать его влево. Через семь сдвигов содержимое регистра будет равно 10000000. Если ничего не предпринять, то следующий сдвиг даст нам все нули. Нам же нужно, чтобы снова загорелся первый светодиод. Значит, надо снова загрузить в Temp начальное значение - 00000001.
А как узнать о том, что пройдено 7 сдвигов? Можно, конечно, написать команду lsl 7 раз, и после каждого раза вызывать задержку. Но мы уже делали примерно то же самое, только вместо сдвига грузили каждый раз новую константу. Нет! Надо сделать хитрее! Если хитрее - тогда надо писать цикл, содержащий в себе сдвиг и задержку. При этом, проверять значение Temp перед каждым сдвигом, и если оно равно 10000000, то сдвиг не делать, а грузить начальное значение.
А как проверить содержимое? А просто! Смотрим следующую команду:
cpi - ComPare register with Immediate - сравнить регистр с константой. В случае равенства результат операции считается нулевым.

Пример:
cpi Temp,0b00100011 - сравнение с двоичной константой
cpi Temp,0x23 - сравнение с шестнадцатеричной константой
cpi Temp,35 - сравнение с десятичной константой

По сути, сравнение - это вычитание из регистра константы. Если результат - ноль - значит они равны. Однако, при этом, содержимое регистра не теряется.
Давайте напишем цикл сдвига:
Init: ldi Temp,0b00000001 ;загрузка начального значения Shift: rcall Delay ;вызов п/п Delay(вывод+задержка) cpi Temp,0b10000000 ;сравнить Temp с крайним значением breq Init ;если равно - перейти на загрузку нач. значения lsl Temp ;иначе - сдвиг влево rjmp Shift ;перейти в начало цикла Shift Все понятно?
Ну тогда теперь сами допишите функцию Delay и прочие вещи, и посмотрите, что изменилось в выполнении программы.
Ничего не изменилось? Внимательно смотрите!
Все равно ничего?
Ну, все правильно - ничего и не должно было поменяться :) А между тем, код "полегчал" раз в 10 по сравнению с самой первой версией и в 2 раза по сравнению с предыдущей!
Думаете, это все? "Легче" уже некуда? Ан нет!!! Дальше я расскажу как сделать программку ЕЩЕ меньше :))).






Рекомендуемый контент




Copyright © 2010-2017 housea.ru. Контакты: info@housea.ru При использовании материалов веб-сайта Домашнее Радио, гиперссылка на источник обязательна.