Как добиться Adafruit Feather M0 Sleep & Wake при внешнем прерывании с помощью любого пина?
В настоящее время я работаю над проектом с низким энергопотреблением, использующим микропроцессор Adafruit Feather M0. Требование моего проекта состоит в том, чтобы иметь возможность переводить процессор в спящий режим и снова выводить его из спящего режима с помощью внешнего прерывания, инициированного акселерометром MPU6050.
Я протестировал следующий пример кода с GitHub - он работает успешно! Вопрос, на который мне нужно ответить, заключается в том, как изменить этот пример кода, чтобы он работал на выводе 13 пера, а не на выводе 6.
#define interruptPin 6
volatile bool SLEEP_FLAG;
void EIC_ISR(void) {
SLEEP_FLAG ^= true; // toggle SLEEP_FLAG by XORing it against true
//Serial.print("EIC_ISR SLEEP_FLAG = ");
//Serial.println(SLEEP_FLAG);
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
delay(3000); // wait for console opening
attachInterrupt(digitalPinToInterrupt(interruptPin), EIC_ISR, CHANGE); // Attach interrupt to pin 6 with an ISR and when the pin state CHANGEs
SYSCTRL->XOSC32K.reg |= (SYSCTRL_XOSC32K_RUNSTDBY | SYSCTRL_XOSC32K_ONDEMAND); // set external 32k oscillator to run when idle or sleep mode is chosen
REG_GCLK_CLKCTRL |= GCLK_CLKCTRL_ID(GCM_EIC) | // generic clock multiplexer id for the external interrupt controller
GCLK_CLKCTRL_GEN_GCLK1 | // generic clock 1 which is xosc32k
GCLK_CLKCTRL_CLKEN; // enable it
while (GCLK->STATUS.bit.SYNCBUSY); // write protected, wait for sync
EIC->WAKEUP.reg |= EIC_WAKEUP_WAKEUPEN4; // Set External Interrupt Controller to use channel 4 (pin 6)
PM->SLEEP.reg |= PM_SLEEP_IDLE_CPU; // Enable Idle0 mode - sleep CPU clock only
//PM->SLEEP.reg |= PM_SLEEP_IDLE_AHB; // Idle1 - sleep CPU and AHB clocks
//PM->SLEEP.reg |= PM_SLEEP_IDLE_APB; // Idle2 - sleep CPU, AHB, and APB clocks
// It is either Idle mode or Standby mode, not both.
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // Enable Standby or "deep sleep" mode
SLEEP_FLAG = false; // begin awake
// Built-in LED set to output and high
PORT->Group[g_APinDescription[LED_BUILTIN].ulPort].DIRSET.reg = (uint32_t)(1<<g_APinDescription[LED_BUILTIN].ulPin); // set pin direction to output
PORT->Group[g_APinDescription[LED_BUILTIN].ulPort].OUTSET.reg = (uint32_t)(1<<g_APinDescription[LED_BUILTIN].ulPin); // set pin mode to high
Serial.println("Setup() Run!");
}
void loop() {
// put your main code here, to run repeatedly:
if (SLEEP_FLAG == true) {
PORT->Group[g_APinDescription[LED_BUILTIN].ulPort].OUTCLR.reg = (uint32_t)(1<<g_APinDescription[LED_BUILTIN].ulPin); // set pin mode to low
Serial.println("I'm going to sleep now.");
__WFI(); // wake from interrupt
SLEEP_FLAG = false;
Serial.println("Ok, I'm awake");
Serial.println();
}
//Serial.print("SLEEP_FLAG = ");
//Serial.println(SLEEP_FLAG);
PORT->Group[g_APinDescription[LED_BUILTIN].ulPort].OUTTGL.reg = (uint32_t)(1<<g_APinDescription[LED_BUILTIN].ulPin); // toggle output of built-in LED pin
delay(1000);
}
Согласно схеме распиновки и таблице данных Atmel, я изо всех сил пытаюсь понять, какие изменения нужно внести, чтобы контакт 13 работал так же, как контакт 6.
Очевидное решение - изменить следующие строки...
#define interruptPin 13
EIC->WAKEUP.reg |= EIC_WAKEUP_WAKEUPEN1; // Set External Interrupt Controller to use channel 4 (pin 6)
Я подозревал канал 1 (WAKEUPEN1) из-за ENINT^1 рядом с контактом 13 на схеме распиновки. Но это не сработало, операция кодового вывода не показывала такое же поведение, как настройка вывода 6.
Я был бы очень благодарен за любые предложения о том, как реализовать этот код для работы с Pin 13. Большое спасибо за вашу поддержку.
1 ответ
Я здесь не авторитет, и ваш код мне кажется правильным.
За исключением того, что вывод показывает, что вывод 13 - это встроенная светодиодная линия, и вы управляете LED_BUILTIN в нескольких местах вашего кода. Это почти наверняка противоречит вашим попыткам использовать 13 в качестве линии прерывания.