Использование INT2/3 на Arduino Micro (Atmega32u4)

В моем проекте используются почти все контакты на этой плате, и мне нужен контакт прерывания для чтения состояния радио (а не для опроса). Я использую I2C, так что остаются INT2 и INT3, которые являются контактами TX и RX для USB/Serial1. Согласно документации, отключение последовательного порта с помощью Serial.end() должно позволить мне получить контроль над этими выводами. Однако использование выводов в качестве обработчиков прерываний не работает. Вот пример скетча:

static int ledpin = 13;
volatile byte state = LOW;

void func()
{
  state = !state; 
}

void setup() {
  Serial.end();

  pinMode(ledpin, OUTPUT);

  // INT2
  pinMode(0, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(0), func, CHANGE);

  // INT3
  pinMode(1, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(1), func, CHANGE);
}

void loop() {
  digitalWrite(ledpin, state); 
}

Этот пример в основном скопирован с веб-сайта Arduino. Все остальные прерывания работают нормально, только INT2 и INT3 нет.

Есть ли способ использовать эти прерывания?

, 👍1

Обсуждение

Откуда ты знаешь, что они не работают? Если срабатывают оба прерывания, то вы этого не заметите. «Последовательный» — это последовательный порт через USB на компьютер. «Serial1» — это аппаратный последовательный порт на контактах 0 и 1. Если вы не используете «Serial1», то контакты 0 и 1 еще не инициализированы как последовательный порт и являются обычными цифровыми контактами, как и любые другие. Удалите Serial.end. Это должно работать, вы можете увеличить байт и распечатать байт на последовательном мониторе (используя USB «Serial»). Есть также прерывания pcint: http://www.pighixxx.com/test/portfolio-items/micro/ Является ли !LOW таким же, как HIGH, или это предположение., @Jot


2 ответа


2

Ваша проблема не в пинах или коде, а в устранении дребезга сигналов. Я изменил метод func() на следующий:

void func()
{
  static uint32_t lastChange = 0; // Обратите внимание, что millis() не изменяется внутри ISR, но может быть прочитана
  if (millis() - lastChange > 100)
  {
    state = !state;
  }
  lastChange = millis(); // Установить новое значение
}

который будет игнорировать ложные прерывания, если они происходят в пределах 100 мс друг от друга. Это решает проблему, которую вы видите, я протестировал ее на Arduino Micro, который у меня валяется.

,

0
/*
2019-08-29 Никола Бернарделли. Просматривая техническое описание ATmega32U4 и применяя шаги
для настройки аналогового компаратора на плате Pro Micro.

При этом я понимаю, что аналого-цифровой преобразователь должен быть выключен.
Итак, если вам нужно придерживаться ATmega32U4, но вам также нужен АЦП (как я делаю в своем текущем проекте), вам, возможно, придется добавить
схему с компаратором, например LM393 или LM339, вместо использования встроенного аналогового компаратора.
Отключение этого прерывания и повторная активация АЦП не были добавлены в этот скетч.

Кроме того, не добавлена «реальная» обработка события, вызванного прерыванием, и скетч оставляет возможность очень быстрого
последовательность запросов на прерывание. Возможно, вы захотите проверить (в настоящее время только один) ответ, приведенный здесь:
https://arduino.stackexchange.com/questions/49195/using-int2-3-on-arduino-micro-atmega32u4

[Я хотел спросить / внести свой вклад здесь https://arduino.stackexchange.com/questions/17480/using-analog-comparator-on-atmega32u4
(Я вижу, что ему 3 года 9 месяцев, но его все еще можно "поискать" в Интернете, вот как я туда попал. Я думаю, что сохранение
информация под соответствующим заголовком является лучшим вариантом, чем открытие новой темы.)
Итак, я создал аккаунт, но оказалось, что у меня недостаточно "репутации" там, чтобы комментировать, поэтому я написал в поле редактирования
готов дать ответ, и это тоже не вышло:
«Спасибо за ваш интерес к этому вопросу. Поскольку он привлек некачественные или спам-ответы, которые пришлось удалить,
для публикации ответа теперь требуется 10 очков репутации на этом сайте (бонус от ассоциации не учитывается)».
Так что... в значительной степени шахматный мат. Ну... их правление, их правила.]
*/


#include "Arduino.h"


#ifndef ARDUINO_AVR_PROMICRO
#error This sketch is meant for the Arduino Pro Micro, it is based on the ATmega32U4 Datasheet and the Pro Micro pinout. \
       You might decide to try it on a different ATmega32U4-based board if the pins choice is OK (please check/change the LED pin number).
#endif


#define THIS_BOARD_LED_BUILTIN 17
#define LED_ON_DURATION 200


volatile bool analogCompInterruptToggled;
unsigned long millisLastTrigger;


void setup() {

  Serial.begin(9600);

  analogCompInterruptToggled = false;
  millisLastTrigger = 0;
  pinMode(THIS_BOARD_LED_BUILTIN, OUTPUT);
  digitalWrite(THIS_BOARD_LED_BUILTIN, HIGH);


  /* As per Atmega32U4 Datasheet starting pag 293 (and linked pages). */


  PRR0 &= ~bit(PRADC); // Отключает снижение мощности для АЦП, чтобы использовать входной мультиплексор АЦП.


  /*
     ACME in ADCSRB: When this bit is written logic one and the ADC is switched off (ADEN in ADCSRA is zero),
     the ADC multiplexer is connected to the negative input to the Analog Comparator. When this bit is written
     logic zero, the Bandgap reference is connected to the negative input of the Analog Comparator
  */
  ADCSRA &= ~bit(ADEN); /* Switches off the ADC so we can use the Muxer with the Analog Comparator instead of the ADC. */
  ADCSRB |= bit(ACME);  /* With the line above => the ADC multiplexer is connected to the negative input of the Analog Comparator. */
                        /* See table at page 295: ACME 0 or (ACME 1 and ADEN 1) => bandgap ref as the Analog Comparator Negative Input. */


  /*                                        ******** A0 NEGATIVE INPUT ********
     Let's select pin ADC7 = A0 as the negative input to the Analog Comparator, as per pag 295 of the ATmega32U4 DataSheet:
     ACME to 1 done above, ADEN to 0 done above, MUX2..0 to 111.
  */
  ADMUX |= 0b00000111;


  /*                                        ******** D7 POSITIVE INPUT ********
     When this bit is set, a fixed bandgap reference voltage replaces the positive input to the Analog Comparator.
     When this bit is cleared, AIN0 is applied to the positive input of the Analog Comparator.
  */
  ACSR &= ~bit(ACBG); // AIN0 = D7 => положительный вход аналогового компаратора


  /* Pages 294-295 of the ATmega32U4 Datasheet. */
  ACSR &= ~bit(ACIC); /* Analog Comparator Input Capture disabled. */


  /* Comparator Interrupt trigger mode. 0-0 => TOGGLE, meaning any change; 1-0 => FALLING; 1-1 => RISING). */
  // ACSR &= ~bit(ACIS1); ACSR &= ~бит(ACIS0); // ПЕРЕКЛЮЧАТЬ
  // ACSR |= бит(ACIS1); ACSR &= ~бит(ACIS0); // ПАДЕНИЕ
     ACSR |= bit(ACIS1);  ACSR |= bit(ACIS0);  // ПОДЪЕМ


  DIDR1 &= ~bit(AIN0D); /* It's actually the rightmost bit, we could write DIDR1 &= ~1 */
  /*
     When this bit is written logic one, the digital input buffer on the AIN0 pin is disabled. [...]
     When an analog signal is applied to the AIN0 pin and the digital input from this pin is not needed,
     this bit should be written logic one to reduce power consumption in the digital input buffer.
  */


  ACSR |= bit(ACIE);
  SREG |= bit(SREG_I);
  /* When the ACIE bit is written logic one and the I-bit in the Status Register is set,
     the Analog Comparator interrupt is activated. When written logic zero, the interrupt is disabled.
  */
}


ISR(ANALOG_COMP_vect) {
  analogCompInterruptToggled = true;
}


void loop() {
  // поместите сюда ваш основной код для многократного запуска:
  if (analogCompInterruptToggled) {
    analogCompInterruptToggled = false;
    digitalWrite(THIS_BOARD_LED_BUILTIN, LOW);
    millisLastTrigger = millis();
    Serial.print("toggled - millis() == ");
    Serial.println(millisLastTrigger);
  }
  else if (millis() > millisLastTrigger + LED_ON_DURATION) {
    digitalWrite(THIS_BOARD_LED_BUILTIN, HIGH);
  }
}
,