먼저 나의 환경은 Ubuntu 20.04, NUCLEO-F411RE 사용 중
Tool은 CMake를 통해 빌드하여 VSCode로 Debug 한다.
2023.09.10 - [프로그래밍/STM32] - [STM32] STM32CubeMX로 CMake설정하기
2023.09.03 - [프로그래밍/STM32] - [STM32] cmake build(feat .bin, .elf, .hex 추출)
2023.09.03 - [프로그래밍/STM32] - [STM32] VSCode 에서 STM32 디버깅하기(.vscode)
1. EXTI 설명
외부 인트럽트(EXTI)를 사용해 보자.
먼저 관련 문서
먼저 아래의 문서를 보면 EXTI에 대한 event mapping이 되어있는데,
요약하자면 EXTI0은 PA0~PH0 핀 중 하나를 선택하여 사용할 수 있다.
마찬가지로 EXTI1은 PA1~PH1 핀 중 하나를 선택하여 사용할 수 있다.
주의할 점은 동시에 불가능하다. 애초에 MX에서 PA0을 EXTI핀으로 설정하고 PB0을 EXTI핀으로 설정하면 PA0핀의 설정이 지워진다.
여기서 특이한 것은 EXTI5~9와 EXTI10~15는 같은 각각 하나의 Address가 지정되어 있다.
EXTI0~4까지는 하나의 핀에 하나의 함수가 연결되는데, EXTI5~9의 5개 핀이 하나의 함수에, EXTI10~15의 6개 핀에 하나의 함수가 연결되어 있다.
즉 EXTI5번부터는 함수에서 어떤 인터럽트가 호출되었는지 구분해줘야 한다.
2. EXTI 설정
cubeMX에 들어가 PA0을 GPIO_EXTI0으로 설정한다.
또한 EXTI10~15를 확인하기 위해 PC10~PC15를 EXTI로 연결해 준다.
NVIC(Nested Vectored Interrupt Controller)에서 EXTI line0 interrupt가 생겼을 것이다. enable을 체크해 주고
EXTI line[15:10] interrupts 또한 enable을 체크해 준다.
이후 Generate Code를 클릭한다.
3. EXTI 코딩
"STM32/Core/Src/stm32f4xx_it.c" 경로로 이동하면 아래의 소스코드가 있을 것이다.
EXTI0_IRQHandler 함수는 하나의 핀과 연결된 반면, EXTI15_10_IRQHandler 함수는 6개의 핀과 연결되어 있는 것을 볼 수 있다.
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
void EXTI15_10_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15);
}
하지만 결국 마지막은 HAL_GPIO_EXTI_IRQHandler의 하나의 함수이다.
EXTI[number]_IRQHandler를 사용하면 따로 관리를 해도 되지만 지금은 테스트만 하는 것으로 굳이 하진 않겠다.
HAL_GPIO_EXTI_IRQHandler 함수를 살펴보면 해당 핀이 SET하게 되면 clear 후 콜백함수를 호출한다.
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}
아래는 콜백함수이다. __weak란 같은 이름인 함수가 발견되었을 때, __weak가 붙은 함수의 우선순위를 뒤로 해달라는 뜻으로 간단하게 사용자 재정의가 가능한 함수라고 생각하면 된다.
아래와 같이 재정의를 하고 RUN을 한다.
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
UNUSED(GPIO_Pin);
}
uint8_t getGPIOPinAddressToNum(uint16_t pin){
uint8_t num = -1;
switch(pin)
{
case GPIO_PIN_0:
num = 0;
break;
case GPIO_PIN_1:
num = 1;
break;
case GPIO_PIN_2:
num = 2;
break;
case GPIO_PIN_3:
num = 3;
break;
case GPIO_PIN_4:
num = 4;
break;
case GPIO_PIN_5:
num = 5;
break;
case GPIO_PIN_6:
num = 6;
break;
case GPIO_PIN_7:
num = 7;
break;
case GPIO_PIN_8:
num = 8;
break;
case GPIO_PIN_9:
num = 9;
break;
case GPIO_PIN_10:
num = 10;
break;
case GPIO_PIN_11:
num = 11;
break;
case GPIO_PIN_12:
num = 12;
break;
case GPIO_PIN_13:
num = 13;
break;
case GPIO_PIN_14:
num = 14;
break;
case GPIO_PIN_15:
num = 15;
break;
}
return num;
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
LOG("intterupt %d pin!", getGPIOPinAddressToNum(GPIO_Pin));
}
그럼 아래와 같이 pin이 출력이 된다.
다만, PC11을 누르지 않아도 출력이 되고 PA0도 스위치를 누르지 않았는데 0이 출력되는 것을 보면 플로팅 때문인 듯하다.
플로팅이더라도 이렇게 자주일어나진 않을 텐데;;; 어쨌건 귀찮으니 풀다운 설정은 하지 않는다.
2022.03.22 - [0. 이론] - 플로팅(Floating)현상이란?
플로팅(Floating)현상이란?
플로팅 현상이란 "떠 있다"라는 뜻으로 아무것도 연결되어있지 않아 전압을 모르는 상태이다. 사실 나는 아무것도 연결이 되어 있지 않은 상태라면 0V라 생각했지만 아니었다. 마치 C언어에서 변
park-duck.tistory.com
자, 그럼 PA0은 하나뿐이니 GPIO_PIN_0만 들어오는 것을 볼 수 있다.
왜냐하면 스위치가 눌러졌을 때 EXTI0_IRQHandler 함수가 실행되어 HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0)을 통해 GPIO_PIN_0이 전달될 테니.
그렇다면 EXTI10_15는 어떨까?
귀찮아서 PC15만 스위치를 연결하고 HAL_GPIO_EXTI_IRQHandler에 로그를 출력해 보았다.
확인해 보면
1. HAL_GPIO_EXTI_IRQHandler 10, 11, 12, 13을 출력
2. interrupt 13pin!을 출력
3. HAL_GPIO_EXTI_IRQHandler 14, 15를 마저 출력
하는 것을 볼 수 있는데
요약하자면
PC10~15중 하나의 인터럽트가 일어나게 되면 HAL_GPIO_EXTI_IRQHandler함수에서 PC10~15중 SET이 되어있는 핀을 찾고 callback함수를 요청하는 것이다.
다시 한번 말하지만 0~4번 핀들은 하나의 핀이기 때문에 EXTI[number]_IRQHandler 함수에서 즉시 함수를 구현해도 되지만
5~9번 핀과 10~15번 핀은 함수를 통해 어떤 핀이 인터럽트를 줬는지 확인을 해야 한다.
5~15번 핀 중 찾을 필요가 없다면 얘기가 달라지지만...
HW에는 잘 모르는 편이라 참고만 하시고 피드백은 환영...
'프로그래밍 > STM32' 카테고리의 다른 글
[STM32] CPU 온도 측정하기 (0) | 2023.09.30 |
---|---|
[STM32] USART를 활용한 print찍기 (0) | 2023.09.30 |
[STM32] STM32CubeMX로 CMake설정하기 (0) | 2023.09.10 |
[STM32] VSCode 에서 STM32 디버깅하기(.vscode) (0) | 2023.09.03 |
[STM32] cmake build(feat .bin, .elf, .hex 추출) (0) | 2023.09.03 |
댓글