Страница 79 из 400

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

Добавлено: Пн мар 21, 2011 13:03:28
Gudd-Head
Финский писал(а):как в Z подставить адрес digits?
Z = регистры 30 и 31. Командой ldi с директивами HI(digits) и LOW(digits) загрузить туда двухбайтный адрес переменной.
Только не думаю что вам это поможет: q - константа.
Изображение
Как вариант, переменную можно прибавлять к R30 - младшему байту указателя Z.

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

Добавлено: Пн мар 21, 2011 14:15:02
DX168B
Если переменная в регистре, то только складывание.
Если с константой, то можно и так: adiw Z, 0x0A ;Где 0x0A - константа.
Но старое значение Z теряется.

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

Добавлено: Пн мар 21, 2011 14:50:34
Финский
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
Если кто увидит, что можно оптимизировать, буду только рад совету.
Еще раз спасибо :))

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

Добавлено: Пн мар 21, 2011 15:01:10
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 байт.

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

Добавлено: Пн мар 21, 2011 15:20:48
Gudd-Head
DX168B писал(а):add ZL, razr
Я в своё время на эти грабли наступил.
Я это подразумевал, но не озвучил :)

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

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

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

Добавлено: Пн мар 21, 2011 15:22:14
DX168B
Ага.. :)

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

Добавлено: Пн мар 21, 2011 15:30:38
Финский
То есть, если в результате
add ZL, razr
выйдем за пределы байта ZL, то к ZH прибавится 0 (r17) +перенос? Ааа, вроде дошло )) Дело в длине адреса массива.
Возникает вопрос -
adc ZH, r17 - добавлять после каждого обращения к массиву, или только после тех, где обращаемся к флешу?. у SRAM вроде меньший диапазон адресов... Или, как вариант, массивы во флеше располагать поближе к началу кода, например после начальной настройки периферии.
*** таблица векторов прерываний ****
*** секция init *****
rjmp MAIN ; перепрыгнули данные
*** массивы данных ***
ARRAY1:
ARRAY2:
...........
*** главный цикл ****
MAIN: ; основной код
Тогда адреса гарантированно будут попадать в однобайтный размер. А в процедуре сэкономим несколько директив ) Правильно мыслю, или снова грабли не заметил?

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

Добавлено: Пн мар 21, 2011 16:07:58
orion777
Gudd-Head писал(а):
orion777 писал(а):Может есть какие то идеи?
Есть: учиться нормально.
Хорошая идея. Особенно если учесть что максимально приближенный к этой теме есть только курс "цифровая техника" в 48 часов, где вам расскажут что такое эл-т "и", "и-не", что есть сдвиговый регистр и т.п. и усё. А если учесть что даже мой руководитель дипломного проекта не умеет ни шить ни писать прошивки к МК, то получается вообще весело.

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

Добавлено: Пн мар 21, 2011 17:10:33
Jack_A
Финский писал(а): Тогда адреса гарантированно будут попадать в однобайтный размер. А в процедуре сэкономим несколько директив ) Правильно мыслю, или снова грабли не заметил?
Неправильно. Если адрес, к примеру, 0x18, то это не значит, что в ZL записываем 0x18, а в ZH - ничего. Нуль в ZH придется занести в любом случае, потому как неизвестно, что там было раньше. При этом неважно - в начале или конце программы расположили массив констант.
А однобайтного адреса констант и переменных не бывает.

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

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

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

clr r17
ldi ZL, Low(ARRAY*2)
ldi ZH, High(ARRAY*2)
add ZL, razr
adc ZH, r17
первую и последнюю команды можно не использовать. В прогах, где каждый такт на счету, может пригодиться.
Хотя, возможно я все усложняю.. :oops:

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

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

По поводу ОЗУ: Там тоже нужно пользоваться переносом, так как в большинстве МК, ОЗУ начинается с адреса периферии 0x0060. Если памяти там 256 байт, то это уже 0x015F
Если памяти там 128 байт, то последний будет по адресу 0x00DF. Тогда перенос не нужен.

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

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

.org 0xF00

Const: .db .......

Массив констант расположен в самом конце флеши, тем не менее младшая часть адреса 0х00 - меньше уже некуда.

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

Добавлено: Пн мар 21, 2011 22:31:34
avreal
Gudd-Head писал(а):

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

clr r17
adc ZH, r17
Тоже так делаю. Как я понимаю, изящней флаг переноса не прибавить.
Дык эта... Не так, чтобы изящнее, но не нужно ни обнулённый регистр держать, ни обнулять по случаю свободный.
http://radiokot.ru/forum/viewtopic.php? ... 40#p726327

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

Добавлено: Пн мар 21, 2011 22:37:12
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) )" Почему именно так записано?

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

Добавлено: Пн мар 21, 2011 23:52:44
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
результат тот же :) .

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

Добавлено: Вт мар 22, 2011 01:19:41
DX168B
Теперь понятно. :)

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

Добавлено: Вт мар 22, 2011 09:50:21
Gudd-Head
avreal писал(а):Дык эта... Не так, чтобы изящнее, но не нужно ни обнулённый регистр держать, ни обнулять по случаю свободный.
http://radiokot.ru/forum/viewtopic.php? ... 40#p726327
Ну, это для косвенного перехода. А я имел в виду просто прибавить флаг переноса к содержимому регистра.

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

Добавлено: Вт мар 22, 2011 12:04:52
DX168B
Ну, более изящных способов я пока не видел. Может и есть.

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

Добавлено: Вт мар 22, 2011 19:57:40
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.
Ну а если вспонить, что вместо прибавления к константе можно вычесть минус-константу, то выйдет показанное выше.

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

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