null
vuild_
Nodes
Flows
Hubs
Login
MENU
GO
Notifications
Login
⌂
Embedded C 학습 로드맵
Structure
what-is-embedded-system
•
임베디드 SW vs 일반 SW
•
CPU 아키텍처 기초
•
메모리 레이아웃
development-environment
•
툴체인 개요
•
프로젝트 & 라이브러리 구조
•
플래싱 & 디버깅
c-language-for-embedded
•
데이터 타입과 이식성
•
비트 연산
•
volatile과 최적화
gpio
•
GPIO 개념
•
출력 제어
•
입력 읽기 & 디바운스
basic-uart
•
UART 프레이밍 & 보레이트
•
송수신 구현
•
UART 디버그 출력
Flow Structure
출력 제어
12 / 15
UART 프레이밍 & 보레이트
☆ Star
↗ Full
입력 읽기 & 디바운스
#gpio
#input
#button
#polling
#debounce
@devpc
|
2026-04-02 05:47:09
|
GET /api/v1/flows/10/nodes/205?fv=2&nv=1
Context:
Flow v2
→
Node v1
0
Views
3
Calls
# 입력 읽기 & 디바운스 ## 버튼 폴링 (Polling) 폴링(Polling)은 메인 루프에서 **주기적으로 핀 상태를 읽어** 버튼 눌림을 감지하는 방식입니다. ``` [ 폴링 방식 흐름 ] while(1) { 핀 상태 읽기 | ┌────┴────┐ Low? High? | | 버튼 눌림 버튼 안 눌림 | 동작 수행 } ``` 인터럽트 방식보다 단순하지만, 메인 루프가 빠르게 돌아야 응답성이 좋습니다. --- ## TC37x: PORT 입력 레지스터 읽기 iLLD에서 핀의 현재 상태를 읽는 함수: ```c #include "IfxPort.h" /* P00.0 핀 상태 읽기 */ boolean pinState = IfxPort_getPinState(&MODULE_P00, 0); /* * TRUE → 핀 High * FALSE → 핀 Low */ ``` 내부적으로는 PORT 모듈의 `IN` 레지스터를 읽습니다. ``` [ PORT IN 레지스터 ] IN 레지스터 (32비트): 비트 0 = P.0의 현재 전압 (High→1, Low→0) 비트 1 = P.1의 현재 전압 ... 비트 15 = P.15의 현재 전압 ``` --- ## 채터링 (Chattering) 물리적인 버튼은 누를 때 스프링처럼 **수십 ms 동안 빠르게 접촉/이탈을 반복**합니다. 이를 채터링(Bouncing/Chattering)이라고 합니다. ``` [ 채터링 파형 ] 이상적인 버튼: 실제 버튼: HIGH ─────┐ HIGH ─────┐ ┌┐┌─ │ │ │││ LOW └────── LOW └─┘└┘└────── 버튼 누름 버튼 누름 ↑ 채터링 발생 구간 (~10~20ms) ``` 채터링을 처리하지 않으면 한 번 누른 버튼이 여러 번 눌린 것으로 감지됩니다. --- ## 소프트웨어 디바운스 (Debounce) 채터링을 소프트웨어로 처리하는 기법입니다. ### 방법 1: 단순 지연 (Delay Debounce) ```c boolean readButton_withDelay(void) { boolean state = IfxPort_getPinState(&MODULE_P00, 0); if (!state) /* Active Low: Low = 눌림 감지 */ { waitTime(IfxStm_getTicksFromMilliseconds(BSP_DEFAULT_TIMER, 20)); state = IfxPort_getPinState(&MODULE_P00, 0); /* 20ms 후 재확인 */ } return !state; /* Active Low 반전 */ } ``` 단순하지만 20ms 동안 CPU가 블로킹됩니다. 실시간 시스템에서는 적합하지 않습니다. ### 방법 2: 카운터 기반 디바운스 (Non-Blocking) ``` [ 카운터 디바운스 알고리즘 ] 매 주기(예: 5ms)마다 호출: 핀 Low 감지? | Yes → 카운터 증가 | 카운터 >= 임계값(예: 4회 = 20ms)? | Yes → "버튼 눌림" 확정 판정 No → 아직 대기 핀 High 감지? → 카운터 초기화 ``` ```c /* 비블로킹 디바운스 예시 */ #define DEBOUNCE_THRESHOLD 4 /* 4회 × 5ms = 20ms */ typedef struct { uint8_t counter; boolean pressed; boolean prevPressed; } ButtonState; void debounce_update(ButtonState *btn) { boolean pinLow = !IfxPort_getPinState(&MODULE_P00, 0); /* Active Low */ if (pinLow) { if (btn->counter < DEBOUNCE_THRESHOLD) btn->counter++; } else { btn->counter = 0; } btn->prevPressed = btn->pressed; btn->pressed = (btn->counter >= DEBOUNCE_THRESHOLD); } /* 엣지 감지: 방금 막 눌렸는지 (Rising Edge) */ boolean isButtonJustPressed(ButtonState *btn) { return (btn->pressed && !btn->prevPressed); } ``` ``` [ 카운터 디바운스 상태 변화 ] 실제 핀: H H L L L L L H (채터링 없는 이상적 예시) 카운터: 0 0 1 2 3 4 4 0 pressed: F F F F F T T F ↑ 확정 판정 (20ms 이상 Low 유지) ``` --- ## 완성 예제: 버튼으로 LED 토글 ```c #include "IfxPort.h" #include "Bsp.h" #define LED_PORT &MODULE_P13 #define LED_PIN 0 #define BTN_PORT &MODULE_P00 #define BTN_PIN 0 static ButtonState btn = {0, FALSE, FALSE}; void gpio_init(void) { IfxPort_setPinMode(LED_PORT, LED_PIN, IfxPort_Mode_outputPushPullGeneral); IfxPort_setPinMode(BTN_PORT, BTN_PIN, IfxPort_Mode_inputPullUp); /* 풀업: 미입력 시 High */ IfxPort_setPinLow(LED_PORT, LED_PIN); } void core0_main(void) { gpio_init(); while (1) { debounce_update(&btn); if (isButtonJustPressed(&btn)) { IfxPort_togglePin(LED_PORT, LED_PIN); /* LED 토글 */ } waitTime(IfxStm_getTicksFromMilliseconds(BSP_DEFAULT_TIMER, 5)); /* 5ms 주기 */ } } ``` --- ## 다른 MCU와의 차이점 > ⚠️ 다른 MCU에서 넘어온다면 이런 점이 다를 수 있습니다. - **디바운스 알고리즘 자체**: 플랫폼 무관하게 동일. C 코드 그대로 이식 가능. - **읽기 함수**: STM32 `HAL_GPIO_ReadPin()`, Arduino `digitalRead()` — 이름만 다름. - **타이머 기반 디바운스**: 더 정밀한 제어를 위해 STM32/TC37x 모두 하드웨어 타이머로 주기 인터럽트를 만들어 디바운스를 실행하는 방식도 자주 사용.
출력 제어
UART 프레이밍 & 보레이트
// COMMENTS
Newest First
ON THIS PAGE
No content selected.