Массивы. Бегущий огонек v2.1
Автор: Сегодня мы заставим огонек не просто бегать слева направо, но и справа налево, из центра к краям и т.д. и т.п.
Можно конечно, поизвращавшись и просидев часик - другой за компом, написать прогу,
которая будет выполнять наши самые извращенные желания по мегаизвращенному алгоритму.И они-таки побегут.
Что же делать? Да вот чего: задать все последовательные состояния светодиодов таблицей.
Иначе говоря - массивом. Итак, в любом месте программы мы можем написать что-то вроде: MyArray: .db 1,15,4,9,12,145,67,90
Это есть массив "MyArray" состоящий из 8 элементов.
Массив размещается в ПЗУ начиная с адреса, на котором стоит метка (MyArray).
То есть, адресу метки соответствует 0-й элемент массива. Но для этого надо сначала узнать этот самый адрес метки. Это сделать очень просто. Надо загрузить этот адрес в регистровую пару. Я еще ничего не говорил про регистровые пары, поэтому - небольшое лир. отступление Регистровые пары Их всего три: X, Y и Z. Они принадлежат к РОН, и состоят, собственно, из шести последних регистров - R26…R31:
X - R26,R27 Для чего нужны регистровые пары? Для работы с 16-битными числами, коим, в частности, является адрес ПЗУ. Однако, мы можем не использовать данные пары, а распоряжаться выделенными для них регистрами так же, как и обычными. При работе с регистровыми парами, младшая и старшая часть обрабатываются по отдельности. Соответственно, зовут их L и H (от слов Low и High). Например, ZH и ZL. Сегодня нам пригодятся следующие команды:
adc - Add with Carry - сложить два регистра с учетом переполнения предыдущей операции
(если результат предыдущей операции > 255).
lpm - Load Program Memory -
загрузить данные из программной памяти (ПЗУ) по адресу из регистровой пары Z в регистр R0. Ну, собственно, теперь мы можем написать такую программульку: ldi Temp,0 ;инициализация регистра ;внутренней адресации массива ReadArray: ldi ZH,High(MyArray*2) ;загрузка адреса 0-го ldi ZL,Low(MyArray*2) ;элемента в рег. пару Z ldi Temp1,0 add ZL,Temp ;прибавление adc ZH,Temp1 ;внутр. адреса lpm ;загрузка из ПЗУ mov Temp1,R0 ;копирование out PortB,Temp1 ;вывод в порт inc Temp ;увелич. внутр. адреса rjmp ReadArray ;в начало цикла MyArray: .db 12,16,3,4,10,17,255,37,158,14,13,98 .db 14,85,30,9,145,52,64,49,119,72,209,46 Эта программа читает последовательно элементы массива MyArray и выводит их в порт. Разъясним некоторые непонятности. Во первых, структура: ldi ZH,High(MyAray*2)
Этой командой мы загружаем в старшую часть пары Z (ZH), старшую часть адреса по метке MyArray. Во-вторых: в нашем массиве две строки. Это не означает, что массив - двухмерный. Просто, мы разбиваем одну длинную строку на несколько более коротких - для удобства. Строк может быть сколько угодно.
ВНИМАНИЕ: В-третьих: данные в массиве могут быть представлены в виде десятичных, шестнадцатеричных, двоичных чисел, а также, эквивалентных значений символов ASCII. Примеры: .db 3,4,5,75,32,12 ;десятичные числа .db 0x2A,0x34,0x17,0xDF ;шестнадцатеричные числа .db 0b01101001,0b11011100 ;двоичные числа .db "Здесь был Вася" ;эквиваленты ASCII
Ну вот, теперь можно писать программу. Единственное что нужно прописать в инициализации: ldi Temp1,0; ;начальный внутренний адрес Далее ищем обработчик и пишем следующее: ;**************************************************** ; ОБРАБОТЧИК ПРЕРЫВАНИЯ КОМПАРАТОРА ;**************************************************** Timer1_comp1: ldi Temp,0 ;обнуление таймера out TCNT1H,Temp out TCNT1L,Temp cpi Temp1,30 ;сравнить с крайним знач. breq Init ;если равно - загрузка нач. знач. ReadArray: ldi ZH,High(Array*2) ;загрузка начального адреса массива ldi ZL,Low(Array*2) ldi Temp,0 ;прибавление внутр. адреса add ZL,Temp1 adc ZH,Temp lpm ;загрузка из ПЗУ mov Temp,R0 ;копирование в РОН inc Temp1 ;увеличение внутр. адреса rjmp Output ;перейти на вывод в порт Init: ldi Temp1,0 ;загрузить нач. значение rjmp ReadArray Output: out PortB,Temp ;вывод в порт reti ;выход из обработчика Array: .db 0b10000001,0b01000010 .db 0b00100100,0b00011000 .db 0b00011000,0b00111100 .db 0b01111110,0b11111111 .db 0b11100111,0b11000011 .db 0b10000001,0b11000001 .db 0b11100001,0b11110001 .db 0b11111001,0b11111101 .db 0b11111111,0b01111111 .db 0b00111111,0b00011111 .db 0b00001111,0b00000111 .db 0b00000011,0b00000001 .db 0b00000011,0b00000101 .db 0b00001001,0b00010001 .db 0b00100001,0b01000001 Ну вот, теперь разбирайтесь. Я все что мог - сказал :) Дальше я расскажу, как сделать много разных эффектов и переключаться между ними. <<--Вспомним пройденное----Поехали дальше-->>
|
|
|||||||||||||||
|
||||