STM32 USART 통신 구현과 내부 원리

RS-232 통신 규격

RS-232은 EIA(Electronic Industries Alliance)에서 표준화한 비동기 직렬 통신 인터페이스입니다. PC 및 산업용 장비에서 널리 활용됩니다.

전기적 특성

  • 논리 HIGH (MARK): -15V ~ -3V
  • 논리 LOW (SPACE): +3V ~ +15V

필요 신호선

전이중 비동기 통신을 위해서는 RX(수신), TX(송신), GND(접지) 세 가지 선만으로 충분합니다.

전압 레벨 변환: MAX3232

CMOS(0V~3.3V/5V)와 RS-232(±3V~±15V) 간의 전압 차이를 해결하기 위해 MAX3232 같은 레벨 변환 IC를 사용합니다. 이 칩은 내부 전하 펌프를 통해 단일 3.3V 전원으로 ±5.4V 이상의 RS-232 레벨을 생성합니다.

STM32 USART 하드웨어 구조

STM32 내부의 USART 모듈은 독립적인 보드레이트 생성기, 송수신 FIFO(실제로는 TDR/RDR 레지스터), 및 다양한 플래그를 포함한 복잡한 구조를 가집니다. 외부 회로는 MAX3232 또는 USB-UART 브리지 칩을 통해 PC와 연결됩니다.

USART 초기화 및 데이터 송수신

1. 클럭 활성화

// GPIOA와 USART1의 APB2 버스 클럭 공급
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);

2. GPIO 핀 설정

GPIO_InitTypeDef gpioCfg;

// PA9: USART1_TX - 대안 기능 푸시풀
gpioCfg.GPIO_Pin = GPIO_Pin_9;
gpioCfg.GPIO_Mode = GPIO_Mode_AF_PP;
gpioCfg.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpioCfg);

// PA10: USART1_RX - 플로팅 입력
gpioCfg.GPIO_Pin = GPIO_Pin_10;
gpioCfg.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &gpioCfg);

3. USART 파라미터 구성

USART_InitTypeDef uartCfg;

uartCfg.USART_BaudRate = 115200;
uartCfg.USART_WordLength = USART_WordLength_8b;
uartCfg.USART_StopBits = USART_StopBits_1;
uartCfg.USART_Parity = USART_Parity_No;
uartCfg.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
uartCfg.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

USART_Init(USART1, &uartCfg);
USART_Cmd(USART1, ENABLE);

이중 클럭 활성화의 의미

초기화 과정에서 두 번의 ENABLE 호출이 존재하는 이유를 명확히 이해해야 합니다:

단계레지스터역할
버스 클럭 공급RCC_APB2ENRUSART 모듈에 클럭 신호 전달
모듈 기능 활성USART_CR1 (UE 비트)보드레이트 생성기 및 송수신 로직 동작

즉, RCC_APB2PeriphClockCmd()는 모듈에 전원(클럭)을 연결하고, USART_Cmd()는 모듈 내부의 실제 회로를 동작시킵니다.

DR 레지스터의 독특한 설계

STM32의 USART_DR는 물리적으로 하나의 주소를 공유하면서도 두 개의 개별 레지스터로 구현되어 있습니다:

  • 쓰기 동작TDR(Transmit Data Register)로 연결, 내부 버스 → 송신 시프트 레지스터
  • 읽기 동작RDR(Receive Data Register)로 연결, 수신 시프트 레지스터 → 내부 버스

이는 하드웨어 설계에서 버스 대역폭을 절약하면서도 직관적인 프로그래밍 모델을 제공하는 방법입니다.

실전 디버 시 고려사항

USART를 디버깅 목적으로 활용할 때 다음 점을 유의해야 합니다:

  1. 실시간성 저하: 보드레이트가 CPU 클럭 대비 매우 느리므로, 과도한 로그 출력은 시스템 타이밍을 해칠 수 있습니다.
  2. 임계구역 침: 인터럽트 핸들러나 RTOS 태스크 전환 중 출력 시 데이터 손상 가능성이 있습니다.
  3. 블로킹 방식의 한계: USART_SendData() 후 TXE 플래그 폴링은 CPU를 낭비하므로, DMA 전송이나 인터럽트 기반 송수신을 권장합니다.
// DMA 기반 송신 예시 (간략화)
void UART1_TX_DMA_Config(uint8_t *buf, uint16_t len) {
    DMA_InitTypeDef dmaInit;
    
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    
    dmaInit.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
    dmaInit.DMA_MemoryBaseAddr = (uint32_t)buf;
    dmaInit.DMA_DIR = DMA_DIR_PeripheralDST;
    dmaInit.DMA_BufferSize = len;
    dmaInit.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    dmaInit.DMA_MemoryInc = DMA_MemoryInc_Enable;
    dmaInit.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    dmaInit.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    dmaInit.DMA_Mode = DMA_Mode_Normal;
    dmaInit.DMA_Priority = DMA_Priority_Medium;
    dmaInit.DMA_M2M = DMA_M2M_Disable;
    
    DMA_Init(DMA1_Channel4, &dmaInit);
    DMA_Cmd(DMA1_Channel4, ENABLE);
    
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
}

태그: STM32 USART RS-232 MAX3232 임베디드 통신

6월 23일 18:25에 게시됨