Z = регистры 30 и 31. Командой ldi с директивами HI(digits) и LOW(digits) загрузить туда двухбайтный адрес переменной.
Только не думаю что вам это поможет: q - константа.
Как вариант, переменную можно прибавлять к R30 - младшему байту указателя Z.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Если переменная в регистре, то только складывание.
Если с константой, то можно и так: adiw Z, 0x0A ;Где 0x0A - константа.
Но старое значение Z теряется.
I am DX168B and this is my favourite forum on internet!
; процедура индикации
DISPLAY:
ldi ZH, High(digits) ; загружаем старший байт адреса массива времени
ldi ZL, Low(digits) ; то же - младший
add ZL, razr ; прибавляем к младшему байту адреса требуемый разряд (от 0-го до 5-го)
ld temp1, Z ; загружаем байт по получившмуся адресу в временный регистр
ldi ZH,High(DATA*2) ;инициализация массива цифр (маски вида 0b00111111 - цифра 0)
ldi ZL,Low(DATA*2) ;
add ZL, temp1 ; прибавляем к нулевому адресу массива выводимую цифру из оперативки (только младший полубайт)
lpm outport, Z ; получившуюся маску загружаем в регистр вывода данных
ldi ZH,High(ADDRESS*2) ; инициализация массива разрядов (маски вида 0b11111110 - нулевой разряд )
ldi ZL,Low(ADDRESS*2)
add ZL, razr ; выбираем из массива адрес, соответствующий текущему разряду
lpm temp3, Z ; загружаем байт в регистр R0
out PORTC, temp3 ; выводим адрес в порт к к-рому подкл. общие катоды
out PORTD, outport ; выводим данные в порт к к-рому подкл. сегменты
inc razr ; увеличиваем разряд, чтобы на след цикле вывести след значение в след адрес
cpi razr, 6 ; как только значение разрядов превышает 5
brne EXIT_DISP
clr razr ; обнуляем счетчик цикла
EXIT_DISP:
ret
Если кто увидит, что можно оптимизировать, буду только рад совету.
Еще раз спасибо
[color=#800000]Техноманьяк и IT-шаман. Танцы с бубном на дому.[/color]
add ZL, razr
Я в своё время на эти грабли наступил. Может сейчас работает, но если вдруг придётся добавить пару строчек в программе, то будут проблемы с чтением данных из массивов.
Часть данных массива могут оказаться по адресу 0x00FA, к примеру а другая часть окажется по адресу 0x0100. А вы не делаете никаких операций со старшим байтом Z. В итоге Вы никогда не сможете прочитать данные с адреса 0x0100 и далее.
Надо так:
Если же не хочется использовать ADC ra, rb
то массивы надо будет жёстко закрепить в конце флеша директивой .org
Причём с какого -нибудь начала по старшему байту адреса.
То есть, если в результате
add ZL, razr
выйдем за пределы байта ZL, то к ZH прибавится 0 (r17) +перенос? Ааа, вроде дошло )) Дело в длине адреса массива.
Возникает вопрос -
adc ZH, r17 - добавлять после каждого обращения к массиву, или только после тех, где обращаемся к флешу?. у SRAM вроде меньший диапазон адресов... Или, как вариант, массивы во флеше располагать поближе к началу кода, например после начальной настройки периферии.
*** таблица векторов прерываний ****
*** секция init *****
rjmp MAIN ; перепрыгнули данные
*** массивы данных ***
ARRAY1:
ARRAY2:
...........
*** главный цикл ****
MAIN: ; основной код
Тогда адреса гарантированно будут попадать в однобайтный размер. А в процедуре сэкономим несколько директив ) Правильно мыслю, или снова грабли не заметил?
[color=#800000]Техноманьяк и IT-шаман. Танцы с бубном на дому.[/color]
Хорошая идея. Особенно если учесть что максимально приближенный к этой теме есть только курс "цифровая техника" в 48 часов, где вам расскажут что такое эл-т "и", "и-не", что есть сдвиговый регистр и т.п. и усё. А если учесть что даже мой руководитель дипломного проекта не умеет ни шить ни писать прошивки к МК, то получается вообще весело.
Финский писал(а):
Тогда адреса гарантированно будут попадать в однобайтный размер. А в процедуре сэкономим несколько директив ) Правильно мыслю, или снова грабли не заметил?
Неправильно. Если адрес, к примеру, 0x18, то это не значит, что в ZL записываем 0x18, а в ZH - ничего. Нуль в ZH придется занести в любом случае, потому как неизвестно, что там было раньше. При этом неважно - в начале или конце программы расположили массив констант.
А однобайтного адреса констант и переменных не бывает.
Извиняюсь, не так выразился. Понятно, что в ZH в любом случае нужно занести старший байт адреса. Просто в случае расположения массива в начале младший байт будет намного меньше предельного значения 0xFF, следовательно при небольших массивах (и размерах смещения к последнему элементу) перенос можно будет не учитывать, и в конструкции
Ну я же написал выше. Ваш код, который Вы выложили в начале может работать, но для пущей надёжности закрепите эти массивы директивой .ORG 0xXXXX. Эта директива не пишется в прошивку. Она лишь указывает компилятору, в какую область флеша расположить этот массив.
Желательно так, чтобы указать в директиве старший байт, а младший, чтобы был нулём.
Тогда можете оперировать только младшим байтом пары Z. Но массив тогда не должен превышать размер 256 байт.
Если Вы, например, расположите массив по адресу 0xA000, то оперируя регистром ZL, вы можете читать байты с адреса 0xA000 по 0xA0FF. Массив лучше расположить в конце флеша.
По поводу ОЗУ: Там тоже нужно пользоваться переносом, так как в большинстве МК, ОЗУ начинается с адреса периферии 0x0060. Если памяти там 256 байт, то это уже 0x015F
Если памяти там 128 байт, то последний будет по адресу 0x00DF. Тогда перенос не нужен.
I am DX168B and this is my favourite forum on internet!
Финский писал(а):Просто в случае расположения массива в начале младший байт будет намного меньше предельного значения 0xFF, следовательно при небольших массивах (и размерах смещения к последнему элементу)
С какого такого перепугу ?
.org 0xF00
Const: .db .......
Массив констант расположен в самом конце флеши, тем не менее младшая часть адреса 0х00 - меньше уже некуда.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Круто, я тоже так хочу.
Только объясните мне выражение "( -(tab1*2) )" Почему именно так записано?
Это просто изящный прием, позволяющий обойти отсутствие в инструкциях AVR команды "суммирование с константой", назовем ее условно ADI.
Пример на десятичных, надо к 100 прибавить 1:
прибавлением
100+1=101
или вычитанием отрицательного числа (-1)
100-(-1)=101
результат тот же .
Gudd-Head писал(а):Ну, это для косвенного перехода.
Ну там раньше обсуждлся косвенный переход. Тут ближе - выборка из массива по индексу. Разницы никакой -- есть фиксированный адрес (16-бит константа) и есть смещение к нему (8-бит переменная), надо сложить.
Можно складывать сначала загружая константу, потом прибавляя переменную и перенос. Тогда, действительно, регистр удобен, хотя
ldi ZL, Low(ARRAY*2)
ldi ZH, High(ARRAY*2)
add ZL, razr
brcc no_carry ; эти две команды вместе с меткой можно для упрощения написания
inc ZH ; оформить в макрос add_carry, принимающий регистр, к которому добавить
no_carry:
так что обнулённый регистр имеет смысл только тогда, когда он обнуляется в начале программы и всегда таким поддерживается. Используется везде без обнуления каждый раз.
Благо, часто не жалко какой-то из «нижних» регистров выделить под ZERO.
Ну а если вспонить, что вместо прибавления к константе можно вычесть минус-константу, то выйдет показанное выше.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Вот такой вопрос назрел. Я немного поправил прошивку автора из статьи http://www.radiokot.ru/circuit/digital/home/56/ Дверной звонок на Attiny2313. Добавил в сообщение два файла: как было и как стало. Мне интересно, почему на моей прошивке при окончании проигрывания мелодии на 12 ноге (откуда звук идёт так скажем) присутствует напряжение 1,31 В? Причем, может присутствовать может и нет. Ни от чего не зависит. Один раз проиграла мелодия-всё спокойно. Ещё раз проиграла при нажатии-опять нормально. Третий раз-хоп, после окончания проигрывания в динамике шипение. Мультиметр пишет 1,31 В. Причем, контроллер не зависает. Нажму кнопку мелодия опять играет, и на ножке после проигрывания может быть снова как 0 так и эти грёбаные 1,31 В.