채터링이란 스위치의 접점이 닫히거나 열리는 순간 기계적인 진동에 의해 매우 짧은 시간 안에 스위치가 붙었다 떨어지는 것을 반복하는 현상으로 Bounce 라고도 한다.
디바운스는 채터링 현상을 억제하는 해결법을 말한다. 커패시터를 추가하는 등 하드웨어적인 방법이 있고 소프트웨어적으로 해결하는 방법이 있다.
아래에선 소프트웨어적으로 해결하는방법을 소개한다.
버튼은 외부 풀다운저항을 달아놨고 EXTI Rising Edge에 트리거 되도록 했다. NVIC 설정도 켜고 각각 버튼이 눌렸을 때 LED가 토글되게 소스코드를 짰다.
디바운스 코드 추가하지 않았을 때
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin==GPIO_PIN_8){
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
}
if(GPIO_Pin==GPIO_PIN_9){
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
if(GPIO_Pin==GPIO_PIN_10){
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
}
}
디바운스 코드 추가했을 때
// ...
uint32_t current_tick_1;
uint32_t current_tick_2;
uint32_t current_tick_3;
uint32_t old_tick_1;
uint32_t old_tick_2;
uint32_t old_tick_3;
// ...
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin==GPIO_PIN_8){
current_tick_1 = HAL_GetTick();
}
if(GPIO_Pin==GPIO_PIN_9){
current_tick_2 = HAL_GetTick();
}
if(GPIO_Pin==GPIO_PIN_10){
current_tick_3 = HAL_GetTick();
}
if(GPIO_Pin==GPIO_PIN_8 && (current_tick_1 - old_tick_1 > 300)){
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
old_tick_1 = current_tick_1;
}
if(GPIO_Pin==GPIO_PIN_9 && (current_tick_2 - old_tick_2 > 300)){
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
old_tick_2 = current_tick_2;
}
if(GPIO_Pin==GPIO_PIN_10 && (current_tick_3 - old_tick_3 > 300)){
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
old_tick_3 = current_tick_3;
}
}
처음 또는 한동안 이벤트가 없다가 ISR에 들어왔을 땐 LED 토글작업을 한 뒤 old_tick 변수를 업데이트 하여 그 뒤 300ms 안에 들어오는 인터럽트는 처리하지 않고 무시하는 코드이다.
전역변수 대신 static 변수 사용한 버전
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
static uint32_t before_tick = 0;
if(GPIO_Pin == GPIO_PIN_13)
{
if(HAL_GetTick() - before_tick >= 300)
{
before_tick = HAL_GetTick();
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
}
}
}
비교영상
EXTI 대신 GPIO Input 사용한 버전
/* USER CODE BEGIN 2 */
uint8_t debounceState = 0;
uint32_t debounceTime = 0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
switch(debounceState)
{
case 0:
if(HAL_GPIO_ReadPin(BT1_GPIO_Port, BT1_Pin))
{
debounceState = 1;
debounceTime = HAL_GetTick();
}
break;
case 1:
if(!HAL_GPIO_ReadPin(BT1_GPIO_Port, BT1_Pin))
{
debounceState = 0;
break;
}
if(HAL_GetTick() - debounceTime >= 100)
{
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
debounceState = 0;
}
break;
}
}
'임베디드 개발 > STM32 (ARM Cortex-M)' 카테고리의 다른 글
STM32 ] ADC + MFC + MySQL, 시리얼 통신 및 DB연동, 검색기능, 실시간 그래프 구현 (쓰레드 사용) (1) | 2022.07.17 |
---|---|
STM32 ] SysTick Timer Callback 함수 사용하기 (0) | 2022.07.14 |
앱 인벤터 ] GPS 모듈, 지자기센서 디버깅용 간단 어플 만들기 - 프로젝트 준비과정 (3) (0) | 2022.07.06 |
STM32 ] NEO-6M 모듈 사용 , GPS 데이터 파싱하는 법 - 프로젝트 준비과정 (1) (0) | 2022.07.03 |
STM32 ] 지자기 센서 HMC5883L 으로 방위각 측정하기 - 프로젝트 준비 과정 (2) (0) | 2022.07.02 |