Skip to main content
semed abubakar
Associate II
January 30, 2018
Solved

STM32L4 EXTERNAL INTERRUPT

  • January 30, 2018
  • 3 replies
  • 2023 views
Posted on January 30, 2018 at 15:53

hello friends i recently got an stm32l4 I just go past the led blink i am trying my hands on interrupts I am trying to configure  a falling edge triggered interrupt on A0 and PC15 so far works fine for GPIOA but the interrupt for GPIOC15 

is not working 

I have enabled pull up on the pin but when i drive it low it doesnt trigger the interrupt during the debug i know cause the counter in the ISR is not incrementing

does anyone know why my c code is below i am using keil ide thank you

#include 'stm32l433xx.h'

extern int cnt,j;

void EXTI0_IRQHandler(void)

{

if (!(GPIOA->IDR & (1<<0)) )

{

if(!(cnt%2))

GPIOC->ODR =~(1<<4);

else

GPIOC->ODR|= (1<<4);

cnt++;

}

//Clear the EXTI pending bits

NVIC_ClearPendingIRQ(EXTI3_IRQn);

EXTI->PR1 |=(1<<0);

}

void EXTI15_IRQHandler(void)

{

j++;

NVIC_ClearPendingIRQ(EXTI15_10_IRQn); //Clear the EXTI pending bits

EXTI->PR1 |=(1<<15);

}

void Config_IO(void)

{

RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;

RCC->AHB2ENR |= RCC_AHB2ENR_GPIOCEN;

RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;

GPIOA->MODER &=~(1<<0); //input mode for A0

GPIOA->MODER &=~(1<<1);

GPIOA->PUPDR |= (1<<0); //pull up on A0

GPIOA->PUPDR &=~(1<<1);

GPIOA->OSPEEDR |=(1<<0); //input mode for A0

GPIOA->OSPEEDR |=(1<<1);

GPIOA ->OTYPER &=~(1<<0);

GPIOB ->MODER &= ~(GPIO_MODER_MODER13_0); // set GPIO 13 as general purpose input

GPIOB ->MODER &= ~(GPIO_MODER_MODER13_1);

GPIOB ->PUPDR &= ~(1<<27); //10000000000 Pull up RB13

GPIOB ->PUPDR |= (1<<26);

GPIOC ->MODER |= GPIO_MODER_MODE12_0; ///set GPIO13 as general output

GPIOC ->MODER &= ~(GPIO_MODER_MODE12_1);

GPIOC ->OTYPER &= ~(GPIO_OTYPER_OT_12); ///push pull output type for GPIOC12

GPIOC ->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR12_0); // high speed for GPPIOC12

GPIOC ->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR12_1);

GPIOC ->PUPDR &= ~(GPIO_PUPDR_PUPDR12); //NO PULL UP*/

GPIOC ->MODER |= (1<<8); //PC4 output mode

GPIOC ->MODER &= ~(1<<9);

GPIOC ->OTYPER |= (1<<4); //open drain on PC4

GPIOC ->OSPEEDR |= (1<<8); //PC4 high speed

GPIOC ->OSPEEDR |= (1<<9);

GPIOC ->PUPDR &=~(0<<8);

GPIOC ->PUPDR &=~(0<<9);

GPIOB->MODER &=~(1<<30); //input mode for B15

GPIOB->MODER &=~(1<<31);

GPIOB ->PUPDR &= ~(1<<31); //10000000000 Pull up B15

GPIOB ->PUPDR |= (1<<30);

GPIOB ->OTYPER &= ~(1<<15); ///push pull output type for GPIOB15

GPIOB ->OSPEEDR &= ~ (1<<30); //PB15 high speed

GPIOB ->OSPEEDR |= (1<<31);

}

void Config_Interrupt(void)

{

SYSCFG->EXTICR[0] &= SYSCFG_EXTICR1_EXTI0_PA;

SYSCFG->EXTICR[3] = SYSCFG_EXTICR4_EXTI15_PB ;

EXTI->IMR1 |= (1<<0);

EXTI->IMR1 |= (1<<15);

EXTI->EMR1 |=(1<<0); //interrupt source is unmaskrd

EXTI->EMR1 |=(1<<15); //Unmask interrupt line 15

EXTI->FTSR1 |= (1<<0); //falling edge line 1

EXTI->FTSR1 |= (1<<15); //falling edge line 15

__enable_irq(); //enable interrupt

NVIC_SetPriority(EXTI0_IRQn,4); //Set priority

NVIC_SetPriority(EXTI15_10_IRQn,4);

NVIC_ClearPendingIRQ(EXTI0_IRQn); //clear pending

NVIC_ClearPendingIRQ(EXTI15_10_IRQn);

NVIC_EnableIRQ(EXTI0_IRQn); ///enable interrupt

NVIC_EnableIRQ(EXTI15_10_IRQn);

}

void Config_IO(void);

void Config_Interrupt(void);

int cnt,i,j;

int main()

{

Config_IO();

Config_Interrupt();

while (1)

{

GPIOC->ODR|= (1<<12);

for(i=0;i<100;i++);

GPIOC->ODR&= ~(1<<12);

for(i=0;i<100;i++);

}

return 0;

}
    This topic has been closed for replies.
    Best answer by Tesla DeLorean
    Posted on January 30, 2018 at 17:14

    void EXTI15_10_IRQHandler(void)

    3 replies

    Tesla DeLorean
    Tesla DeLoreanBest answer
    Guru
    January 30, 2018
    Posted on January 30, 2018 at 17:14

    void EXTI15_10_IRQHandler(void)

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    waclawek.jan
    Super User
    January 30, 2018
    Posted on January 30, 2018 at 17:25

    and set RCC_APB2ENR.SYSCFGEN

    semed abubakar
    Associate II
    January 30, 2018
    Posted on January 30, 2018 at 18:03

    Thank you waclawek i  i modified the code like you suggested i have changed the IRQ handler to 

    void EXTI15

    _10_

    IRQHandler(void)

      and i set  

    RCC_APB2ENR.SYSCFGEN in my config_io fucntion line 40

    the interrupt is still not triggering i tried another pin PB3 but so far thats not working either  the code looks like this now

    #include 'stm32l433xx.h'

    extern int cnt,j;

    void EXTI0_IRQHandler(void)

    {

    if (!(GPIOA->IDR & (1<<0)) )

    {

    if(!(cnt%2))

    GPIOC->ODR =~(1<<4);

    else

    GPIOC->ODR|= (1<<4);

    cnt++;

    }

    //Clear the EXTI pending bits

    NVIC_ClearPendingIRQ(EXTI3_IRQn);

    EXTI->PR1 |=(1<<0);

    }

    void EXTI15_10_IRQHandler(void)

    {

    cnt++;

    j++;

    NVIC_ClearPendingIRQ(EXTI15_10_IRQn); //Clear the EXTI pending bits

    EXTI->PR1 |=(1<<15);

    }

    void EXTI1_IRQHandler(void)

    { cnt++;

    j++;

    NVIC_ClearPendingIRQ(EXTI1_IRQn); //Clear the EXTI pending bits

    EXTI->PR1 |=(1<<3);

    }

    void Config_IO(void)

    {

    RCC->APB2ENR |=(1<<0);                     //SYSCFG ENABLE

    RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;

    RCC->AHB2ENR |= RCC_AHB2ENR_GPIOCEN;

    RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;

    GPIOA->MODER &=~(1<<0); //input mode for A0

    GPIOA->MODER &=~(1<<1);

    GPIOA->PUPDR |= (1<<0); //pull up on A0

    GPIOA->PUPDR &=~(1<<1);

    GPIOA->OSPEEDR |=(1<<0); //input mode for A0

    GPIOA->OSPEEDR |=(1<<1);

    GPIOA ->OTYPER &=~(1<<0);

    GPIOB ->MODER &= ~(GPIO_MODER_MODER13_0); // set GPIO 13 as general purpose input

    GPIOB ->MODER &= ~(GPIO_MODER_MODER13_1);

    GPIOB ->PUPDR &= ~(1<<27); //10000000000 Pull up RB13

    GPIOB ->PUPDR |= (1<<26);

    GPIOC ->MODER |= GPIO_MODER_MODE12_0; ///set GPIO13 as general output

    GPIOC ->MODER &= ~(GPIO_MODER_MODE12_1);

    GPIOC ->OTYPER &= ~(GPIO_OTYPER_OT_12); ///push pull output type for GPIOC12

    GPIOC ->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR12_0); // high speed for GPPIOC12

    GPIOC ->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR12_1);

    GPIOC ->PUPDR &= ~(GPIO_PUPDR_PUPDR12); //NO PULL UP*/

    GPIOC ->MODER |= (1<<8); //PC4 output mode

    GPIOC ->MODER &= ~(1<<9);

    GPIOC ->OTYPER |= (1<<4); //open drain on PC4

    GPIOC ->OSPEEDR |= (1<<8); //PC4 high speed

    GPIOC ->OSPEEDR |= (1<<9);

    GPIOC ->PUPDR &=~(0<<8);

    GPIOC ->PUPDR &=~(0<<9);

    GPIOB->MODER &=~(1<<30); //input mode for B15

    GPIOB->MODER &=~(1<<31);

    GPIOB ->PUPDR &= ~(1<<31); //10000000000 Pull up B15

    GPIOB ->PUPDR |= (1<<30);

    GPIOB ->OTYPER &= ~(1<<15); ///push pull output type for GPIOB15

    GPIOB ->OSPEEDR |= (1<<30); //PB15 high speed

    GPIOB ->OSPEEDR |= (1<<31);

    GPIOB->MODER &=~(1<<6); //input mode for B3

    GPIOB->MODER &=~(1<<7);

    GPIOB ->PUPDR &= ~(1<<7); //10000000000 Pull up B3

    GPIOB ->PUPDR |= (1<<6);

    GPIOB ->OTYPER &= ~(1<<3); ///push pull output type for GPIOB3

    GPIOB ->OSPEEDR |= (1<<6); //PB15 high speed

    GPIOB ->OSPEEDR |= (1<<7);

    }

    void Config_Interrupt(void)

    {

    SYSCFG->EXTICR[0] &= SYSCFG_EXTICR1_EXTI0_PA;

    SYSCFG->EXTICR[1] = SYSCFG_EXTICR4_EXTI15_PB ;

    SYSCFG->EXTICR[1] = SYSCFG_EXTICR1_EXTI1_PB ;

    EXTI->IMR1 |= (1<<0);

    EXTI->IMR1 |= (1<<15);

    EXTI->IMR1 |= (1<<3);

    EXTI->EMR1 |=(1<<0); //interrupt source is unmaskrd

    EXTI->EMR1 |=(1<<15); //Unmask interrupt line 15

    EXTI->EMR1 |=(1<<3);

    EXTI->FTSR1 |= (1<<0); //falling edge line 1

    EXTI->FTSR1 |= (1<<15); //falling edge line 15

    EXTI->FTSR1 |= (1<<3);

    __enable_irq(); //enable interrupt

    NVIC_SetPriority(EXTI0_IRQn,4); //Set priority

    NVIC_SetPriority(EXTI15_10_IRQn,4);

    NVIC_SetPriority(EXTI1_IRQn,4);

    NVIC_ClearPendingIRQ(EXTI0_IRQn); //clear pending

    NVIC_ClearPendingIRQ(EXTI15_10_IRQn);

    NVIC_ClearPendingIRQ(EXTI1_IRQn);

    NVIC_EnableIRQ(EXTI0_IRQn); ///enable interrupt

    NVIC_EnableIRQ(EXTI15_10_IRQn);

    NVIC_EnableIRQ(EXTI3_IRQn);

    }

    #include 'stm32l433xx.h'

    extern int cnt,j;

    void EXTI0_IRQHandler(void)

    {

    if (!(GPIOA->IDR & (1<<0)) )

    {

    if(!(cnt%2))

    GPIOC->ODR =~(1<<4);

    else

    GPIOC->ODR|= (1<<4);

    cnt++;

    }

    //Clear the EXTI pending bits

    NVIC_ClearPendingIRQ(EXTI3_IRQn);

    EXTI->PR1 |=(1<<0);

    }

    void EXTI15_10_IRQHandler(void)

    {

    cnt++;

    j++;

    NVIC_ClearPendingIRQ(EXTI15_10_IRQn); //Clear the EXTI pending bits

    EXTI->PR1 |=(1<<15);

    }

    void EXTI1_IRQHandler(void)

    { cnt++;

    j++;

    NVIC_ClearPendingIRQ(EXTI1_IRQn); //Clear the EXTI pending bits

    EXTI->PR1 |=(1<<3);

    }

    #include 'stm32l433xx.h'

    void Config_IO(void);

    void Config_Interrupt(void);

    int cnt,i,j;

    int main()

    {

    Config_IO();

    Config_Interrupt();

    while (1)

    {

    GPIOC->ODR|= (1<<12);

    for(i=0;i<100;i++);

    GPIOC->ODR&= ~(1<<12);

    for(i=0;i<100;i++);

    }

    return 0;

    }
    waclawek.jan
    Super User
    January 31, 2018
    Posted on January 31, 2018 at 10:24

    Read back the SYSCFG and GPIO registers and check if they contain what you expect.

    Look at the actual vector table (in binary, or better in disassembled binary) if the address at expected position points to the actual interrupt routine.

    JW

    henry.dick
    Associate II
    January 31, 2018
    Posted on January 31, 2018 at 12:11

    the flow looks generally right. two suggestions:

    1) simplify your code to a minimalist framework. 

    2) be consistent: if you are using pin13 as the exti, program your code so it consistently use that pin. I typically define a mask and use that mask throughout my code so if I want to move to a different pin, I can. your code has tons of hard-coded numbers that are inconsistent from one place to another, making it hard to track.