Где найти флаг прерывания для ядер платы Arduino сторонних производителей?
Этот вопрос может быть немного широким, но я столкнулся с очевидно классической проблемой с прерываниями Arduino, когда флаг нарастающего или спадающего фронта срабатывает до того, как технически возникает нарастающий или спадающий фронт до того, как вывод будет поднят на высокий уровень/ низкий уровень, и микроконтроллер «запоминает»; это событие произошло, и прерывание запускается в тот момент, когда оно привязывается к выводу. В данном случае я работаю с модулем Artemis от Sparkfun (используя Микроконтроллер Apollo3). Соответствующий код можно увидеть ниже:
#define SLEEP_INTERRUPT 4
void setup
{
pinMode(SLEEP_INTERRUPT, INPUT);
#ifdef DEBUG
Serial.print("About to attach interrupt");
#endif
attachInterrupt(digitalPinToInterrupt(SLEEP_INTERRUPT), sleepModeSwitch, FALLING);
#ifdef DEBUG
Serial.print("Interrupt attached");
#endif
}
void sleepModeSwitch()
{
#ifdef DEBUG
Serial.print("Interrupt triggered! button status: "); Serial.println(digitalRead(SLEEP_INTERRUPT));
#endif
if(sleep_mode_status == false)
{
goToSleep();
}
else
{
wakeUp();
}
}
void goToSleep()
{
sleep_mode_status = true;
#ifdef DEBUG
Serial.println("Going to sleep");
delay(50); //Подождем, пока сериал завершится
Serial.end(); //Выключение UART(ов)
#endif
// выключаем светодиод.
digitalWrite(LED_BUILTIN, LOW);
// Остановить рекламу BLE.
BLE.stopAdvertise() ;
powerControlADC(false);
for(int x = 0; x < 50; x++)
{
if(x != 4)
{
am_hal_gpio_pinconfig(x, g_AM_HAL_GPIO_DISABLE);
}
}
//Выключение Flash, SRAM, кэша
am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_CACHE); //Отключаем КЭШ
am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_FLASH_512K); //Выключаем все, кроме понижения 512k
am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_SRAM_64K_DTCM); //Выключаем все, кроме понижения 64к
//am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_ALL); //Выключаем всю память (не восстанавливается)
// // Включаем прерывания ядра.
am_hal_interrupt_master_enable();
// //Включаем прерывание таймера в NVIC.
// NVIC_EnableIRQ(STIMER_CMPR6_IRQn);
//Перейти в режим глубокого сна.
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}
void wakeUp()
{
am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_MAX);
// Снова включаем контакты UART0
am_hal_gpio_pinconfig(48, g_AM_BSP_GPIO_COM_UART_TX);
am_hal_gpio_pinconfig(49, g_AM_BSP_GPIO_COM_UART_RX);
am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_UART0);
initializeADC();
#ifdef DEBUG
Serial.begin(115200);
Serial.println("Waking up! Hello world!");
#endif
deepSleepTimer = millis() ;
sleep_mode_status = false;
}
Основываясь на моих исследованиях, решение этой проблемы — просто очистить флаг прерывания вручную, прежде чем прикреплять прерывание к нужному контакту. К сожалению, пока методы, которые я нашел, работают только для плат AVR, и я не уверен, где искать дополнительную информацию о том, как получить доступ к флагу прерывания в скетче для стороннего ядра Arduino. . Есть ли у кого-нибудь предложения, с чего начать?
@E.HP.S, 👍1
Обсуждение1 ответ
Лучший ответ:
Флаг нарастающего или спадающего фронта срабатывает до того, как технически возникает нарастающий или спадающий фронт перед тем, как штифт перейдет в высокий/низкий уровень, и микроконтроллер «запомнит»; это событие произошло, прерывание запускается в тот момент, когда оно прикрепляется к выводу
Не существует «технически» об этом. Это то, что должно произойти. Как только вы настроите прерывание (как вы это делаете в setup
), процессор запомнит, что условие произошло, независимо от того, разрешены прерывания или нет.
Если вы хотите, чтобы прерывание обрабатывалось только после определенного момента, тогда да, вам следует очистить поле «прерывание произошло». флаг в MCU перед разрешением прерываний.
Ваш вопрос довольно неконкретен относительно того, о каких именно процессорах вы говорите, но я бы, конечно, очистил все соответствующие флаги перед подключением прерывания.
Я не уверен, где искать дополнительную информацию о том, как получить доступ к флагу прерывания в скетче для стороннего ядра Arduino
Техническое описание устройства на этом конкретном ядре?
Судя по техническим данным для Apollo3 Blue SoC :
6.3.2.15 Регистр INTLR
Прерывания мастера ввода-вывода: очищены
СМЕЩ: 0x00000228
АДРЕС ЭКЗЕМПЛЯРА 0: 0x5000C228
Запишите в этот регистр бит от 1, чтобы очистить статус прерывания, связанный с этим битом.
Однако у меня нет под рукой такого процессора, чтобы его протестировать.
Добавил ссылку на устройство и ссылку на даташит микроконтроллера, который в нем содержится. В данном случае это модуль Artemis от Sparkfun, содержащий SoC Apollo3 Blue SoC от Ambiq. И вы правы, я спрашивал об этом в более общем плане, намереваясь в целом узнать, где научиться очищать эти флаги, когда я работаю с другим микроконтроллером, с которым разбираюсь., @E.HP.S
@E.HP.S См. исправленный ответ., @Nick Gammon
- Как получить исходные файлы для библиотек Arduino?
- Использование millis() и micros() внутри процедуры прерывания
- Подсчет импульсов с прерыванием
- Wire.h не найден!
- Устранение дребезга кнопки с помощью прерывания
- Программа arduino выдаёт ошибку expected //primary-expression before ')' token error: //expected ';' before '}' token E
- Почему необходимо использовать ключевое слово volatile для глобальных переменных при обработке прерываний в ардуино?
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
Не уверен, что понимаю проблему, но похоже, что вы могли бы объявить изменчивое логическое значение isReady=false, а в верхней части обработчика сказать что-то вроде
if(!isReady)return;
и добавитьisReady=true;
после вашего вызова AttachInterrupt. Или, может быть, просто заглушить первый вызов с помощьюif(!isReady){ isReady=true;return;}
в обработчике., @dandavisМожете ли вы исключить следующую возможную причину вашей проблемы? https://github.com/sparkfun/Arduino_Apollo3/issues/416, @6v6gt
@ 6v6gt Может ли подтягивающий резистор на 10 кОм устранить эту проблему?, @E.HP.S
Из этого отчета о проблеме следует, что, если это имеет отношение к вашему случаю, его решит внешнее подтягивание. Если вы вызываете AttachInterrupt() только в setup(), вы также можете сделать трюк (обходной путь) с глобальной переменной, скажем,
endOfSetup
и игнорировать любые вызовы ISR, где она не была установлена. Очистка, очистка флагов и т. д. перед использованием AttachInterrupt() очень распространена, поэтому, ИМХО, неправильно, что вам нужно идти под уровень абстракции, чтобы сделать это., @6v6gt@ 6v6gt Я последовал совету из других источников (и от Дандависа) и сделал программное устранение дребезга с помощью функции millis(), чтобы прерывание не зашло слишком далеко, если оно вызывается слишком часто. Я также говорил об этом с кем-то на форуме Sparkfun, и мы, возможно, это исправили. Кажется, проблема была в файле commonInterrupt.cpp ядра. Не уверен, но я, по крайней мере, предотвратил это преждевременное прерывание, чтобы оно не испортило устройство, даже если я не уверен, что вообще остановил его работу. Все еще экспериментирую, @E.HP.S