Подвисание при использовании прерываний.

alakond
Offline
Зарегистрирован: 24.01.2014
#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 тоже перестает мигать. 

Logik
Offline
Зарегистрирован: 05.08.2014

Вызов Serial.print из прерывания - уже жесть, из основного цикла и из прерывания - гарантирован плавающий глюк. Код Serial.print не потокобезопасен. Вызывать тока из основного цикла. А вылетает когда в основном цикле начали делать Serial.print, произошло прерывание и тоже вызвало Serial.print.

 

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

На какой плате тестируете? Я на Меге для отладки постоянно Serial.print из прерывания вызываю. Уже даже переживать по этому поводу перестал - ни разу глюка не было...

Nerwin
Offline
Зарегистрирован: 23.12.2014

Logik пишет:

когда в основном цикле начали делать Serial.print, произошло прерывание и тоже вызвало Serial.print.

Можно на время выполнения print основного цикла вырубать прерывания, правда тогда можно что-то важное пропустить

Maverik
Offline
Зарегистрирован: 12.09.2012

Gippopotam пишет:

На какой плате тестируете? Я на Меге для отладки постоянно Serial.print из прерывания вызываю. Уже даже переживать по этому поводу перестал - ни разу глюка не было...

дык у него же два прерывания одновременно кативированы, плюс еще delay() который тоже рекомендуют избегать.

чего гадать, нужно убрать обращения serial и посмотреть чо получится.

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Maverik пишет:

Gippopotam пишет:

На какой плате тестируете? Я на Меге для отладки постоянно Serial.print из прерывания вызываю. Уже даже переживать по этому поводу перестал - ни разу глюка не было...

дык у него же два прерывания одновременно кативированы, плюс еще delay() который тоже рекомендуют избегать.

чего гадать, нужно убрать обращения serial и посмотреть чо получится.

Согласен

Coolerr
Offline
Зарегистрирован: 30.06.2014

От делеев в основном цикле тоже бы избавиться, я тут недавно наступил на эти грабли UART тормозил, а задержка было всего 200мс, а у тебя целых две секунды т.е прога тупо эти 2 секунды висит нихрена не делая и прерывания не отлавливая.

step962
Offline
Зарегистрирован: 23.05.2011

Coolerr пишет:

От делеев в основном цикле тоже бы избавиться, я тут недавно наступил на эти грабли 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;
		}
	}
}

 

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Скорее всего проблема в том, что два прерывания могут наступить одновременно.

Я думаю следует попробовать в обработчике энкодера запрещать прерывания от кнопки (все равно одновременно не бывает).

bwn
Offline
Зарегистрирован: 25.08.2014

Не могут прервания наступить одновременно. В первую очередь выполняется прерывание имеющее более высокий приоритет. Самый высокий приоритет у Reset.

MacSim
Offline
Зарегистрирован: 28.11.2012

Возможно прерывания вызываются на столько часто, что основная программа не выполняется:

Во время выполнения прерывания1 возникает этоже прерывание 1а, 1а ставится в очередь, по завершении 1-го выполняется 1а и снова возникает прерывание.