Правильнее запоминать в обработчике состояние SREG и, при выходе, восстанавливать. По коду. Довольно объёмный и с ходу не вкуриш. Лучше "съесть слона по частям".
;----------------------------------------
service_ADCC: ;прерывание от АЦП
IN R0,SREG
; В даном случае, прерывание от АЦП обрабатывается в фоновом режиме
; по сему - устанавливаем флаг, что АЦП преобразование закончено
; и разрешена фоновая обработка, и выходим
sbr r_flag_r25, (1<<int_acp); описание регистра (set_&_def.inc) ; !!!!!!!!!!!!! эта команда трогает флаги
; для отладки - что сдесь заходили - инвертируем пин порта
sbic pinb,3; пропустить если пин = 0
rjmp m_msh3
sbi portb,3 ; установить пин в 1
rjmp m_mshe3
m_msh3:
cbi portb,3 ;сбросить пин в 0
m_mshe3:
OUT SREG,R0
reti
; end --- service_ADCC ----
Здравствуйте.
Спасибо всем за участие, проблема решена - не правильная последовательность обращения к регистрам ADCH и ADCL.
Цытата из "Микроконтроллеры AVR семейства Mega. Евстифеев А.В. (2007)" (стр 415, параграф 9.3, третий обзац): -
" Обращение к регистрам ADCH и ADCL для получения результата
преобразования должно выполняться в определенной последовательности:
сначала необходимо прочитать регистр ADCL, а затем ADCH. Это
требование связано с тем, что после обращения к регистру ADCL процессор
блокирует доступ к регистрам данных со стороны АЦП до тех пор, пока не
будет прочитан регистр ADCH. ..."
akl - спасибо, ценное замичание, что команды "CBR" и "SBR" изменяют "SREG".
(и уже раз вылавливал глюки из-за не сохраненного "SREG" - все = мимо ус-шей)
Я R0 и R1 заложил как "для особого случая" - это регистры с "двойным дном" - используются в составе других команд.
Для сверхоперативного стека лучше с R2 начинать (предварительно впихнув его содержимое в обычный стек).
BOB51 - Ваша правда, R1 и R0 - подобие аккумулятору, в них записываются результаты умножения, и их стараюсь держать особняком, но как-то так вырвалось... , и вообще (сугубо мое мнение), если есть время и место нужно уходить в "SRAM" (ОЗУ) - меньше возни с пушами и попами .
Команды LDS и STS ни чем не отличаются (по быстродействию) от POP и PUSH. Для экономии времени входа и выхода в/из прерывания логичнее использовать сохранение SREG и используемых регистров верхней половины в зарезервированных r2..r15.
Разве что размером в ПЗУ (4 байта против двух) Vaha
Сброс в ОЗУ для SREG это единственно возможный вариант "быстрого сохранения" (то ли командой IN/OUT, то ли через "отображение РСФ на память").
Однако помимо прочего есть еще и куча возможных наложений при достаточно солидной программе.
Посему лучше создать область "теневого стека", которая при необходимости дублируется в штатном стеке.
В тот "теневой стек" можно и иные регистры копипастить, а не только SREG - на то есть две вкусняшки - MOV r,r и MOW r,r .
Последний раз редактировалось BOB51 Пн ноя 05, 2018 08:49:26, всего редактировалось 1 раз.
На то и стек - следить за содержимым надо в обязательном порядке.
А пересылку РСФ-регистр-память ОЗУ надо потом также и назад делать.
Что касательно SREG штука весьма избыточная (ибо надо также и указатель адреса хранить - то ли в явном виде как содержимое регистровой пары, то-ли в неявном в составе соответствующих команд).
Подбирается решение под конкретную программу с учетом всех за и против.
BOB51
Из выше изложенного, я мало чего понял (можно сказать вообще ничего)
1) "Сброс в ОЗУ для SREG это единственно возможный вариант "быстрого сохранения" (то ли командой IN/OUT, то ли через "отображение РСФ на память")" - РСФ это - регистр состояния флагов? != SREG?, и как понять "отображение РСФ на память"?
2) "Посему лучше создать область "теневого стека", которая при необходимости дублируется в штатном стеке" - что такое "теневой стек" - как он реализован?, еще и в штатном стеке?
3) "В тот "теневой стек" можно и иные регистры копипастить, а не только SREG - на то есть две вкусняшки - MOV r,r и MOW r,r" ("MOW r,r" -возможно очепятка?, имелось ввиду "MOVW r,r"?) - если "теневой стек" находится в SRAM-е (ОЗУ) - то каким боком "вкусняшки - mov(w) r,r" - это-же AVR - ?
РСФ - регистры специальных функций (порты, управление и прочие начиная с адреса 0x20 и до первых ячеек ОЗУ данных).
Они же (область РСФ) доступны также и как пространство ввода-вывода командами in и out.
К регистру управления можно обратится или как к УВВ (командами in и out) или как к области памяти командами работы с памятью LD/ST , но тогда к имени регистра добавляем 0x20 к примеру
in r16,portb = lds r16,(portb+0x20) /исправил
Как область памяти ОЗУ могут также адресоваться и регистры регистрового банка R0-R31.
Помимо того для регистров R0-R31 предусмотрены специальные скоростные пересылки регистр-регистр (mov r,r) и регистровая пара-регистровая пара (movw rp,rp), что весьма удобно при скоростном копировании блоков рабочих регистров.
Такой вариант - скоростное хранение выборочного количества данных и называется "теневым стеком" - правда само название позаимствовано у ПИКов - там это аппаратный модуль, работающий по прерываниям, но сам принцип ускоренного сохранения критических данных применим и в программной реализации для любого МК.
как пример...
в программе прерывания нужно сменить значение регистров-указателей, а затем восстановить.
Можно и через обычный стек, а можно и по иному (если есть запас "пустующих" регистров в младшей области регистрового файла)
movw r14,zl
movw r12,yl
movw r10,xl
собственно тело подпрограмы
movw xl,r10
movw yl,r12
movw zl,r14
ну и подобные операции в зависимости от расперделения ресурсов программы.
Последний раз редактировалось BOB51 Ср ноя 07, 2018 11:47:04, всего редактировалось 1 раз.
[uquote="BOB51",url="/forum/viewtopic.php?p=3499281#p3499281"]РСФ - регистры специальных функций (порты, управление и прочие начиная с адреса 0x20 и до первых ячеек ОЗУ данных).
Они же (область РСФ) доступны также и как пространство ввода-вывода командами in и out.
К регистру управления можно обратится или как к УВВ (командами in и out) или как к области памяти командами работы с памятью LD/ST , но тогда к имени регистра добавляем 0x20 к примеру
in r16,portb = ld r16,(portb+0x20)[/uquote]
Для команд IN OUT доступны адреса 0...0x3F. Адресное пространство ОЗУ у младшеньких AVR 0x60 или 0x100(0x200), которые постарше
Можно закоментировать в m8def.inc, а можно применить директиву .undef, но всё это не позволит пользоваться регистрами с XH по ZL.
Корректней использовать для своих целей другие регистры.
Добавлено after 3 minutes 55 seconds:
[uquote="akl",url="/forum/viewtopic.php?p=3525038#p3525038"]Это не ошибка, а предупреждение.[/uquote] Это предупреждение с точки зрения синтаксиса, но ошибка с точки зрения программирвания. ИМХО, варнинги нельзя игнорировать, я так когда-то делал и зря .
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Не получится...
Для регистров только через undef...
Другое дело, ежли регистр как ячейка памяти....
Однако проверять надо, и это несколько иной тип обращения, нежли к регистру должен будет применяться.
Что-то тут не так. 9RIK то не выложил код где он r26 переопределяет и я предположу, что он наверное перепутал местами левый и правый операнды директивы.
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Не проходит.
Это ж не ячейка памяти, а регистр.
У них несколько иной смысл для дефайна.
Более оптимально заранее подготовить модель регистров и дальше в проекте уже ею руководствоваться.
С присвонеием имен ячейкам ОЗУ значительно проще. Хотя и там могут иметься неприятности.
Да делов-то... игнорируй это предупреждение. Всё будет хорошо, если ты не пользуешься регистрами X,Y,Z ведь ты можешь ненароком попортить указатели если они где-то используются глобально обращаясь к своим переменным... Лучше, конечно, этого не делать.
Можно убрать или сделать .undef для этих регистров, чтобы не ругалось, но тогда НЕЛЬЗЯ БУДЕТ обращаться к индексным регистрам - вы попортите свои переменные. Если у вас в программе не задействованы индексные регистры глобально - можно убрать соответствующие определения, а если используется временно и только по месту, то перед использованием обязательно сделать PUSH для пары регистров, а по окончанию POP чтобы не портить свои переменные.