SPI 모드 CPOL CPHA: 0~3 설정 데이터시트 판독법과 펌웨어

임베디드 보드 개발 과정에서 고속 SPI(Serial Peripheral Interface) 플래시 메모리나 정밀 ADC, 센서를 마이크로컨트롤러(MCU)와 연동할 때 수신 데이터의 상위 1비트가 누락되거나 전체 바이트가 1비트씩 시프트되어 깨지는 현상은 가장 흔하게 마주치는 직렬 통신 결함입니다. 물리적 오실로스코프 신호 상으로는 깨끗한 구형파 클록과 데이터가 인가되고 있음에도 불구하고 통신 에러가 지속되는 핵심 원인은 바로 SPI 모드 CPOL CPHA 설정 불일치에 따른 샘플링 타이밍 위상 오류입니다.

I2C와 달리 표준화된 프로토콜 공식 규격 문서가 부재한 SPI 통신은 모토로라(Motorola)가 제안한 4가지 클록 극성(CPOL) 및 클록 위상(CPHA) 조합에 의존합니다. 마스터와 슬레이브 디바이스가 기대하는 클록 아이들(Idle) 전위와 첫 번째 래치(Latch) 에지가 단 반 주기라도 어긋나면, 셋업 타임(Setup Time)과 홀드 타임(Hold Time)이 침범당해 프레임 전체의 무결성이 붕괴하므로 데이터시트 타이밍도를 판독하는 하드웨어적 접근이 필수적입니다.

SPI 모드 CPOL CPHA 타이밍 다이어그램 및 클록 위상 샘플링 분석

SPI 모드 CPOL CPHA: 클록 극성과 위상 조합의 4대 동작 메커니즘

SPI 인터페이스의 동기화 원리는 클록 신호(SCK/SCLK)의 유휴 상태 전위 레벨과 데이터 비트 샘플링 기준 에지라는 두 가지 독립된 변수로 결정됩니다. 클록 극성인 CPOL(Clock Polarity)은 칩 선택 신호(CS/SS)가 활성화(Low)된 후 실제 통신이 시작되기 직전 SCK 라인이 유지하는 기본 전압 상태를 정의합니다. CPOL=0은 아이들 상태가 접지 레벨(Low)임을 뜻하며, CPOL=1은 풀업 전원 레벨(High)로 대기함을 규정합니다.

클록 위상을 결정하는 CPHA(Clock Phase)는 데이터 라인(MOSI, MISO)의 비트를 어느 에지에서 샘플링(래치)하고 어느 에지에서 다음 비트로 전환(토글)할 것인지를 지정합니다. CPHA=0은 SCK의 첫 번째 천이 에지에서 즉각 데이터를 래치함을 의미하고, CPHA=1은 두 번째 천이 에지에서 데이터를 읽어 들이도록 하드웨어 시프트 레지스터를 구동합니다.

"SPI 버스 통신에서 마스터와 슬레이브는 동일한 클록 모드로 구성되어야 합니다. CPHA=0일 때 첫 번째 데이터 비트는 첫 클록 에지가 발생하기 전에 이미 MOSI 라인에 유효하게 출력(Setup)되어 있어야 하며, CPHA=1일 때는 첫 클록 에지가 데이터를 구동하고 두 번째 에지에서 샘플링이 완료됩니다."
— Texas Instruments Application Report (SLAA584): Key Considerations for Choosing SPI

TI 기술 문서에서 명시하듯, CPHA=0 모드에서는 클록이 아직 뛰지 않는 아이들 구간에서 CS 신호가 떨어지는 순간(Falling Edge) 최상위 비트(MSB)가 데이터 라인에 미리 셋업되어 있어야 합니다. 이 타이밍 조건을 인지하지 못하고 마스터 펌웨어를 잘못 초기화하면 첫 번째 비트를 완전히 놓쳐 1비트 좌측/우측 편향 에러를 유발하게 됩니다.

SPI 모드 0부터 3까지의 SCK 에지 정렬 및 데이터 토글 비교도

디바이스 데이터시트 타이밍도에서 SPI 모드 0~3 판독하는 법

부품 제조사 데이터시트가 "Mode 0" 또는 "Mode 3"과 같이 친절하게 명시하지 않는 경우, 엔지니어는 데이터시트 전반부의 'Serial Interface Timing' 다이어그램을 보고 직접 레지스터 비트를 매핑해야 합니다. 판독 절차는 단순한 2단계 판별법을 따릅니다.

데이터시트 타이밍 파형 2단계 판독 프로세스
1단계: CS가 High일 때 SCK 레벨 관측
→
Low면 CPOL=0 / High면 CPOL=1
→
2단계: 데이터 안정 구간(수직 점선) 관측
→
첫 에지면 CPHA=0 / 둘째 에지면 CPHA=1
* 실무 핵심: 데이터시트에서 데이터 버스가 교차하는 지점(X 표시)은 변경(Toggle) 시점이며, 수직 점선이나 화살표는 샘플링(Latch) 시점임
SPI 모드CPOL (클록 극성)CPHA (클록 위상)데이터 래치(샘플링) 에지대표 지원 반도체 및 디바이스
모드 0 (Mode 0)0 (아이들 Low)0 (첫 번째 에지)상승 에지 (Rising Edge)W25Qxx SPI 플래시, 범용 SD카드, NRF24L01
모드 1 (Mode 1)0 (아이들 Low)1 (두 번째 에지)하강 에지 (Falling Edge)특수 모터 드라이버 IC, 일부 산업용 DAC
모드 2 (Mode 2)1 (아이들 High)0 (첫 번째 에지)하강 에지 (Falling Edge)레거시 통신 모듈, 특정 센서 인터페이스
모드 3 (Mode 3)1 (아이들 High)1 (두 번째 에지)상승 에지 (Rising Edge)고속 NOR Flash, MPU9250 IMU, ADIS16xxx 센서

위 비교표에서 알 수 있듯이, 시장에 출시된 대다수의 고속 SPI 플래시 메모리와 고성능 디지털 센서들은 모드 0(0,0)과 모드 3(1,1)을 동시에 지원(Dual-mode compatibility)하도록 설계되어 있습니다. 이는 두 모드 모두 데이터 래치가 '상승 에지(Rising Edge)'에서 동일하게 일어나기 때문이며, 아이들 상태가 Low냐 High냐의 차이만 존재합니다.

STM32 MCU SPI 제어 레지스터 CR1의 CPOL CPHA 비트 매핑 구조

STM32 하드웨어 레지스터 직접 제어 및 동적 모드 전환 펌웨어

여러 이종 슬레이브 디바이스가 단일 SPI 버스를 공유하면서 각자 다른 모드(예: 센서는 Mode 0, 디스플레이는 Mode 3)를 요구할 때, 펌웨어는 CS 핀을 활성화하기 전에 SPI 컨트롤러의 제어 레지스터를 실시간으로 재구성해야 합니다.

아래 C/C++ 펌웨어 코드는 STM32F4/G4 마이크로컨트롤러 환경에서 라이브러리 오버헤드 없이 `SPI_CR1` 레지스터의 CPOL 및 CPHA 비트를 하드웨어 수준에서 안전하게 스위칭하고 전송을 수행하는 구현 스니펫입니다.

#include <stdint.h>
#include "stm32f4xx.h"

typedef enum {
    SPI_MODE_0 = 0, // CPOL=0, CPHA=0
    SPI_MODE_1 = 1, // CPOL=0, CPHA=1
    SPI_MODE_2 = 2, // CPOL=1, CPHA=0
    SPI_MODE_3 = 3  // CPOL=1, CPHA=1
} SpiMode_t;

// SPI 모듈 활성화 상태에서 CR1 비트 변경 시 결함 발생 방지 루틴
void SPI1_Set_Mode(SpiMode_t mode) {
    // 1. 진행 중인 송수신 완료 대기 (TXE=1, BSY=0 검증)
    while (!(SPI1->SR & SPI_I2S_FLAG_TXE));
    while (SPI1->SR & SPI_I2S_FLAG_BSY);

    // 2. SPI 컨트롤러 일시 비활성화 (SPE 비트 클리어)
    SPI1->CR1 &= ~SPI_CR1_SPE;

    // 3. 기존 CPOL (비트 1), CPHA (비트 0) 마스크 클리어
    SPI1->CR1 &= ~(SPI_CR1_CPOL | SPI_CR1_CPHA);

    // 4. 새로운 모드 비트 주입
    switch (mode) {
        case SPI_MODE_0:
            // CPOL=0, CPHA=0 (추가 세트 불필요)
            break;
        case SPI_MODE_1:
            SPI1->CR1 |= SPI_CR1_CPHA;
            break;
        case SPI_MODE_2:
            SPI1->CR1 |= SPI_CR1_CPOL;
            break;
        case SPI_MODE_3:
            SPI1->CR1 |= (SPI_CR1_CPOL | SPI_CR1_CPHA);
            break;
    }

    // 5. SPI 컨트롤러 재활성화
    SPI1->CR1 |= SPI_CR1_SPE;
}

uint8_t SPI1_TransmitReceive_Byte(uint8_t tx_data) {
    // 송신 버퍼 빌 때까지 대기 후 데이터 기입
    while (!(SPI1->SR & SPI_I2S_FLAG_TXE));
    SPI1->DR = tx_data;

    // 수신 버퍼 채워질 때까지 대기 후 데이터 리턴
    while (!(SPI1->SR & SPI_I2S_FLAG_RXNE));
    return (uint8_t)(SPI1->DR);
}

위 펌웨어에서 핵심적인 방어 로직은 `SPI1->CR1 &= ~SPI_CR1_SPE`를 통해 통신 모듈을 완전히 끈 후 비트를 변경하는 점입니다. ARM Cortex-M 구조상 SPI가 활성화된 상태에서 CPOL/CPHA 레지스터를 강제로 덮어쓰면 SCK 라인에 허위 클록 글리치(Spurious Glitch)가 방출되어 슬레이브가 엉뚱한 비트를 래치하는 치명적 버그가 발생합니다.

SPI 타이밍 무결성 실무 하드웨어 체크리스트

  • CS 셋업/홀드 시간 준수: CS 신호가 Low로 떨어진 후 첫 클록 에지까지의 지연 시간($t_{CSS}$)과 마지막 에지 후 High 복귀 지연($t_{CSH}$)을 최소 50ns 이상 확보한다.
  • SCK 라인 종단 저항 배치: 20MHz 이상의 고속 SPI 라우팅 시 클록 반사 링잉을 억제하기 위해 마스터 출력 핀 바로 옆에 $22\Omega \sim 33\Omega$ 댐핑 저항을 직렬 실장한다.
  • 공통 모드 버스 풀업 저항: 모드 3(CPOL=1) 운용 시 슬레이브 리셋이나 부팅 시의 전위 플로팅을 방지하기 위해 SCK 라인에 약한 풀업($10\text{k}\Omega$)을 배치한다.
  • MOSI/MISO 배선 길이 매칭: 수십 MHz 초고속 환경에서는 클록과 데이터 라인 간의 스큐(Skew)를 최소화하기 위해 트레이스 길이를 등장 배선(Length Matching)한다.
오실로스코프로 실측한 SPI SCK 클록과 MOSI 데이터 에지 정합 파형

실무 엔지니어링 FAQ

Q1. 모드 0 디바이스를 모드 3 마스터로 구동해도 통신이 정상 동작하는 이유는 무엇입니까?

모드 0(CPOL=0, CPHA=0)과 모드 3(CPOL=1, CPHA=1)은 둘 다 데이터 래칭이 SCK 상승 에지(Rising Edge)에서 수행되기 때문입니다. 슬레이브 하드웨어 내부가 단지 상승 에지에서 데이터를 읽고 하강 에지에서 데이터를 내보내는 단순 에지 트리거 회로로 구성되어 있다면, CS 활성화 시점의 아이들 상태 차이만 감수할 수 있다면 두 모드 간 상호 호환이 성립합니다.

Q2. 수신 바이트가 좌측으로 1비트씩 시프트(예: 0x55 대신 0xAA)되는 현상의 원인은 무엇입니까?

슬레이브는 CPHA=0(첫 번째 에지 샘플링)을 기대하고 있는데 마스터 MCU가 CPHA=1(두 번째 에지 샘플링)로 구성되어 있을 때 발생하는 전형적인 타이밍 역전 현상입니다. 마스터가 첫 클록 에지를 데이터 래칭에 쓰지 않고 넘겨버리면서 최상위 비트(MSB)가 유실되고 그 다음 비트부터 읽어 들이므로 1비트 좌측 시프트 결과가 반환됩니다.

Q3. SPI 통신 속도를 50MHz 이상으로 올릴 때 왜 CPHA=0 모드가 더 취약합니까?

CPHA=0 모드는 첫 클록 에지가 발생하기 전에 데이터가 이미 유효하게 안정화되어 있어야 하는 $t_{valid}$ 제약이 매우 가혹합니다. 초고속 주파수에서는 CS가 떨어지는 순간부터 첫 번째 클록 상승 에지까지의 물리적 시간이 수 나노초에 불과하므로 슬레이브의 내부 출력 버퍼 지연(Propagation Delay)이 이를 따라가지 못해 셋업 타임 위반이 발생하기 때문입니다.

공식 기술 가이드 및 표준 규격 레퍼런스

함께 보면 좋은 글

📌 안내
이 글은 정보 제공을 목적으로 작성되었으며, 실제 기기·환경·정책에 따라 결과가 다를 수 있습니다. 보다 정확하고 최신인 정보는 아래 공신력 있는 기관의 자료를 함께 참고하시기 바랍니다.

Similar Posts