attiny85 сбрасывает себя вместо процедуры пробуждения

У меня есть digispark attiny85, и я использование SLEEP_MODE_PWR_DOWN для перехода в спящий режим и пробуждения с помощью внешнего прерывания на выводе 2. Я пытаюсь подсчитать количество полученных прерываний с помощью приведенного ниже кода.

Проблема заключается в том, что при каждом низком сигнале на выводе 2 attiny85 сам сбрасывает (перезагружает) вместо пробуждения процессора и продолжает работу с того места, где остановился. Я могу определить это, увидев, как светодиод мигает 3 раза (как в setup()) при каждом низком сигнале.

Есть ли ограничения на это оборудование? Как я могу только просыпаться из сна и не перезагружаться? Буду признателен, если вы приведёте мне пример.

#include <avr/interrupt.h>
#include <avr/sleep.h>

//изменено с http://playground.arduino.cc/Learning/arduinoSleepCode

int ledPin = 0;            // светодиод подключен к цифровому выводу 0
int interruptPin = 1;      // Светодиод, показывающий действие прерывания
int wakePin = 2;            // активный НИЗКИЙ, кратковременно заземлите этот контакт, чтобы проснуться
unsigned int counter = 0;

void setup(){
  pinMode(ledPin, OUTPUT);         // устанавливаем цифровой вывод как выход
  pinMode(interruptPin, OUTPUT);   // устанавливаем цифровой вывод как выход
  pinMode(wakePin, INPUT_PULLUP);        // устанавливаем цифровой вывод в качестве входа
  digitalWrite(wakePin, HIGH);
  counter = 0;
  //моргаем несколько раз, чтобы мы могли определить загрузку & петля
     digitalWrite (interruptPin, HIGH);    // устанавливаем цифровой вывод как выход
    delay(250);
     digitalWrite (interruptPin, LOW);    // устанавливаем цифровой вывод как выход
    delay(250);
     digitalWrite (interruptPin, HIGH);    // устанавливаем цифровой вывод как выход
    delay(250);
     digitalWrite (interruptPin, LOW);    // устанавливаем цифровой вывод как выход
    delay(250);
     digitalWrite (interruptPin, HIGH);    // устанавливаем цифровой вывод как выход
    delay(250);
     digitalWrite (interruptPin, LOW);    // устанавливаем цифровой вывод как выход
    delay(250);
}


void sleepNow(){         

    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // здесь устанавливается спящий режим
    sleep_enable();                          // включает бит сна в регистре mcucr, поэтому сон возможен
    attachInterrupt(0, wakeUpNow, LOW);     // используем прерывание 0 (контакт 2) и запускаем функцию WakeUpNow, когда контакт 2 становится НИЗКИМ
    digitalWrite(interruptPin, LOW); 

    sleep_mode();                          // здесь устройство фактически переведено в спящий режим!!

    sleep_disable();                       // первое, что делаем после пробуждения: отключаем сон...
    detachInterrupt(0);                    // отключает вывод прерывания 3, поэтому код WakeUpNow не будет выполняться в обычное время работы.
    delay(250);                           // ждем 2 секунды. чтобы люди могли заметить светодиод прерывания, показывающий, что прерывание обработано
    digitalWrite (interruptPin, HIGH);       // выключаем светодиод прерывания

}



void wakeUpNow(){        // здесь прерывание обрабатывается после пробуждения

  //выполняем код после пробуждения перед возвратом к функции цикла()
  // таймеры и код, использующий таймеры (serial.print и т. д.), здесь работать не будут.
 digitalWrite(interruptPin, HIGH);
}


void loop(){
   digitalWrite(interruptPin, HIGH);
  //digitalWrite(ledPin, ВЫСОКИЙ); // включаем светодиод
  counter++;
  delay(5000);                           // ждем секунду
  sleepNow();                      // здесь вызывается функция сна
}

, 👍2

Обсуждение

Просто мысль: разве логика detachInterrupt не должна быть в методе wakeUpNow?, @Filip Franik

Я так не думаю, Филипп, в большинстве примеров в Интернете, как вы можете видеть, WakeUpNow() использовать необязательно. большинство людей используют эту пустую функцию., @ozkolonur


1 ответ


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

0

Я нашел это и могу подтвердить, что оно работает. на digispark attiny85.

void sleepTillChg() {  // Сток 0,02 мА во время сна здесь
    GIMSK |= _BV(PCIE);                     // Включить прерывания по смене контактов
    PCMSK |= _BV(PCINT0);                   // Используем PB0 (был PB3) в качестве контакта прерывания
    // Отключаем ненужную периферию
    ADCSRA &= ~_BV(ADEN);                   // АЦП выключен
    ACSR |= _BV(ACD); // Отключаем аналоговый компаратор

    set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // заменяет приведенный выше оператор
    sleep_enable();                         // Устанавливает бит включения режима сна в регистре MCUCR (SE BIT)
    sei();                                  // Разрешаем прерывания
    sleep_cpu();                            // спать... Зззз

    cli();                                  // Запретить прерывания
    PCMSK &= ~_BV(PCINT0);                  // Выключаем PB0 (был PB3) как вывод прерывания
    sleep_disable();                        // Очистить бит SE
    sei();                                  // Разрешаем прерывания
}

ISR(PCINT0_vect) {
    // Это вызывается, когда происходит прерывание, но нам не нужно ничего в нем делать
}

кредиты должны идти https://www.instructables.com/id/3-Minute-Game-Timer/

,