본문 바로가기
MCU/C2000

[TMS320F28377D] SPI 사용법 : Bitfield 구조 활용 예제 코드

by linuxgo 2025. 8. 18.
반응형

TI의 TMS320F28377D는 C2000 Delfino 시리즈의 32비트 마이크로컨트롤러로, 고속 데이터 통신을 위해 SPI(Serial Peripheral Interface) 모듈을 제공합니다. SPI는 마스터-슬레이브 구조를 기반으로 한 고속 동기 직렬 통신 프로토콜로, 센서, 디스플레이, 메모리 장치 등과의 통신에 적합합니다. 이 문서에서는 TMS320F28377D SPI 모듈의 설정 방법, Bitfield 구조를 활용한 레지스터 설정, 그리고 실용적인 예제 코드를 제공하여 초보자와 숙련된 개발자 모두 쉽게 활용할 수 있도록 돕겠습니다.

1. TMS320F28377D SPI 모듈 개요

TMS320F28377D는 최대 4개의 SPI 모듈(SPIA, SPIB, SPIC, SPID)을 포함하며, 각 모듈은 마스터 또는 슬레이브 모드로 동작할 수 있습니다. 아래는 주요 사양입니다:

  • 클럭 소스: 시스템 클럭(SYSCLK, 최대 200MHz) 또는 저속 주변 클럭(LSPCLK)
  • 데이터 길이: 1~16비트 가변 데이터 워드
  • 클럭 속도: 최대 25MHz (마스터 모드)
  • 전송 모드: 4가지 클럭 위상/극성 조합 (SPI Mode 0~3)
  • FIFO: 16단계 송/수신 FIFO 지원
  • 인터럽트: 송신/수신 완료, 오버런, 언더런 등
  • 칩 셀렉트(CS): 소프트웨어 또는 하드웨어 제어
  • 주요 기능:
    • 마스터/슬레이브 모드 지원
    • 루프백 테스트 모드
    • SPI 타이밍 제어 (클럭 분주, 위상/극성 설정)
    • DMA 연동 가능

2. SPI Bitfield 설정 상세

TMS320F28377D의 SPI 레지스터는 Bitfield 구조로 정의되어 있으며, F2837xD_spi.h 헤더 파일을 통해 접근합니다. Bitfield는 레지스터의 개별 비트를 명확히 설정하여 코드 가독성과 유지보수성을 높입니다. 주요 레지스터와 Bitfield는 다음과 같습니다:

2.1 SPICCR (SPI Configuration Control Register)

  • bit.SPICHAR: 데이터 워드 길이 (0: 1비트, 15: 16비트)
  • bit.CLKPOLARITY: 클럭 극성 (0: 상승 에지, 1: 하강 에지)
  • bit.HS_MODE: 고속 모드 활성화 (1: 활성화)
  • bit.SPISWRESET: SPI 소프트웨어 리셋 (0: 리셋, 1: 정상 동작)

2.2 SPICTL (SPI Operation Control Register)

  • bit.MASTER_SLAVE: 모드 선택 (0: 슬레이브, 1: 마스터)
  • bit.TALK: 송신 활성화 (1: 활성화)
  • bit.SPIINTENA: 인터럽트 활성화 (1: 활성화)
  • bit.CLK_PHASE: 클럭 위상 (0: 데이터 선행, 1: 데이터 후행)

2.3 SPIBRR (SPI Baud Rate Register)

  • bit.SPIBRR: 보율 설정 (0~127, 보율 = LSPCLK / (SPIBRR + 1))

2.4 SPISTS (SPI Status Register)

  • bit.BUFFULL_FLAG: 송신 버퍼 풀 플래그
  • bit.INT_FLAG: 수신 인터럽트 플래그
  • bit.OVERRUN_FLAG: 수신 오버런 플래그

2.5 SPIFFTX (SPI FIFO Transmit Register)

  • bit.TXFFIENA: 송신 FIFO 인터럽트 활성화
  • bit.TXFIFO: 송신 FIFO 리셋 (0: 리셋, 1: 정상)
  • bit.SPIFFENA: FIFO 활성화 (1: 활성화)

2.6 SPIFFRX (SPI FIFO Receive Register)

  • bit.RXFFIENA: 수신 FIFO 인터럽트 활성화
  • bit.RXFIFORESET: 수신 FIFO 리셋 (0: 리셋, 1: 정상)

2.7 SPIFFCT (SPI FIFO Control Register)

  • bit.TXDLY: 송신 지연 (0~7 클럭)

3. SPI 설정 절차

SPI 모듈을 효과적으로 설정하려면 다음 단계를 따라야 합니다:

  1. 시스템 초기화:
    •    InitSysCtrl()를 호출하여 시스템 클럭과 PLL을 초기화합니다.
    •    인터럽트를 비활성화하고 PIE를 초기화합니다 (DINT, InitPieCtrl, InitPieVectTable).
  2. SPI 클럭 활성화:
    •    CpuSysRegs.PCLKCR0.bit.SPIx_A = 1을 설정하여 원하는 SPI 모듈(x=A/B/C/D)의 클럭을 활성화합니다.
    •    보호된 레지스터 접근을 위해 EALLOW와 EDIS 사용.
  3. GPIO 설정:
    •    SPI 핀(SIMO, SOMI, SPICLK, SPISSTE)을 해당 모듈로 설정합니다 (예: GpioCtrlRegs.GPAMUXx).
    •    칩 셀렉트(CS) 핀을 GPIO로 설정하거나 소프트웨어로 제어.
  4. SPI 리셋:
    •    SPICCR.bit.SPISWRESET = 0으로 SPI 모듈 리셋, 설정 후 SPISWRESET = 1로 정상 동작.
  5. SPI 모드 설정:
    •    SPICCR.bit.CLKPOLARITY와 SPICTL.bit.CLK_PHASE로 클럭 위상/극성 설정 (Mode 0~3).
    •    SPICCR.bit.SPICHAR로 데이터 길이 설정.
    •    SPICTL.bit.MASTER_SLAVE로 마스터/슬레이브 모드 선택.
  6. 보율 설정:
    •    SPIBRR.bit.SPIBRR로 보율 설정 (보율 = LSPCLK / (SPIBRR + 1)).
  7. FIFO 설정 (필요 시):
    •    SPIFFTX.bit.SPIFFENA = 1로 FIFO 활성화.
    •    SPIFFTX.bit.TXFIFO와 SPIFFRX.bit.RXFIFORESET으로 FIFO 초기화.
  8. 인터럽트 설정 (필요 시):
    •    SPICTL.bit.SPIINTENA 또는 SPIFFTX.bit.TXFFIENA로 인터럽트 활성화.
    •    PIE 벡터 테이블에 인터럽트 서비스 루틴(ISR) 등록.
  9. SPI 활성화:
    •    SPICTL.bit.TALK = 1로 송신 활성화.
    •    SPICCR.bit.SPISWRESET = 1로 SPI 동작 시작.

4. SPI 설정 고려사항

  • 클럭 설정: LSPCLK(기본 50MHz)에서 보율 계산 (예: SPIBRR=49 → 1MHz).
  • 모드 선택: 대상 장치의 SPI 모드(0~3) 확인 (클럭 위상/극성).
  • 칩 셀렉트: 하드웨어 CS(SPISTE) 또는 소프트웨어 GPIO 제어.
  • FIFO 사용: 대량 데이터 전송 시 FIFO 활성화로 효율성 증대.
  • 인터럽트: 실시간 데이터 처리 시 인터럽트 활용.
  • 루프백 테스트: SPICCR.bit.LOOPBACK으로 내부 테스트 가능.

5. 실용적인 SPI 예제 코드 (Bitfield 구조)

아래는 TMS320F28377D SPI 모듈을 Bitfield 구조로 설정한 3개의 실용적인 예제 코드입니다. 각 예제는 Code Composer Studio(CCS)와 C2000Ware 환경에서 실행 가능합니다.

5.1 예제 1: 기본 SPI 마스터 전송

// File: spi_basic_master.c
// Description: TMS320F28377D SPI 기본 마스터 전송 (8비트, 1MHz, Mode 0) 예제
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 초기화
    IER = 0x0000; // CPU 인터럽트 비활성화
    IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
    InitPieVectTable(); // PIE 벡터 테이블 초기화

    // GPIO 설정 (SPIA: SIMO, SOMI, SPICLK, SPISSTE)
    EALLOW;
    GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1; // GPIO16을 SPIA SIMO로 설정
    GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1; // GPIO17을 SPIA SOMI로 설정
    GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1; // GPIO18을 SPIA SPICLK로 설정
    GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1; // GPIO19을 SPIA SPISSTE로 설정
    GpioCtrlRegs.GPBDIR.bit.GPIO31 = 1; // GPIO31을 출력(LED)으로 설정
    GpioDataRegs.GPBSET.bit.GPIO31 = 1; // LED 켜기
    EDIS;

    // SPIA 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR0.bit.SPI_A = 1; // SPIA 모듈 클럭 활성화
    EDIS;

    // SPIA 설정 (Bitfield 사용)
    SpiaRegs.SPICCR.bit.SPISWRESET = 0; // SPI 리셋
    SpiaRegs.SPICCR.bit.SPICHAR = 7; // 8비트 데이터
    SpiaRegs.SPICCR.bit.CLKPOLARITY = 0; // Mode 0: 클럭 극성 0
    SpiaRegs.SPICTL.bit.CLK_PHASE = 0; // Mode 0: 클럭 위상 0
    SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1; // 마스터 모드
    SpiaRegs.SPICTL.bit.TALK = 1; // 송신 활성화
    SpiaRegs.SPIBRR.bit.SPIBRR = 49; // 보율 1MHz (LSPCLK=50MHz/(49+1))
    SpiaRegs.SPICCR.bit.SPISWRESET = 1; // SPI 활성화

    // 데이터 전송
    Uint16 data = 0x55AA; // 테스트 데이터
    SpiaRegs.SPITXBUF = data; // 송신 버퍼에 데이터 쓰기
    while(SpiaRegs.SPISTS.bit.INT_FLAG == 0); // 수신 완료 대기
    Uint16 received = SpiaRegs.SPIRXBUF; // 수신 데이터 읽기

    for(;;); // 무한 루프
}

설명:

  • 기능: SPIA를 마스터 모드로 설정하여 8비트 데이터(0x55AA)를 1MHz로 전송 및 수신.
  • 설정: Mode 0(클럭 극성/위상 0), 8비트 데이터, 보율 1MHz, 마스터 모드.
  • GPIO: GPIO16(SIMO), GPIO17(SOMI), GPIO18(SPICLK), GPIO19(SPISSTE), GPIO31(LED).
  • 출력: SPIA를 통해 데이터 송수신, 정상 동작 시 LED ON.

5.2 예제 2: SPI FIFO 사용

// File: spi_fifo.c
// Description: TMS320F28377D SPI FIFO 사용 예제 (8비트, 1MHz, Mode 1)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

void main(void) {
    // 시스템 초기화
    InitSys UartCtrl(); // 시스템 클럭 및 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 초기화
    IER = 0x0000; // CPU 인터럽트 비활성화
    IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
    InitPieVectTable(); // PIE 벡터 테이블 초기화

    // GPIO 설정 (SPIA: SIMO, SOMI, SPICLK, SPISSTE)
    EALLOW;
    GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1; // GPIO16을 SPIA SIMO로 설정
    GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1; // GPIO17을 SPIA SOMI로 설정
    GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1; // GPIO18을 SPIA SPICLK로 설정
    GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1; // GPIO19을 SPIA SPISSTE로 설정
    GpioCtrlRegs.GPBDIR.bit.GPIO31 = 1; // GPIO31을 출력(LED)으로 설정
    GpioDataRegs.GPBSET.bit.GPIO31 = 1; // LED 켜기
    EDIS;

    // SPIA 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR0.bit.SPI_A = 1; // SPIA 모듈 클럭 활성화
    EDIS;

    // SPIA 설정 (Bitfield 사용)
    SpiaRegs.SPICCR.bit.SPISWRESET = 0; // SPI 리셋
    SpiaRegs.SPICCR.bit.SPICHAR = 7; // 8비트 데이터
    SpiaRegs.SPICCR.bit.CLKPOLARITY = 0; // Mode 1: 클럭 극성 0
    SpiaRegs.SPICTL.bit.CLK_PHASE = 1; // Mode 1: 클럭 위상 1
    SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1; // 마스터 모드
    SpiaRegs.SPICTL.bit.TALK = 1; // 송신 활성화
    SpiaRegs.SPIBRR.bit.SPIBRR = 49; // 보율 1MHz (LSPCLK=50MHz/(49+1))

    // FIFO 설정
    SpiaRegs.SPIFFTX.bit.SPIFFENA = 1; // FIFO 활성화
    SpiaRegs.SPIFFTX.bit.TXFIFO = 1; // 송신 FIFO 리셋 해제
    SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1; // 수신 FIFO 리셋 해제
    SpiaRegs.SPIFFCT.bit.TXDLY = 0; // 송신 지연 없음
    SpiaRegs.SPICCR.bit.SPISWRESET = 1; // SPI 활성화

    // 다중 데이터 전송
    Uint16 data[] = {0x1234, 0x5678, 0x9ABC, 0xDEF0}; // 테스트 데이터 배열
    int i;
    for(i = 0; i < 4; i++) {
        SpiaRegs.SPITXBUF = data[i]; // FIFO에 데이터 쓰기
        while(SpiaRegs.SPIFFRX.bit.RXFFST < 1); // 수신 FIFO에 데이터 대기
        Uint16 received = SpiaRegs.SPIRXBUF; // 수신 데이터 읽기
    }

    for(;;); // 무한 루프
}

설명:

  • 기능: SPIA를 마스터 모드로 설정하여 8비트 데이터 배열을 FIFO를 통해 1MHz로 전송 및 수신.
  • 설정: Mode 1(클럭 극성 0, 위상 1), 8비트 데이터, 보율 1MHz, FIFO 활성화.
  • GPIO: GPIO16(SIMO), GPIO17(SOMI), GPIO18(SPICLK), GPIO19(SPISSTE), GPIO31(LED).
  • 출력: SPIA를 통해 다중 데이터 송수신, 정상 동작 시 LED ON.

5.3 예제 3: SPI 인터럽트 기반 데이터 전송

// File: spi_interrupt.c
// Description: TMS320F28377D SPI 인터럽트 기반 데이터 전송 예제 (8비트, 1MHz, Mode 0)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

volatile Uint16 tx_data = 0xA5A5; // 송신 데이터
volatile Uint16 rx_data = 0; // 수신 데이터

__interrupt void spiA_isr(void)
{
    rx_data = SpiaRegs.SPIRXBUF; // 수신 데이터 읽기
    SpiaRegs.SPITXBUF = tx_data; // 다음 데이터 송신
    SpiaRegs.SPIFFTX.bit.TXFFINTCLR = 1; // 송신 인터럽트 플래그 클리어
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP6; // PIE ACK 클리어
}

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 초기화
    IER = 0x0000; // CPU 인터럽트 비활성화
    IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
    InitPieVectTable(); // PIE 벡터 테이블 초기화

    // 인터럽트 벡터 설정
    EALLOW;
    PieVectTable.SPIA_TX_INT = &spiA_isr; // SPIA 송신 인터럽트 벡터 설정
    EDIS;

    // GPIO 설정 (SPIA: SIMO, SOMI, SPICLK, SPISSTE)
    EALLOW;
    GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1; // GPIO16을 SPIA SIMO로 설정
    GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1; // GPIO17을 SPIA SOMI로 설정
    GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1; // GPIO18을 SPIA SPICLK로 설정
    GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1; // GPIO19을 SPIA SPISSTE로 설정
    GpioCtrlRegs.GPBDIR.bit.GPIO31 = 1; // GPIO31을 출력(LED)으로 설정
    GpioDataRegs.GPBSET.bit.GPIO31 = 1; // LED 켜기
    EDIS;

    // SPIA 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR0.bit.SPI_A = 1; // SPIA 모듈 클럭 활성화
    EDIS;

    // SPIA 설정 (Bitfield 사용)
    SpiaRegs.SPICCR.bit.SPISWRESET = 0; // SPI 리셋
    SpiaRegs.SPICCR.bit.SPICHAR = 7; // 8비트 데이터
    SpiaRegs.SPICCR.bit.CLKPOLARITY = 0; // Mode 0: 클럭 극성 0
    SpiaRegs.SPICTL.bit.CLK_PHASE = 0; // Mode 0: 클럭 위상 0
    SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1; // 마스터 모드
    SpiaRegs.SPICTL.bit.TALK = 1; // 송신 활성화
    SpiaRegs.SPIBRR.bit.SPIBRR = 49; // 보율 1MHz (LSPCLK=50MHz/(49+1))

    // FIFO 및 인터럽트 설정
    SpiaRegs.SPIFFTX.bit.SPIFFENA = 1; // FIFO 활성화
    SpiaRegs.SPIFFTX.bit.TXFIFO = 1; // 송신 FIFO 리셋 해제
    SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1; // 수신 FIFO 리셋 해제
    SpiaRegs.SPIFFTX.bit.TXFFIENA = 1; // 송신 FIFO 인터럽트 활성화
    SpiaRegs.SPIFFTX.bit.TXFFINTCLR = 1; // 송신 인터럽트 플래그 클리어
    PieCtrlRegs.PIEIER6.bit.INTx1 = 1; // PIE 그룹 6, SPIA TX 인터럽트 활성화
    IER |= M_INT6; // CPU 인터럽트 6 활성화
    SpiaRegs.SPICCR.bit.SPISWRESET = 1; // SPI 활성화

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

    // 초기 데이터 송신
    SpiaRegs.SPITXBUF = tx_data;

    for(;;); // 무한 루프
}

설명:

  • 기능: SPIA를 마스터 모드로 설정하여 8비트 데이터(0xA5A5)를 인터럽트를 통해 1MHz로 연속 송수신.
  • 설정: Mode 0(클럭 극성/위상 0), 8비트 데이터, 보율 1MHz, FIFO 및 송신 인터럽트 활성화.
  • GPIO: GPIO16(SIMO), GPIO17(SOMI), GPIO18(SPICLK), GPIO19(SPISSTE), GPIO31(LED).
  • 출력: SPIA를 통해 연속 데이터 송수신, 정상 동작 시 LED ON.

6. 사용 방법

6.1 환경 설정

  • C2000Ware 설치: C:\ti\c2000\C2000Ware_x_xx_xx_xx에서 라이브러리 다운로드.
  • CCS 프로젝트: TMS320F28377D 타겟으로 프로젝트 생성, F28x_Project.h 포함.
  • 링커 파일: device_support\f2837xd 폴더에서 링커 파일 추가.

6.2 코드 실행

  • 각 예제를 별도의 .c 파일로 저장하거나, main.c에 복사.
  • 원하는 예제만 실행되도록 다른 코드 주석 처리.

6.3 하드웨어 준비

  • SPI 연결: SIMO, SOMI, SPICLK, SPISSTE 핀을 슬레이브 장치에 연결.
  • 칩 셀렉트: SPISSTE를 하드웨어 CS로 사용하거나 GPIO로 소프트웨어 제어.
  • LED: GPIO31에 LED 연결 (정상 동작 확인용).
  • 테스트 장치: SPI 슬레이브 장치(예: EEPROM, 센서) 연결.

6.4 디버깅

  • CCS Expressions 창: SpiaRegs.SPIRXBUF, SpiaRegs.SPISTS 확인.
  • 인터럽트 상태: SpiaRegs.SPIFFTX.bit.TXFFINT 점검.
  • 레지스터 모니터링: SpiaRegs.SPICCR, SpiaRegs.SPICTL 확인.
  • 오실로스코프: SPICLK, SIMO, SOMI 신호 확인.

7. 추가 팁

  • 루프백 테스트: SPICCR.bit.LOOPBACK = 1로 내부 테스트.
  • 보율 최적화: 대상 장치의 최대 클럭 속도 확인.
  • C2000Ware 참고: C:\ti\c2000\C2000Ware_x_xx_xx_xx\device_support\f2837xd\examples\cpu1\spi.
  • 문제 해결:
    •    데이터 손실: FIFO 상태(SPIFFRX.bit.RXFFST) 확인.
    •    통신 실패: 클럭 위상/극성, 보율 설정 점검.
    •    인터럽트 미동작: PIE 설정, ISR 등록 확인.
  • TI 리소스: TI E2E 포럼, C2000Ware 예제.

8. 결론

이 문서는 TMS320F28377D SPI 모듈의 설정 방법과 Bitfield 구조를 활용한 예제 코드를 제공하여, 초보자부터 숙련된 개발자까지 쉽게 활용할 수 있도록 구성했습니다. 기본 마스터 전송, FIFO 사용, 인터럽트 기반 전송 예제를 통해 다양한 SPI 애플리케이션에 적용 가능합니다.

키워드: TMS320F28377D, SPI, C2000, 마이크로컨트롤러, Code Composer Studio, FIFO, 인터럽트, 마스터 모드,  직렬 통신, 클럭 위상, 보율

반응형