Skip to main content
Associate 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? 

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

Pavel A.
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);

 

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.
PetrarkaAuthorBest answer
Associate 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