cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F401RE Pushbutton interrupt

Petrarka
Associate II

So here's the code ; The issue with it is that whenever I press the button, weird things occur, such as my output resetting completely-going to the maximum, at my output I have a variable PWM signal

 

void PB_Init(void){
  	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
    GPIOC->MODER |= ( 0x0 << GPIO_MODER_MODE13_Pos);
    GPIOC->PUPDR |= ( 0x1 << GPIO_PUPDR_PUPD13_Pos);
}

void EXTI15_10_Init(void){
    PB_Init(); // Initialize PC13 as input.

    RCC->APB2ENR |= (1<<14);      // Enable System configuration controller
    SYSCFG->EXTICR[3] &= ~(1<<7); // Select Port C as source, EXTIx = 0b0010
    SYSCFG->EXTICR[3] &= ~(1<<6); // Select Port C as source, EXTIx = 0b0010
    SYSCFG->EXTICR[3] |= (1<<5);  // Select Port C as source, EXTIx = 0b0010
    SYSCFG->EXTICR[3] &= ~(1<<4); // Select Port C as source, EXTIx = 0b0010
    EXTI->IMR |= (1<<13);         // Disable interrupt request mask on EXTI line 13
    EXTI->FTSR |= (1<<13);        // Enable EXTI on Falling edge
    EXTI->RTSR &= ~(1<<13);       // Disable EXTI on Rising edge
    RCC->APB2ENR &= ~(1<<14);     // Disable System configuration controller
}
volatile bool flag=0;
void EXTI15_10_IRQHandler(void){
	if(flag==0){
	TIM2->CR1|=TIM_CR1_CEN;
	flag=!flag;
	EXTI->PR |= (1<<13);  // Clear PR to re-enable EXTI interrupt

	}else{
		TIM2->CR1&=~TIM_CR1_CEN;
		flag=!flag;
		EXTI->PR |= (1<<13);  // Clear PR to re-enable EXTI interrupt
	}

}


void Interrupt_Init(void){
    EXTI15_10_Init(); // Step 1, this is defined elsewhere
    NVIC->IP[EXTI15_10_IRQn] =  (1 << 4);    // Step 3: Set priority to 1
    NVIC->ISER[40 >> 5] |= (1 << (40 % 32)); // Step 4: Enable interrupt
}

 

, can anyone point me in the right direction? 

1 ACCEPTED SOLUTION

Accepted Solutions

Hello, I have fixed the issue and will mark it as a solution when I can

here's the code

void Interrupt_Init(void){
    EXTI15_10_Init(); 
    NVIC->IP[EXTI15_10_IRQn] =  (1 << 4);    
    NVIC->ISER[40 >> 5] |= (1 << (40 % 32)); 
}

union InterruptFlag {
    struct {
       volatile bool flag: 1; // Just one bit for our flag
       volatile bool press: 1;
    } bits_access;
    uint32_t reg; // We'll use this for byte access
};
volatile union InterruptFlag flag = { .bits_access.flag = 0 }; // Initialize to 0
volatile uint16_t pressTime;
volatile bool lastButtonPress=0;
volatile bool buttonPress=1;

void EXTI15_10_IRQHandler(void){
flag.bits_access.flag = !flag.bits_access.flag;
EXTI->PR |= (1<<13);  // Clear PR to re-enable EXTI interrupt

}

//main 

  while (1)
  {

	  int x;
	      for(x=0; x<500; x++)
	      {
	    	  if(flag.bits_access.flag== 1){
	    		  	  	x=x-1;
	    	  	        TIM2->CCR1=x;
	    	  	  }
	    	  else{
	    		  	  	TIM2->CCR1=x;
	    		  	  	delayTRIP(1);
	    	  }}

	      for(x=500; x>0; x--)
	      {
	    	  if(flag.bits_access.flag== 1){
	    		  	  	  x=x+1;
	    		  	  	  TIM2->CCR1=x;
	    	 	    	  	  }
	    	  else{
	    	 	     	  TIM2->CCR1=x;
	    	 	          delayTRIP(1);
	      }

	  }
  }}


the issue was that I wasnt checking for the flag at the right time and used the wrong registers for the stopping of the PWM

View solution in original post

3 REPLIES 3
Pavel A.
Evangelist III

Does your button jitter?

Sarra.S
ST Employee

Hello @Petrarka

You should ensure that the interrupt flag is cleared only after you've handled the interrupt:

 

void EXTI15_10_IRQHandler(void){
    if(EXTI->PR & EXTI_PR_PR13){ // Check if the interrupt is for EXTI line 13
        if(flag == 0){
            TIM2->CR1 |= TIM_CR1_CEN; // Enable TIM2
            flag = 1;
        } else {
            TIM2->CR1 &= ~TIM_CR1_CEN; // Disable TIM2
            flag = 0;
        }
        EXTI->PR |= EXTI_PR_PR13; // Clear the pending bit for EXTI line 13
    }
}

 

Also when clearing the mode bits for pin 13 to set it as an input, I think it should be an AND instead of an OR which won't clear the bits if they are already set to 1

GPIOC->MODER &= ~(0x0 << GPIO_MODER_MODE13_Pos);

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hello, I have fixed the issue and will mark it as a solution when I can

here's the code

void Interrupt_Init(void){
    EXTI15_10_Init(); 
    NVIC->IP[EXTI15_10_IRQn] =  (1 << 4);    
    NVIC->ISER[40 >> 5] |= (1 << (40 % 32)); 
}

union InterruptFlag {
    struct {
       volatile bool flag: 1; // Just one bit for our flag
       volatile bool press: 1;
    } bits_access;
    uint32_t reg; // We'll use this for byte access
};
volatile union InterruptFlag flag = { .bits_access.flag = 0 }; // Initialize to 0
volatile uint16_t pressTime;
volatile bool lastButtonPress=0;
volatile bool buttonPress=1;

void EXTI15_10_IRQHandler(void){
flag.bits_access.flag = !flag.bits_access.flag;
EXTI->PR |= (1<<13);  // Clear PR to re-enable EXTI interrupt

}

//main 

  while (1)
  {

	  int x;
	      for(x=0; x<500; x++)
	      {
	    	  if(flag.bits_access.flag== 1){
	    		  	  	x=x-1;
	    	  	        TIM2->CCR1=x;
	    	  	  }
	    	  else{
	    		  	  	TIM2->CCR1=x;
	    		  	  	delayTRIP(1);
	    	  }}

	      for(x=500; x>0; x--)
	      {
	    	  if(flag.bits_access.flag== 1){
	    		  	  	  x=x+1;
	    		  	  	  TIM2->CCR1=x;
	    	 	    	  	  }
	    	  else{
	    	 	     	  TIM2->CCR1=x;
	    	 	          delayTRIP(1);
	      }

	  }
  }}


the issue was that I wasnt checking for the flag at the right time and used the wrong registers for the stopping of the PWM