Можно ли отсоединить прерывание на определенное время
Аппаратное обеспечение: Arduino Uno Версия ПО: 1.8.13
В моем скетче есть процедура обработки прерывания, которая срабатывает при нарастающем фронте цифрового контакта 2. Что я хочу сделать сейчас, так это отсоединить прерывание, как только оно было запущено один раз, и снова подключить его, как только пройдет определенное количество времени (> 1 с).
Однако, несмотря на попытки, я не нашел возможности сделать это.
Я попытался отсоединить его в самом ISR и снова подключить в основном цикле с задержкой после ручной очистки флага прерывания. Однако при таком подходе время отключения прерывания зависит от момента времени, когда прерывание срабатывает, что нежелательно.
Есть ли лучшее решение для этого? Заранее спасибо за каждый ответ
@L1nuS01, 👍2
1 ответ
Лучший ответ:
Стандартный способ сделать это так же, как вы описали (но с неблокирующим стилем кодирования, как в примере BlinkWithoutDelay
): отсоединить в ISR и установить флаг и метку времени. Затем в основном коде проверьте флаг и время с момента получения метки времени. В коде, который выглядит примерно так (обратите внимание, я не учел некоторые аргументы функций присоединения/отсоединения):
volatile byte flag = 0;
volatile unsigned long timestamp = 0;
#define REACTIVATE_INTERVAL 1000
void ISR_function(){
detachInterrupt(...);
flag = 1;
timestamp = millis();
}
void setup(){
attachInterrupt(..., ISR_function, ...);
}
void loop(){
if(flag && millis() - timestamp > REACTIVATE_INTERVAL){
flag = 0;
attachInterrupt(..., ISR_function, ...);
}
// Остальная часть вашего основного кода с этого момента
}
Чтобы это работало правильно, вы, конечно же, должны использовать неблокирующий стиль кодирования в своем основном коде, то есть никаких delay()
(кроме очень маленьких) и никаких блокирующих в то время как
циклы. Если они есть в вашем основном коде, вы должны переписать его, чтобы он был неблокирующим. Не только для этой функции, но и для любого дальнейшего расширения вашего проекта. Неблокирующий стиль программирования — важный принцип, который следует соблюдать, особенно в микроконтроллерах.
Без неблокирующего стиля кодирования вам пришлось бы использовать прерывание по таймеру, чтобы повторно подключить прерывание по контакту. Хотя это вполне возможно, нет особого смысла настраивать дополнительные периферийные устройства Arduino только для этого.
- ATmega328P - проблема с использованием таймера 2 для генерации тона
- Точность синхронизации Arduino nano
- Интервальный таймер на Arduino: Сомнения по поводу библиотеки TimerOne
- Заставить TCNT оставаться ниже OCRxA на ATmega328P
- Эмуляция Arduino Uno с помощью QEMU: прерывания не работают
- Arduino непрерывно считывает значение АЦП с помощью прерывания
- Генерация стабильной частоты
- 4-битный счетчик вверх и вниз
Это именно то, что я искал. Меня раздражал тот факт, что прерывание заставляет таймер прекращать увеличиваться, но теперь это имеет смысл. Спасибо :), @L1nuS01
Вы имеете в виду, что
millis()
перестанет считать, находясь внутри ISR? Это правильно. Но здесь это не имеет значения, так как мы просто получаем текущее значение и они очень быстро уходят из ISR, @chrisl