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

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

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

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

Сообщение DX168B »

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

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

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

Сообщение 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!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

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

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

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

Сообщение DX168B »

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

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

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

Сообщение orion777 »

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

Сообщение Jack_A »

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

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

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

Сообщение 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!
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 6323
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

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

.org 0xF00

Const: .db .......

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

Сообщение avreal »

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

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

clr r17
adc ZH, r17
Тоже так делаю. Как я понимаю, изящней флаг переноса не прибавить.
Дык эта... Не так, чтобы изящнее, но не нужно ни обнулённый регистр держать, ни обнулять по случаю свободный.
http://radiokot.ru/forum/viewtopic.php? ... 40#p726327
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение 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
Откуда: Воронеж, Россия

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

Сообщение DX168B »

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

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

avreal писал(а):Дык эта... Не так, чтобы изящнее, но не нужно ни обнулённый регистр держать, ни обнулять по случаю свободный.
http://radiokot.ru/forum/viewtopic.php? ... 40#p726327
Ну, это для косвенного перехода. А я имел в виду просто прибавить флаг переноса к содержимому регистра.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение DX168B »

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

Сообщение 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
Откуда: СПб

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

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

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