STM32F407G-DISC1 개발일지 (3)
이번 시리즈에서는 STM32F407 기반 EVM Borad인 STM32F407G-DISC1을 IAR과 Standard Peripheral Libraries로 제어하기 위한 튜토리얼 내용이 담긴 포스팅입니다.
👨💻 개발일지 (3) : GPIO with External Interrupt
지난번 포스팅인 🔗 STM32F407G-DISC1 개발일지 (2) STM32F407G-DISC1 Board에 내장되어있는 LED 4개를 Button을 이용해 Polling 기법으로 토글하는 방법을 알아봤다. 이번에는 외부 인터럽트와 Button을 이용해 LED를 토글하는 법을 알아보자. 만약 Polling 과 Interrupt 기법의 차이가 궁금하다면 nRF52832의 개발일지에서 확인해 보자. 👇👇
1. STM32F407VG EXIT
EXIT(External Interrupt)는 외부에서 오는 신호에의해 발생하는 Interrupt를 말한다. 이러한 외부 신호는 Trigger를 이용한다. 즉 High ➞ Low, Low ➞ High로 둘 다 신호 레벨이 변경되는 시점에서 인터럽트를 발생시킨다. 이런 EXIT를 이용하면 단순한 Button 혹은 Switch를 이용해 신호를 주는 것 뿐아니라, MCU 간의 통신 등 여러가지 방법으로 사용될 수 있다.
우선 STM32F407의 외부 인터럽트가 가능한 GPIO Port 및 Pin을 알아보자. EXIT에 관련 정보는 🔗 STM32F047 Reference Manual 의 page 371에서 찾을 수 있다.
위 내용은 메뉴얼 page 382에 Figure 42. External interrupt/event GPIO mapping (STM32F405xx/07xx and STM32F415xx/17xx) 의 일부를 가져온 것이다. STM32F407 시리즈에서 각 GPIO Port는 같은 Pin 라인을 공유한다. 즉 Port A가 Line 0을 사용하면 Port B 혹은 Port C는 외부인터럽트 0를 사용하지 못한다.
Port I를 제외하면 각 Line을 16개(0 ~ 15)를 사용하므로 총16개의 외부인터럽트를 사용할 수 있지만, 실제 인터럽트 핸들러는 총 7가지의 인터럽트 핸들러가 존재한다.
- EXIT0_IRQHandler
- EXIT1_IRQHandler
- EXIT2_IRQHandler
- EXIT3_IRQHandler
- EXIT4_IRQHandler
- EXIT9_5_IRQHandler
- EXIT15_10_IRQHandler
즉 외부 인터럽트 5 ~ 9 사이는 같은 인터럽트 핸들러에 진입하며, 10 ~ 15 사이의 외부인터럽트 역시 같은 인터럽트 핸들러로 진입하게 된다.
STL을 이용한 EXIT
Standard Periph Library를 이용해 STM32F407G-DISC1을 제어하는 코드를 작성해 업로드해보자. 📝
2.1 STM32F407G-DISC1 EXIT Code ✍
이번 코드 역시 LED를 토글링하는 코드지만, 이번에는 Polling이 아닌 Interrupt기반으로 좀 더 CPU 자원 낭비를 하지 않는 효율적인 코드를 작성해 보자.
/**
******************************************************************************
* @file Project/GPIO/GPIO_EXIT/main.c
* @author Geunhyeok Lee
* @version V0.0.1
* @date 05-February-2022
* @brief Main program
******************************************************************************
*/
#include "main.h"
int main()
{
GPIO_EXIT_Configuration();
while(1)
{
;
}
return 0;
}
void GPIO_EXIT_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Medium_Speed;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Medium_Speed;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x060;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_Init(&NVIC_InitStructure);
return;
}
/******************************** END OF FILE *********************************/
/**
******************************************************************************
* @file Project/GPIO/GPIO_EXIT/main.h
* @author Geunhyeok Lee
* @version V0.0.1
* @date 06-February-2022
* @brief Main program header
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void GPIO_EXIT_Configuration(void);
#endif /* __MAIN_H */
/******************************** END OF FILE *********************************/
/**
******************************************************************************
* @file Project/GPIO/GPIO_EXIT/stm32f4xx_it.c
* @author Geunhyeok Lee
* @version V0.0.1
* @date 06-February-2022
* @brief Main Interrupt Service Routines.
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_it.h"
#include "main.h"
/** @addtogroup Template_Project
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/******************************************************************************/
/* Cortex-M4 Processor Exceptions Handlers */
/******************************************************************************/
/**
* @brief This function handles NMI exception.
* @param None
* @retval None
*/
void NMI_Handler(void)
{
}
/**
* @brief This function handles Hard Fault exception.
* @param None
* @retval None
*/
void HardFault_Handler(void)
{
/* Go to infinite loop when Hard Fault exception occurs */
while (1)
{
}
}
/**
* @brief This function handles Memory Manage exception.
* @param None
* @retval None
*/
void MemManage_Handler(void)
{
/* Go to infinite loop when Memory Manage exception occurs */
while (1)
{
}
}
/**
* @brief This function handles Bus Fault exception.
* @param None
* @retval None
*/
void BusFault_Handler(void)
{
/* Go to infinite loop when Bus Fault exception occurs */
while (1)
{
}
}
/**
* @brief This function handles Usage Fault exception.
* @param None
* @retval None
*/
void UsageFault_Handler(void)
{
/* Go to infinite loop when Usage Fault exception occurs */
while (1)
{
}
}
/**
* @brief This function handles SVCall exception.
* @param None
* @retval None
*/
void SVC_Handler(void)
{
}
/**
* @brief This function handles Debug Monitor exception.
* @param None
* @retval None
*/
void DebugMon_Handler(void)
{
}
/**
* @brief This function handles PendSVC exception.
* @param None
* @retval None
*/
void PendSV_Handler(void)
{
}
/**
* @brief This function handles SysTick Handler.
* @param None
* @retval None
*/
void SysTick_Handler(void)
{
}
/******************************************************************************/
/* STM32F4xx Peripherals Interrupt Handlers */
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
/* available peripheral interrupt handler's name please refer to the startup */
/* file (startup_stm32f4xx.s). */
/******************************************************************************/
/**
* @brief This function handles PPP interrupt request.
* @param None
* @retval None
*/
/*void PPP_IRQHandler(void)
{
}*/
/**
* @brief This function handles External0 interrupt request.
* @param None
* @retval None
*/
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line0);
GPIO_ToggleBits(GPIOD, GPIO_Pin_12);
}
}
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/**
******************************************************************************
* @file Project/GPIO/GPIO_EXIT/stm32f4xx_it.h
* @author Geunhyeok Lee
* @version V0.0.1
* @date 06-February-2022
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_IT_H
#define __STM32F4xx_IT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
void EXTI0_IRQHandler(void);
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_IT_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
지난 포스팅에 GPIO를 제하기위한 GPIO_Configuration
함수에 몇가지 내용을 추가하고 이름만 바꿔 GPIO_EXIT_Configuration
함수를 만들고 그 외 변경사항은 이제부터 인터럽트를 추가하기 때문에 STL 예제 템플릿에 맞춰 stm32f4xx_it.c
와 stm32f4xx_it.h
파일을 만들고 필요한 인터럽트 핸들러를 추가했다.
2.2 STM32F407G-DISC1 EXIT Code 살펴보기 👨🏫
인터럽트 기능이 추가된 만큼 지난번과 비교해 달라진 부분을 살펴보자. 가장 먼저 눈에 띄는 것은 새로운 구조체이다.
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef
구조체는 외부 인터럽트의 초기화를 위한 구조체이며, NVIC_InitTypeDef
구조체는 인터럽트가 발생되면 ARM 코어에서 이 인터럽트의 우선순위 혹은 인터럽트 핸들러주소 같은 정보를 초기화 해주는 구조체이다.
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x060;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_Init(&NVIC_InitStructure);
이제 나머지 부분을 살펴보자. 외부 인터럽트를 이용하기 위해서는 System configuration controller(SYSCFG) 라는 컨트롤러의 레지스터를 이용해야한다. 당연히 이 컨트롤러를 활성화하기 위해 연결된 버스에 클록을 인가시켜야 하며 연결된 버스는 APB2이다.
SYSCFG_EXTILineConfig
함수는 SYSCFG 레지스터인 SYSCFG_EXTICR4x(x: 1 ~ 4)에 적절한 값을 할당하는 함수이다. 이 함수를 이용하면 GPIO Port는 어떤 외부 인터럽트 Pin을 사용하는지를 명시해 준다.
나머지는 구조체 멤버변수를 초기화하는 내용이므로 간단하게만 살펴보자.
-
EXTI_Line: EXTI_Line0 ~ 23까지 사용하며, 16~23 까지는 특별한 이벤트를위해 사용되며 나머지는 일반적인 외부 인터럽트로 사용할 수 있다.
-
EXTI_LineCmd: 외부 인터럽트를 사용/비사용을 정한다.
-
EXTI_Mode: 외부 인터럽트 혹은 외부 이벤트를 정한다.
- EXTI_Mode_Interrupt
- EXTI_Mode_Event
-
EXTI_Trigger: 외부 인터럽트의 트리거를 정한다.
- EXTI_Trigger_Rising
- EXTI_Trigger_Falling
- EXTI_Trigger_Rising_Falling
-
NVIC_IRQChannel : 인터럽트 핸들러를 설정한다(정해져 있음).
-
NVIC_IRQChannelCmd: 외부 인터럽트 핸들러의 사용/비사용을 정한다.
-
NVIC_IRQChannelPreemptionPriority: 인터럽트의 주 우선순위
-
NVIC_IRQChannelSubPriority: 인터럽트의 부 우선순위
마지막으로 인터럽트 핸들러에 Break point를 설정하고 버튼을 누르면 핸들러로 잘 진입하는 모습을 확인할 수 있다.
🔗 Cheesam31 GitHub STM32F407VG_Basic Repository(GPIO_EXIT)
Author And Source
이 문제에 관하여(STM32F407G-DISC1 개발일지 (3)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@cheesam31/STM32F407G-DISC1-개발일지-3저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)