Atmega8 + sleep + attachInterrupt

Тема в разделе "Arduino & Shields", создана пользователем Salk, 24 окт 2016.

  1. Salk

    Salk Гик

    Приветствую! Начал изучать данные функции только сейчас, так раньше в проектах этого не требовалось и сразу столкнулся с затруднениями. 'Шью Atmega8 через ISP Arduino UNO. Atmega8 работает на внутреннем кварце 1 МГц'.
    Первое: стандартным, "доступным" для большинства пользователей, методом сна
    Код (C++):
    ADCSRA = 0;                             // отключить АЦП
      set_sleep_mode (SLEEP_MODE_PWR_DOWN);   // выбор режима сна
      // noInterrupts ();                     // выключить прерывания
      // interrupts ();                       // включить прерывания
      sleep_enable();                         // разрешить сон
      sleep_cpu ();                           // спать цп
    удалось снизить потребление с 8 мА всего до 5 мА. Изучая данную статью, не смог понять строки:
    Код (C++):
    // turn off brown-out enable in software
      MCUCR = bit (BODS) | bit (BODSE);
      MCUCR = bit (BODS);
    Откуда берется "BODS" ? Компилятор требует его объявить. Как снизить потребление еще хоть на чуть-чуть меньше?

    Второе: неудача с прерываниями. На Atmega8 два прерывания - INT0 (PD2) и INT1 (PD3), 1 и 32 ноги, если смотреть по корпусу TQFP32. Пишу следующий тестовый код:
    Код (C++):
    #include <avr/sleep.h>

    #define LED A5        // PC5 - светодиод
    #define PUSK 3        // PD3 - запуск - внешнее прерывание INT1
    #define GABARIT 4     // PD4 - включение габаритов
    #define STOP_MOTOR 2  // PD2 - глохнет двигатель - внешнее прерывание INT0
    #define DXO_1 9       // PB1 - управление первым ДХО
    #define DXO_2 10      // PB2 - управление вторым ДХО

    volatile int state = LOW;

    void setup()
    {
      pinMode(LED, OUTPUT);
      pinMode(DXO_1, OUTPUT);
      pinMode(DXO_2, OUTPUT);
      pinMode(PUSK, INPUT);
      pinMode(GABARIT, INPUT);
      pinMode(STOP_MOTOR, INPUT);

      digitalWrite(DXO_1, LOW);
      digitalWrite(DXO_2, LOW);

      // atmega_sleep(); // сон

      // вызываем прерывание
      attachInterrupt(INTF0, ddd, RISING); // с низкого уровня на высокий
    // INTF0, менял на PUSK(3) и STOP_MOTOR(2) - эффект тот же
    }

    void loop()
    {
      // меняем состояние светодиода
      digitalWrite(LED, state);
    }

    void ddd()
    {
      state = !state;
    }

    void atmega_sleep()
    {
      ADCSRA = 0;                             // отключить АЦП
      set_sleep_mode (SLEEP_MODE_PWR_DOWN);   // выбор режима сна
      // noInterrupts ();                     // выключить прерывания
      // interrupts ();                       // включить прерывания
      sleep_enable();                         // разрешить сон
      sleep_cpu ();                           // спать цп
    }
    Ничего не происходит, светодиод ноль внимания. Что я делаю не так, куда капать? Спасибо.
    Посмотреть вложение 6478
     

    Вложения:

    • ATmega8A_l.jpg
      ATmega8A_l.jpg
      Размер файла:
      112,6 КБ
      Просмотров:
      554
  2. rkit

    rkit Гуру

    В таком сне avr ловят не все типы прерываний, а только по низкому уровню, если память не изменяет. В даташите довольно доступно про сон разжевано.
     
  3. ZAZ-965

    ZAZ-965 Гуру

    BODS and BODSE only available for picoPower devices ATmega48PA/88PA/168PA/328P
     
  4. Salk

    Salk Гик

    Понял спасибо.