SAMD21G External Interrupts

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hellosmiley,

I am trying to use External Interrupt Controller on Atmel SAMD21G18 microcontroler. Program must be written in Arduino IDE. I wrote a short program(code below) which should handle External Interrupts, but it doesn't work. Can someone help me or show working code examplewink? I can't use ASF library, because program is written in arduinofrown.

Thank you in advancesmiley.

 

#define LED1 PORT_PA17
#define SWITCH PORT_PA14

void setup()
{
  SerialUSB.begin(9600);

  PORT->Group[0].PINCFG[14].reg = PORT_PINCFG_PULLEN;//PULL_DOWN on PA14
  REG_PORT_OUTSET0 |= PORT_PA14;//PULL-UP on PA14
  PORT->Group[0].PINCFG[14].reg = PORT_PINCFG_PMUXEN;//peripheral function
  PORT->Group[0].PMUX[14].reg = PORT_PMUX_PMUXE_A;//pheripheral function A

  PM->APBAMASK.reg |= PM_APBAMASK_EIC;//APB clock for EIC

  GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_ID_EIC;//Generic clock foe EIC
  GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_CLKEN;//Generic clock

  EIC->INTENSET.reg = EIC_INTENSET_EXTINT14;//EXTINT14
  EIC->CONFIG[0].reg = EIC_CONFIG_SENSE0_HIGH;//High level detection
  EIC->CTRL.reg |= EIC_CTRL_ENABLE;//EIC Enable
  NVIC_EnableIRQ(EIC_IRQn);//EIC interrupts enable
}

void loop()
{

}

void EIC_Handler(void)
{
  if(EIC->INTFLAG.bit.EXTINT14 == 1)
  {
    SerialUSB.println("External interrupt");
    //EIC->INTFLAG.bit.EXTINT14 = 0;
  }
  else
  {
    SerialUSB.println("Interrupts");
  }
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is a similar case for PA15 (there is a button that connects to GND there so this is looking for a falling edge).

#include "sam.h"

void EIC_Handler(void)
{
    if (EIC->INTFLAG.bit.EXTINT15 == 1) {
        EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT15;
    }
}

int main(void)
{
    REG_PORT_OUTSET0 = PORT_PA15;// PULL-UP on PA15
    PORT->Group[0].PINCFG[15].reg = PORT_PINCFG_PMUXEN | PORT_PINCFG_PULLEN;
    PORT->Group[0].PMUX[15 / 2].reg = PORT_PMUX_PMUXO_A;

    PM->APBAMASK.reg |= PM_APBAMASK_EIC;

    GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_EIC | GCLK_CLKCTRL_CLKEN;

    EIC->INTENSET.reg = EIC_INTENSET_EXTINT15;
    EIC->CONFIG[1].reg = EIC_CONFIG_SENSE7_FALL;
    EIC->CTRL.reg |= EIC_CTRL_ENABLE;
    NVIC_EnableIRQ(EIC_IRQn);
      
    while (1) {
    }
}

 

In your code you overwrite PINCFG here:

PORT->Group[0].PINCFG[14].reg = PORT_PINCFG_PMUXEN;//peripheral function

And this writes to the wrong register (there is an even and odd setting in each PMUX hence for pin 14 you need to write the even value for index 7):

  PORT->Group[0].PMUX[14].reg = PORT_PMUX_PMUXE_A;//pheripheral function A

You are supposed to configure this with a single write (don't use |= for this register):
 

  GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_ID_EIC;//Generic clock foe EIC
  GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_CLKEN;//Generic clock

This writes in the wrong place:

  EIC->CONFIG[0].reg = EIC_CONFIG_SENSE0_HIGH;//High level detection

EIC->CONFIG[0] has the setting for EXTINT 0-7 and EIC->CONFIG[1] has it for EXTINT 8-15. You need to set EIC_CONFIG_SENSE6_<something> in EIC->CONFIG[1] (1 x 8 + 6 = 14).

 

/Lars