본문 바로가기
MCU/C2000

TMS320F28388D DSP SPI 사용법: DriverLib API로 SPI 설정 및 코드(수정)

by linuxgo 2025. 8. 17.

소개

이 문서에서는 Texas Instruments의 TMS320F28388D 마이크로컨트롤러에서 SPI(Serial Peripheral Interface) 모듈을 DriverLib API를 사용하여 설정하고 사용하는 방법을 상세히 다룹니다. C2000 시리즈의 고성능 마이크로컨트롤러인 TMS320F28388D의 SPI 모듈을 활용하여 SPI 통신을 구현하는 방법을 배우고, 다양한 독립적인 예제 코드를 통해 실제 구현 방법을 익힐 수 있습니다. 각 코드에는 상세한 주석이 포함되어 있으며, Code Composer Studio(CCS) 환경에서 실행 가능합니다.

1. TMS320F28388D SPI 개요

TMS320F28388D는 Texas Instruments의 C2000 시리즈에 속하는 32비트 마이크로컨트롤러로, 최대 4개의 SPI 모듈(SPI-A, SPI-B, SPI-C, SPI-D)을 제공합니다. SPI는 마스터-슬레이브 구조의 고속 직렬 통신 프로토콜로, 센서, 디스플레이, 메모리 장치 등 다양한 주변 장치와의 통신에 적합합니다.

SPI 모듈의 주요 특징

  • 통신 속도: 시스템 클럭을 기반으로 최대 50Mbps 지원 (200MHz SYSCLK 기준).
  • 데이터 길이: 1~16비트 데이터 전송 지원.
  • 모드: 마스터 또는 슬레이브 모드 지원.
  • 클럭 폴러리티/페이즈: 4가지 SPI 모드(0~3) 지원.
  • 인터럽트: 송수신 완료 및 에러 인터럽트 지원.
  • FIFO: 16단어 송수신 FIFO 제공.
  • 고급 기능: 칩 셀렉트(CS) 관리, 루프백 테스트 모드.

DriverLib API는 하드웨어 레지스터를 직접 조작하는 대신 추abstraction된 함수를 제공하여 SPI 설정을 간소화합니다.

2. 주요 SPI DriverLib API 함수

아래는 TMS320F28388D의 SPI 모듈을 제어하기 위해 자주 사용되는 DriverLib API 함수와 그 사용 방법입니다.

2.1. SPI 기본 설정 관련 함수

SPI_setConfig(base, lspclk, baudRate, protocol, mode, bitCount)

  • 설명: SPI 설정(비트율, 프로토콜, 모드, 데이터 길이)을 구성합니다.
  • 매개변수:
    • base (SPI 모듈의 베이스 주소, 예: SPIA_BASE).
    • lspclk (저속 주변 클럭, Hz 단위, 예: SysCtl_getLowSpeedClock(DEVICE_OSCSRC_FREQ)).
    • baudRate (원하는 비트율, Hz 단위, 슬레이브 모드에서는 0 설정).
    • protocol (클럭 폴러리티/페이즈, 예: SPI_PROT_POL0PHA0).
    • mode (마스터/슬레이브, 예: SPI_MODE_MASTER, SPI_MODE_SLAVE).
    • bitCount (데이터 비트 수, 1~16).
  • 사용 예:
    SPI_setConfig(SPIA_BASE, 50000000, 1000000, SPI_PROT_POL0PHA0, SPI_MODE_MASTER, 8); // 1Mbps, 모드 0, 마스터, 8비트
    SPI_setConfig(SPIA_BASE, 50000000, 0, SPI_PROT_POL0PHA0, SPI_MODE_SLAVE, 8); // 슬레이브, 모드 0, 8비트
    

SPI_enableModule(base)

  • 설명: SPI 모듈을 활성화합니다.
  • 매개변수:
    • base (SPI 모듈의 베이스 주소).
  • 사용 예:
    SPI_enableModule(SPIA_BASE); // SPI-A 모듈 활성화
    

SPI_disableModule(base)

  • 설명: SPI 모듈을 비활성화합니다.
  • 매개변수:
    • base (SPI 모듈의 베이스 주소).
  • 사용 예:
    SPI_disableModule(SPIA_BASE); // SPI-A 모듈 비활성화
    

2.2. 데이터 송수신 관련 함수

SPI_writeDataNonBlocking(base, data)

  • 설명: 비차단 방식으로 데이터를 전송합니다. FIFO가 가득 차면 데이터가 무시될 수 있음.
  • 매개변수:
    • base (SPI 모듈의 베이스 주소).
    • data (전송할 데이터, 최대 16비트).
  • 사용 예:
    SPI_writeDataNonBlocking(SPIA_BASE, 0x55); // 8비트 데이터 0x55 전송
    

SPI_readDataNonBlocking(base)

  • 설명: 비차단 방식으로 데이터를 수신합니다.
  • 매개변수:
    • base (SPI 모듈의 베이스 주소).
  • 반환값: 수신된 데이터 (16비트).
  • 사용 예:
    uint16_t rxData = SPI_readDataNonBlocking(SPIA_BASE); // 수신 데이터 읽기
    

SPI_transmitNBytes(base, txData, numBytes, timeout)

  • 설명: FIFO를 통해 지정된 바이트 수의 데이터를 송신합니다 (차단 방식).
  • 매개변수:
    • base (SPI 모듈의 베이스 주소).
    • txData (송신 데이터 배열 포인터).
    • numBytes (전송할 바이트 수).
    • timeout (타임아웃 값, 0은 무한 대기).
  • 사용 예:
    uint16_t txData = 0xAA;
    SPI_transmitNBytes(SPIA_BASE, &txData, 1, 0); // 8비트 데이터 0xAA 송신
    

SPI_receiveNBytes(base, rxData, numBytes, timeout)

  • 설명: FIFO를 통해 지정된 바이트 수의 데이터를 수신합니다 (차단 방식).
  • 매개변수:
    • base (SPI 모듈의 베이스 주소).
    • rxData (수신 데이터 배열 포인터).
    • numBytes (수신할 바이트 수).
    • timeout (타임아웃 값, 0은 무한 대기).
  • 사용 예:
    uint16_t rxData;
    SPI_receiveNBytes(SPIA_BASE, &rxData, 1, 0); // 8비트 데이터 수신
    

2.3. 인터럽트 관련 함수

SPI_enableInterrupt(base, intFlags)

  • 설명: SPI 인터럽트를 활성화합니다.
  • 매개변수:
    • base (SPI 모듈의 베이스 주소).
    • intFlags (인터럽트 플래그, 예: SPI_INT_RX_DATA_TX_EMPTY for 수신 완료, SPI_INT_RX_OVERRUN for 오버런).
  • 사용 예:
    SPI_enableInterrupt(SPIA_BASE, SPI_INT_RX_DATA_TX_EMPTY | SPI_INT_RX_OVERRUN); // 수신 및 오버런 인터럽트 활성화
    

SPI_clearInterruptStatus(base, intFlags)

  • 설명: 인터럽트 플래그를 지웁니다.
  • 매개변수:
    • base (SPI 모듈의 베이스 주소).
    • intFlags (지울 인터럽트 플래그).
  • 사용 예:
    SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_RX_DATA_TX_EMPTY); // 수신 인터럽트 플래그 지우기
    

Interrupt_register(intNumber, handler)

  • 설명: 인터럽트 서비스 루틴(ISR)을 등록합니다.
  • 매개변수:
    • intNumber (인터럽트 번호, 예: INT_SPIA_RX).
    • handler (ISR 함수 포인터).
  • 사용 예:
    Interrupt_register(INT_SPIA_RX, &spiAISR); // SPI-A 수신 ISR 등록
    

3. SPI 설정 및 동작 원리

  • 시스템 초기화: 시스템 클럭, Watchdog, GPIO 초기화(Device_init(), Device_initGPIO()), 인터럽트 모듈 초기화(Interrupt_initModule(), Interrupt_initVectorTable()).
    • Watchdog 활성화는 SysCtl_enableWatchdog()와 SysCtl_serviceWatchdog() 사용.
  • SPI 모듈 설정:
    • 클럭 활성화: SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SPIA).
    • 모듈 비활성화 후 설정: SPI_disableModule(), SPI_setConfig(), SPI_setcharLength().
    • 마스터 모드: 비트율 설정(SPI_setBaudRate), 클럭과 칩 셀렉트 제어.
    • 슬레이브 모드: 비트율은 외부 마스터가 결정, SPI_transmitNBytes로 응답 데이터 준비.
    • FIFO 활성화: SPI_enableFIFO(), SPI_setFIFOInterruptLevel().
  • 인터럽트 설정(선택):
    • 수신 및 오버런 인터럽트 활성화(SPI_INT_RX_DATA_TX_EMPTY, SPI_INT_RX_OVERRUN).
    • ISR 등록(Interrupt_register).
  • SPI 활성화: SPI_enableModule() 호출 후 송수신 시작.
    • 마스터: SPI_transmitNBytes, SPI_receiveNBytes로 데이터 송수신.
    • 슬레이브: SPI_transmitNBytes로 응답 데이터 준비, SPI_readDataNonBlocking으로 수신 처리.

4. SPI 예제 코드

아래는 독립적인 SPI 예제 코드로, C2000Ware의 DriverLib를 기반으로 작성되었습니다. GPIO 설정은 별도의 initGPIO() 함수로 분리되어 있으며, 모든 코드는 CCS에서 바로 실행 가능합니다. 비트율 계산, SPI 모드, 칩 셀렉트(CS) 관리는 코드와 주석에 명시적으로 포함됩니다.

TMS320F28388D DSP SPI

4.1. 예제 1: 기본 SPI 마스터 송신

SPI-A를 사용하여 1Mbps로 8비트 데이터를 마스터 모드로 전송합니다.

#include "driverlib.h"
#include "device.h"
#include "spi.h"

// 디버깅용 상태 변수: SPI 모듈의 현재 상태를 추적
volatile uint32_t spiStatus = 0; // 0: 초기화 완료, 1: SPI 동작 중, 0xFFFF: 오류

// 칩 셀렉트 핀 정의 (외부 GPIO 사용)
#define CS_PIN 19 // GPIO19를 칩 셀렉트로 사용 (STE 핀과 동일)

// GPIO 초기화 함수: SPI 통신 및 디버깅용 LED 핀 설정
void initGPIO(void)
{
    // SPI-A SIMO 핀 설정 (GPIO16)
    GPIO_setPinConfig(GPIO_16_SPIA_SIMO);       // GPIO16을 SPI-A SIMO로 설정
    GPIO_setDirectionMode(16, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(16, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)

    // SPI-A SOMI 핀 설정 (GPIO17)
    GPIO_setPinConfig(GPIO_17_SPIA_SOMI);       // GPIO17을 SPI-A SOMI로 설정
    GPIO_setDirectionMode(17, GPIO_DIR_MODE_IN); // 입력 모드로 설정
    GPIO_setPadConfig(17, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)

    // SPI-A CLK 핀 설정 (GPIO18)
    GPIO_setPinConfig(GPIO_18_SPIA_CLK);        // GPIO18을 SPI-A CLK로 설정
    GPIO_setDirectionMode(18, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(18, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)

    // SPI-A STE 핀 설정 (GPIO19, 칩 셀렉트)
    GPIO_setPinConfig(GPIO_19_SPIA_STEN);       // GPIO19를 SPI-A STE로 설정
    GPIO_setDirectionMode(19, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(19, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)
    GPIO_writePin(CS_PIN, 1);                   // CS 핀 초기 상태 HIGH (비활성화)

    // 디버깅용 LED 설정 (GPIO34, LAUNCHXL-F28379D 기준)
    GPIO_setPinConfig(GPIO_34_GPIO34);          // GPIO34를 일반 GPIO로 설정
    GPIO_setDirectionMode(34, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(34, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 활성화
    GPIO_writePin(34, 0);                       // 초기 LED 상태 OFF
}

// SPI-A 초기화 함수: SPI 모듈 설정 및 활성화
void initSPI(void)
{
    // SPI-A 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SPIA); // SPI-A 모듈에 클럭 공급

    // SPI 모듈 초기화
    SPI_disableModule(SPIA_BASE);                   // 설정 전 모듈 비활성화

    // SPI 설정
    uint32_t lspclk = SysCtl_getLowSpeedClock(DEVICE_OSCSRC_FREQ); // LSPCLK 주파수
    uint32_t baudRate = 1000000;                    // 목표 비트율: 1Mbps

    // LSPCLK 검증
    if (lspclk != 50000000)                         // 예상 LSPCLK(50MHz)와 다를 경우
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        return;
    }

    // SPI 설정: 모드, 비트율, 데이터 길이
    SPI_setcharLength(SPIA_BASE, 8);               // 8비트 데이터 길이
    SPI_setBaudRate(SPIA_BASE, lspclk, baudRate);  // 비트율 1Mbps
    SPI_setConfig(SPIA_BASE, lspclk, SPI_PROT_POL0PHA0, SPI_MODE_CONTROLLER, baudRate, 8);
    SPI_enableTalk(SPIA_BASE);                     // 송신 활성화
    SPI_setEmulationMode(SPIA_BASE, SPI_EMULATION_FREE_RUN); // 에뮬레이션 모드: Free Run

    // FIFO 활성화 및 설정
    SPI_enableFIFO(SPIA_BASE);                     // 송수신 FIFO 활성화
    SPI_setFIFOInterruptLevel(SPIA_BASE, SPI_FIFO_TX4, SPI_FIFO_RX4); // FIFO 인터럽트 레벨 설정
    SPI_setTxFifoTransmitDelay(SPIA_BASE, 0);      // 전송 지연 0 사이클

    // SPI 모듈 활성화
    SPI_enableModule(SPIA_BASE);                   // SPI-A 모듈 동작 시작

    // 상태 업데이트
    spiStatus = 1;                                 // SPI 동작 중 상태
}

void main(void)
{
    // 시스템 초기화: PLL, Watchdog, 주변 장치 클럭 설정
    Device_init();                                  // 시스템 클럭, Watchdog, 주변 장치 초기화

    // GPIO 기본 초기화
    Device_initGPIO();                              // GPIO 모듈 초기화

    // SPI 관련 GPIO 설정
    initGPIO();                                     // SPI 핀 및 디버깅용 LED 설정

    // 인터럽트 모듈 초기화
    Interrupt_initModule();                         // 인터럽트 컨트롤러 초기화
    Interrupt_initVectorTable();                    // 인터럽트 벡터 테이블 초기화

    // 시스템 클럭 검증
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ); // 시스템 클럭 확인
    if (sysClockHz != 200000000)                    // 클럭이 200MHz가 아닌 경우
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        GPIO_writePin(34, 0);                       // LED OFF로 오류 표시
        ESTOP0;                                     // 디버깅용 정지
    }

    // SPI-A 초기화
    initSPI();                                      // SPI-A 모듈 초기화 및 설정

    // 초기화 오류 확인
    if (spiStatus != 1)                             // 초기화 실패 시
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        GPIO_writePin(34, 0);                       // LED OFF로 오류 표시
        ESTOP0;                                     // 디버깅용 정지
    }

    // 글로벌 인터럽트 활성화
    EINT;                                           // CPU 인터럽트 활성화

    // Watchdog 활성화
    SysCtl_enableWatchdog();                        // Watchdog 모듈 활성화
    SysCtl_serviceWatchdog();                       // Watchdog 서비스 시작

    // 테스트 데이터 준비
    uint16_t txData = 0x55;                        // 송신 데이터 (8비트)
    uint16_t rxData = 0;                           // 수신 데이터 버퍼

    // 메인 루프: SPI 데이터 전송 및 수신
    for(;;)
    {
        // Watchdog 서비스
        SysCtl_serviceWatchdog();                   // Watchdog 타이머 리셋

        // 칩 셀렉트 활성화 (LOW)
        GPIO_writePin(CS_PIN, 0);                   // CS 핀을 LOW로 설정
        DEVICE_DELAY_US(10);                        // CS 활성화 후 대기

        // SPI 데이터 송신 (FIFO 기반)
        SPI_transmitNBytes(SPIA_BASE, &txData, 1, 0); // 8비트 데이터 1개 전송
        while (SPI_isBusy(SPIA_BASE)) {}            // 전송 완료 대기

        // SPI 데이터 수신 (FIFO 기반)
        SPI_receiveNBytes(SPIA_BASE, &rxData, 1, 0); // 8비트 데이터 1개 수신
        while (SPI_isBusy(SPIA_BASE)) {}            // 수신 완료 대기

        // 칩 셀렉트 비활성화 (HIGH)
        GPIO_writePin(CS_PIN, 1);                   // CS 핀을 HIGH로 설정
        DEVICE_DELAY_US(10);                        // CS 비활성화 후 대기

        // 디버깅용: 상태 및 수신 데이터 표시
        GPIO_writePin(34, (spiStatus == 1 && rxData != 0) ? 1 : 0); // 정상 동작 및 데이터 수신 시 LED ON
        DEVICE_DELAY_US(1000000);                   // 1초 대기
    }
}

설명:

  • 기능: SPI-A를 통해 1Mbps로 8비트 데이터를 마스터 모드로 전송, 칩 셀렉트 관리.
  • 설정: 비트율 1Mbps (BRP=49), 모드 0(CPOL=0, CPHA=0), 마스터 모드, 8비트 데이터.
  • GPIO: GPIO16(SIMO), GPIO17(SOMI), GPIO18(CLK), GPIO19(STE, CS), GPIO34(LED).
  • 칩 셀렉트: GPIO19(STE)를 수동으로 제어하여 슬레이브 선택/해제.
  • 출력: SPI 데이터 주기적 전송, 정상 동작 시 LED ON.

4.2. 예제 2: SPI 수신 및 인터럽트

SPI-A를 사용하여 데이터를 수신하고 인터럽트를 통해 처리합니다.

#include "driverlib.h"
#include "device.h"

// 디버깅용 상태 변수: SPI 모듈의 현재 상태를 추적
volatile uint32_t spiStatus = 0; // 0: 초기화 완료, 1: SPI 동작 중, 0xFFFF: 오류

// 수신 데이터 저장 버퍼
volatile uint16_t rxData = 0;   // 수신된 데이터를 저장
volatile uint16_t rxFlag = 0;   // 수신 완료 플래그 (인터럽트 발생 시 설정)

// 칩 셀렉트 핀 정의
#define CS_PIN 19 // GPIO19를 칩 셀렉트로 사용 (STE 핀과 동일)

// GPIO 초기화 함수: SPI 통신 및 디버깅용 LED 핀 설정
void initGPIO(void)
{
    // SPI-A SIMO 핀 설정 (GPIO16)
    GPIO_setPinConfig(GPIO_16_SPIA_SIMO);       // GPIO16을 SPI-A SIMO로 설정
    GPIO_setDirectionMode(16, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(16, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)

    // SPI-A SOMI 핀 설정 (GPIO17)
    GPIO_setPinConfig(GPIO_17_SPIA_SOMI);       // GPIO17을 SPI-A SOMI로 설정
    GPIO_setDirectionMode(17, GPIO_DIR_MODE_IN); // 입력 모드로 설정
    GPIO_setPadConfig(17, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)

    // SPI-A CLK 핀 설정 (GPIO18)
    GPIO_setPinConfig(GPIO_18_SPIA_CLK);        // GPIO18을 SPI-A CLK로 설정
    GPIO_setDirectionMode(18, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(18, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)

    // SPI-A STE 핀 설정 (GPIO19, 칩 셀렉트)
    GPIO_setPinConfig(GPIO_19_SPIA_STEN);       // GPIO19를 SPI-A STE로 설정
    GPIO_setDirectionMode(19, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(19, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)
    GPIO_writePin(CS_PIN, 1);                   // CS 핀 초기 상태 HIGH (비활성화)

    // 디버깅용 LED 설정 (GPIO34, LAUNCHXL-F28379D 기준)
    GPIO_setPinConfig(GPIO_34_GPIO34);          // GPIO34를 일반 GPIO로 설정
    GPIO_setDirectionMode(34, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(34, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 활성화
    GPIO_writePin(34, 0);                       // 초기 LED 상태 OFF
}

// SPI 인터럽트 서비스 루틴: 데이터 수신 시 호출
__interrupt void spiAISR(void)
{
    // 데이터 수신
    rxData = SPI_readDataNonBlocking(SPIA_BASE); // FIFO에서 수신 데이터 읽기
    rxFlag = 1;                                 // 수신 플래그 설정 (수신 완료 표시)

    // 인터럽트 플래그 지우기
    SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_RX_DATA_TX_EMPTY); // 수신 인터럽트 플래그 클리어
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);                // PIE 그룹 6 인터럽트 ACK
}

// SPI-A 초기화 함수: SPI 모듈 설정 및 인터럽트 활성화
void initSPI(void)
{
    // SPI-A 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SPIA); // SPI-A 모듈에 클럭 공급

    // SPI 모듈 초기화
    SPI_disableModule(SPIA_BASE);                   // 설정 전 모듈 비활성화

    // SPI 설정
    uint32_t lspclk = SysCtl_getLowSpeedClock(DEVICE_OSCSRC_FREQ); // LSPCLK 주파수
    uint32_t baudRate = 1000000;                    // 목표 비트율: 1Mbps

    // LSPCLK 검증
    if (lspclk != 50000000)                         // 예상 LSPCLK(50MHz)와 다를 경우
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        return;
    }

    // SPI 설정: 모드, 비트율, 데이터 길이
    SPI_setcharLength(SPIA_BASE, 8);               // 8비트 데이터 길이
    SPI_setBaudRate(SPIA_BASE, lspclk, baudRate);  // 비트율 1Mbps
    SPI_setConfig(SPIA_BASE, lspclk, SPI_PROT_POL0PHA0, SPI_MODE_CONTROLLER, baudRate, 8);
    SPI_enableTalk(SPIA_BASE);                     // 송신 활성화
    SPI_setEmulationMode(SPIA_BASE, SPI_EMULATION_FREE_RUN); // 에뮬레이션 모드: Free Run

    // FIFO 활성화 및 설정
    SPI_enableFIFO(SPIA_BASE);                     // 송수신 FIFO 활성화
    SPI_setFIFOInterruptLevel(SPIA_BASE, SPI_FIFO_TX4, SPI_FIFO_RX4); // FIFO 인터럽트 레벨 설정
    SPI_setTxFifoTransmitDelay(SPIA_BASE, 0);      // 전송 지연 0 사이클

    // 인터럽트 활성화
    SPI_enableInterrupt(SPIA_BASE, SPI_INT_RX_DATA_TX_EMPTY); // 수신 완료 인터럽트 활성화

    // SPI 모듈 활성화
    SPI_enableModule(SPIA_BASE);                   // SPI-A 모듈 동작 시작

    // 상태 업데이트
    spiStatus = 1;                                 // SPI 동작 중 상태
}

void main(void)
{
    // 시스템 초기화: PLL, Watchdog, 주변 장치 클럭 설정
    Device_init();                                  // 시스템 클럭, Watchdog, 주변 장치 초기화

    // GPIO 기본 초기화
    Device_initGPIO();                              // GPIO 모듈 초기화

    // SPI 관련 GPIO 설정
    initGPIO();                                     // SPI 핀 및 디버깅용 LED 설정

    // 인터럽트 모듈 초기화
    Interrupt_initModule();                         // 인터럽트 컨트롤러 초기화
    Interrupt_initVectorTable();                    // 인터럽트 벡터 테이블 초기화

    // SPI 인터럽트 ISR 등록
    Interrupt_register(INT_SPIA_RX, &spiAISR);      // SPI-A 수신 인터럽트 서비스 루틴 등록

    // 시스템 클럭 검증
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ); // 시스템 클럭 확인
    if (sysClockHz != 200000000)                    // 클럭이 200MHz가 아닌 경우
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        GPIO_writePin(34, 0);                       // LED OFF로 오류 표시
        ESTOP0;                                     // 디버깅용 정지
    }

    // SPI-A 초기화
    initSPI();                                      // SPI-A 모듈 초기화 및 설정

    // 초기화 오류 확인
    if (spiStatus != 1)                             // 초기화 실패 시
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        GPIO_writePin(34, 0);                       // LED OFF로 오류 표시
        ESTOP0;                                     // 디버깅용 정지
    }

    // 글로벌 인터럽트 활성화
    EINT;                                           // CPU 인터럽트 활성화

    // Watchdog 활성화
    SysCtl_enableWatchdog();                        // Watchdog 모듈 활성화
    SysCtl_serviceWatchdog();                       // Watchdog 서비스 시작

    // 테스트 데이터 준비
    uint16_t txData = 0x55;                        // 송신 데이터 (8비트)

    // 메인 루프: SPI 데이터 송신 및 상태 모니터링
    for(;;)
    {
        // Watchdog 서비스
        SysCtl_serviceWatchdog();                   // Watchdog 타이머 리셋

        // 칩 셀렉트 활성화 (LOW)
        GPIO_writePin(CS_PIN, 0);                   // CS 핀을 LOW로 설정
        DEVICE_DELAY_US(10);                        // CS 활성화 후 대기

        // SPI 데이터 송신 (FIFO 기반)
        SPI_transmitNBytes(SPIA_BASE, &txData, 1, 0); // 8비트 데이터 1개 전송
        while (SPI_isBusy(SPIA_BASE)) {}            // 전송 완료 대기

        // 칩 셀렉트 비활성화 (HIGH)
        GPIO_writePin(CS_PIN, 1);                   // CS 핀을 HIGH로 설정
        DEVICE_DELAY_US(10);                        // CS 비활성화 후 대기

        // 디버깅용: 상태 및 수신 데이터 표시
        GPIO_writePin(34, (spiStatus == 1 && rxFlag == 1) ? 1 : 0); // 정상 동작 및 데이터 수신 시 LED ON
        DEVICE_DELAY_US(1000000);                   // 1초 대기
    }
}

설명:

  • 기능: SPI-A를 통해 8비트 데이터 수신, 인터럽트로 처리.
  • 설정: 비트율 1Mbps (BRP=49), 모드 0(CPOL=0, CPHA=0), 마스터 모드, 8비트 데이터, 수신 인터럽트 활성화.
  • GPIO: GPIO16(SIMO), GPIO17(SOMI), GPIO18(CLK), GPIO19(STE, CS), GPIO34(LED).
  • 칩 셀렉트: GPIO19(STE)를 수동으로 제어 (수신에서는 외부 마스터가 CS 제어).
  • 출력: 데이터 수신 시 rxFlag 설정, LED ON.

4.3. 예제 3: SPI 송수신 및 에러 처리

SPI-A를 사용하여 송수신을 동시에 수행하고 에러를 감지합니다.

#include "driverlib.h"
#include "device.h"
#include "spi.h"

// 디버깅용 상태 변수: SPI 모듈의 현재 상태를 추적
volatile uint32_t spiStatus = 0; // 0: 초기화 완료, 1: SPI 동작 중, 0xFFFF: 오류
volatile uint32_t errorCount = 0; // SPI 에러 발생 횟수 카운트

// 송수신 데이터
uint16_t txData = 0x55;         // 송신 데이터 (8비트, 하위 8비트 사용)
volatile uint16_t rxData = 0;   // 수신된 데이터를 저장
volatile uint16_t rxFlag = 0;   // 수신 완료 플래그

// 칩 셀렉트 핀 정의
#define CS_PIN 19 // GPIO19를 칩 셀렉트로 사용 (STE 핀과 동일)

// GPIO 초기화 함수: SPI 통신 및 디버깅용 LED 핀 설정
void initGPIO(void)
{
    // SPI-A SIMO 핀 설정 (GPIO16)
    GPIO_setPinConfig(GPIO_16_SPIA_SIMO);       // GPIO16을 SPI-A SIMO로 설정
    GPIO_setDirectionMode(16, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(16, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)

    // SPI-A SOMI 핀 설정 (GPIO17)
    GPIO_setPinConfig(GPIO_17_SPIA_SOMI);       // GPIO17을 SPI-A SOMI로 설정
    GPIO_setDirectionMode(17, GPIO_DIR_MODE_IN); // 입력 모드로 설정
    GPIO_setPadConfig(17, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)

    // SPI-A CLK 핀 설정 (GPIO18)
    GPIO_setPinConfig(GPIO_18_SPIA_CLK);        // GPIO18을 SPI-A CLK로 설정
    GPIO_setDirectionMode(18, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(18, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)

    // SPI-A STE 핀 설정 (GPIO19, 칩 셀렉트)
    GPIO_setPinConfig(GPIO_19_SPIA_STEN);       // GPIO19를 SPI-A STE로 설정
    GPIO_setDirectionMode(19, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(19, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)
    GPIO_writePin(CS_PIN, 1);                   // CS 핀 초기 상태 HIGH (비활성화)

    // 디버깅용 LED 설정 (GPIO34, LAUNCHXL-F28379D 기준)
    GPIO_setPinConfig(GPIO_34_GPIO34);          // GPIO34를 일반 GPIO로 설정
    GPIO_setDirectionMode(34, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(34, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 활성화
    GPIO_writePin(34, 0);                       // 초기 LED 상태 OFF
}

// SPI 에러 인터럽트 서비스 루틴: 에러 발생 시 호출
__interrupt void spiAErrorISR(void)
{
    // 에러 카운터 증가
    errorCount++;                               // 에러 발생 시 카운터 증가 (디버깅용)
    spiStatus = 0xFFFF;                         // 오류 상태 설정

    // 인터럽트 플래그 지우기
    SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_RX_OVERRUN); // 수신 오버런 인터럽트 플래그 클리어
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);           // PIE 그룹 6 인터럽트 ACK
}

// SPI 수신 인터럽트 서비스 루틴: 데이터 수신 시 호출
__interrupt void spiAISR(void)
{
    // 데이터 수신
    rxData = SPI_readDataNonBlocking(SPIA_BASE); // FIFO에서 수신 데이터 읽기
    rxFlag = 1;                                 // 수신 플래그 설정

    // 인터럽트 플래그 지우기
    SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_RX_DATA_TX_EMPTY); // 수신 인터럽트 플래그 클리어
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);                // PIE 그룹 6 인터럽트 ACK
}

// SPI-A 초기화 함수: SPI 모듈 설정 및 인터럽트 활성화
void initSPI(void)
{
    // SPI-A 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SPIA); // SPI-A 모듈에 클럭 공급

    // SPI 모듈 초기화
    SPI_disableModule(SPIA_BASE);                   // 설정 전 모듈 비활성화

    // SPI 설정
    uint32_t lspclk = SysCtl_getLowSpeedClock(DEVICE_OSCSRC_FREQ); // LSPCLK 주파수
    uint32_t baudRate = 1000000;                    // 목표 비트율: 1Mbps

    // LSPCLK 검증
    if (lspclk != 50000000)                         // 예상 LSPCLK(50MHz)와 다를 경우
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        errorCount++;
        return;
    }

    // SPI 설정: 모드, 비트율, 데이터 길이
    SPI_setcharLength(SPIA_BASE, 8);               // 8비트 데이터 길이
    SPI_setBaudRate(SPIA_BASE, lspclk, baudRate);  // 비트율 1Mbps
    SPI_setConfig(SPIA_BASE, lspclk, SPI_PROT_POL0PHA0, SPI_MODE_CONTROLLER, baudRate, 8);
    SPI_enableTalk(SPIA_BASE);                     // 송신 활성화
    SPI_setEmulationMode(SPIA_BASE, SPI_EMULATION_FREE_RUN); // 에뮬레이션 모드: Free Run

    // FIFO 활성화 및 설정
    SPI_enableFIFO(SPIA_BASE);                     // 송수신 FIFO 활성화
    SPI_setFIFOInterruptLevel(SPIA_BASE, SPI_FIFO_TX4, SPI_FIFO_RX4); // FIFO 인터럽트 레벨 설정
    SPI_setTxFifoTransmitDelay(SPIA_BASE, 0);      // 전송 지연 0 사이클

    // 인터럽트 활성화
    SPI_enableInterrupt(SPIA_BASE, SPI_INT_RX_DATA_TX_EMPTY | SPI_INT_RX_OVERRUN); // 수신 및 오버런 인터럽트

    // SPI 모듈 활성화
    SPI_enableModule(SPIA_BASE);                   // SPI-A 모듈 동작 시작

    // 상태 업데이트
    spiStatus = 1;                                 // SPI 동작 중 상태
}

void main(void)
{
    // 시스템 초기화: PLL, Watchdog, 주변 장치 클럭 설정
    Device_init();                                  // 시스템 클럭, Watchdog, 주변 장치 초기화

    // GPIO 기본 초기화
    Device_initGPIO();                              // GPIO 모듈 초기화

    // SPI 관련 GPIO 설정
    initGPIO();                                     // SPI 핀 및 디버깅용 LED 설정

    // 인터럽트 모듈 초기화
    Interrupt_initModule();                         // 인터럽트 컨트롤러 초기화
    Interrupt_initVectorTable();                    // 인터럽트 벡터 테이블 초기화

    // SPI 인터럽트 ISR 등록
    Interrupt_register(INT_SPIA_RX, &spiAISR);      // 수신 인터럽트 서비스 루틴 등록
    Interrupt_register(INT_SPIA_RX, &spiAErrorISR); // 에러 인터럽트 서비스 루틴 등록 (동일 벡터 공유)

    // 시스템 클럭 검증
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ); // 시스템 클럭 확인
    if (sysClockHz != 200000000)                    // 클럭이 200MHz가 아닌 경우
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        errorCount++;
        GPIO_writePin(34, 0);                       // LED OFF로 오류 표시
        ESTOP0;                                     // 디버깅용 정지
    }

    // SPI-A 초기화
    initSPI();                                      // SPI-A 모듈 초기화 및 설정

    // 초기화 오류 확인
    if (spiStatus != 1)                             // 초기화 실패 시
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        errorCount++;
        GPIO_writePin(34, 0);                       // LED OFF로 오류 표시
        ESTOP0;                                     // 디버깅용 정지
    }

    // 글로벌 인터럽트 활성화
    EINT;                                           // CPU 인터럽트 활성화

    // Watchdog 활성화
    SysCtl_enableWatchdog();                        // Watchdog 모듈 활성화
    SysCtl_serviceWatchdog();                       // Watchdog 서비스 시작

    // 메인 루프: SPI 데이터 송수신
    for(;;)
    {
        // Watchdog 서비스
        SysCtl_serviceWatchdog();                   // Watchdog 타이머 리셋

        // 칩 셀렉트 활성화 (LOW)
        GPIO_writePin(CS_PIN, 0);                   // CS 핀을 LOW로 설정
        DEVICE_DELAY_US(10);                        // CS 활성화 후 대기

        // SPI 데이터 송신 (FIFO 기반)
        SPI_transmitNBytes(SPIA_BASE, &txData, 1, 0); // 8비트 데이터 1개 전송
        while (SPI_isBusy(SPIA_BASE)) {}            // 전송 완료 대기

        // 칩 셀렉트 비활성화 (HIGH)
        GPIO_writePin(CS_PIN, 1);                   // CS 핀을 HIGH로 설정
        DEVICE_DELAY_US(10);                        // CS 비활성화 후 대기

        // 디버깅용: 상태 표시
        GPIO_writePin(34, (spiStatus == 1 && errorCount == 0 && rxFlag == 1) ? 1 : 0); // 정상 동작 및 데이터 수신 시 LED ON
        DEVICE_DELAY_US(1000000);                   // 1초 대기
    }
}

설명:

  • 기능: SPI-A로 송수신 동시 수행, 에러 인터럽트 처리.
  • 설정: 비트율 1Mbps (BRP=49), 모드 0(CPOL=0, CPHA=0), 마스터 모드, 8비트 데이터, 수신 및 오버런 인터럽트 활성화.
  • GPIO: GPIO16(SIMO), GPIO17(SOMI), GPIO18(CLK), GPIO19(STE, CS), GPIO34(LED).
  • 칩 셀렉트: GPIO19(STE)를 수동으로 제어하여 슬레이브 선택/해제.
  • 출력: 데이터 송수신, 에러 발생 시 LED OFF.

4.4. 예제 4: SPI 슬레이브 모드

SPI-A를 슬레이브 모드로 설정하여 데이터를 수신합니다.

#include "driverlib.h"
#include "device.h"
#include "spi.h"

// 디버깅용 상태 변수: SPI 모듈의 현재 상태를 추적
volatile uint32_t spiStatus = 0; // 0: 초기화 완료, 1: SPI 동작 중, 0xFFFF: 오류
volatile uint32_t errorCount = 0; // SPI 에러 발생 횟수 카운트

// 송수신 데이터
uint16_t txData = 0x55;         // 송신 데이터 (8비트, 슬레이브 응답용)
volatile uint16_t rxData = 0;   // 수신된 데이터를 저장
volatile uint16_t rxFlag = 0;   // 수신 완료 플래그

// GPIO 초기화 함수: SPI 통신 및 디버깅용 LED 핀 설정
void initGPIO(void)
{
    // SPI-A SIMO 핀 설정 (GPIO16, 슬레이브에서는 입력)
    GPIO_setPinConfig(GPIO_16_SPIA_SIMO);       // GPIO16을 SPI-A SIMO로 설정
    GPIO_setDirectionMode(16, GPIO_DIR_MODE_IN); // 입력 모드로 설정 (슬레이브)
    GPIO_setPadConfig(16, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (마스터 데이터시트 확인 필요)

    // SPI-A SOMI 핀 설정 (GPIO17, 슬레이브에서는 출력)
    GPIO_setPinConfig(GPIO_17_SPIA_SOMI);       // GPIO17을 SPI-A SOMI로 설정
    GPIO_setDirectionMode(17, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(17, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (마스터 데이터시트 확인 필요)

    // SPI-A CLK 핀 설정 (GPIO18, 슬레이브에서는 입력)
    GPIO_setPinConfig(GPIO_18_SPIA_CLK);        // GPIO18을 SPI-A CLK로 설정
    GPIO_setDirectionMode(18, GPIO_DIR_MODE_IN); // 입력 모드로 설정 (슬레이브)
    GPIO_setPadConfig(18, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (마스터 데이터시트 확인 필요)

    // SPI-A STE 핀 설정 (GPIO19, 슬레이브에서는 입력)
    GPIO_setPinConfig(GPIO_19_SPIA_STEN);       // GPIO19를 SPI-A STE로 설정
    GPIO_setDirectionMode(19, GPIO_DIR_MODE_IN); // 입력 모드로 설정 (슬레이브, 외부 마스터 제어)
    GPIO_setPadConfig(19, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (마스터 데이터시트 확인 필요)

    // 디버깅용 LED 설정 (GPIO34, LAUNCHXL-F28379D 기준)
    GPIO_setPinConfig(GPIO_34_GPIO34);          // GPIO34를 일반 GPIO로 설정
    GPIO_setDirectionMode(34, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(34, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 활성화
    GPIO_writePin(34, 0);                       // 초기 LED 상태 OFF
}

// SPI 에러 인터럽트 서비스 루틴: 에러 발생 시 호출
__interrupt void spiAErrorISR(void)
{
    // 에러 카운터 증가
    errorCount++;                               // 에러 발생 시 카운터 증가
    spiStatus = 0xFFFF;                         // 오류 상태 설정

    // 인터럽트 플래그 지우기
    SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_RX_OVERRUN); // 수신 오버런 인터럽트 플래그 클리어
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);           // PIE 그룹 6 인터럽트 ACK
}

// SPI 수신 인터럽트 서비스 루틴: 데이터 수신 시 호출
__interrupt void spiAISR(void)
{
    // 데이터 수신
    rxData = SPI_readDataNonBlocking(SPIA_BASE); // FIFO에서 수신 데이터 읽기
    rxFlag = 1;                                 // 수신 플래그 설정

    // 슬레이브 응답 데이터 준비
    SPI_transmitNBytes(SPIA_BASE, &txData, 1, 0); // 다음 전송을 위해 8비트 데이터 준비

    // 인터럽트 플래그 지우기
    SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_RX_DATA_TX_EMPTY); // 수신 인터럽트 플래그 클리어
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);                // PIE 그룹 6 인터럽트 ACK
}

// SPI-A 초기화 함수: SPI 모듈을 슬레이브 모드로 설정
void initSPI(void)
{
    // SPI-A 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SPIA); // SPI-A 모듈에 클럭 공급

    // SPI 모듈 초기화
    SPI_disableModule(SPIA_BASE);                   // 설정 전 모듈 비활성화

    // SPI 설정
    uint32_t lspclk = SysCtl_getLowSpeedClock(DEVICE_OSCSRC_FREQ); // LSPCLK 주파수

    // LSPCLK 검증
    if (lspclk != 50000000)                         // 예상 LSPCLK(50MHz)와 다를 경우
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        errorCount++;
        return;
    }

    // SPI 설정: 모드, 데이터 길이 (비트율은 마스터가 결정)
    SPI_setcharLength(SPIA_BASE, 8);               // 8비트 데이터 길이
    SPI_setConfig(SPIA_BASE, lspclk, 0, SPI_PROT_POL0PHA0, SPI_MODE_SLAVE, 8);
    SPI_enableTalk(SPIA_BASE);                     // 송신 활성화
    SPI_setEmulationMode(SPIA_BASE, SPI_EMULATION_FREE_RUN); // 에뮬레이션 모드: Free Run

    // FIFO 활성화 및 설정
    SPI_enableFIFO(SPIA_BASE);                     // 송수신 FIFO 활성화
    SPI_setFIFOInterruptLevel(SPIA_BASE, SPI_FIFO_TX4, SPI_FIFO_RX4); // FIFO 인터럽트 레벨 설정
    SPI_setTxFifoTransmitDelay(SPIA_BASE, 0);      // 전송 지연 0 사이클

    // 인터럽트 활성화
    SPI_enableInterrupt(SPIA_BASE, SPI_INT_RX_DATA_TX_EMPTY | SPI_INT_RX_OVERRUN); // 수신 및 오버런 인터럽트

    // SPI 모듈 활성화
    SPI_enableModule(SPIA_BASE);                   // SPI-A 모듈 동작 시작

    // 초기 응답 데이터 준비
    SPI_transmitNBytes(SPIA_BASE, &txData, 1, 0);  // FIFO에 초기 송신 데이터 로드

    // 상태 업데이트
    spiStatus = 1;                                 // SPI 동작 중 상태
}

void main(void)
{
    // 시스템 초기화: PLL, Watchdog, 주변 장치 클럭 설정
    Device_init();                                  // 시스템 클럭, Watchdog, 주변 장치 초기화

    // GPIO 기본 초기화
    Device_initGPIO();                              // GPIO 모듈 초기화

    // SPI 관련 GPIO 설정
    initGPIO();                                     // SPI 핀 및 디버깅용 LED 설정

    // 인터럽트 모듈 초기화
    Interrupt_initModule();                         // 인터럽트 컨트롤러 초기화
    Interrupt_initVectorTable();                    // 인터럽트 벡터 테이블 초기화

    // SPI 인터럽트 ISR 등록
    Interrupt_register(INT_SPIA_RX, &spiAISR);      // 수신 인터럽트 서비스 루틴 등록
    Interrupt_register(INT_SPIA_RX, &spiAErrorISR); // 에러 인터럽트 서비스 루틴 등록 (동일 벡터 공유)

    // 시스템 클럭 검증
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ); // 시스템 클럭 확인
    if (sysClockHz != 200000000)                    // 클럭이 200MHz가 아닌 경우
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        errorCount++;
        GPIO_writePin(34, 0);                       // LED OFF로 오류 표시
        ESTOP0;                                     // 디버깅용 정지
    }

    // SPI-A 초기화
    initSPI();                                      // SPI-A 모듈 초기화 및 설정

    // 초기화 오류 확인
    if (spiStatus != 1)                             // 초기화 실패 시
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        errorCount++;
        GPIO_writePin(34, 0);                       // LED OFF로 오류 표시
        ESTOP0;                                     // 디버깅용 정지
    }

    // 글로벌 인터럽트 활성화
    EINT;                                           // CPU 인터럽트 활성화

    // Watchdog 활성화
    SysCtl_enableWatchdog();                        // Watchdog 모듈 활성화
    SysCtl_serviceWatchdog();                       // Watchdog 서비스 시작

    // 메인 루프: 상태 모니터링
    for(;;)
    {
        // Watchdog 서비스
        SysCtl_serviceWatchdog();                   // Watchdog 타이머 리셋

        // 디버깅용: 상태 표시
        GPIO_writePin(34, (spiStatus == 1 && errorCount == 0 && rxFlag == 1) ? 1 : 0); // 정상 동작 및 데이터 수신 시 LED ON
        DEVICE_DELAY_US(1000000);                   // 1초 대기
    }
}

설명:

  • 기능: SPI-A를 슬레이브 모드로 설정하여 8비트 데이터 수신.
  • 설정: 모드 0(CPOL=0, CPHA=0, 마스터 데이터시트 확인), 슬레이브 모드, 8비트 데이터, 수신 인터럽트 활성화.
  • GPIO: GPIO16(SIMO, 입력), GPIO17(SOMI), GPIO18(CLK, 입력), GPIO19(STE, 입력), GPIO34(LED).
  • 칩 셀렉트: GPIO19(STE)는 외부 마스터가 제어.
  • 출력: 데이터 수신 시 rxFlag 설정, LED ON.
  • 용도: 외부 마스터 장치(예: 다른 MCU)와 통신.

4.5. 예제 5: 다중 데이터 송수신

SPI-A를 사용하여 여러 데이터를 연속적으로 송수신합니다.

#include "driverlib.h"
#include "device.h"
#include "spi.h"

// 디버깅용 상태 변수: SPI 모듈의 현재 상태를 추적
volatile uint32_t spiStatus = 0; // 0: 초기화 완료, 1: SPI 동작 중, 0xFFFF: 오류
volatile uint32_t errorCount = 0; // SPI 에러 발생 횟수 카운트

// 송수신 데이터 배열
uint16_t txData[4] = {0x11, 0x22, 0x33, 0x44}; // 송신 데이터 배열 (8비트 데이터로 사용)
volatile uint16_t rxData[4] = {0};              // 수신 데이터 저장 배열
volatile uint16_t rxFlag = 0;                   // 수신 완료 플래그 (4바이트 수신 시 설정)

// 칩 셀렉트 핀 정의
#define CS_PIN 19 // GPIO19를 칩 셀렉트로 사용 (STE 핀과 동일)

// GPIO 초기화 함수: SPI 통신 및 디버깅용 LED 핀 설정
void initGPIO(void)
{
    // SPI-A SIMO 핀 설정 (GPIO16)
    GPIO_setPinConfig(GPIO_16_SPIA_SIMO);       // GPIO16을 SPI-A SIMO로 설정
    GPIO_setDirectionMode(16, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(16, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)

    // SPI-A SOMI 핀 설정 (GPIO17)
    GPIO_setPinConfig(GPIO_17_SPIA_SOMI);       // GPIO17을 SPI-A SOMI로 설정
    GPIO_setDirectionMode(17, GPIO_DIR_MODE_IN); // 입력 모드로 설정
    GPIO_setPadConfig(17, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)

    // SPI-A CLK 핀 설정 (GPIO18)
    GPIO_setPinConfig(GPIO_18_SPIA_CLK);        // GPIO18을 SPI-A CLK로 설정
    GPIO_setDirectionMode(18, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(18, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)

    // SPI-A STE 핀 설정 (GPIO19, 칩 셀렉트)
    GPIO_setPinConfig(GPIO_19_SPIA_STEN);       // GPIO19를 SPI-A STE로 설정
    GPIO_setDirectionMode(19, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(19, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 (슬레이브 데이터시트 확인 필요)
    GPIO_writePin(CS_PIN, 1);                   // CS 핀 초기 상태 HIGH (비활성화)

    // 디버깅용 LED 설정 (GPIO34, LAUNCHXL-F28379D 기준)
    GPIO_setPinConfig(GPIO_34_GPIO34);          // GPIO34를 일반 GPIO로 설정
    GPIO_setDirectionMode(34, GPIO_DIR_MODE_OUT); // 출력 모드로 설정
    GPIO_setPadConfig(34, GPIO_PIN_TYPE_PULLUP); // 풀업 저항 활성화
    GPIO_writePin(34, 0);                       // 초기 LED 상태 OFF
}

// SPI 에러 인터럽트 서비스 루틴: 에러 발생 시 호출
__interrupt void spiAErrorISR(void)
{
    // 에러 카운터 증가
    errorCount++;                               // 에러 발생 시 카운터 증가
    spiStatus = 0xFFFF;                         // 오류 상태 설정

    // 인터럽트 플래그 지우기
    SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_RX_OVERRUN); // 수신 오버런 인터럽트 플래그 클리어
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);           // PIE 그룹 6 인터럽트 ACK
}

// SPI 수신 인터럽트 서비스 루틴: 다중 데이터 수신 처리
__interrupt void spiAISR(void)
{
    // 데이터 수신 (4바이트)
    SPI_receiveNBytes(SPIA_BASE, rxData, 4, 0); // FIFO에서 4바이트 수신
    rxFlag = 1;                                // 수신 플래그 설정

    // 인터럽트 플래그 지우기
    SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_RX_DATA_TX_EMPTY); // 수신 인터럽트 플래그 클리어
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);                // PIE 그룹 6 인터럽트 ACK
}

// SPI-A 초기화 함수: SPI 모듈 설정 및 인터럽트 활성화
void initSPI(void)
{
    // SPI-A 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SPIA); // SPI-A 모듈에 클럭 공급

    // SPI 모듈 초기화
    SPI_disableModule(SPIA_BASE);                   // 설정 전 모듈 비활성화

    // SPI 설정
    uint32_t lspclk = SysCtl_getLowSpeedClock(DEVICE_OSCSRC_FREQ); // LSPCLK 주파수
    uint32_t baudRate = 1000000;                    // 목표 비트율: 1Mbps

    // LSPCLK 검증
    if (lspclk != 50000000)                         // 예상 LSPCLK(50MHz)와 다를 경우
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        errorCount++;
        return;
    }

    // SPI 설정: 모드, 비트율, 데이터 길이
    SPI_setcharLength(SPIA_BASE, 8);               // 8비트 데이터 길이
    SPI_setBaudRate(SPIA_BASE, lspclk, baudRate);  // 비트율 1Mbps
    SPI_setConfig(SPIA_BASE, lspclk, SPI_PROT_POL0PHA0, SPI_MODE_CONTROLLER, baudRate, 8);
    SPI_enableTalk(SPIA_BASE);                     // 송신 활성화
    SPI_setEmulationMode(SPIA_BASE, SPI_EMULATION_FREE_RUN); // 에뮬레이션 모드: Free Run

    // FIFO 활성화 및 설정
    SPI_enableFIFO(SPIA_BASE);                     // 송수신 FIFO 활성화
    SPI_setFIFOInterruptLevel(SPIA_BASE, SPI_FIFO_TX4, SPI_FIFO_RX4); // FIFO 인터럽트 레벨 설정
    SPI_setTxFifoTransmitDelay(SPIA_BASE, 0);      // 전송 지연 0 사이클

    // 인터럽트 활성화
    SPI_enableInterrupt(SPIA_BASE, SPI_INT_RX_DATA_TX_EMPTY | SPI_INT_RX_OVERRUN); // 수신 및 오버런 인터럽트

    // SPI 모듈 활성화
    SPI_enableModule(SPIA_BASE);                   // SPI-A 모듈 동작 시작

    // 상태 업데이트
    spiStatus = 1;                                 // SPI 동작 중 상태
}

void main(void)
{
    // 시스템 초기화: PLL, Watchdog, 주변 장치 클럭 설정
    Device_init();                                  // 시스템 클럭, Watchdog, 주변 장치 초기화

    // GPIO 기본 초기화
    Device_initGPIO();                              // GPIO 모듈 초기화

    // SPI 관련 GPIO 설정
    initGPIO();                                     // SPI 핀 및 디버깅용 LED 설정

    // 인터럽트 모듈 초기화
    Interrupt_initModule();                         // 인터럽트 컨트롤러 초기화
    Interrupt_initVectorTable();                    // 인터럽트 벡터 테이블 초기화

    // SPI 인터럽트 ISR 등록
    Interrupt_register(INT_SPIA_RX, &spiAISR);      // 수신 인터럽트 서비스 루틴 등록
    Interrupt_register(INT_SPIA_RX, &spiAErrorISR); // 에러 인터럽트 서비스 루틴 등록 (동일 벡터 공유)

    // 시스템 클럭 검증
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ); // 시스템 클럭 확인
    if (sysClockHz != 200000000)                    // 클럭이 200MHz가 아닌 경우
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        errorCount++;
        GPIO_writePin(34, 0);                       // LED OFF로 오류 표시
        ESTOP0;                                     // 디버깅용 정지
    }

    // SPI-A 초기화
    initSPI();                                      // SPI-A 모듈 초기화 및 설정

    // 초기화 오류 확인
    if (spiStatus != 1)                             // 초기화 실패 시
    {
        spiStatus = 0xFFFF;                         // 오류 상태 설정
        errorCount++;
        GPIO_writePin(34, 0);                       // LED OFF로 오류 표시
        ESTOP0;                                     // 디버깅용 정지
    }

    // 글로벌 인터럽트 활성화
    EINT;                                           // CPU 인터럽트 활성화

    // Watchdog 활성화
    SysCtl_enableWatchdog();                        // Watchdog 모듈 활성화
    SysCtl_serviceWatchdog();                       // Watchdog 서비스 시작

    // 메인 루프: 다중 데이터 송수신
    for(;;)
    {
        // Watchdog 서비스
        SysCtl_serviceWatchdog();                   // Watchdog 타이머 리셋

        // 칩 셀렉트 활성화 (LOW)
        GPIO_writePin(CS_PIN, 0);                   // CS 핀을 LOW로 설정
        DEVICE_DELAY_US(10);                        // CS 활성화 후 대기

        // SPI 데이터 송신 (FIFO 기반)
        SPI_transmitNBytes(SPIA_BASE, txData, 4, 0); // 4바이트 데이터 송신
        while (SPI_isBusy(SPIA_BASE)) {}            // 송신 완료 대기

        // 칩 셀렉트 비활성화 (HIGH)
        GPIO_writePin(CS_PIN, 1);                   // CS 핀을 HIGH로 설정
        DEVICE_DELAY_US(10);                        // CS 비활성화 후 대기

        // 디버깅용: 상태 표시
        GPIO_writePin(34, (spiStatus == 1 && errorCount == 0 && rxFlag == 1) ? 1 : 0); // 정상 동작 및 데이터 수신 시 LED ON
        DEVICE_DELAY_US(1000000);                   // 1초 대기
    }
}

설명:

  • 기능: SPI-A로 다중 데이터(4개)를 연속적으로 송수신.
  • 설정: 비트율 1Mbps (BRP=49), 모드 0(CPOL=0, CPHA=0), 마스터 모드, 8비트 데이터, 수신 인터럽트 활성화.
  • GPIO: GPIO16(SIMO), GPIO17(SOMI), GPIO18(CLK), GPIO19(STE, CS), GPIO34(LED).
  • 칩 셀렉트: GPIO19(STE)를 수동으로 제어하여 슬레이브 선택/해제.
  • 출력: 4개 데이터 송수신, 수신 완료 시 LED ON.
  • 용도: 다중 데이터 전송이 필요한 애플리케이션(예: 센서 데이터 수집).

5. 추가 고려 사항

  • 비트율 계산: 비트율은 LSPCLK / (BRP + 1)로 계산. 예: 50MHz LSPCLK, 1Mbps → BRP=49. 코드에서 명시적으로 계산하여 설정.
  • SPI 모드: 클럭 폴러리티(CPOL)와 페이즈(CPHA)에 따라 4가지 모드(0~3) 선택. 예제에서는 모드 0 사용, 슬레이브 장치의 데이터시트 확인 필요.
  • 칩 셀렉트(CS): STE 핀(GPIO19)을 수동으로 제어하거나 별도의 GPIO로 관리 가능. 마스터 모드에서 CS 핀을 LOW로 설정하여 슬레이브 선택, HIGH로 설정하여 해제.
  • GPIO 설정: 고속 신호를 위해 풀업/풀다운 저항 조정 필요.
  • C2000Ware: 예제 코드는 C2000Ware의 DriverLib 기반. C:\ti\c2000에 설치.
  • 디버깅: 오실로스코프 또는 로직 분석기로 SPI 신호 확인 권장.

키워드: TMS320F28388D, SPI, DriverLib, C2000, Serial Peripheral Interface, Code Composer Studio, 마스터 모드, 슬레이브 모드, 인터럽트, 에러 처리, FIFO, 다중 데이터 송수신, 비트율 계산, 칩 셀렉트