Всем привет
Вот возникла у меня такая задачка - есть обработчик прерываний, который обрабатывает опред. события типа нажатие кнопок.
Хочется, чтобы после события начинал исполняться другой кусок программы, а не тот из которого вышли в прерывание.
Собственно вопрос - можно ли уйти из прерывания по rjmp ?
Как нужно почистить стек ? Просто заново настроить указатель стека ?
Флаги какие-то надо чистить ?
Что еще сделать ?
Есть ли разница между ATTiny13 и ATMega8 ?
придумал новые детальки : оптимистор и пессимистор ...
осталось придумать для чего они нужны ))))
Да, можно уйти по rjmp.
Только после такого перехода у Вас останутся выключенными прерывания, включить которые обратно можно командой sei.
И в стеке останется адрес возврата. Можно либо заново проинициализировать стек, либо просто увеличить указатель стека на размер сохраненного адреса. Это обычно один-два байта. Зависит от размера флеш данной модели контроллера.
Указанные Вами МК с точки зрения логики и организации ядра не отличаются. Отличаются в части периферии, тактовых частот и количества ног.
В ATtiny13 и ATmega8 счетчик команд двухбайтный. Соответственно, если так уж надо прыгать из обработчика в середину программы, надо убрать из стека 2 байта, поднять флаг I регистра SREG и прыгать.
А они непременно будут, ибо прерывание придёт в произвольный момент программы, когда она может что-то сама класть на стек или ещё куда. И выход не в ту же функцию из прерывания приведёт к наслоению не завершённых задач.
sei
rjmp куда-т
А в промежуток между этими командами рано или поздно придёт ещё одно прерывание. Операция же не атомарная.
Последний раз редактировалось da-nie Пт дек 19, 2014 21:08:34, всего редактировалось 1 раз.
Если придет "нормальное" прерывание - ничего страшного, Вы же не боитесь, что оно придет в момент вызова процедуры или if'а. Впрочем, если такое же, все равно ничего страшного, себя-то оно из стека вычищает перед разрешением. Ну прыгнет в другое место, так по логике Miw так и должно быть.
Miw писал(а):Всем привет
Вот возникла у меня такая задачка....
на азме можно всё, что может МК. Но...
как уже прозвучало выше - Вы мягко говоря создаёте сами себе проблемы. Тактовая у Вас небось несколько мегагерц?
несколько миллионов(!) раз в секунду выполняются однобайтовые команды. и событие от клавы (а это человек как я понимаешь), может произойти максимум пару десятков в секунду. У вас разброс десятки-сотни тысяч(!) тактов между максимально возможными нажатиями... Ну а нафига Вам в этой ситуации всё нафик резко прекращать? если сюда добавить ышо тему дребезга(вряд-ли Вы наворотили триггера по входам клавы) - то вообще не понятно Ваше стремление...
дело конечно же житейское. каждый извращается как может...
но вот с консерваторией как то не айс выходит...
да я вот сам думаю, что не айс прыгать куда-то, но все же
Частота всего 0,6 MHz, мне пока хватает ))
Прерывания от таймера каждые 0,1 секунды
Вот чего делаю - гирлянда RGB, Тинька 13, в памяти есть команды - просто светить, мигать, fade in, fade out, бегущий огонь и т.п.
Основной цикл читает команду и потом ее исполняет, время задается в счетчиках и кратно 10 сек,
то бишь каждая команда выполняется как отдельная функция и длится 10 секунд * каунтер.
Есть две кнопки, при нажатии и удержании первой хочу сделать экспресс переход на чтение новой команды.
Посоветуйте, может быть есть более простой способ реализовать такое поведение
P.S. Выход из прерывания я сделал - по первой кнопке все работает нормально, а вот при удержании второй делаю переход на Reset
С этим переходом что-то глючит пока, хотя казалось бы тут все должно работать )))
Видимо сразу же вслед обрабатывается одинарное нажатие на эту же кнопку
придумал новые детальки : оптимистор и пессимистор ...
осталось придумать для чего они нужны ))))
Мне кажется, вы не тот камушек выбрали для таких задач. У тини13 только два выхода шим, что маловато для полноценного управления RGB. Или же надо будет извращаться с программным шимом
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);//переходим к следующему эффекту
}
А в промежуток между этими командами рано или поздно придёт ещё одно прерывание. Операция же не атомарная.
А в промежуток между этими командами никогда ничего не придет. Т.к. после sei гарантированно выполняется следующая за ней команда. Смотрите описание команд от Атмел
А что конкретно там написано по поводу sei? В моих источниках (книжка "Микроконтроллеры Tiny и Mega") указано только лишь, что после выхода из прерывания процессор гарантированно выполнит ещё одну команду программы. Но ничего не сказано, что после разрешения прерывания не будет сгенерировано прерывание, если флаг необходимости прерывания установлен.
В даташите вот так сходу я также не вижу ничего подобного. Но, быть может, это потому, что далеко не все изучали в школе и институте английский и способны на нём хорошо читать. Поэтому я и спрашиваю, что именно там написано.
Вам нужен не даташит на конкретный контроллер, а общий документ по системе команд. Я сейчас не имею доступа к компьютеру, поэтому не могу точно сказать ни названия документа, ни что там написано. Воспользуйтесь гулом.
Дословно в переводе на русский там написано, что команда, следующая за sei, будет выполнена однозначно и бесприкословно сразу за ней.