Ассемблер (ASM) для AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Gudd-Head »

Финский писал(а):как в Z подставить адрес digits?

Z = регистры 30 и 31. Командой ldi с директивами HI(digits) и LOW(digits) загрузить туда двухбайтный адрес переменной.
Только не думаю что вам это поможет: q - константа.
Изображение
Как вариант, переменную можно прибавлять к R30 - младшему байту указателя Z.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение DX168B »

Если переменная в регистре, то только складывание.
Если с константой, то можно и так: adiw Z, 0x0A ;Где 0x0A - константа.
Но старое значение Z теряется.
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
Финский
Открыл глаза
Сообщения: 59
Зарегистрирован: Сб авг 28, 2010 13:29:43
Откуда: Докучаевск, Донецк
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Финский »

Gudd-Head, спасибо огромное! Может похоже на быдлокодинг :oops: , но получилось следующее:

Код: Выделить всё

; процедура индикации
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]
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение DX168B »

add ZL, razr
Я в своё время на эти грабли наступил. Может сейчас работает, но если вдруг придётся добавить пару строчек в программе, то будут проблемы с чтением данных из массивов.
Часть данных массива могут оказаться по адресу 0x00FA, к примеру а другая часть окажется по адресу 0x0100. А вы не делаете никаких операций со старшим байтом Z. В итоге Вы никогда не сможете прочитать данные с адреса 0x0100 и далее.
Надо так:

Код: Выделить всё

clr r17
ldi ZL, Low(ARRAY*2)
ldi ZH, High(ARRAY*2)
add ZL, razr
adc ZH, r17

Если же не хочется использовать ADC ra, rb
то массивы надо будет жёстко закрепить в конце флеша директивой .org
Причём с какого -нибудь начала по старшему байту адреса.

Код: Выделить всё

.org 0xA000
ARRAY:
.db .......

В таком случае размер массива желательно не должен быть более 256 байт.
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Gudd-Head »

DX168B писал(а):add ZL, razr
Я в своё время на эти грабли наступил.

Я это подразумевал, но не озвучил :)

Код: Выделить всё

clr r17
adc ZH, r17

Тоже так делаю. Как я понимаю, изящней флаг переноса не прибавить.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение DX168B »

Ага.. :)
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
Финский
Открыл глаза
Сообщения: 59
Зарегистрирован: Сб авг 28, 2010 13:29:43
Откуда: Докучаевск, Донецк
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Финский »

То есть, если в результате
add ZL, razr
выйдем за пределы байта ZL, то к ZH прибавится 0 (r17) +перенос? Ааа, вроде дошло )) Дело в длине адреса массива.
Возникает вопрос -
adc ZH, r17 - добавлять после каждого обращения к массиву, или только после тех, где обращаемся к флешу?. у SRAM вроде меньший диапазон адресов... Или, как вариант, массивы во флеше располагать поближе к началу кода, например после начальной настройки периферии.
*** таблица векторов прерываний ****
*** секция init *****
rjmp MAIN ; перепрыгнули данные
*** массивы данных ***
ARRAY1:
ARRAY2:
...........
*** главный цикл ****
MAIN: ; основной код
Тогда адреса гарантированно будут попадать в однобайтный размер. А в процедуре сэкономим несколько директив ) Правильно мыслю, или снова грабли не заметил?
[color=#800000]Техноманьяк и IT-шаман. Танцы с бубном на дому.[/color]
orion777
Родился
Сообщения: 14
Зарегистрирован: Пн сен 29, 2008 23:16:59

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение orion777 »

Gudd-Head писал(а):
orion777 писал(а):Может есть какие то идеи?

Есть: учиться нормально.

Хорошая идея. Особенно если учесть что максимально приближенный к этой теме есть только курс "цифровая техника" в 48 часов, где вам расскажут что такое эл-т "и", "и-не", что есть сдвиговый регистр и т.п. и усё. А если учесть что даже мой руководитель дипломного проекта не умеет ни шить ни писать прошивки к МК, то получается вообще весело.
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Jack_A »

Финский писал(а):Тогда адреса гарантированно будут попадать в однобайтный размер. А в процедуре сэкономим несколько директив ) Правильно мыслю, или снова грабли не заметил?

Неправильно. Если адрес, к примеру, 0x18, то это не значит, что в ZL записываем 0x18, а в ZH - ничего. Нуль в ZH придется занести в любом случае, потому как неизвестно, что там было раньше. При этом неважно - в начале или конце программы расположили массив констант.
А однобайтного адреса констант и переменных не бывает.
Аватара пользователя
Финский
Открыл глаза
Сообщения: 59
Зарегистрирован: Сб авг 28, 2010 13:29:43
Откуда: Докучаевск, Донецк
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Финский »

Извиняюсь, не так выразился. Понятно, что в ZH в любом случае нужно занести старший байт адреса. Просто в случае расположения массива в начале младший байт будет намного меньше предельного значения 0xFF, следовательно при небольших массивах (и размерах смещения к последнему элементу) перенос можно будет не учитывать, и в конструкции

Код: Выделить всё

clr r17
ldi ZL, Low(ARRAY*2)
ldi ZH, High(ARRAY*2)
add ZL, razr
adc ZH, r17

первую и последнюю команды можно не использовать. В прогах, где каждый такт на счету, может пригодиться.
Хотя, возможно я все усложняю.. :oops:
[color=#800000]Техноманьяк и IT-шаман. Танцы с бубном на дому.[/color]
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение DX168B »

Ну я же написал выше. Ваш код, который Вы выложили в начале может работать, но для пущей надёжности закрепите эти массивы директивой .ORG 0xXXXX. Эта директива не пишется в прошивку. Она лишь указывает компилятору, в какую область флеша расположить этот массив.
Желательно так, чтобы указать в директиве старший байт, а младший, чтобы был нулём.
Тогда можете оперировать только младшим байтом пары Z. Но массив тогда не должен превышать размер 256 байт.
Если Вы, например, расположите массив по адресу 0xA000, то оперируя регистром ZL, вы можете читать байты с адреса 0xA000 по 0xA0FF. Массив лучше расположить в конце флеша.

По поводу ОЗУ: Там тоже нужно пользоваться переносом, так как в большинстве МК, ОЗУ начинается с адреса периферии 0x0060. Если памяти там 256 байт, то это уже 0x015F
Если памяти там 128 байт, то последний будет по адресу 0x00DF. Тогда перенос не нужен.
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Jack_A »

Финский писал(а):Просто в случае расположения массива в начале младший байт будет намного меньше предельного значения 0xFF, следовательно при небольших массивах (и размерах смещения к последнему элементу)


С какого такого перепугу ?

.org 0xF00

Const: .db .......

Массив констант расположен в самом конце флеши, тем не менее младшая часть адреса 0х00 - меньше уже некуда.
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение avreal »

Gudd-Head писал(а):

Код: Выделить всё

clr r17
adc ZH, r17
Тоже так делаю. Как я понимаю, изящней флаг переноса не прибавить.

Дык эта... Не так, чтобы изящнее, но не нужно ни обнулённый регистр держать, ни обнулять по случаю свободный.
viewtopic.php?f=20&t=5931&start=1440#p726327
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение DX168B »

avreal писал(а):А я - так:

Код: Выделить всё

        mov     ZL, in_dat
        clr     ZH
        subi    ZL, Low( -(tab1*2) )
        sbci    ZH, High( -(tab1*2) )
        lpm     out_dat, Z

Круто, я тоже так хочу. :) :beer:
Только объясните мне выражение "( -(tab1*2) )" Почему именно так записано?
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
IM1
Грызет канифоль
Сообщения: 268
Зарегистрирован: Вт фев 16, 2010 12:10:38
Откуда: Воронеж, Россия

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение IM1 »

DX168B писал(а):
avreal писал(а):А я - так:

Код: Выделить всё

        mov     ZL, in_dat
        clr     ZH
        subi    ZL, Low( -(tab1*2) )
        sbci    ZH, High( -(tab1*2) )
        lpm     out_dat, Z

Круто, я тоже так хочу. :) :beer:
Только объясните мне выражение "( -(tab1*2) )" Почему именно так записано?
Это просто изящный прием, позволяющий обойти отсутствие в инструкциях AVR команды "суммирование с константой", назовем ее условно ADI.
Пример на десятичных, надо к 100 прибавить 1:
прибавлением
100+1=101
или вычитанием отрицательного числа (-1)
100-(-1)=101
результат тот же :) .
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение DX168B »

Теперь понятно. :)
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Gudd-Head »

avreal писал(а):Дык эта... Не так, чтобы изящнее, но не нужно ни обнулённый регистр держать, ни обнулять по случаю свободный.
viewtopic.php?f=20&t=5931&start=1440#p726327

Ну, это для косвенного перехода. А я имел в виду просто прибавить флаг переноса к содержимому регистра.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение DX168B »

Ну, более изящных способов я пока не видел. Может и есть.
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение avreal »

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:
ни по тактам, ни по словам не длиннее, чем

Код: Выделить всё

    clr     r17
    ldi     ZL, Low(ARRAY*2)
    ldi     ZH, High(ARRAY*2)
    add     ZL, razr
    adc     ZH, r17
так что обнулённый регистр имеет смысл только тогда, когда он обнуляется в начале программы и всегда таким поддерживается. Используется везде без обнуления каждый раз.
Благо, часто не жалко какой-то из «нижних» регистров выделить под ZERO.
Ну а если вспонить, что вместо прибавления к константе можно вычесть минус-константу, то выйдет показанное выше.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Аватара пользователя
ЮТ
Вымогатель припоя
Сообщения: 623
Зарегистрирован: Чт июн 11, 2009 07:25:24
Откуда: СПб

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение ЮТ »

Вот такой вопрос назрел. Я немного поправил прошивку автора из статьи http://www.radiokot.ru/circuit/digital/home/56/ Дверной звонок на Attiny2313. Добавил в сообщение два файла: как было и как стало. Мне интересно, почему на моей прошивке при окончании проигрывания мелодии на 12 ноге (откуда звук идёт так скажем) присутствует напряжение 1,31 В? Причем, может присутствовать может и нет. Ни от чего не зависит. Один раз проиграла мелодия-всё спокойно. Ещё раз проиграла при нажатии-опять нормально. Третий раз-хоп, после окончания проигрывания в динамике шипение. Мультиметр пишет 1,31 В. Причем, контроллер не зависает. Нажму кнопку мелодия опять играет, и на ножке после проигрывания может быть снова как 0 так и эти грёбаные 1,31 В.
Вложения
Стало.rar
(13.61 КБ) 196 скачиваний
Было.rar
(6.06 КБ) 202 скачивания
Ответить

Вернуться в «AVR»