Почему не работает прерывание после нажатия кнопки

Реализовать обработку прерывания при нажатии кнопки, и самого старта по переднему фронту, вывод прерывания и к которому подключена кнопка 11. Почему не работает прерывание после нажатия кнопки?

#include <PinChangeInterrupt.h>

const uint8_t buttonPin = 11;
volatile bool buttonPressed = false;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  attachPCINT(buttonPin, buttonISR, RISING);
  Serial.begin(9600);
}

void loop() {
  if (buttonPressed) {
    Serial.println("Button pressed!");
    buttonPressed = false;
  }
}

void buttonISR() {
  buttonPressed = true;
}

Модель:

, 👍0

Обсуждение

Нагрузки на осциллографе может быть достаточно, чтобы отсоединить контакт 11. Рассмотрите возможность отсоединения осциллографа от контакта 11 и повторения теста. Если это сработает, я создам ответ с более подробной информацией и вещами, которые можно попробовать., @st2000

Снял осциллограф с контакта 11, все равно не работает, @Good York

Вы пробовали прикрепить Interrupt вместо этого? https://reference.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/ обратите внимание на использование digitalPinToInterrupt и на то, что только определенные контакты на каждой модели могут использоваться как таковые. Если это работает, вероятно, ошибка в вашем PinChangeInterrupt.h или с чем он связан., @Abel

Пробовал attachInterrupt(digitalPinToInterrupt(buttonPin), buttonISR, FALLING) тоже не работает, @Good York

См. https://reference.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/. Обратите внимание, что GPIO 11 НЕ отображается в столбце таблицы со списком выводов, которые можно использовать для генерации прерываний (за исключением nano 33 IOT, Zero и 101) — рекомендуем использовать 2 или 3. Если вы хотите прерывание по переднему фронту, используйте резистор PULL DOWN. https://www.seeedstudio.com/blog/2020/02/21/pull-up-resistor-vs-pull-down-differences-arduino-guide/ Таким образом, нажатие кнопки, а не ее отпускание приводит к int . Наконец, подтвердите, что кнопка будет подпрыгивать., @DrG

Но вывод 11 — это прерывание PCINT3?, @Good York

Какую плату вы используете? Вот хороший простой пример того, как сделать что-то подобное — это может помочь https://roboticsbackend.com/arduino-interrupts/ (мне следовало добавить в этот список хотя бы еще одну плату)., @DrG

Я использую arduino uno, задача следующая: Кнопку нужно подключить к соответствующему пину прерывания PCINT3. Имеется ли в виду задача какие пины запускают прерывание PCINT3, тогда можно было бы подключиться к 3 или 2 пину, @Good York

Я думаю, мне нужно сделать через прерывания смены контакта, что-то вроде этого: void setup () { pinMode (кнопкаPin, INPUT_PULLUP); PCMSK0 |= (1 << PCINT3); PCIFR |= (1 << PCIE0); attachInterrupt(digitalPinToInterrupt(buttonPin), buttonISR, RISING); Серийный.начать(9600); } но это не работает, @Good York

Извините, но я не могу интерпретировать вашу задачу для вас. Вот еще одна хорошая ссылка, которая может помочь. https://gammon.com.au/interrupts Сами разберетесь., @DrG

возможно ли отслеживать нажатие кнопки с помощью прерываний смены контакта?, @Good York

Обратите внимание на небольшую разницу между вашим attachPCINT и в [примере](https://github.com/NicoHood/PinChangeInterrupt/blob/master/examples/PinChangeInterrupt_Led/PinChangeInterrupt_Led.ino#L45). Есть дополнительный digitalPinToPCINT, в основном вы, вероятно, ловите радио на какой-то другой пин., @KIIV

@GoodYork, я так понимаю, вы ничего этого не делали с реальным оборудованием. Что вопрос основан только на эмуляции? Вы должны были сказать это в вопросе. Пожалуйста, вернитесь и отредактируйте свой вопрос, четко указав, что вопрос основан только на эмуляции am. (Если вам интересно, почему эмуляция не отражает реальный мир... возможно, нам следует начать с того, что такие компании, как Atmel (теперь Microchip), вряд ли раскроют все о конструкции своего процессора.), @st2000


1 ответ


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

2

Я только что проверил правильный код с некоторыми изменениями:

#include <PinChangeInterrupt.h>

const uint8_t buttonPin = 11;

volatile bool buttonPressed = false;

void buttonISR() {
  buttonPressed = true;
}


void loop() {
  if (buttonPressed) {
    delay(20);
    buttonPressed = false;

    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  }
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  attachPCINT(digitalPinToPCINT(buttonPin), buttonISR, RISING);

  pinMode(LED_BUILTIN, OUTPUT);
}

А с attachPCINT(digitalPinToPCINT(buttonPin), buttonISR, RISING); все работает безупречно. Разница лишь в том, что digitalPinToPCINT (как пытается предложить каждый пример для библиотеки PinChangeInterrupt).

Вы также пробовали attachInterrupt + digitalPinToInterrupt с выводом 11, но Arduino Uno имеет только два контакта D2 и D3, поддерживающих внешние прерывания. Так что это не могло работать с D11. Это также зависит от MCU (см. справку по attachInterrupt()). р>

PCINT более или менее связан со старыми AVR, такими как Atmega328 или Atmega2560. И PCINT в Atmega2560 доступен не на всех портах (он использует ISR для каждого порта и имеет много портов.

Если причиной является симулятор proteus, вы также можете опустить ISR (поскольку вы здесь ничего серьезного не делаете) и просто опросить пин:

const uint8_t buttonPin = 11;
bool buttonPressed = false;

void loop() {
  bool pinHigh = (digitalRead(buttonPin) == HIGH);

  if (pinHigh && buttonPressed) { // кнопка отпущена
    delay(20);
    buttonPressed = false;
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  } else if (!pinHigh && !buttonPressed) {
    buttonPressed = true;
  }
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
}
,

Просто чтобы подчеркнуть это, digitalPinToInterrupt предназначена для контактов D2 и D3 на Uno (эта функция возвращает 0 или 1 соответственно) при использовании с attachInterrupt, однако digitalPinToPCINT предназначена для прерываний **Pin Change**, которые ОП использует., @Nick Gammon

Почему у меня не работает, я использую arduino uno, @Good York

@GoodYork вам нужно изменить: attachPCINT(buttonPin, buttonISR, RISING); на attachPCINT(digitalPinToPCINT(buttonPin), buttonISR, RISING); или просто попробуйте использовать мой код (он переключает встроенный светодиод - он очень прост откат тоже), @KIIV

Я скопировал ваш код, просто заменил светодиод на Serial.println, и что-то у меня не работает, @Good York

Возможно проблема с проводкой. Или, если вы пробуете это только в эмуляторе, обычно это не очень хорошо работает с ISR., @KIIV

Я делаю это в эмуляторе Proteus, @Good York

@GoodYork Пожалуйста, сфотографируйте свою проводку и измените свой вопрос, включив эту фотографию., @Nick Gammon

@NickGammon У меня есть только та модель, которая уже прикреплена к вопросу., @Good York

*Я делаю это в эмуляторе Proteus* - вы не указали это в своем вопросе. Эмуляторы **могут неточно воспроизводить** то, что происходит в реальной жизни. Следовательно, ваша проблема в эмуляторе. Попробуйте использовать настоящую Ардуино., @Nick Gammon

*У меня есть только та модель, которая уже прикреплена к вопросу* - если у вас есть эмулятор, то у вас даже этого нет. Я прочитал вопрос и увидел, что вы утверждали, что используете Arduino Uno., @Nick Gammon

*Почему у меня не работает, я использую arduino uno* - вы должны были сказать "Я использую Arduino Uno в эмуляторе Proteus". Один из них — это реальная аппаратная часть, которая ведет себя предсказуемым образом, которую мы все можем протестировать. Другая часть программного обеспечения., @Nick Gammon

то это просто невозможно сделать в эмуляторе?, @Good York

Вы можете сделать это без прерываний, я обычно просто опрашиваю кнопки каждые несколько миллисекунд. Добавлен код без isr, @KIIV

@KIIV *задача такая: Кнопку надо подключить к соответствующему пину прерывания PCINT3* - у них задача, которая использовать PCINT3. Задача не в том, чтобы решить какую-то реальную проблему., @Nick Gammon