Skip to main content
Visitor II
April 30, 2024
Solved

STM32F401RE Pushbutton interrupt

  • April 30, 2024
  • 2 replies
  • 1143 views

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? 

    This topic has been closed for replies.
    Best answer by Petrarka

    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

    2 replies

    Super User
    April 30, 2024

    Does your button jitter?

    ST Employee
    May 3, 2024

    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);

     

    PetrarkaAuthorAnswer
    Visitor II
    May 8, 2024

    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