1. SPI 통신이란?
SPI는 모토로라에서 제안한 동기식(Synchronous), 전이중(Full-Duplex)(데이터 송신과 수신이 동시에 이루어짐) 방식의 직렬 통신입니다. 주로 MCU와 센서, 메모리(Flash), 디스플레이 간의 고속 데이터 전송에 사용됩니다. I2C에 비해 통신 속도가 매우 빠르다. 1:N 통신이 가능하다=하나의 마스터에 여러 개의 슬레이브를 연결할 수 있다.
핀 구성 (4-Wire)
- SCLK (Serial Clock): 통신 속도를 결정하는 클럭 (Master가 생성).
- MOSI (Master Out Slave In): 마스터에서 슬레이브로 데이터 전송.
- MISO (Master In Slave Out): 슬레이브에서 마스터로 데이터 전송.
- CS/SS (Slave Select): 통신할 슬레이브를 선택 (보통 Active Low).
2. 핵심 파라미터: CPOL과 CPHA
SPI를 처음 연결할 때 가장 많이 하는 실수가 바로 SPI Mode 설정입니다. 데이터시트의 Timing Diagram을 보고 아래 4가지 모드 중 하나를 선택해야 합니다.
| Mode | CPOL (Polarity) | CPHA (Phase) | 설명 |
|---|
| 0 | 0 | 0 | Idle 시 클럭 Low, 첫 번째 엣지에서 샘플링 |
| 1 | 0 | 1 | Idle 시 클럭 Low, 두 번째 엣지에서 샘플링 |
| 2 | 1 | 0 | Idle 시 클럭 High, 첫 번째 엣지에서 샘플링 |
| 3 | 1 | 1 | Idle 시 클럭 High, 두 번째 엣지에서 샘플링 |
3. ATmega328P SPI 주요 레지스터 정리
AVR 아키텍처에서 SPI를 제어하려면 크게 3가지 레지스터(SPCR, SPSR, SPDR)만 이해하면 됩니다.
1) SPCR (SPI Control Register)
SPI의 동작 모드와 설정을 담당하는 가장 중요한 레지스터입니다.
| Bit | Name | Description |
|---|
| 7 | SPIE | SPI Interrupt Enable: 1로 설정 시 전송 완료 인터뷰트 활성화 |
| 6 | SPE | SPI Enable: 1로 설정 시 SPI 모듈 활성화 |
| 5 | DORD | Data Order: 1이면 LSB First, 0이면 MSB First |
| 4 | MSTR | Master/Slave Select: 1이면 Master 모드, 0이면 Slave 모드 |
| 3 | CPOL | Clock Polarity: 1이면 Idle 시 High, 0이면 Low |
| 2 | CPHA | Clock Phase: 데이터 샘플링 시점 결정 (Mode 설정) |
| 1:0 | SPR1:0 | SPI Clock Rate: 분주비 설정 (SCK 속도 결정) |
2) SPSR (SPI Status Register)
현재 통신 상태를 확인하거나 속도를 배속하는 데 사용합니다.
- Bit 7 - SPIF (SPI Interrupt Flag): 데이터 전송이 완료되면 1이 됩니다.
SPDR 레지스터를 읽거나 인터럽트가 실행되면 자동으로 0이 됩니다.
- Bit 6 - WCOL (Write Collision Flag): 전송 중에
SPDR에 데이터를 쓰려고 하면 발생합니다.
- Bit 0 - SPI2X (Double SPI Speed Bit): 1로 설정하면 SPI 속도가 2배 빨라집니다.
3) SPDR (SPI Data Register)
실제 데이터를 주고받는 통로입니다.
- 쓰기: 이 레지스터에 값을 넣으면 즉시 전송이 시작됩니다 (Master 모드일 때).
- 읽기: 전송이 완료된 후 이 레지스터를 읽으면 수신된 데이터를 얻을 수 있습니다.
4. 표준 SPI 통신 시퀀스 (Standard Sequence)
SPI 통신이 시작되고 끝날 때까지 하드웨어 내부에서 일어나는 논리적 순서입니다. 개발자는 이 타이밍을 이해해야 정확한 드라이버 코드를 작성할 수 있습니다.
단계별 동작 과정
-
Slave 선택 (SS/CS Assert)
- Master가 통신하고자 하는 특정 Slave의 SS(Slave Select) 핀을 Low(0)로 떨어뜨립니다.
- 이때부터 해당 Slave는 활성화되어 Master의 클럭에 반응할 준비를 합니다.
-
클럭 생성 (SCLK Generation)
- Master가 설정된 보드레이트(Baud Rate)에 맞춰 SCLK 신호를 출력하기 시작합니다.
- CPOL 설정에 따라 클럭의 시작 레벨(High or Low)이 결정됩니다.
-
데이터 교환 (Data Shift-out/in)
- MOSI: Master는 출력할 비트를 MOSI 라인에 싣습니다.
- MISO: Slave는 응답 비트를 MISO 라인에 싣습니다.
- CPHA 설정에 따라 클럭의 첫 번째 또는 두 번째 엣지에서 데이터를 샘플링(읽기)합니다.
- 보통 8비트(1바이트) 단위로 이 과정이 8번 반복됩니다.
-
전송 완료 플래그 (Interrupt Flag)
- 8비트 전송이 완료되면 MCU 내부의 SPIF(SPI Interrupt Flag)가 1로 세팅됩니다.
- 인터럽트가 설정되어 있다면 ISR(Interrupt Service Routine)이 실행됩니다.
-
Slave 해제 (SS/CS De-assert)
- 데이터 전송이 모두 끝나면 Master는 SS 핀을 다시 High(1)로 올립니다.
- Slave는 비활성 상태로 돌아가며 MISO 라인을 High-Z(플로팅) 상태로 만듭니다.
⚠️ 시퀀스 제어 시 주의사항
- Dummy Byte: SPI는 송신과 수신이 동시에 일어납니다. 슬레이브로부터 데이터를 읽기만 하고 싶을 때도, 마스터는 반드시 의미 없는 데이터(0xFF 등)를 송신하여 클럭을 생성해주어야 합니다.
- CS 딜레이: 아주 빠른 MCU를 사용할 경우, CS를 Low로 내린 직후 너무 빨리 데이터를 보내면 슬레이브가 준비되지 않아 첫 비트가 깨질 수 있습니다. 필요시 아주 짧은 지연 시간(Software Delay)을 주어야 합니다.