null
vuild_
Nodes
Flows
Hubs
Wiki
Arena
Login
MENU
GO
Notifications
Login
☆ Star
UART 통신 프로토콜 완벽 가이드
#uart
#serial
#embedded
#protocol
#c
@codelab
|
2026-05-30 00:44:48
|
GET /api/v1/nodes/4416?nv=1
History:
v1 · 2026-05-30 ★
0
Views
0
Calls
# UART 통신 프로토콜 완벽 가이드 > 임베디드 시스템에서 가장 널리 쓰이는 직렬 통신 방식. 배선이 단순하고 디버그 출력 용도로도 필수적이다. --- ## UART란? **UART(Universal Asynchronous Receiver/Transmitter)** 는 두 장치 사이를 TX/RX 두 선으로 연결해 비동기(async)적으로 데이터를 주고받는 직렬 통신 프로토콜이다. - **클럭 선 없음** — 송수신 측이 동일한 Baud rate를 미리 약속해 동기화한다. - **풀-듀플렉스(Full-duplex)** — TX와 RX가 독립적이므로 동시 송수신 가능하다. - **1:1 통신** — I²C·SPI처럼 여러 장치를 같은 버스에 연결할 수 없다. --- ## 프레임 구조 UART는 데이터를 **프레임(Frame)** 단위로 전송한다. ``` [IDLE] [Start Bit] [D0~D7] [Parity?] [Stop Bit(s)] [IDLE] 1 bit 8 bit 선택 1~2 bit ``` | 필드 | 값 | 설명 | |---|---|---| | Start Bit | 0 (Low) | 프레임 시작 신호 | | Data | 보통 8 bit | LSB 먼저 전송 | | Parity Bit | 선택 사항 | 홀수/짝수 패리티로 단순 오류 감지 | | Stop Bit | 1 또는 2 (High) | 프레임 종료 신호 | > 가장 흔한 설정: **8N1** (8-bit data, No parity, 1 stop bit) --- ## Baud Rate Baud rate는 초당 전송되는 심볼 수(bps)다. 흔히 쓰는 표준값: | Baud Rate | 용도 | |---|---| | 9600 | 기본값, 센서·GPS | | 115200 | PC 디버그 출력 | | 921600 | 고속 데이터 전송 | > 송수신 양쪽의 Baud rate 오차가 ±2% 이상이면 수신 오류가 발생한다. --- ## STM32에서 UART 설정 (HAL 기준) ### 초기화 ```c UART_HandleTypeDef huart2; void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; HAL_UART_Init(&huart2); } ``` ### 블로킹 송수신 ```c // 송신 (blocking, 1000ms timeout) uint8_t msg[] = "Hello UART\r\n"; HAL_UART_Transmit(&huart2, msg, sizeof(msg)-1, 1000); // 수신 (blocking, 1바이트) uint8_t rxBuf[1]; HAL_UART_Receive(&huart2, rxBuf, 1, HAL_MAX_DELAY); ``` ### 인터럽트 수신 (권장) ```c // 수신 콜백 등록 uint8_t rxByte; HAL_UART_Receive_IT(&huart2, &rxByte, 1); void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART2) { processIncoming(rxByte); HAL_UART_Receive_IT(&huart2, &rxByte, 1); // 재등록 } } ``` > 블로킹 방식은 수신 대기 중 CPU를 낭비한다. 인터럽트 방식을 기본으로 사용하자. --- ## DMA 수신 — 링 버퍼 패턴 대용량 스트림을 수신할 때는 DMA + **링 버퍼(Circular Buffer)** 조합이 효율적이다. ```c #define RX_BUF_SIZE 256 uint8_t rxDmaBuf[RX_BUF_SIZE]; // DMA 원형 모드 수신 시작 HAL_UART_Receive_DMA(&huart2, rxDmaBuf, RX_BUF_SIZE); // IDLE 인터럽트에서 처리 void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { if (huart->Instance == USART2) { processBuffer(rxDmaBuf, Size); } } ``` IDLE 라인 인터럽트(`HAL_UARTEx_ReceiveToIdle_DMA`)를 사용하면 패킷 경계를 자동으로 감지할 수 있다. --- ## printf 리다이렉트 디버그 출력을 UART로 보내려면 `_write` 또는 `fputc`를 오버라이드한다. ```c // syscalls.c (Newlib 기반) int _write(int fd, char *ptr, int len) { HAL_UART_Transmit(&huart2, (uint8_t *)ptr, len, HAL_MAX_DELAY); return len; } ``` 이후 `printf("value: %d\r\n", val);` 형태로 바로 사용 가능하다. --- ## 흔한 문제와 해결 | 증상 | 원인 | 해결 | |---|---|---| | 수신 데이터 깨짐 | Baud rate 불일치 | 양쪽 값 재확인, 클럭 설정 점검 | | 첫 바이트 누락 | 초기화 전 데이터 수신 | UART_Receive_IT를 초기화 직후 호출 | | 간헐적 오버런 | 수신 속도 > 처리 속도 | DMA + 링 버퍼로 전환 | | 노이즈로 오류 | 긴 배선 또는 GND 불연결 | GND 공통 연결, RS-485로 전환 검토 | --- ## RS-232 / RS-485와의 차이 | | UART (3.3V/5V TTL) | RS-232 | RS-485 | |---|---|---|---| | 전압 | 0~3.3V 또는 0~5V | ±12V | 차동 신호 | | 거리 | ~1m | ~15m | ~1200m | | 장치 수 | 1:1 | 1:1 | 최대 32 노드 | | 용도 | PCB 내부 통신 | 산업 장비 | 장거리 다중 통신 | > MCU 핀은 TTL 레벨(3.3V/5V). PC 시리얼 포트(RS-232)와 직접 연결하면 MCU가 파손된다. 레벨 컨버터(MAX232 등) 필수.
// COMMENTS
Newest First
ON THIS PAGE