External Interrupt using Registers

This is another tutorial in the Register based programming series and today we will see how can we use the external interrupt in STM32. This tutorial will also introduce the working with interrupts in STM32

I am going to focus on F4 and F1 series here. The code will be mainly written for F4 series, but wherever the changes are needed according to the F1 series, I will include them also

Let’s start by configuration first

Configuration

GPIO Configuration

First of all we will start with configuring the GPIO. I have already covered this for the F4 series and the F1 Series in my previous Tutorial, STM32 GPIO INPUT Configuration

Go to the above link, and see the configuration part.

INTERRUPT Configuration

We need to configure the External Interrupt and to do so, the steps are shown below

	/*************>>>>>>> STEPS FOLLOWED <<<<<<<<************
	
	1. Enable the SYSCFG/AFIO bit in RCC register 
	2. Configure the EXTI configuration Register in the SYSCFG/AFIO
	3. Disable the EXTI Mask using Interrupt Mask Register (IMR)
	4. Configure the Rising Edge / Falling Edge Trigger
	5. Set the Interrupt Priority
	6. Enable the interrupt
	
	********************************************************/

Let’s cover them one by one

1. Enable the SYSCFG/AFIO Bit

This bit will enable the configuration controller clock. In F4 series, we can do this by enabling the SYSCFG bit in the RCC_APB2ENR Register

RCC->APB2ENR |= (1<<14);  // Enable SYSCNFG

In F1 Series, we need to enable the AFIO bit in the RCC_APB2ENR Register

RCC->APB2ENR |= (1<<0);  // Enable AFIO CLOCK

2. Configure the EXTI configuration Register

In the F4 Series, External Interrupt Configuration can be found in the SYSCFG Registers. These EXTI configuration Registers are divided into 4 groups

  • SYSCFG_EXTICR1 (EXTI0 to EXTI3)
  • SYSCFG_EXTICR1 (EXTI4 to EXTI7)
  • SYSCFG_EXTICR1 (EXTI8 to EXTI11)
  • SYSCFG_EXTICR1 (EXTI12 to EXTI15)

Since we are using PA1, we will be using SYSCFG_EXTICR1.

As you can see above, to configure the EXTI line for PA1, we need to modify bits 7:6:5:4 with 0:0:0:0

SYSCFG->EXTICR[0] &= ~(0xf<<4);  // Bits[7:6:5:4] = (0:0:0:0)  -> configure EXTI1 line for PA1

Similarly in F1 series, instead of SYSCFG, we have AFIO Registers. Rest of the logic and the code is identical

AFIO->EXTICR[0] &= ~(0xf<<4);  // Bits[7:6:5:4] = (0:0:0:0)  -> configure EXTI1 line for PA1

3. Disable the EXTI Mask

Now onwards the steps will be common for the F4 and F1 series. Here we will disable the mask for the respective pin. This can be done by modifying the Interrupt Mask Register (EXTI_IMR)

As you can see above, in order to disable the mask from a particular pin, we need to write a ‘1’ in the respective location.

EXTI->IMR |= (1<<1);  // Bit[1] = 1  --> Disable the Mask on EXTI 1

4. Configure the Rising/Falling Edge Trigger

We can configure either we want the interrupt to trigger on the rising edge, or the falling edge of the input signal. These configuration can be controlled in the Rising trigger Selection Register (EXTI_RTSR) and the Falling trigger selection register (EXTI_FTSR).

I am selecting the Rising trigger for this tutorial, so I will enable the Rising trigger and Disable the Falling trigger

EXTI->RTSR |= (1<<1);  // Enable Rising Edge Trigger for PA1
	
EXTI->FTSR &= ~(1<<1);  // Disable Falling Edge Trigger for PA1

5. Set the Interrupt Priority and Enable the Interrupt

Well to do this, we need to use some predefined NVIC functions and you can see them below

NVIC_SetPriority (EXTI1_IRQn, 1);  // Set Priority
	
NVIC_EnableIRQ (EXTI1_IRQn);  // Enable Interrupt

Here 1 is the priority for the EXTI1 Interrupt. Basically lower the value, highest is the priority. So here I am keeping this priority pretty high.

This completes the configuration for the Interrupt. Now before going to the main code, let’s see the IRQ Handler


IRQ HANDLER

The steps to handle the Interrupt are shown below

	/*************>>>>>>> STEPS FOLLOWED <<<<<<<<************
	
	1. Check the Pin, which trgerred the Interrupt
	2. Clear the Interrupt Pending Bit
	
	********************************************************/

To check and clear the Interrupt Pending bit, we need to see the interrupt pending register (EXTI_PR)

This Pending Register bit is set whenever the interrupt is triggered.

if (EXTI->PR & (1<<1))    // If the PA1 triggered the interrupt
{
        flag = 1;
	EXTI->PR |= (1<<1);  // Clear the interrupt flag by writing a 1 
}
  • Here we will check if the interrupt is triggered by the pin PA1. This can be done by checking the pending bit in EXTI_PR
  • Next we will perform the operation and clear the bit by writing a ‘1’ in the respective bit
  • Here I am just setting a flag, and the rest of the code will be handled in the main function


The MAIN Function

int main ()
{
	SystemInit();
	GPIO_Config ();
	TIM2_Config();
	Interrupt_Config ();
	
	while (1)
	{
		if (flag)
		{
			Delay_ms(100);  // avoid debouncing
			count++;
			flag = 0;
		}
	}
}
  • As you can see above, after initializing everything we will check if the flag is set
  • This flag will be set whenever the interrupt is triggered
  • Then we will wait for few milliseconds for the debouncing
  • Next increment the counter and reset the flag again


Result

Check out the Video Below




Info

You can help with the development by DONATING Below.
To download the project, click the DOWNLOAD button.

Subscribe
Notify of

5 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
keyboard_arrow_up