Внешнее прерывание не работает на 3,3 В atmega168

Я сделал плату на 3,3 В и установил как atmega328p (которую я снял с 3,3 В pro mini), так и atmega168, которую я загрузил (используя USBtinyISP, выбрав плату "Arduino Pro или Pro Mini" и "atmega168 (3,3 В, 8 МГц") .

Все отлично работает с atmega328 — код работает и прерывания тоже — какая функция выводит Arduino из спящего режима при повышении INT0.

Однако на Atmega168 прерывание не работает. Весь нормальный код работает как положено (связь, инструкции и т.д.), только не прерывание. Когда Arduino переходит в спящий режим, я не могу его разбудить, так как прерывание не работает.

Основной код ниже:

#include <avr/sleep.h>//эта библиотека AVR содержит методы, управляющие спящими режимами

byte interruptPin = 2; // Включаем/выключаем плату
unsigned long shutDownTimer = 0; // Таймер для выключения


void setup() {
  Serial.begin(57600);
  pinMode(interruptPin, INPUT); // Установите вывод d2 на вход, используя встроенный подтягивающий резистор
  Serial.println("Starting");

}

void loop() {
  Serial.println("Awake");
  delay(1000);

  // Управление отключением
  if (digitalRead(interruptPin) == LOW ) {
    Serial.println("Shutdown detected");
    shutDownTimer = millis();
    while (digitalRead(interruptPin) == LOW ) {
      if (millis() - shutDownTimer > 1000) {
        Serial.println("sleep mode triggered");
        Going_To_Sleep();
      }
    }
  }
}

void Going_To_Sleep() {
  sleep_enable();//Включение спящего режима
  delay(1000);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);//Установка спящего режима, в нашем случае полного сна
  delay(1000); // подождите секунду, чтобы светодиод погас перед тем, как перейти в спящий режим
  attachInterrupt(0, wakeUp, RISING);//присоединение прерывания к контакту d2

  Serial.println("Interrrupt attached");//Печать сообщения на последовательный монитор
  sleep_cpu();//активация спящего режима
  Serial.println("just woke up!");//следующая строка кода, выполняемая после прерывания

}

void wakeUp() {
  sleep_disable();//Отключаем спящий режим
  detachInterrupt(0); //Удаляет прерывание от контакта 2;
  Serial.println("Interrrupt Fired - wakeup");//Печать сообщения на последовательный монитор

}

Вместо использования "attachInterrupt(0, wakeUp, RISING);" Я также пробовал следующее, которое также не работает:

attachInterrupt(INT0, wakeUp, RISING);
attachInterrupt(digitalPinToInterrupt(interruptPin), wakeUp, RISING);
attachInterrupt(32, wakeUp, RISING);  // так как это контакт чипа? Радуйся, Мария
attachInterrupt(2, wakeUp, RISING);  //очевидно, это не сработает, Радуйся, Мария 2

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

, 👍0

Обсуждение

Ваш Serial.println внутри ISR подвергает вас опасности заблокироваться там. Попробуйте вместо этого использовать светодиод или что-то в этом роде., @timemage


2 ответа


Лучший ответ:

0

Согласно техническому описанию Atmega168 :

Обратите внимание, что распознавание падения или роста прерывания по фронту на INT0 или INT1 требуют наличия тактового генератора ввода-вывода, описанного в Раздел 6.1 «Системы тактирования и их распределение» на стр. 23. Обнаружено прерывание низкого уровня на INT0 и INT1 асинхронно. Это означает, что это прерывание можно использовать для пробуждения части также из режимов сна, отличных от режима ожидания. Часы ввода-вывода останавливаются во всех спящих режимах, кроме режима ожидания

Другими словами, только прерывание LOW выводит его из спящего режима.

Сказав это, Atmega328P действительно выходит из спящего режима с прерыванием нарастания или спада, как я ранее подтвердил Atmel, однако я не могу с уверенностью сказать, применимо ли это улучшение (по сравнению с тем, что указано в техническом описании). до 168.

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

Кроме того, не выполняйте последовательную печать внутри ISR. Современные версии библиотеки справляются с этим лучше, чем в прошлом, но это все еще может быть проблемой. Как предложено в комментарии, попробуйте мигать светодиодом, а не печатать что-то. Или ничего не печатать, ведь вы что-то печатаете, когда оно просыпается. Зачем печатать что-то лишнее внутри ISR? Это просто напрашивается на неприятности.

,

Я не видел в техпаспорте Atmega328P информации о том, что он работает с подъемом, а Atmega168 не работает с подъемом. Однако он действительно работает в соответствии с тем, что вы говорите. Мне просто нужно использовать Atmega328 для этого приложения. Спасибо., @Troy Cados


1

В зависимости от того, какой сигнал вы используете для пробуждения Arduino, вы также можете обнаружить, что прерывания по изменению контакта являются альтернативой прерываниям, инициируемым фронтом, которые вы используете в настоящее время. Обычно они более предсказуемы в своем поведении и менее подвержены нюансам интерпретации таблиц данных. См. https://playground.arduino.cc/Main/PinChangeInterrupt/ примеры их использования.

,