Embedded

ARM Cortex M4 core - (2) EXTI로 FND 제어

MiddleJo 2024. 9. 4. 16:46

EXTI.zip
7.04MB

목차

1. 배경

2. 보드 구성 및 소스코드

3. 실습결과

 

 

1. 배경

 

 

EXTI는 외부 인터럽트라는 뜻입니다.

인터럽트는 CPU의 효율이 떨어지지 않고

특정 이벤트들을 처리할 수 있도록 도와줍니다.

또한, 다른 방식보다 처리 속도가 굉장히 빠르기 때문에

사용을 위해 알아둘 필요가 있습니다.

 

 

2. 보드 구성 및 소스코드

기본적으로, Board Select 선택 시 불필요한 기능이 포함되어

코드가 길어지고 보기 불편합니다.

따라서 MCU 방법으로 직접 세팅하겠습니다.

기본 상태에서 코딩이 필요한 부분만을 언급할 예정이며,

자세한 것은 첨부된 파일을 참고하시면 됩니다.

 

- 보드 세팅

 

- NVIC 세팅

 

 

 

 

NUCLEO-F429ZI 매뉴얼을 참고하여

몇 가지 실험할 포트만 활성화하였습니다.

또한, 인터럽트 사용을 위해 NVIC 설정을 해주었습니다.

 

- 인터럽트 신호 선택

 

PC13으로 연결된 USER 버튼으로 인터럽트를 일으키겠습니다.

HAL_GPIO_EXTI_IRQHandler 함수를 블록 씌우고 F3을 누르면,

 

 

다음과 같은 함수를 확인할 수 있고,

아래에 있는 HAL_GPIO_EXTI_Callback 함수는 weak 처리되어 있습니다.

이제 이 함수를 main.c로 가져와 커스텀합니다.

 

- EXTI_Callback

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if (GPIO_Pin == GPIO_PIN_13)
		{
			EXTI_flag = 1;
		}
}
/* USER CODE END 4 */

 

위와 같이 버튼이 눌렸을 때 flag를 1로 주어 main 함수에서 활용할 수 있도록 합니다.

 

 

- Main

/* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  switch (currentState)
	      {
	        case STATE_SEG_DISPLAY:
	          if (EXTI_flag == 1)
	          {
	            currentState = STATE_EXTI_PROCESS;
	            EXTI_flag = 0;
	            HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
//	            last_tick = HAL_GetTick();
	          }
	          else
	          {
//	            if (HAL_GetTick() - last_tick >= 1000)
//	            {
	              GPIOD->BSRR = seg[segment_index];
	              segment_index = (segment_index + 1) % 10;
	              HAL_Delay(1000);
//	              last_tick = HAL_GetTick();
//	            }
	          }
	          break;

	        case STATE_EXTI_PROCESS:
	          HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
	          HAL_Delay(1000);
	          HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
	          HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
	          HAL_Delay(1000);
	          HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
	          HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET);
	          HAL_Delay(1000);
	          HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET);

	          currentState = STATE_SEG_DISPLAY;
//	          last_tick = HAL_GetTick();  // 상태가 복귀될 때 시간 재설정
	          break;

	  }
	  /* USER CODE END WHILE */

 

대기상태로 기다리다가, EXTI_flag 신호가 들어오면 EXTI Process로 전이합니다.

PB0, PB7, PB14 (LED들)을 차례대로 키고 끈 뒤, 다시 작업으로 복귀합니다.

 

flag가 0인 경우에는, FND의 숫자가 계속 증가하도록 하는데,

아래와 같이 변수로 정의해 둔 것을 사용합니다.

자세한 7-segment 설명은 생략합니다.

 

tick의 경우는 인터럽트 이후 시간을 기다렸다가 갈 건지 등을 조절하기 위해 만들었습니다만,

굳이 사용하지 않겠습니다.

 

- PV

/* USER CODE BEGIN PV */

typedef enum {
  STATE_SEG_DISPLAY,
  STATE_EXTI_PROCESS
} StateType;

StateType currentState = STATE_SEG_DISPLAY;
volatile uint8_t EXTI_flag = 0;
volatile uint8_t segment_index = 0;
// volatile uint32_t last_tick = 0;

uint32_t seg[10] = {
        0x003f00c0,  // 0
        0x000600f9,  // 1
        0x005b00a4,  // 2
        0x004f00b0,  // 3
        0x00660099,  // 4
        0x006d0092,  // 5
        0x007d0082,  // 6
        0x002700d8,  // 7
        0x007f0080,  // 8
        0x006f0090   // 9
};

/* USER CODE END PV */

 

 

 

3. 실습결과

 

 

시간에 따라 FND가 증가하다가,

버튼을 누르면 인터럽트에 의해 LED가 차례대로 켜지고,

다시 증가합니다.