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

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


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
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

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

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

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

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

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

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

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

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

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

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

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

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

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

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

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

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

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

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

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

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

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

Точно "само"? Вообще-то это было бы неправильное поведение. Покажите скомпилированный 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 раз.

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

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

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 пользователей онлайн

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

    • Ну что же могу сказать собрал пробную макетку не по плееру пока что просто для запуска и проверки UART написанным мною в ATMEGA16. Но впринцепи там всё совпадает по местоположению и после я допаяю эту макетку и уже проверю с плеером. А это нужно было чтоб проверить UART. Проверка показала что он вполне так хорошо работает как на передачу так и на приём. Проверял я в связке с компом через FT232. Сделал на той же скорости 9600 и внешним кварцем на 7.3728 MHz. Теперь же как я думаю нужно будет уже подсобрать дальше макетку под плеер и как то пока с компом отлаживать передачу и приём команд UART и строить свой сценарий работы плеера оперируя данными командами. После черновой наброски можно будет и к самому плееру подключаться и проверять уже с ним.
    • Судя по отверстиям в плате, будут прикручены как-то насквозь? У вас эскизика крепления к радиатору нет случайно? Как-то не складывается в голове, как будет осуществляться тепловой контакт транзисторов с радиатором...
    • Если речь про мультисим, то он работает у меня на древнем компе пенсионэре с i5, которому 12 лет. Никогда не вникал, что он там грузит, за ненадобностью. Касаемо усилителей, например, анализатор спектра расчитывает, довольно быстро, если ставить в анализаторе, минимум разрешения, без фанатизма, иначе можно и заночевать у компа. А разрешение зависит от исследуемой, основной частоты. А потом удивляются, иногда, штойта при 0,001-0,003% гармоник такой говенный звук? А то шта ниже лес палок торчит, так тож какбы не слышно ужо, люди говорят.
    • R23 не катит - явно не тот номинал, наверно 597кОм
    • Он довольно бесполезен в нашу современность. Всё, что нужно добавить к 7104 вместо второго чипа, находится на скрине, который вы скинули. Основная проблема с дискретной реализацией, имхо, в ключах и в таймингах. И если вторые ещё кое-как можно обеспечить чисто ардуиновскими костылями при таких разрядностях, то побороть утечку ключей трудно. Можно искать ADG411 конечно, и делать полностью дискретную реализацию самому, но эту проблему как раз и призвана решить 7104. Проектировщику остаётся взять два хороших ОУ, компарь, опору, и сделать схему похожую 8052 со скрина, а 7104 сама разберется с управлением Два 74hc165 регистра, и данные можно выгружать в МК. Что интересно, эта топология автонуля ещё ближе к схеме АЦП В7-38. Такая система автонуля мне больше нравится, чем автонуль в 7135, в которой ключ автонуля включен между очень чувствительным к утечкам инвертирующим входом интегратора и выходом, а тут между выходом и неинвертом, что не даёт утечке ключа автонуля "подсаживать" конденсатор интегратора. Я могу ошибаться в том, насколько хорошо это реально влияет на характеристики, мне просто больше нравится такая раздельная система, когда конденсатор автонуля не включен в цепь интегратора. Так или иначе, эти АЦП, по сути, есть пик двухтактной топологии, и что-то более крутое придумать будет сложно, остаётся лишь повторять, будь то в дискрете или используя микросхемы. Выжать больше 16 бит я думаю не выйдет, сложно объяснить, но это упирается в размахи напряжения, и слишком большое увеличение резистора интегратора/его емкости (что увеличивает влияние утечек, ухудшающих линейность). Не зря в 7104 питание аналоговой части +/-15В, а на интеграторе аж 9В. На эту тему там написано, что это компромисс между всеми ошибками:   И на всякий случай, нет, MAX132 не считается, потому что у неё многотактное интегрирование
    • Всем здравствуйте! Пока на улице идут ливни, я занялся написаем скетча для приемника. Написал, подключил, проверил, все работает! Но вылезла очень большая проблема. Когда подаю питание, севера становится в среднее положение, но потом ее начинает не по детски колбасить. То в одну сторону, то в другую, то она не двигается, то очень сильно гудит и "вибрирует" качалкой. При этом L7805CV дико греется. Уже спустя 3 секунды палец обжигает. В чем может быть дело? Я так полагаю, это нехватка тока для сервы? Кушает она немало... P.S На форумах пишут, что серва кушает до 2.5А в состоянии полного клина. При движении от 0.2 до 0.9А...
  • Похожий контент

×
×
  • Создать...