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

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
uwrtey
Поставщик валерьянки для Кота
Сообщения: 2309
Зарегистрирован: Пт июл 17, 2009 07:34:07
Откуда: Свердловская обл.

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

Сообщение uwrtey »

тогда может подскажите ..
в общем есть передатчик ( точнее кодер ) на 20 команд
который сначала опрашивает клавиатуру и записывает данные в ОЗУ, затем читает ОЗУ и если находит хоть одну нажатую кнопку идет на формирование посылки.
проблема в том что передатчик шлет неправильную посылку - а если конкретнее то шлет посылку кода кнопки из следующего столбца
вместо кода кнопки №1 посылается код кнопки №5 и самое интересное вместо кода кнопки №17 посылается код кнопки №1
как будто передача сместилась на 1 байт :shock: но при этом еще и зациклилась! :shock: :shock: в монтаже косяков нету....

ЗЫ код очень хорошо комментирован....
Вложения
transmitt_2.1_s_indicatorom_preryvaniya.asm
(11.45 КБ) 330 скачиваний
передатчик.GIF
(50.46 КБ) 342 скачивания
не зная броду не лезь к вольтмоду
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

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

Сообщение Alexeyslav »

Я сталкивался с подобным эффектом когда разрабатывал одно устройство. Проблема заключалась в том что процессы происходящие в электрической схеме были не так быстры как работает контроллер - он банально успевал считать состояние кнопок до того как напряжение на них нарастет до актуального состояния и поэтому получалось так что контроллер всегда считывал предыдущую строку. введи паузу между установкой напряжения на шине и считыванием состояния кнопок - буквально несколько микросекунд!
Емкость монтажа и входов контроллера, конечное сопротивление диодов делают свое дело - напряжение выбора столбцов несколько запаздывает от сигнала контроллера. Получается что считываем мы вторую линию но напряжение на входах держится еще от первой...
Идеальным вообще было бы избавится от задержек(мало ли пыль налипнет или что еще и увеличит емкость монтажа) переделав алгоритм сканирования - считывать состояние как бы с запаздыванием: вместо того чтобы считывать после установки напряжения на столбце, считывать линию ДО установки напряжения на столбце. Т.е. установили напряжение на первой линии и ждем следующего цикла сканирования, когда наступает очередь второй линии - считываем значение для ПЕРВОЙ линии и только после этого устанавливаем напряжение на второй и так далее. При непрерывном сканировании проблем никаких не должно возникнуть.
Аватара пользователя
uwrtey
Поставщик валерьянки для Кота
Сообщения: 2309
Зарегистрирован: Пт июл 17, 2009 07:34:07
Откуда: Свердловская обл.

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

Сообщение uwrtey »

:shock:
спасибо, попробую!
не зная броду не лезь к вольтмоду
Аватара пользователя
uwrtey
Поставщик валерьянки для Кота
Сообщения: 2309
Зарегистрирован: Пт июл 17, 2009 07:34:07
Откуда: Свердловская обл.

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

Сообщение uwrtey »

Alexeyslav, спасибо большущее ! помогло! :beer:
не зная броду не лезь к вольтмоду
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

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

Сообщение Alexeyslav »

Для этого есть слева кнопочка с "+".
casus
Родился
Сообщения: 13
Зарегистрирован: Вс дек 16, 2012 01:53:53
Откуда: Новый Уренгой

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

Сообщение casus »

Помогите пожалста разобраться с кодом, хочу скопировать массив в стек.
Симуляцию выполняю на VMLAB, симулятор при вызове говорит
[PC = $A503, Time = 18.10 ms, {GEN}]: Program counter outside the valid space
каким образом A5 03 из массива в PC попало немогу понять

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

Array:
.db 9,0x10,0x24,0x15,0x11,0x2F,0x98,0xC7,0x03,0xA5

CopyToRam:
   ldi row, 0x01         ;row счетчик

   ldi ZH,High(Array*2)      ;читаем адрес
   ldi ZL, Low(Array*2)      ;пишем в Z
   lpm            
   mov col,R0         ;col количество байт в массиве
   
CRCnt:
   mov Tmp0, col         ;проверяем все ли передано
   ldi Tmp1,0x01
   add Tmp0, Tmp1
   eor Tmp0, row
   breq CREnd

   ldi ZH,High(Array*2)      ;читаем адрес
   ldi ZL, Low(Array*2)      ;пишем в Z

   ldi Tmp0,0         ;плюсуем смещение
   add ZL,row
   adc ZH,Tmp0

   lpm
   push R0                                       ;ложим R0 в стек
   inc row
   rjmp CRCnt

CREnd:   
ret
Аватара пользователя
Engineer_Keen
Друг Кота
Сообщения: 3868
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

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

Сообщение Engineer_Keen »

Вы командой PUSH положили в конец стека то, что считали из Array, как вы думаете, что произойдет при первом же ret? Ага проц из конца стека прочитает адрес возврата, вот вам и результат. Хотите передавать данные через стек, сначала выньте оттуда адрес возврата и перед ret верните его обратно.
Аватара пользователя
ChipKiller
Сверлит текстолит когтями
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

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

Сообщение ChipKiller »

хочу скопировать массив в стек.
... вопрос для чего? ... посмотрите как С-компиляторы передают локальные параметры
casus
Родился
Сообщения: 13
Зарегистрирован: Вс дек 16, 2012 01:53:53
Откуда: Новый Уренгой

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

Сообщение casus »

Спасибо огромное. Все понял. А как грамотно вынуть адрес возврата?
я так понимаю вынуть слово по адресу SPL:SPH
и закинуть его после переменных?
У меня еще имеется таймер. боюсь что при вызове прерывания он нагадит в стек

P.S.Можете посоветовать литературу для изучения ATMega168?
проблема в том что начал с DataSheet
Пример передачи из даташита

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

USART_Transmit:
; Wait for empty transmit buffer
sbis UCSRnA,UDREn
rjmp USART_Transmit
; Put data (r16) into buffer, sends the data
out UDRn,r16
ret

А на самом деле вместо OUT надо использовать STS
SBIS по тойже причине не работает.
т.к. UDR0 - memory mapped
пока понял кучу времени убил. Подскажите где посмотреть рабочие примеры
Последний раз редактировалось casus Вс дек 16, 2012 14:01:56, всего редактировалось 2 раза.
Аватара пользователя
ChipKiller
Сверлит текстолит когтями
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

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

Сообщение ChipKiller »

при возникновении прерывания запись в стек идет "автоматом", а при выходе из него все возвращается к исходному значению......

можно сохранить SPL:SPH например в X или Y и потом через них работать со стеком
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

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

Сообщение Alexeyslav »

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

Ограничения для SBIS только одно - она может обращаться только к одной половине регистров, а OUT может обратится к портам только до адреса $3F. Если нужный порт лежит выше - тогда надо использовать STS.

Регистры коммуникационных портов обычно лежат в пределах досягаемости команды OUT. Может в меге168 все это переиначили? Странно это всё... Вероятно используются не те константы для обращения к портам. Попробуйте сравнить заголовочник для контроллера с константами приведенными в даташите.
Аватара пользователя
ILYAUL
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср мар 28, 2012 21:45:24
Откуда: ВО

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

Сообщение ILYAUL »

Сама подпрограмма обработки прерывания в обязательном порядке должна позаботится чтобы вернуть все к тому состоянию как было до вызова
Это Вы погорячились , совсем не обязательно. Вот на всякий случай вернуть флаг I это да , да и то не обязательно.
Чем отличается команда rcall от прерывания - да ни чем.

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

.org OVF0addr

можно написать

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

rjmp TIM0_OVF   ; Timer0 Overflow Handler

а можно и

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

rcall TIM0_OVF   ; Timer0 Overflow Handler
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

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

Сообщение Alexeyslav »

Флаг I после обработки прерывания будет безусловно УСТАНОВЛЕН. Так работает команда возврата из прерывания. т.к. не может быть такой ситуации когда обработка прерывания начинается при запрещенных прерываниях. Если вызвать обработчик прерывания из программы при помощи CALL - то мы ССЗБ, после возврата из такого прерывания хотим мы такого или нет но прерывания будут разрешены. И у нас будет всего один такт чтобы запретить их снова(без последствий ли?), если прерывания не должны быть разрешены. Если забыть это сделать - возможны непредсказуемые(но иногда вполне очевидные) последствия.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15546
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

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

Сообщение BOB51 »

Если машина ушла в прерывание, а в качестве возврата использовано RET ( а не RETI) флаг I останется в 1...
Программный вызов прерывания совсем необязательно выполнять командой CALL - достаточно с помощью соответствующей серии команд (макрос-заготовки) установить соответствующий флаг прерывания.
:tea:
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

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

Сообщение zero648 »

ILYAUL писал(а):Чем отличается команда rcall от прерывания - да ни чем.

Есть небольшая разница, RCALL вызываете в программе когда это вам нужно, а прерывание наступает внезапно для основной программы, и при возврате из прерывания могут испортиться регистры, которые в прерывании используются и флаги, и тогда программа может пойти не так как задумано, хотя всё вроде правильно по алгоритму, вот тогда начинаем чесать репу, что не так, :shock: .... а хез?
Аватара пользователя
ILYAUL
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср мар 28, 2012 21:45:24
Откуда: ВО

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

Сообщение ILYAUL »

Флаг I после обработки прерывания будет безусловно УСТАНОВЛЕН
Опять горячитесь и не будет , если например я этого не захочу.
Как работает аппаратный обработчик прерывания. Помимо запоминания адреса возврата , он сбрасывает и флаг I т.к. входя в сам обработчик мы уже не ждём заподлянки от других прерываний. Если надо сохранить SREG , что тоже не всегда нужно, только в случае использования в прерывании команд сравнения , что само по себе ОЧЕНЬ плохой тон принаписании обработчиков прерываний, то флага I там нет- о сброшен.
Возвращает в SREG этот флаг , команда RETI , которая ближайшая родственица команде RET , которая отличается от родствености тем , что флаг не возвращает. Всё остальное она выполняет также как и команда reti/ Так, что Ваше
безусловно УСТАНОВЛЕН
зависит от каманды выхода из прерывания.
Если вызвать обработчик прерывания из программы при помощи RCALL
Вы не разобрались с Выше приведённым мной кодом. Посмотрите ещё раз и внимательно. В момент вызова rjmp или rcall флаг I уже сброшен.
RCALL вызываете в программе когда это вам нужно, а прерывание наступает внезапно для основной программы
:)) Кто же Вам сказал , что в прерывании мне не нужно вызвать именно эту подпрограмму , которую я независимо от прерывания могу вызвать когда мне угодно, но например с другими входными условиями.

Вообще-то одно и тоже прерывание , может вызывать N-ое количество его обработчиков , причём независимых друг от друга. Тут кто-то очень хорошо сказал про написании програм на asm и С. Вот только забыл в какой теме это было. Но сказано верно. Так , что не загоняйте себя в шоры это возможно , а это нет. ASM позволяет с процем делать многое и не всегда по правилам.
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

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

Сообщение Alexeyslav »

А я и говорю что аппаратный вызов прерывания сбрасывает признак I чем запрещает прерывания на время работы обработчика. последующая команда RETI устанавливает его назад. этот бит I - нигде не запоминается, команда просто устанавливает его и точка. даже если вызовешь при запрещенных прерываних обработчик при помощи конструкции rcall - после выхода из обработчика прерывания неожиданно окажутся разрешенными. Этот поведение остается на совести программиста.
При этом, кстати, если прерывания до вызова были разрешены возникает другая проблема - обработчик прерывания может быть не рассчитан на то что во время его выполнения может возникнуть и быть обработано ДРУГОЕ прерывание, он рассчитывает на тот факт что во время обработки прерывания все остальные прерывания ЗАПРЕЩЕНЫ и обработчик прерван быть не может. Ладно если в прерывании используем лишь парочку инкрементов, а если что-то посложнее и возникновение прерывания посреди обработчика может привести к непредсказуемым последствиям?

Это однозначно плохой подход вызывать прерывание при помощи rcall.

И кстати, когда возникает прерывание то аппаратно происходит rcall и вложенный rcall должен быть подавлен как минимум, иначе при попытке выйти из такого прерывания(rcall вместо rjmp в таблице векторов) управление будет передано на следующую инструкцию, которой будет следующий обработчик по таблице... а не в точку возникновения прерывания. ладно если следующий вектор не определен и на его месте стоит затычка reti - просто прерывание удлинится на 8 тактов, а если нет?

Кто же Вам сказал , что в прерывании мне не нужно вызвать именно эту подпрограмму , которую я независимо от прерывания могу вызвать когда мне угодно, но например с другими входными условиями.

Тогда ваша подпрограмма должна обладать непременным свойством - реентерабельностью.
А так же подпрограмма должна ОООЧЕНЬ аккуратно обходится с переменными основной программы, впрочем это условие будет соблюдено если подпрограмма будет реентерабельной.
Аватара пользователя
ILYAUL
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср мар 28, 2012 21:45:24
Откуда: ВО

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

Сообщение ILYAUL »

Программу пишет человек , обработчики , пишет человек. Всё что Вы написали человек и должен предусмотреть. И вызов другог прерывания в обработчике первого не сос тавляет сложностей. Кстати в XMEGA - так и сделано. Сами выбираете , что может прервать процесс обработки прерывания , а что нет. Флаг I вообще не сбрасывается.
Вот Вам код

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

pop temp
pop temp
push R0
push R1
reti

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

Это однозначно плохой подход вызывать прерывание при помощи rcall.
Вы попробуйте сами , вместо rjmp- rcall и тогда судите
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

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

Сообщение Alexeyslav »

прервать процесс обработки прерывания можно при помощи RETI, но единственный способ в МЕГАХ (не ХМЕГА) использовать вложенные прерывания - это разрешить прерывания в обработчике прерывания. Вообще со вложенными прерываниями количество возможных проблем и неудобства растет в геометрической прогрессии.

Из описания регистра статуса(ATMEGA168-48-88):
The I-bit is cleared by hardware after an interrupt has occurred, and is set by
the RETI instruction to enable subsequent interrupts.

Никаких неоднозначностей здесь нет.
casus
Родился
Сообщения: 13
Зарегистрирован: Вс дек 16, 2012 01:53:53
Откуда: Новый Уренгой

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

Сообщение casus »

Подскажите, как можно организовать динамический массив в озу?
Например под буфер приемника, для послед. обработки, если количество данных неизвестно, но к примеру ограниченно 255ю.
Плюс ко всему мне нужно передвигаться по массиву, в моем случае
озу 0x0200-0x04FF, тоесть 1.5Kb памяти, используя смещение.
Каким образом смещать регистр адрессации массива, если STS и LDS восьмибитные?
Ответить

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