Страница 1 из 3
Можно ли выйти из прерывания не по reti ?
Добавлено: Пт дек 19, 2014 14:31:22
Miw
Всем привет
Вот возникла у меня такая задачка - есть обработчик прерываний, который обрабатывает опред. события типа нажатие кнопок.
Хочется, чтобы после события начинал исполняться другой кусок программы, а не тот из которого вышли в прерывание.
Собственно вопрос - можно ли уйти из прерывания по rjmp ?
Как нужно почистить стек ? Просто заново настроить указатель стека ?
Флаги какие-то надо чистить ?
Что еще сделать ?
Есть ли разница между ATTiny13 и ATMega8 ?
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Пт дек 19, 2014 14:54:04
eess9
На чем пишите? Если на ассемблере, то я вам не помошник

Если си, то это вполне реально релизовать.
Miw писал(а):Есть ли разница между ATTiny13 и ATMega8 ?
Оба восьмибитные контроллеры AVR архитектуры от Atmel (хотя и в разных семействах). Отличаются периферией очень сильно.
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Пт дек 19, 2014 15:43:48
Miw
на Асме вестимо ))
Пишу прогу для гирлянды, пока вставил в обработчик вот такие строчки :
Код: Выделить всё
F_But1HoldCommand:
ldi ZH,High(DISPArray*2) ; start commands from tbe begining
ldi ZL,Low(DISPArray*2)
ldi Temp1,RamEnd
out SPL,Temp1 ; LIFO init
clr But1Press ; clear Button statuses
clr But2Press
ldi Temp1,1
mov FlashStat,Temp1 ; enable flash and cicles
clr LoopStat ; enable Next Read of command
rjmp Loop
ret
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Пт дек 19, 2014 15:45:01
Pink-Pank
Да, можно уйти по rjmp.
Только после такого перехода у Вас останутся выключенными прерывания, включить которые обратно можно командой sei.
И в стеке останется адрес возврата. Можно либо заново проинициализировать стек, либо просто увеличить указатель стека на размер сохраненного адреса. Это обычно один-два байта. Зависит от размера флеш данной модели контроллера.
Указанные Вами МК с точки зрения логики и организации ядра не отличаются. Отличаются в части периферии, тактовых частот и количества ног.
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Пт дек 19, 2014 15:50:07
Miw
Pink-Pank писал(а):
Только после такого перехода у Вас останутся выключенными прерывания
Вот это ценно, спасибо!
Проверю сегодня дома в AVR Studio и потом на макетке
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Пт дек 19, 2014 16:44:18
da-nie
Хочется, чтобы после события начинал исполняться другой кусок программы, а не тот из которого вышли в прерывание.
Тогда зачем прерывание? Крутитесь в цикле и смотрите кнопки.
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Пт дек 19, 2014 17:46:19
COKPOWEHEU
В ATtiny13 и ATmega8 счетчик команд двухбайтный. Соответственно, если так уж надо прыгать из обработчика в середину программы, надо убрать из стека 2 байта, поднять флаг I регистра SREG и прыгать.
Но правильнее будет обрабатывать кнопку в основном цикле, а не искать грабли в прерываниях и стеке.
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Пт дек 19, 2014 19:52:35
da-nie
а не искать грабли в прерываниях и стеке.
А они непременно будут, ибо прерывание придёт в произвольный момент программы, когда она может что-то сама класть на стек или ещё куда. И выход не в ту же функцию из прерывания приведёт к наслоению не завершённых задач.
sei
rjmp куда-т
А в промежуток между этими командами рано или поздно придёт ещё одно прерывание.

Операция же не атомарная.

Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Пт дек 19, 2014 20:06:41
COKPOWEHEU
Если придет "нормальное" прерывание - ничего страшного, Вы же не боитесь, что оно придет в момент вызова процедуры или if'а. Впрочем, если такое же, все равно ничего страшного, себя-то оно из стека вычищает перед разрешением. Ну прыгнет в другое место, так по логике Miw так и должно быть.
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Пт дек 19, 2014 21:05:26
kolobok0
Miw писал(а):Всем привет
Вот возникла у меня такая задачка....
на азме можно всё, что может МК. Но...
как уже прозвучало выше - Вы мягко говоря создаёте сами себе проблемы. Тактовая у Вас небось несколько мегагерц?
несколько миллионов(!) раз в секунду выполняются однобайтовые команды. и событие от клавы (а это человек как я понимаешь), может произойти максимум пару десятков в секунду. У вас разброс десятки-сотни тысяч(!) тактов между максимально возможными нажатиями... Ну а нафига Вам в этой ситуации всё нафик резко прекращать? если сюда добавить ышо тему дребезга(вряд-ли Вы наворотили триггера по входам клавы) - то вообще не понятно Ваше стремление...
дело конечно же житейское. каждый извращается как может...
но вот с консерваторией как то не айс выходит...
удачи Вам
(круглый)
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Сб дек 20, 2014 00:06:37
Miw
да я вот сам думаю, что не айс прыгать куда-то, но все же
Частота всего 0,6 MHz, мне пока хватает ))
Прерывания от таймера каждые 0,1 секунды
Вот чего делаю - гирлянда RGB, Тинька 13, в памяти есть команды - просто светить, мигать, fade in, fade out, бегущий огонь и т.п.
Основной цикл читает команду и потом ее исполняет, время задается в счетчиках и кратно 10 сек,
то бишь каждая команда выполняется как отдельная функция и длится 10 секунд * каунтер.
Есть две кнопки, при нажатии и удержании первой хочу сделать экспресс переход на чтение новой команды.
Посоветуйте, может быть есть более простой способ реализовать такое поведение
P.S. Выход из прерывания я сделал - по первой кнопке все работает нормально, а вот при удержании второй делаю переход на Reset
С этим переходом что-то глючит пока, хотя казалось бы тут все должно работать )))
Видимо сразу же вслед обрабатывается одинарное нажатие на эту же кнопку
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Сб дек 20, 2014 08:19:21
Viper115
Мне кажется, вы не тот камушек выбрали для таких задач. У тини13 только два выхода шим, что маловато для полноценного управления RGB. Или же надо будет извращаться с программным шимом
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Сб дек 20, 2014 09:23:47
da-nie
то бишь каждая команда выполняется как отдельная функция и длится 10 секунд * каунтер.
А что мешает внутри каждой команды проверять кнопки и выходить наружу?
Код: Выделить всё
unsigned char mode=0;//режим работы
while(1)
{
if (mode==0) mode=мигаем_так(mode);
if (mode==1) mode=мигаем_сяк(mode);
if (mode==2) mode=мигаем_эдак(mode);
}
unsigned char мигаем_так(unsigned char mode)
{
unsigned char button_state=0;//кнопка не нажата
unsigned char button_counter=0;//счётчик, чтобы исключить дребезг контактов и узнать длительность нажатия
unsigned short counter=0;
while(counter<10000)
{
if (нажали кнопку)
{
if (button_counter<255) button_counter++;//увеличиваем до предела
}
else//кнопка отпущена
{
button_counter=0;
if (button_state==1) //делаем, что там нужно делать для одиночного нажатия
if (button_state==2) break;//при длительном нажатии переходим следующей команде
}
/*
мигаем
*/
if (button_counter>=10 && button_counter<100) button_state=1;//кнопку нажали однократно
if (button_counter>100) button_state=2;//кнопку нажали длительно
counter++;
}
return(mode+1);//переходим к следующему эффекту
}
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Сб дек 20, 2014 11:37:52
COKPOWEHEU
Или сделать для каждого эффекта конечный автомат. Вот пример для более многоногого контроллера, демонстрация принципа.
Код: Выделить всё
void eff_run(){ //эффект бегущего огня
static unsigned char time=0; // текущее состояние
PORTB = (1<<time);
if(time++>7)time=0;
}
const unsigned char anim_arr[5]={0x00,0x01,0x03,0x07,0x0F};
void eff_anim(){ //эффект анимации, заданной последовательностью кадров
static unsigned char time=0;PORTB = (1<<time);
if(time++>7)time=0;
PORTB = anim_arr[time];
if(time++>5)time=0;
}
int main(){
...
unsigned char mode=0;
while(1){
if(test_button()){if(mode++>2)mode=0;} //по нажатию кнопки - изменение режима
switch(mode){
case 0: eff_run(); break;
case 1: eff_anim(); break;
default:;
}
...
}
}
Разумеется, тут много чего можно оптимизировать, но для демонстрации сойдет.
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Сб дек 20, 2014 11:56:43
Pink-Pank
da-nie писал(а):
sei
rjmp куда-т
А в промежуток между этими командами рано или поздно придёт ещё одно прерывание.

Операция же не атомарная.

А в промежуток между этими командами никогда ничего не придет. Т.к. после sei гарантированно выполняется следующая за ней команда. Смотрите описание команд от Атмел
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Сб дек 20, 2014 12:22:26
da-nie
А что конкретно там написано по поводу sei? В моих источниках (книжка "Микроконтроллеры Tiny и Mega") указано только лишь, что после выхода из прерывания процессор гарантированно выполнит ещё одну команду программы. Но ничего не сказано, что после разрешения прерывания не будет сгенерировано прерывание, если флаг необходимости прерывания установлен.
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Сб дек 20, 2014 12:38:14
Pink-Pank
Скачайте официальную документацию от Атмел с описанием команд. Все увидите сами.
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Сб дек 20, 2014 12:58:06
da-nie
В даташите вот так сходу я также не вижу ничего подобного. Но, быть может, это потому, что далеко не все изучали в школе и институте английский и способны на нём хорошо читать. Поэтому я и спрашиваю, что именно там написано.
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Сб дек 20, 2014 13:15:47
akl
Re: Можно ли выйти из прерывания не по reti ?
Добавлено: Сб дек 20, 2014 13:18:55
Pink-Pank
Вам нужен не даташит на конкретный контроллер, а общий документ по системе команд. Я сейчас не имею доступа к компьютеру, поэтому не могу точно сказать ни названия документа, ни что там написано. Воспользуйтесь гулом.
Дословно в переводе на русский там написано, что команда, следующая за sei, будет выполнена однозначно и бесприкословно сразу за ней.