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

Работа с прерываниями PCINIT Atmega88

Здравствуйте нужна помощь в применении внешнего прерывания PCINIT.

 

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

И есть внешняя кнопка, которая переводит в режим ожидания. Вот на эту ногу и надо сделать прерывание, нажата она может быть в любой момент исполнения программы, даже перед включением.

Как мне понятно, что эта функция работает про простому изменение уровня. То есть нажали кнопку произошло прерывание, отпустили, опять произошло прерывание?

Подскажите как можно организовать работу с этим прерыванием, чтобы при нажатии конпки мы выполняли один и тот же цикл (например мигание светодиодом), а при отпускании начинали тот цикл в котором произошло прерывание?

И еще такой вопрос это прерывание всё таки на весь порт, или на отдельную ногу? меня смущает, то что мне CAVR предлагает создать свою функцию по этому прерываню, как весь порт:

interrupt [PC_INT2] void pin_change_isr2(void)
{
// Place your code here

}

Но при этом есть настройка указать какую ногу использовать :

// Interrupt on any change on pins PCINT16-23: On
EICRA=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EIMSK=(0<<INT1) | (0<<INT0);
PCICR=(1<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);
PCMSK2=(1<<PCINT23) | (0<<PCINT22) | (0<<PCINT21) | (0<<PCINT20) | (0<<PCINT19) | (0<<PCINT18) | (0<<PCINT17) | (0<<PCINT16);
PCIFR=(1<<PCIF2) | (0<<PCIF1) | (0<<PCIF0);

 

Поделиться сообщением


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

... функция работает про простому изменение уровня. То есть нажали кнопку произошло прерывание, отпустили, опять произошло прерывание?

Да, прерывание возникает при каждом изменении уровня.

 

...как можно организовать работу с этим прерыванием, чтобы при нажатии конпки мы выполняли один и тот же цикл (например мигание светодиодом), а при отпускании начинали тот цикл в котором произошло прерывание?

При возникновении прерывания проверяете состояние порта: при 1-выполняется одна задача, при 0-другая.

 

... это прерывание всё таки на весь порт, или на отдельную ногу?

В регистре PCICR – Pin change interrupt control registe разрешаются прерывания на группу выводов, а в регистрах PCMSK0(1,2) – Pin change mask register 0(1,2) на каждый конкретный вывод порта.

В ДШ все описано.

Поделиться сообщением


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

При возникновении прерывания проверяете состояние порта: при 1-выполняется одна задача, при 0-другая.

Это то понятно, у меня вопрос был в другом как выйти из цикла по этому прерыванию и вернуться в начало этого цикла обратно.

Поясню:

Возникло прерывание на порту стало 1, на это у меня прописана функция мигать светодиодом. При этом программа выполняла какую то другую задачу из моих трёх основных циклов. Возникло повторное прерывание, я проверил, что стало 0, и мне надо вернуться именно в тот цикл (причем в начало), откуда я вышел.

Мне это видится так:

в функции

interrupt [PC_INT2] void pin_change_isr2(void)

я пишу, цикл в котором мигаю светодиодом, пока на этой ноге 1.

Как только там стало 0, я выхожу из цикла и прописываю условия перехода обратно в ранее исполняемые циклы:

начинаю сравнивать значения переменных которые меняются в двух первых циклах.

Если предположим первая переменная не приняла значение 1, то я ставлю на этот цикл метку М1: , и отправляюсь туда операцией goto M1.

Если значения переменных во втором цикле 0, то ставлю туда метку М2:, и отправлюсь туда goto M2.

Если значения переменных обоих циклов приняли значения 1, то значил в момент прерывания выполнялся третий цикл, и я отправляюсь туда goto M3.

 

правильное ли такое рассуждение?

 

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

Поделиться сообщением


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

правильное ли такое рассуждение?

не правильное.

volatile char mode = 0;

interrupt [PC_INT2] void pin_change_isr2(void){
   if(PINB & (1<<PB0))
      mode = 1;
   else
      mode = 0;
}

int main(void){
   while(1){ // главный цикл
      while(mode == 0){
         // цикл первой задачи
      }
      while(mode == 1){
         // цикл второй задачи
      }
   }
}

как-то так в общих чертах

Поделиться сообщением


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

не правильное.

 

как-то так в общих чертах

Спасибо, да я уже почти разобрался. Точнее подсказали, что после прерывания код продолжает исполнятся с того момента где был прерван, я этого не знал, поэтому и спрашивал: как мне вернуться в то место где произошло прерывание?

Поделиться сообщением


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

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

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

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

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

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

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

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