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

Обсуждаем контроллеры компании Atmel.
Ответить
Прорезались зубы
Аватара пользователя
Сообщения: 244
Зарегистрирован: Пт сен 10, 2010 20:39:32
Откуда: Украина Луганская обл.

Сообщение Coldheart »

[uquote="BOB51",url="/forum/viewtopic.php?p=3116560#p3116560"]Для формирования точных интервалов предназначены аппаратные таймеры.
Программные циклы в качестве задержек имеют крайне ограниченное применение из-за различных факторов.[/uquote]
Да это я естественно понимаю, но не в 7 раз же погрешность. Мне надо мигать светодиодом раз в 3 часа, +-10 мин. Точность не нужна совершенно.
Реклама
akl
Друг Кота
Сообщения: 4470
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

FUSE- БИТ CKDIV8 снимите.
Реклама
Прорезались зубы
Аватара пользователя
Сообщения: 244
Зарегистрирован: Пт сен 10, 2010 20:39:32
Откуда: Украина Луганская обл.

Сообщение Coldheart »

[uquote="akl",url="/forum/viewtopic.php?p=3116580#p3116580"]FUSE- БИТ CKDIV8 снимите.[/uquote]
спасибоОО огромнейшее!! :beer:
akl
Друг Кота
Сообщения: 4470
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

По мне, гораздо проще программные задержки формировать пользуясь возможностями ассемблера.

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

.equ   Fo=4800000
T:
	LDI	R23,BYTE4(1*Fo/6-1)
	LDI	R22,BYTE3(1*Fo/6-1)
	LDI	R21,BYTE2(1*Fo/6-1)
	LDI	R20,BYTE1(1*Fo/6-1)		;1 сек
;	LDI	R23,BYTE4(3*3600*Fo/6)
;	LDI	R22,BYTE3(3*3600*Fo/6)
;	LDI	R21,BYTE2(3*3600*Fo/6)
;	LDI	R20,BYTE1(3*3600*Fo/6)	;3 часа

L:
	SUBI	R20,1
	SBCI	R21,0
	SBCI	R22,0
	SBCI	R23,0
	BRSH	L
	RJMP	T
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

CKDIV8 дает только стартовое состояние предделителя "по умолчанию", а уж потом - как CLKPS3:..:CLKPS0 поставиш, так и покатится.
А вот неизвестно чего в OSCCAL при начальной загрузке попавшее гораздо более проблем создаст.
И насчет программных циклов...
Хороши, пока не включены прерывания (либо гарантировано защищены от оных).
8)
Реклама
Друг Кота
Аватара пользователя
Сообщения: 7083
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Сообщение Ivanoff-iv »

Уморшить контроллер на 3 часа :shock: да ещё и прерывания выключить :shock: :shock: если Вам надо пирог через 3 часа из духовки вынуть, тоже тиканье часов считать будете? :)) и ни на что не отвлекаться чтобы со счету не сбили :)) :))
даже если контроллер больше ни чем не занят пусть лучше спит как кот, (или ест :hunger: ) - а от такой практики лучше уходить, чтобы не дай бог не привыкнуть :)) :)) :)) .
тем более прерывание использовать не сложно (а темболее когда время задержки не меняется) в подпрограмме добавляешь переменную - где хранится адрес на который прыгнуть и переменную таймера, допустим вызов нашей подпрограммы происходит 1раз в миллисекунду, а нам надо подождать 100 миллисекунд - в переменную таймера вносим 99 (отсчет текущего прерывания только начался) а в адрес - адрес следующей команды и выходим из подпрограммы.
При вызове подпрограммы проверяем таймер если 0 - идем по адресу, если нет декремент таймера и выход.

Добавлено after 1 minute 14 seconds:
П.С. ни чего не имею против программных таймеров на малые интервалы
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Реклама
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Есть маахонькая разница:
1. программный интервал сформированный на основе повторяющихся циклично машинных кодов;
2. программный интервал на основе генерации метки аппаратным блоком
при условии, что длительность интервала между метками значительно превосходит разумную внешнюю погрешность.
Первый пункт хорош на сверхмалых интервалах, второй - основа всех типов счета "длинных" интервалов/программных RTC.
8)
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Ivanoff-iv писал(а):тем более прерывание использовать не сложно
я бы приблизительный таймер на 3 часа делал вообще без прерываний и задержек - на WDT. тупо по сбросу ячейку памяти инкрементировал бы и все - строго линейный алгоритм, без прерываний :) а между сбросами наглухо усыплял бы МК.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Прорезались зубы
Аватара пользователя
Сообщения: 244
Зарегистрирован: Пт сен 10, 2010 20:39:32
Откуда: Украина Луганская обл.

Сообщение Coldheart »

Что-то я в двух соснах разобраться не могу
Подскажите, сколько циклов в данном коде?

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

 
    ldi  r18, 2
    ldi  r19, 142
L1: 
    dec  r19
    brne L1
    dec  r18
    brne L1
    nop
Вроде ж 2*142+1=285, на деле получается около 840. AVR Delay Loop Calculator говорит что будет 1200.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Coldheart писал(а):Подскажите, сколько циклов в данном коде?
Вы забыли, что после первого обнуления r19 в нем будет 0 и его маленький цикл уже не 142 раза прокрутится, а 256.

т.е. количество прогонов всего кода у вас будет равно 142 + 256, а не 142 + 142. а количество тактов надо считать соответственно - тут я не подскажу, ибо точно не помню, сколько тактов каждая команда занимает.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

Даже если этот код загнать в студию, то можно пронаблюдать за количеством тактов на каждую команду.
Декремент выполняется за один такт, также, как и присваивание.
А вот команды ветвления (переходов) выполняются за один такт, если НЕ ВЫПОЛНЯЕТСЯ условие, и за два такта если ВЫПОЛНЯЕТСЯ условие, т.к. надо адрес (метку) перехода еще грузануть.

Итого. (расчет примерный).
2 такта на то, чтобы присвоить два значения переменным (регистрам Р18 и Р19).
1 такт на декремент 142
2 такта НА КАЖДЫЙ РАЗ на переход, т.к. условие у вас ВЫПОЛНЯЕТСЯ (флаг нулевого результата Z не равен нулю)
И все это по кругу 142 раза. Т.е. 2+(3*142) = 428
Потом, как вам и сказал Роман, счет начинается уже не с 142, а с 256, т.к. новое значение никто не грузил в Р19.
1 такт на декремент Р18 (он стал равен 1)
2 такта на переход на метку Л1.
И по новой
1 такт на декремент 256
2 такта на переход
Итого 1+2+(3*256) = 771
428+771 = 1199.

Ах, да, там же еще декремент Р18 до нуля и выход из цикла. Вот и еще пара тактов.
Станислав
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 33
Зарегистрирован: Сб апр 20, 2013 22:56:52

Сообщение Lavad »

Доброго времени суток!
Пишу на Бейсике, но в Ассемблер "метнулся" из-за того, что программа уже на 96-98% забита (Atmega8). Причесываю, перечесываю и ужимаю ее не один день. Думал, часто повторяющуюся арифметику выполнить в ASM-блоке. Нашел в книге Ревича перемножение многобайтных чисел, чуть изменил под себя, прогнал в симуляторе Баскома... работает! НО! Как и большинство учебников и сайтов, ВЕЗДЕ практикуется ввод в регистры РОН готовых значений. А если в программе это/и значение/я меняются? У меня уже извилины выпрямились в одну линию от гор информации, литературы и попыток "направить" в регистр переменную :-(. Подскажите, пожалуйста, кто понимает, по паре моментов:
1) Баском (2.0.7.5) упорно ругается 222-ой ошибкой на строку:
!LDI R16 , Y
Заносить готовые HEX-данные в регистр, с последующей обработкой и результатом - без проблем! А переменную (даже с объявлением через .def) не дает. Что не так? КАК отправлять переменную в регистр?
2) Конечный результат разнесен в 3-х регистрах. С директивой STS могу вынести за ASM-блок все три байта, объединить, "превратить" в число... Но, может быть, в Ассемблере имеется что-то короче для получения конечного (числового) результата из нескольких регистров? А иначе теряется смысл в этих танцах - результирующий код намного превышает код заменяемый.

P.S. Баском позволяет поместить переменную в фигурные скобки (правда, так и не нашел описания этим скобкам):
!LDI R16 , {Y}
Но все равно, в конечном итоге, в целевом регистре будет 0 :-( и, следовательно, результат будет искажен.
О человеке говорят не потоки изрыгаемых слов, а его дела и поступки.
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

[uquote="Lavad",url="/forum/viewtopic.php?p=3125494#p3125494"]1) Баском (2.0.7.5) упорно ругается 222-ой ошибкой на строку:
!LDI R16 , Y
Заносить готовые HEX-данные в регистр, с последующей обработкой и результатом - без проблем! А переменную (даже с объявлением через .def) не дает. Что не так? КАК отправлять переменную в регистр?[/uquote]
X,Y,Z - существующие регистровые пары (R26-R31 или XH,XL,YH,YL,ZH,ZL), поэтому в качестве второго аргумента LDI их использовать некорректно. Попробуйте использовать другое, более осмысленное имя для переменной (ну или константы, раз LDI используется).
[uquote="Lavad",url="/forum/viewtopic.php?p=3125494#p3125494"]2) Конечный результат разнесен в 3-х регистрах. С директивой STS могу вынести за ASM-блок все три байта, объединить, "превратить" в число... Но, может быть, в Ассемблере имеется что-то короче для получения конечного (числового) результата из нескольких регистров? А иначе теряется смысл в этих танцах - результирующий код намного превышает код заменяемый.[/uquote]
Тут не понятно что конкретно нужно получить и как данные расположены. Например, имея 3 байта подряд можно выгадать 1 слово в программной памяти, используя ST X+,rn с предварительной загрузкой регистровой пары XH:XL начальным адресом (STS занимает 2 слова, а ST одно, но нужно потратить еще пару на LDI). Для оптимизации такого места нужно видеть весь код.
Неправильно собранная из неисправных деталей схема нуждается в отладке и сразу не работает... (С)
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 33
Зарегистрирован: Сб апр 20, 2013 22:56:52

Сообщение Lavad »

[uquote="Engineer_Keen",url="/forum/viewtopic.php?p=3125552#p3125552"]X,Y,Z - существующие регистровые пары (R26-R31 или XH,XL,YH,YL,ZH,ZL),...
...более осмысленное имя для переменной (ну или константы...[/uquote]
А где Вы видите в моем примере использование старших регистров R26-R31?
Осмысленные имена... Так и поступаю. Здесь "Y" вписал лишь для краткости.
А константы... В процессе работы программы значение переменной, которую пытаюсь отправить в регистры, постоянно меняется.
[uquote="Engineer_Keen",url="/forum/viewtopic.php?p=3125552#p3125552"]Тут не понятно что конкретно нужно получить и как данные расположены. Например, имея 3 байта подряд можно выгадать 1 слово в программной памяти, используя ST X+,rn с предварительной загрузкой регистровой пары XH:XL начальным адресом (STS занимает 2 слова, а ST одно, но нужно потратить еще пару на LDI). Для оптимизации такого места нужно видеть весь код.[/uquote]
В Ассемблере у меня не то что первые шаги, а поползновения :-) Так что с понятием "память" и использованием директив мне еще потеть и пыхтеть.
Вот рабочий код, с ручной подстановкой данных (а-ля константа):
СпойлерDim tmp1 As Byte
Dim tmp2 As Byte
'data = 16 [$0010] 1-ый множитель
'koef = 2489 [$09B9] 2-ой множитель
'temp = 39824 [$9B90] -> ожидаемый результат
!.def dataL = R4 ; $10 - младший разряд
!.def dataH = R5 ; $00 - старший разряд
!.def koefL = R2 ; $B9 - младший разряд
!.def koefH = R3 ; $09 - старший разряд
!.def tmp1 = R16 ; $90 - младший разряд
!.def tmp2 = R17 ; $9B - старший разряд
!ldi R24 , $10
!mov R4 , R24
!ldi R24 , $00
!mov R5 , R24
!ldi R24 , $b9
!mov R2 , R24
!ldi R24 , $09
!mov R3 , R24
!clr tmp2 ; очищаем старший разряд R18
!mul dataL , koefL ; умножаем младшие разряды => R4 * R2 => $09 * $13 = $AB => копируем в R0,R1
!mov tmp1 , R0 ; копируем R0 в мл. разр. результата R16 => $AB => R16
!mov tmp2 , R1 ; копируем R1 в ср. разр. результата R17 => $00 => R17
!mul dataH , koefL ; умножаем старший на младший => R5 * R2 => $01 * $13 = $13 => копируем в R0,R1
!add tmp2 , R0 ; складываем R17 и R0 => $00 + $13 = $13 => R17
!mul dataL , koefH ; умножаем младший на старший => R4 * R3 => $09 * $01 = $09 => копируем в R0,R1
!add tmp2 , R0 ; складываем R17 и R0 => $13 + $09 = 1C => R17
!mul dataH , koefH ; умножаем старший на старший => R5 * R3 => $01 * $01 = $01 => копируем в R0,R1
!sts {tmp1} , tmp1
!sts {tmp2} , tmp2

Dim tmp4 As String * 6
Dim tmp5 As Word
tmp4 = Hex(tmp2)
tmp4 = tmp4 + Hex(tmp1) ' $9B90
tmp5 = HexVal(tmp4) ' 39824
Результат разнесен по регистрам R16,R17. Их то я и вытаскиваю директивой STS и форматирую последними тремя строками. Это извлечение можно выполнить менее емким кодом?

По поводу переменной... Перед ASM-блоком разбил число поразрядно и пытался впихнуть в регистры (оба разряда тут присвоены одной переменной - это лишь для попытки "пропихивания")

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

Dim Y As String * 2    
X = 2489     
Y = Hex(High(X))                   ' -> 09     
Y = Hex(Low(X))                    ' -> b9
Проблемка в том, что куда-то не туда увели меня танцы - 16-ричные результаты смог получить лишь для переменной String :-(. В чем ошибка? Но полный тупик даже не в этом. В регистры пытался отправлять переменную ВСЕХ типов - и Ворд, и Лонг, и Байт,... Один ответ у Баскома - 222-ая ошибка.
О человеке говорят не потоки изрыгаемых слов, а его дела и поступки.
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Проблема больше в том, что все "высокоуровневые" компиляторы сами решают чего куда поместить...
А вставка на ассемблере предусматривает прямое вмешательство в логику распределения ресурсов...
Обязательно надо учитывать правила предварительного освобождения/резервирования тех ресурсов в "высокоуровневом", которые будут использованы вставкой на ассемблере. А там... у каждого компилятора свои правила... не всегда в явном виде указаны...
:roll:
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Не работал с баском, но гугль говорит что 222 это некорректный символ в команде, значит у вас что-то не то с "грамматикой". Код вы сначала не привели, откуда мне знать что "Y" был как пример? Привычный asm-компилятор АВР-студии за "LDI R16,Y" вполне закономерно послал бы вас с формулировкой "неправильное число". Привели бы конкретный пример на какую строчку ругается, может знатоки баскома наставят на путь истинный.
Насколько я понял надо ассемблером умножить data (word) на koef (word) и результат получить в temp (должен быть dword, двух байт тут маловато).
Может тут че поможет...
Неправильно собранная из неисправных деталей схема нуждается в отладке и сразу не работает... (С)
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 33
Зарегистрирован: Сб апр 20, 2013 22:56:52

Сообщение Lavad »

[uquote="Engineer_Keen",url="/forum/viewtopic.php?p=3125815#p3125815"]Не работал с баском, но гугль говорит что 222 это некорректный символ в команде...[/uquote]
Спасибо, конечно! :-) Об ошибке я и сказал в первом сообщении. Подобная страница имеется и в скупой справке Баскома. Она изначально ничем не помогла. Там в регистр загружают или адрес переменной, или уже готовые значения. Но нет ничего (либо "не врубился") о загрузке самой переменной.
[uquote="Engineer_Keen",url="/forum/viewtopic.php?p=3125815#p3125815"]Привели бы конкретный пример на какую строчку ругается,...[/uquote]
Вообще-то :shock: , в самом начале и привел:
LDI R16 , Y
На нее и ругается. Полное ругательство:
Illegal character [expected (, got '' [Y]] , in File....
Если верно понимаю, он ожидал открывающую скобку, а получил... ничего.
[uquote="Engineer_Keen",url="/forum/viewtopic.php?p=3125815#p3125815"]Насколько я понял надо ассемблером умножить data (word) на koef (word) и результат получить в temp (должен быть dword, двух байт тут маловато).[/uquote]
Поняли верно, но обратив внимание на разрядность множителей, согласитесь, что и Ворда хватает. Те, размерности, что использовал в коде - это почти потолок их значений, которые могут быть в программе. А конечный результат в 65535 (дес) или FFFF (hex) - в программе невозможен.
И код (в моей проблеме) тот же самый. За исключением, что вместо готовых 16-ричных значений прописываю переменную. Какого бы типа ни была переменная (Word, Byte. String,...) - ругань одна и та же. Вот и возвращаюсь к вопросу: как в регистр загрузить переменную?
О человеке говорят не потоки изрыгаемых слов, а его дела и поступки.
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Так на
LDI R16 , Y
и ассемблер матюкнётся -
LDI R16,k где k 0-255 (константа), но никак не зарезервированное имя регистровой пары Yh:Yl (R29:R28)
(LD R16,Y к примеру - загрузка R16 из ячейки памяти по адресу указанному в Yh:Yl (R29:R28)).
В принципе всегда рекомендуется избегать применения "зарезервированных имен" не по назначению!
8)
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

[uquote="Lavad",url="/forum/viewtopic.php?p=3125845#p3125845"]Вообще-то :shock: , в самом начале и привел:
LDI R16 , Y
На нее и ругается. Полное ругательство:
Illegal character [expected (, got '' [Y]] , in File....
Если верно понимаю, он ожидал открывающую скобку, а получил... ничего.[/uquote]
Ну так мы с ВОВ51 уже сказали что Y в LDI нельзя вторым аргументом писать, это имя регистра, а должна быть константа.
Одной командой LDI в регистр переменную из RAM загрузить нельзя. Либо напрямую через LDS, либо через LD с индексными регистрами (X,Y,Z), по ссылке что я привел выше как раз пример. И за один раз одной ассемблерной командой больше чем байт не загрузить, для word надо два регистра и две команды загрузки, типа:

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

Dim A As word
LOADADR a, X
!Ld R16, X+  
!Ld R17, X+ 
Неправильно собранная из неисправных деталей схема нуждается в отладке и сразу не работает... (С)
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Ладно...
Повторюсь для новеньких КОТЯТ
шпора AVR.pdf
(60.25 КБ) 244 скачивания
:beer:
Ответить

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