2013-08-30 3 views
0

На микроконтроллере, не работающем на какой-либо ОС, когда он ввел процедуру и занят выполнением каких-то длинных циклов, как я могу заставить микроконтроллер преждевременно отказаться от этой процедуры (т.е. вернуться к вызывающей процедуре) в качестве ответа на прерывание (например, тот, который генерируется, когда пользователь нажал кнопку)?Как прервать процесс на микроконтроллере с прерыванием?

Есть ли решение лучше: 1) опроса кнопка или общие переменные между петлями, 2) вручную модифицирующего адрес возврата в стеке, 3), используя операционную систему, и 4) жесткое кодирование POP и Инструкции JUMP в ISR?

Большое спасибо!

+1

Непонятно, почему вы хотите отказаться от рутины, в которой находитесь, и немедленно отбросить назад. Можете ли вы предоставить нам еще один контекст? Ваш собственный вариант 1 и 3 не был бы немедленным, но может работать для ваших нужд, в то время как варианты 2 и 4 являются немедленными, но кажутся хрупкими, как черт. – Ross

ответ

0

Микроконтроллеры используют аппаратные прерывания, которые обычно конфигурируются в первой части вашего кода. Один вывод может быть сконфигурирован как внешнее прерывание и может быть создана корреляционная функция.

Предоставьте нам:

  1. Микроконтроллер вы используете PIC/AVR?
  2. Язык кодирования, использующий C/ASM?
  3. Компилятор, который вы используете? CCS/Hi-tech и т. Д.
  4. У вас есть предпочтительная IDE? MPLAB

Тогда мы можем дать вам более конкретные решения по вашему вопросу

+0

Я думаю, что ваш ответ был бы лучше, как комментарий, хотя ваш представитель еще не дает комментариев. Я также считаю, что вы неправильно понимаете требования OP: я считаю, что просто отказаться от цикла в ответ на кнопку. Я не думаю, что OP ищет «как мне запустить код при нажатии кнопки». @dwelch, похоже, больше зависит от того, что хочет этот вопрос. – Ross

+0

Да, у меня нет комментариев для комментариев. После другого ответа я понял, что я пропустил интерпретацию вопроса. –

1

Если вы хотите длительная функция, которая будет ярлыком прерывания, и сделать это в чистой материи, действительно, есть только один способ вам нужно для создания чистого возврата в функции. Как вы скажете, что функция возврата может иметь прерывание, установите общий ресурс (например, переменную), и цикл цикла/функции может вернуться. Или вы можете опросить какой-то опрос в области переднего плана (например, булавка gpio, таймер и т. Д.).

Обычно то, что вы хотели бы сделать, это нечто иное. Вы разрешаете задачам переднего плана выполнять задачи с низким приоритетом, например, обновлять дисплей или обрабатывать ввод пользователя или что-то в этом роде, и вы не заставляете его преждевременно покидать функции, вместо этого в isr вы обрабатываете все, что нужно, приоритет.

Это или вы можете сделать мини-os, если хотите, и иметь разные потоки, прерывания, которые улавливают аппаратные события, которые необходимо обработать, оставить эту информацию и/или обменять потоки (сохранить копию всех регистров, используемых текущий исполняемый код, замените все регистры кодом обработчика и верните код обработчика). Если isr ​​не меняет местами, тогда будет появляться периодический таймер, который увидит событие приоритета и свопинг, а затем периодический таймер будет заменяться, когда обработчик приоритета работает на холостом ходу. Или обработчик приоритета может вызывать функцию перед ее простоя, чтобы вернуть коммутатор обратно в поток переднего плана. Не сложный, более сложный, чем простой isrs, да, но все же не очень сложный.

0

Для PIC или AVR все ОС имеют тенденцию играть со стеком в любом случае, поэтому я бы рассмотрел вариант 2-4, который будет одним и тем же (за исключением того, что кто-то другой реализовал и протестировал манипуляцию стека.)

Я бы рекомендовал вариант 1, поскольку он был бы самым портативным. Действительно быстрый способ сделать это в вашем коде:

//Consider using static int if all the code is in one file 
int WasButtonPressed; 

//Change this to match your complier for interrupts 
void __attribute__((__interrupt__,no_auto_psv)) _Interrupt 
{ 
    //Rewrite this to use whatever button polling method 
    if (PORTAbits.RA0) { 
     WasButtonPressed = 1; 
    } 
} 

//Testing to see if the interrupt fired and then get out of the function 
#define HANDLE_BUTTON() { if (WasButtonPressed) return; } 

Затем вы можете перец свой цикл с HANDLE_BUTTON(); вызовов.

Смежные вопросы