본문 바로가기
-----ETC-----/C++ 임베디드 시스템 프로그래밍 시리즈

[C++ 임베디드 시스템 프로그래밍 시리즈] Day 17: SPI 통신

by cogito21_cpp 2024. 8. 1.
반응형

SPI 통신의 개요

SPI(Serial Peripheral Interface) 통신은 빠른 데이터 전송 속도를 제공하는 동기식 직렬 통신 방식입니다. SPI는 주로 센서, 디스플레이, 메모리 등과 같은 주변 장치와 마이크로컨트롤러 간의 데이터 전송에 사용됩니다. 오늘은 SPI 통신의 기본 개념과 사용 방법을 학습하겠습니다.

1. SPI 통신의 기본 개념

SPI는 다음과 같은 특징을 가집니다:

  • 주 마스터-슬레이브 구조: 하나의 마스터와 여러 슬레이브 장치 간의 통신을 지원합니다.
  • 4개의 주요 신호 라인:
    • MOSI (Master Out Slave In): 마스터에서 슬레이브로 데이터 전송
    • MISO (Master In Slave Out): 슬레이브에서 마스터로 데이터 전송
    • SCK (Serial Clock): 클럭 신호
    • SS (Slave Select): 슬레이브 선택 신호

2. SPI 통신 설정

SPI 통신을 사용하려면 마스터와 슬레이브의 SPI 설정을 맞춰야 합니다. Arduino에서는 SPI 라이브러리를 사용하여 SPI 통신을 쉽게 구현할 수 있습니다.

3. SPI 통신 사용 예제

다음 예제에서는 두 개의 Arduino 보드를 사용하여 SPI 통신을 구현하는 방법을 보여줍니다. 하나의 보드는 마스터로, 다른 보드는 슬레이브로 설정하여 데이터를 송수신합니다.

 

하드웨어 연결

  1. Arduino 1 (마스터):
    • MOSI: Arduino 2의 MOSI 핀에 연결
    • MISO: Arduino 2의 MISO 핀에 연결
    • SCK: Arduino 2의 SCK 핀에 연결
    • SS: Arduino 2의 SS 핀에 연결
    • GND: Arduino 2의 GND에 연결
  2. Arduino 2 (슬레이브):
    • MOSI: Arduino 1의 MOSI 핀에 연결
    • MISO: Arduino 1의 MISO 핀에 연결
    • SCK: Arduino 1의 SCK 핀에 연결
    • SS: Arduino 1의 SS 핀에 연결
    • GND: Arduino 1의 GND에 연결

예제: 마스터 코드 (Arduino 1)

#include <SPI.h>

const int ssPin = 10; // Slave Select 핀

void setup() {
    Serial.begin(9600); // 시리얼 통신 시작
    pinMode(ssPin, OUTPUT);
    SPI.begin(); // SPI 마스터 시작
}

void loop() {
    digitalWrite(ssPin, LOW); // 슬레이브 선택
    SPI.transfer("Hello from Master"); // 데이터 송신
    digitalWrite(ssPin, HIGH); // 슬레이브 선택 해제
    delay(1000); // 1초 대기
}

 

예제: 슬레이브 코드 (Arduino 2)

#include <SPI.h>

volatile boolean received = false;
char data;

void setup() {
    Serial.begin(9600); // 시리얼 통신 시작
    pinMode(MISO, OUTPUT);
    SPI.attachInterrupt(); // SPI 인터럽트 활성화
    SPI.begin(); // SPI 슬레이브 시작
}

ISR(SPI_STC_vect) { // SPI 인터럽트 서비스 루틴
    data = SPDR; // 수신된 데이터 읽기
    received = true; // 데이터 수신 플래그 설정
}

void loop() {
    if (received) {
        Serial.print("Received: ");
        Serial.println(data); // 수신된 데이터 출력
        received = false; // 플래그 재설정
    }
}

 

위 코드에서는 첫 번째 Arduino 보드가 마스터로 설정되어 데이터를 송신하고, 두 번째 Arduino 보드가 슬레이브로 설정되어 데이터를 수신하여 시리얼 모니터에 출력합니다. 슬레이브 코드에서는 SPI 인터럽트를 사용하여 데이터를 수신합니다.

 

4. SPI 통신을 활용한 프로젝트

SPI 통신을 활용하여 다양한 프로젝트를 구현할 수 있습니다. 예를 들어, SD 카드에 데이터를 저장하거나, SPI 디스플레이에 데이터를 출력하는 프로젝트를 구현할 수 있습니다.

 

예제: SPI SD 카드에 데이터 저장

다음 예제는 SPI를 사용하여 SD 카드에 데이터를 저장하는 방법을 보여줍니다.

 

하드웨어 연결

  1. SD 카드 모듈 연결:
    • VCC: 5V
    • GND: GND
    • MOSI: Arduino 11
    • MISO: Arduino 12
    • SCK: Arduino 13
    • CS: Arduino 10

 

SD 라이브러리 설치

SD 카드를 사용하려면 SD 라이브러리를 설치해야 합니다.

  1. Arduino IDE 라이브러리 매니저 열기:
    • Sketch -> Include Library -> Manage Libraries...
  2. 라이브러리 검색 및 설치:
    • SD를 검색하고, SD 라이브러리를 설치합니다.

예제: SD 카드에 데이터 저장

#include <SPI.h>
#include <SD.h>

const int csPin = 10; // Chip Select 핀

void setup() {
    Serial.begin(9600); // 시리얼 통신 시작
    if (!SD.begin(csPin)) {
        Serial.println("SD card initialization failed!");
        return;
    }
    Serial.println("SD card initialized.");
}

void loop() {
    File dataFile = SD.open("data.txt", FILE_WRITE);

    if (dataFile) {
        dataFile.println("Hello, SD card!"); // 데이터 저장
        dataFile.close();
        Serial.println("Data written to file.");
    } else {
        Serial.println("Error opening file.");
    }

    delay(1000); // 1초 대기
}

 

위 코드에서는 SD 라이브러리를 사용하여 SD 카드를 초기화하고, 데이터를 파일에 저장합니다. 데이터는 1초마다 "data.txt" 파일에 기록됩니다.

 

마무리

오늘은 SPI 통신을 사용하여 데이터를 송수신하는 방법을 학습했습니다. 두 아두이노 간의 SPI 통신, SPI를 사용한 SD 카드 데이터 저장 등의 예제를 통해 SPI 통신의 기본 개념과 활용 방법을 익혔습니다. 다음 날에는 CAN 통신에 대해 더 깊이 알아보겠습니다.

질문이나 추가적인 피드백이 있으면 언제든지 댓글로 남겨 주세요.

Day 18 예고

다음 날은 "CAN 통신"에 대해 다룰 것입니다. CAN 통신을 사용하여 여러 장치 간의 데이터 송수신 방법을 학습하고, 실습 예제를 통해 이해를 돕겠습니다.

반응형