Перейти к содержанию

Сбрасываются Регистры После Обработки Прерываний. Как С Этим Жить?


anton2488

Рекомендуемые сообщения

UPD

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

Изучаю авр и столкнулся с непреодолимой для меня проблемой.

Простая программа АЦП>програмный делитель>шим. Регистр, в котором постоянно хранится число сдвигов для деления всё время сбрасывается в 0, при этом при этом установленный бит в порте не сбрасывается(сделал для проверки). Не важно, записан ли регистр в РЕСЕТ или в прерывании через кнопку, всё равно происходит сброс. Как такое может быть?

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

Что я делаю не так? Помогите новичку.

.def temp1=r16
.def temp2=r17
.def div1=r18
.def div2=r19


.cseg
.org 0x0000
rjmp RESET
reti//1
rjmp vol//2
reti//3
reti//4
reti//5
reti//6
reti//7
rjmp adcpwm
reti//9
reti//10
reti//11
reti//12
reti//13
reti//14
reti//15

RESET:

ldi r16, (0<<WDRF)// остановка ст. таймера.
out MCUSR, r16
; Write logical one to WDCE and WDE
; Keep old prescaler setting to prevent unintentional Watchdog Reset
in r16, WDTCR
ori r16, (1<<WDCE)|(1<<WDE)
out WDTCR, r16
; Turn off WDT
ldi r16, (0<<WDE)
out WDTCR, r16

ldi temp1,0b00000011
out ddrb,temp1

ldi temp1,0b00011000
out portb,temp1

ldi temp1,0b11000011
out tccr0a,temp1

ldi temp1,0b00000001
out tccr0b,temp1

ldi temp1,0b00100001//УСТАНОВЛЕН СДВИГ ВЛЕВО
out admux,temp1

ldi temp1,0b11101111
out adcsra,temp1

ldi temp1,0b00000000
out adcsrb,temp1

ldi temp1,0b00000000
out mcucr,temp1

ldi temp1,0b00100000
out gimsk,temp1

ldi temp1,0b00011000
out pcmsk,temp1

ldi div1,3// запись коэф деления в постоянный регистр

sei

start:
rjmp start

adcpwm:// прерывание АЦП---------------------------------------------
in temp1,adcl
in temp2,adch

mov div2,div1 // запись коэф. деления из постоянного рег во временный

tst div2//деление
breq zap
l1:
lsr temp2
ror temp1
dec div1
brne l1

zap://запись в шим
out ocr0a,temp2
out ocr0b,temp2
reti

VOL://прерывание кнопки----------------------------------------------------
ldi div1,3// запись коэф деления в постоянный регистр

sbi portb,1//индикатор прерывания


reti

Изменено пользователем anton2488
Ссылка на комментарий
Поделиться на другие сайты

А где инициализация стека?

Регистры SPH:SPL не иницилизированы, откуда возникает переполнение стека и сброс контроллера.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

По конкретнее можно? Какой регистр "постоянно сбрасывается"? div1 в прерывании?

К замечаниям COKPOWENEU добавлю, что заходя в прерывания нужно сохранять в стеке, используемые регистры, а выходя из прерывания - восстанавливать. Не забывайте и про регистр состояния SREG. Иначе логика хода программы после выполнения прерывания может поменяться. Это по организации и "хорошему тону".

А по существу, Вы используете регистр div1. Заходя в прерывание, копируете его и проверяете на нулевое значение его копию div2, а уменьшаете (декрементируете) почему-то div1. Естественно, после трех прерываний Ваш регистр будет иметь значение 0.

Изменено пользователем Геннадий
Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

А где инициализация стека?

Регистры SPH:SPL не иницилизированы, откуда возникает переполнение стека и сброс контроллера.

в авр студио 5 и 6 не нужно инициализировать, всё само.

По конкретнее можно? Какой регистр "постоянно сбрасывается"? div1 в прерывании?

К замечаниям COKPOWENEU добавлю, что заходя в прерывания нужно сохранять в стеке, используемые регистры, а выходя из прерывания - восстанавливать. Не забывайте и про регистр состояния SREG. Иначе логика хода программы после выполнения прерывания может поменяться. Это по организации и "хорошему тону".

А по существу, Вы используете регистр div1. Заходя в прерывание, копируете его и проверяете на нулевое значение его копию div2, а уменьшаете (декрементируете) почему-то div1. Естественно, после трех прерываний Ваш регистр будет иметь значение 0.

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

Про сохранение регистров не слышал. Чем это вызвано? Каким образом прерывание может изменить значение регистров, если с ними не работают в прерывании. Но идея хороша, можно сэкономить регистр.

Ссылка на комментарий
Поделиться на другие сайты

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Точно "само"? Вообще-то это было бы неправильное поведение. Покажите скомпилированный hex-файл.

Насчет прерываний - речь не о конкретном а об общем случае. А там возможны хотя бы операции сравнение, инкремента/декремента и прочие, влияющие на SREG. Представьте если такое прерывание возникнет между cp и breq. То, что шанс возникновения такой ошибки мал только усугубляет ситуацию: труднее найти ошибку. Ну и прерывание часто использует те же регистры, что и основная программа, а чтобы они друг другу не мешали, при входе и выходе в прерывание делают пары push/pop. Плюс не надо запоминать какое прерывание с какими регистрами работает. Например, в прерывании надо инкременировать содержимое ячейки 0x0100 ОЗУ.

ANY_INT:
  push r16   ;сохраняем r16
  in r16,SREG
  push r16   ;сохраняем SREG

  lds r16,0x0100 ;какие-то полезные действия
  inc r16
  sts 0x0100,r16

  pop r16   ;восстанавливаем SREG
  out SREG,r16
  pop r16   ;восстанавливаем r16
reti

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

COKPOWEHEU все уже объяснил. В обработчике прерывания нужно сохранять/восстанавливать только используемые в этом прерывании регистры и SREG, чтобы при возвращении из прерывания все эти регистры содержали те же значения, что и при входе в прерывание. Тогда основная программа будет выполняться по принципу "как ни в чем не бывало". Это гарантирует логику основного цикла без изменений (последствий прерываний). А чтобы не забивать стек излишними сохранениями я, например, сохраняю SREG в свободном регистре младшей группы R3-R15, т.к. они редко используются.

Ссылка на комментарий
Поделиться на другие сайты

Точно "само"? Вообще-то это было бы неправильное поведение. Покажите скомпилированный hex-файл.

Насчет прерываний - речь не о конкретном а об общем случае. А там возможны хотя бы операции сравнение, инкремента/декремента и прочие, влияющие на SREG. Представьте если такое прерывание возникнет между cp и breq. То, что шанс возникновения такой ошибки мал только усугубляет ситуацию: труднее найти ошибку. Ну и прерывание часто использует те же регистры, что и основная программа, а чтобы они друг другу не мешали, при входе и выходе в прерывание делают пары push/pop. Плюс не надо запоминать какое прерывание с какими регистрами работает. Например, в прерывании надо инкременировать содержимое ячейки 0x0100 ОЗУ.

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

контроллер тини45

:020000020000FC
:100000000FC0189518951895189518951895189566
:1000100035C0189518951895189518951895189530
:1000200000E004BF01B5086101BD00E001BD03E0CF
:1000300007BB08E108BB03E80ABD01E003BF01E21A
:1000400007B90FEE06B900E003B928E07894B39B36
:100050000CC0B49B01C0FBCFB49BFECF2830B9F3DA
:1000600040FD01C023954395F2CFB39BFECF2223E1
:1000700071F340FF01C02A954A95E9CF04B115B14B
:10008000322F332361F0169507953A95E1F740FF3B
:1000900006C0612F502F66955795050F161F19BD85
:0400A00018BD1895DA
:00000001FF

Сейчас возникла друга проблема. Пытаюсь перенести программу на мегу48

ldi temp1,0b01100000

out admux,temp1

пишет ошибку

Error 1 Operand 1 out of range: 0x7c

каким образом вносить данные в эти регистры если in и out не работают с этими адресами?

тут случайно банк памяти не нужно переключать?

А, нашёл

<a name="#top">lds r2, $FF00 ; Загрузить в r2 содержимое SRAM по адресу $FF00

add r2, r1 ; Сложить r1 с r2

sts $FF00, r2 ; Записать обратно

Изменено пользователем anton2488
Ссылка на комментарий
Поделиться на другие сайты

Пишите sts admux,temp1. Она более "дальнобойная".

А есть другие команды, которыми можно записать?

Я сейчас не могу записать единицу в 6 бит, который запускает цап.

ldi temp1,0b11101111

sts adcsra,temp1

а записывается 0b10101111

В чем может быть причина, и как записать бит? В тини всё нормально записывается.

Ссылка на комментарий
Поделиться на другие сайты

:020000020000FC
:100000000FC0189518951895189518951895189566
:1000100035C0189518951895189518951895189530
:1000200000E004BF01B5086101BD00E001BD03E0CF
:1000300007BB08E108BB03E80ABD01E003BF01E21A
:1000400007B90FEE06B900E003B928E07894B39B36
:100050000CC0B49B01C0FBCFB49BFECF2830B9F3DA
:1000600040FD01C023954395F2CFB39BFECF2223E1
:1000700071F340FF01C02A954A95E9CF04B115B14B
:10008000322F332361F0169507953A95E1F740FF3B
:1000900006C0612F502F66955795050F161F19BD85
:0400A00018BD1895DA
:00000001FF

Как и следовало ожидать, записи в SPH:SPL нет. Должно быть что-то вроде 0FE5 0DBF 01E0 0EBF (ldi r16,5F | out 0x3D,r16 | ldi r16,0x01 | out 0x3E,r16 где 0x3D=SPL, 0x3E=SPH, 0x015F=RAMEND). То есть стек все-таки не инициализирован.

Сейчас возникла друга проблема. Пытаюсь перенести программу на мегу48

ldi temp1,0b01100000

out admux,temp1

пишет ошибку

Error 1 Operand 1 out of range: 0x7c

Рекомендую такой код

.macro uout
   .if @0<0x40
       out @0,@1
   .else
       sts @0,@1
   .endif
.endm
.macro uin
   .if @1<0x40
       in @0,@1
   .else
       lds @0,@1
   .endif
.endm

Использование вместо обычных in / out

ldi temp1,0b01100000

uout admux,temp1

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

А где смотреть нужно?

Вот я добавил инициализацию стека.

Но указатель стека и раньше и сейчас указывает на то же значение 0x015F

:020000020000FC
:100000000FC0189518951895189518951895189566
:1000100039C018951895189518951895189518952C
:1000200001E00EBF0FE50DBF00E004BF01B50861A0
:1000300001BD00E001BD03E007BB08E108BB03E828
:100040000ABD01E003BF01E207B90FEE06B900E007
:1000500003B928E07894B39B0CC0B49B01C0FBCFDC
:10006000B49BFECF2830B9F340FD01C023954395E2
:10007000F2CFB39BFECF222371F340FF01C02A953C
:100080004A95E9CF04B115B1322F332361F01695AB
:1000900007953A95E1F740FF06C0612F502F66950E
:0C00A0005795050F161F19BD18BD1895C7
:00000001FF

Спасибо, макросы попробую. Для регистров выше 0x40 требуется sts, в даташите указаны какие то адреса в скобках 0x20 (0x40) EEDR что они означают?

Не знаете почему не устанавливается бит ADSC запуска ацп в adcsra на меге48? Даже не знаю куда копать, в даташите о особых условиях запуска ничего не нашёл.

Ссылка на комментарий
Поделиться на другие сайты

ATmega48P


.def temp1=r16
.def temp2=r17

.cseg
.org 0x0000
rjmp RESET
reti//1
reti//2
reti//3
reti//4
reti//5
reti//6
reti//7
reti//8
reti//9
reti//10
reti//11
reti//12
reti//13
reti//14
reti//15
reti//16
reti//17
reti//18
reti//19
reti//20
reti//21
rjmp adcpwm
reti//23
reti//24
reti//25
reti//26

RESET:


ldi r16, high(RAMEND); Main program start
out SPH,r16 ; Set Stack Pointer to top of RAM
ldi r16, low(RAMEND)
out SPL,r16

ldi temp1,0b00000000
out ddrb,temp1

ldi temp1,0b11100000
out ddrd,temp1

ldi temp1,0b00000000
out ddrc,temp1

ldi temp1,0b00000000
out portb,temp1

ldi temp1,0b00000000
out portc,temp1

//timer
ldi temp1,0b10100011
out tccr0a,temp1

ldi temp1,0b00000001
out tccr0b,temp1

//adc
ldi temp1,0b00100000//УСТАНОВЛЕН СДВИГ ВЛЕВО
sts admux,temp1

ldi temp1,0b00000000
sts adcsrb,temp1

ldi temp1,0b10101111//инициализация без запуска цап
sts adcsra,temp1
ldi temp1,0b11101111//инициализация с запуском цап
sts adcsra,temp1
sei


start:

rjmp start

adcpwm://запись из цап в шим

lds temp1,adcl
lds temp2,adch

sbi portd,7// проверка прерывания

out ocr0a,temp2

reti

Изменено пользователем anton2488
Ссылка на комментарий
Поделиться на другие сайты

Reti//21 лишняя строка в таблице векторов и таблица длиннее на один вектор. Именно на строке reti//21 должен находиться вектор прерывания по окончанию преобразования.

Ссылка на комментарий
Поделиться на другие сайты

Reti//21 лишняя строка в таблице векторов и таблица длиннее на один вектор. Именно на строке reti//21 должен находиться вектор прерывания по окончанию преобразования.

Помогло! Дурацкая ошибка. Непонятно, почему бит adsc не загорается в симуляторе, из-за этого пошёл не в том направлении. Есть ли возможность в симуляторе эмитировать прерывания по цап, чтобы проверять вектора? Простая установка флагов ничего не даёт.

Изменено пользователем anton2488
Ссылка на комментарий
Поделиться на другие сайты

По идее должно быть при выставлении ADIF ну и глобального прерывания.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Опять какая то странная ситуация возникла(мега48п)

clr r16

out EEARH, r16

out EEARL, r16

sbi eecr,0

in div1,eedr

Error 1 Undefined symbol: EEARH

вот прямо из даташита копировал

; Set up address (r18:r17) in address register

out EEARH, r18

out EEARL, r17

; Start eeprom read by writing EERE

sbi EECR,EERE

; Read data from Data Register

in r16,EEDR

с EEARL всё нормально работает

Изменено пользователем anton2488
Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...