Подвисание при использовании прерываний.
- Войдите на сайт для отправки комментариев
Чт, 25/12/2014 - 00:45
#define encoder0PinA 2
#define encoder0PinB 4
#define encoder0PinSW 3
#define LED 13
volatile long encoder0Pos = 0;
void setup() {
pinMode(encoder0PinA, INPUT);
digitalWrite(encoder0PinA, HIGH); // turn on pullup resistor
pinMode(encoder0PinB, INPUT);
digitalWrite(encoder0PinB, HIGH); // turn on pullup resistor
pinMode(encoder0PinSW, INPUT);
digitalWrite(encoder0PinSW, HIGH); // turn on pullup resistor
attachInterrupt(0, doEncoder, CHANGE);
attachInterrupt(1, doEncoderSW, CHANGE);
pinMode(LED, OUTPUT);
Serial.begin (9600);
// Serial.println("start"); // a personal quirk
}
void loop()
{
digitalWrite(LED, HIGH);
delay(1000);
digitalWrite(LED, LOW);
delay(1000);
Serial.println ("LED1");
}
void doEncoder() {
if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
encoder0Pos--;
} else {
encoder0Pos++;
}
Serial.println (encoder0Pos);
}
void doEncoderSW(){
if (digitalRead(encoder0PinSW) == LOW){
Serial.println ("SW");
}
else {
}
}
В какой то момент времени SerialPrintLn подвисает, но, самое противное, что LED = 13 тоже перестает мигать.
Вызов Serial.print из прерывания - уже жесть, из основного цикла и из прерывания - гарантирован плавающий глюк. Код Serial.print не потокобезопасен. Вызывать тока из основного цикла. А вылетает когда в основном цикле начали делать Serial.print, произошло прерывание и тоже вызвало Serial.print.
На какой плате тестируете? Я на Меге для отладки постоянно Serial.print из прерывания вызываю. Уже даже переживать по этому поводу перестал - ни разу глюка не было...
когда в основном цикле начали делать Serial.print, произошло прерывание и тоже вызвало Serial.print.
Можно на время выполнения print основного цикла вырубать прерывания, правда тогда можно что-то важное пропустить
На какой плате тестируете? Я на Меге для отладки постоянно Serial.print из прерывания вызываю. Уже даже переживать по этому поводу перестал - ни разу глюка не было...
дык у него же два прерывания одновременно кативированы, плюс еще delay() который тоже рекомендуют избегать.
чего гадать, нужно убрать обращения serial и посмотреть чо получится.
На какой плате тестируете? Я на Меге для отладки постоянно Serial.print из прерывания вызываю. Уже даже переживать по этому поводу перестал - ни разу глюка не было...
дык у него же два прерывания одновременно кативированы, плюс еще delay() который тоже рекомендуют избегать.
чего гадать, нужно убрать обращения serial и посмотреть чо получится.
Согласен
От делеев в основном цикле тоже бы избавиться, я тут недавно наступил на эти грабли UART тормозил, а задержка было всего 200мс, а у тебя целых две секунды т.е прога тупо эти 2 секунды висит нихрена не делая и прерывания не отлавливая.
От делеев в основном цикле тоже бы избавиться, я тут недавно наступил на эти грабли UART тормозил, а задержка было всего 200мс, а у тебя целых две секунды т.е прога тупо эти 2 секунды висит нихрена не делая и прерывания не отлавливая.
С чего бы это? В delay прерывания не маскируются:
void delay(unsigned long ms) { uint16_t start = (uint16_t)micros(); while (ms > 0) { if (((uint16_t)micros() - start) >= 1000) { ms--; start += 1000; } } }Скорее всего проблема в том, что два прерывания могут наступить одновременно.
Я думаю следует попробовать в обработчике энкодера запрещать прерывания от кнопки (все равно одновременно не бывает).
Не могут прервания наступить одновременно. В первую очередь выполняется прерывание имеющее более высокий приоритет. Самый высокий приоритет у Reset.
Возможно прерывания вызываются на столько часто, что основная программа не выполняется:
Во время выполнения прерывания1 возникает этоже прерывание 1а, 1а ставится в очередь, по завершении 1-го выполняется 1а и снова возникает прерывание.