PA5 (내장 LED) : LD2 추가, GPIO Output
PC13 (내장 버튼) : B1 추가, GPIO Input
버튼은 Input Mode의 풀업으로 설정해준다.
main.c
의 while문에
while (1)
{
int ret = HAL_GPIO_ReadPin(GPIOC, B1_Pin);
if (ret == 0) // 풀업이므로, 버튼 눌릴 때가 0
{
HAL_GPIO_TogglePin(GPIOA,LD2_Pin);
}
HAL_Delay(100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
핀 번호에 최대 16 개 Interrupt Pin 으로 설정 가능
Interrupt PIN 들은 같은 PIN 번호를 가지면 안됨 ex) PA0 사용시 PB0 사용불가
각 포트마다 총 7개
의 인터럽트를 사용할 수 있습니다.
0,1,2,3,4,[9:5],[15:10]
이다. ex) PA5를 사용하면 PA9를 사용할 수 없다. 하지만 PB9는 사용가능하다.
NVIC : 중첩 인터럽트시 우선순위 관한 인터럽트 지정, 우선순위를 CPU 대신 관리해주는 회로
우선순위가 같다면, 인터럽트가 발생되지 않고 먼저 실행되는 것부터 진행한다.
PA5 (내장 LED) : LD2 추가, GPIO Output
PC13 (내장 버튼) : B1 추가, GPIO EXTI(인터럽트)
Rising Edge 및 내부 풀업으로 인터럽트 설정, NVIC도 Enable 시켜준다.
stm~~_it.c
파일 중 EXTI15_10_IRQHandler
하단에
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_13)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
}
}
Delay 함수에 Break Pointer(좌측 바 더블클릭)걸고 Trace를 해보자!
Trace : F5(함수 진입), F6(다음 브레이크 포인트로 이동), F7(함수에서 빠져나오기)
__weak void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* Add a freq to guarantee minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)(uwTickFreq);
}
# 현재 tick - 초기 tick이 설정한 delay 값보다 크면 끝
while ((HAL_GetTick() - tickstart) < wait)
{
}
}
초기 셋팅을 하지 않고, 인터럽트 내부에 Delay함수를 사용하면 에러가 발생한다. 이는 tick의 우선순위가 15로 낮기 때문입니다. (우선순위 높음(0) ~ 우선순위 낮음(15)
따라서, 초기셋팅에서 우선순위를 다음 이미지와 같이 변경해줍니다.
그러면, 인터럽트 내부에 위치해있는 tick 함수가 정상 작동합니다.
main.c
내부 : 터미널에 # 반복 찍기
uint8_t buf[10] = "#";
while (1)
{
HAL_UART_Transmit(&huart2, buf, 10, 100);
HAL_Delay(100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
stm_it.c
: 인터럽트 핸들러 밑에
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_13)
{
HAL_Delay(3000); // 초기설정시 사용가능한 Delay 함수
// 초기 설정하지 않을시 for문을 사용한 Delay
for(int j=0; j<2; j++)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 1);
for(int i=0; i<100000; i++);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 0);
for(int i=0; i<100000; i++);
}
}
}
하드웨어적 / 소프트웨어적으로 버튼떨림 현상
을 방지한다.