본문 바로가기
MCU/C2000

TMS320F28377D DSP CAN 사용법 : Bitfield 구조 활용 예제 코드(수정)

by linuxgo 2025. 8. 18.

TI의 TMS320F28377D는 C2000 Delfino 시리즈의 32비트 마이크로컨트롤러로, 산업 자동화, 모터 제어, 전력 변환 등에서 CAN(Controller Area Network) 통신을 지원합니다. CAN 모듈은 ISO 11898 표준을 준수하며, 고속, 신뢰성 높은 네트워크 통신을 제공합니다. 이 문서에서는 TMS320F28377D의 CAN 모듈 설정 방법, Bitfield 구조를 활용한 레지스터 설정, 그리고 실용적인 예제 코드를 제공하여 초보자와 숙련된 개발자 모두가 쉽게 활용할 수 있도록 돕겠습니다.

1. TMS320F28377D CAN 모듈 개요

TMS320F28377D는 두 개의 CAN 모듈(CANA, CANB)을 포함하며, 각 모듈은 최대 32개의 메일박스를 지원합니다. 주요 사양은 다음과 같습니다:

  • 클럭 소스: 시스템 클럭(SYSCLK, 최대 200MHz)
  • 전송 속도: 최대 1Mbps (CAN 2.0B 프로토콜 지원)
  • 메일박스: 32개 (송신/수신 설정 가능)
  • 식별자: 표준(11비트) 및 확장(29비트) ID 지원
  • 주요 기능:
    •    자동 재전송
    •    우선순위 기반 메일박스 처리
    •    타임스탬프 기능
    •    에러 카운터 및 인터럽트
    •    로컬 수락 필터(LAM, Local Acceptance Mask)
  • 인터럽트: 수신, 송신, 에러, 상태 변경 등
  • 저전력 모드: 슬립 모드 지원

2. CAN Bitfield 설정 상세

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

2.1 CAN_CTL (CAN 제어 레지스터)

  • bit.Init: 초기화 모드 (1: 초기화, 0: 정상 동작)
  • bit.CCE: 설정 변경 허용 (1: 활성화)
  • bit.SWR: 소프트웨어 리셋
  • bit.ABO: 자동 버스 온 (1: 활성화)
  • bit.IE0/bit.IE1: 인터럽트 활성화 (메일박스 및 에러)

2.2 CAN_ES (CAN 상태 레지스터)

  • bit.RxOk: 성공적 수신 상태
  • bit.TxOk: 성공적 송신 상태
  • bit.LEC: 마지막 에러 코드
  • bit.PER: 패리티 에러 감지
  • bit.EPass: 에러 패시브 상태
  • bit.BOff: 버스 오프 상태

2.3 CAN_BTR (비트 타이밍 레지스터)

  • bit.BRP: 보드레이트 프리스케일러
  • bit.TSEG1/bit.TSEG2: 비트 타이밍 세그먼트 1/2
  • bit.SJW: 동기화 점프 폭
  • bit.BRPE: 보드레이트 프리스케일러 확장

2.4 CAN_IF1/IF2 (인터페이스 레지스터)

  • bit.MsgVal: 메일박스 유효 (1: 유효)
  • bit.Xtd: 확장 ID 사용 (1: 29비트, 0: 11비트)
  • bit.Dir: 방향 (1: 송신, 0: 수신)
  • bit.DATA_A/bit.DATA_B: 데이터 바이트 설정 (0-3, 4-7)
  • bit.Mask: 마스크 필드 설정
  • bit.RxIE: 수신 인터럽트 활성화
  • bit.UMask: 수락 마스크 사용
  • bit.NewDat: 새로운 데이터 플래그

2.5 CAN_IF1MSK/CAN_IF2MSK (수락 마스크 레지스터)

  • bit.Msk: 수락 마스크 설정 (예: 0x7FF로 11비트 ID 완전 매칭)
  • bit.MXtd: 확장 ID 마스크 사용 여부
  • bit.MDir: 방향 마스크

3. CAN 설정 절차

CAN 모듈을 설정하려면 다음 단계를 따릅니다:

  1. 시스템 초기화:
    •   InitSysCtrl()로 시스템 클럭과 PLL 초기화
    •   인터럽트 비활성화 및 PIE 초기화 (DINT, InitPieCtrl, InitPieVectTable)
  2. CAN 클럭 활성화:
    •   CpuSysRegs.PCLKCR10.bit.CAN_A 또는 CpuSysRegs.PCLKCR10.bit.CAN_B를 1로 설정
    •   EALLOW와 EDIS로 보호된 레지스터 접근
  3. GPIO 설정:
    •   CAN TX/RX 핀 설정 (예: GPIO8=CANRXA, GPIO10=CANTXA)
    •   GPIO_SetupPinMux로 멀티플렉싱 설정
    •   GPIO_SetupPinOptions로 핀 입출력 설정
  4. CAN 초기화:
    •   CAN_CTL.bit.Init = 1로 초기화 모드 진입
    •   CAN_BTR로 보드레이트 설정 (예: 1Mbps)
    •   CAN_CTL.bit.CCE = 0으로 비트 타이밍 설정 완료
  5. 메일박스 설정:
    •   CAN_IF1CMD 또는 CAN_IF2CMD로 메일박스 설정
    •   ID, 마스크(CAN_IF1MSK/CAN_IF2MSK), 방향 설정
    •   CAN_IF1CMD.bit.Mask 또는 CAN_IF2CMD.bit.Mask로 마스크 필드 활성화
    •   CAN_IF1MCTL.bit.UMask 또는 CAN_IF2MCTL.bit.UMask로 마스크 사용 설정
  6. 인터럽트 설정 (필요 시):
    •   CAN_CTL.bit.IE0/bit.IE1로 인터럽트 활성화
    •   PieVectTable에 벡터 설정 (예: PieVectTable.CANA0_INT)
  7. CAN 실행:
    •   CAN_CTL.bit.Init = 0으로 정상 모드 진입

4. CAN 설정 고려사항

  • 보드레이트: SYSCLK와 비트 타이밍으로 정확한 보드레이트 계산 (예: 1Mbps = 200MHz / (BRP * (TSEG1 + TSEG2 + 1)))
  • 메일박스: 송신/수신 메일박스 분리 및 우선순위 설정
  • 필터링: LAM으로 특정 ID만 수신
  • 에러 처리: CAN_ES.bit.LEC로 에러 모니터링
  • 인터럽트: 수신/송신 완료 시 인터럽트 활용

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

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

TMS320F28377D CAN

5.1 예제 1: 기본 CAN 송신

// File: can_basic_transmit.c
// Description: TMS320F28377D CANA 기본 송신 예제 (Bitfield 구조, driverlib GPIO)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D
// Notes: 1Mbps CAN 송신, BLINKY_LED_GPIO로 상태 표시, 폴링 방식, F2837xD_can.h 비트필드 준수 (대문자 비트 이름 수정)

#include "F28x_Project.h"

// LED 정의 (LAUNCHXL-F28379D 기준)
#define BLINKY_LED_GPIO 31

// 함수 프로토타입
void setupGpio(void);
void initCAN(void);
void sendCANMessage(void);

void main(void) {
    // 시스템 초기화
    InitSysCtrl();                          // 시스템 클럭 및 PLL 초기화 (SYSCLK=200MHz)
    InitGpio();                             // GPIO 초기화
    setupGpio();                            // CAN 및 LED GPIO 설정
    DINT;                                   // 모든 인터럽트 비활성화
    InitPieCtrl();                          // PIE 초기화
    IER = 0x0000;                           // CPU 인터럽트 비활성화
    IFR = 0x0000;                           // 대기 중인 인터럽트 플래그 지우기
    InitPieVectTable();                     // PIE 벡터 테이블 초기화
    EINT;                                   // 글로벌 인터럽트 활성화
    ERTM;                                   // 실시간 인터럽트 활성화

    // CAN 초기화
    initCAN();

    // CAN 메시지 송신
    sendCANMessage();

    // 송신 완료 후 LED 켜기
    GPIO_WritePin(BLINKY_LED_GPIO, 1);

    // 무한 루프
    for(;;) {
        // 에러 상태 확인
        if (CanaRegs.CAN_ES.bit.BOff || CanaRegs.CAN_ES.bit.EPass) {
            GPIO_WritePin(BLINKY_LED_GPIO, 0); // 에러 시 LED OFF
            // 필요 시 재초기화: initCAN();
        }
    }
}

void setupGpio(void) {
    EALLOW;
    // CAN GPIO 설정
    GPIO_SetupPinMux(8, GPIO_MUX_CPU1, 2);  // GPIO8: CANRXA
    GPIO_SetupPinMux(10, GPIO_MUX_CPU1, 2); // GPIO10: CANTXA
    // LED GPIO 설정
    GPIO_SetupPinMux(BLINKY_LED_GPIO, GPIO_MUX_CPU1, 0); // LED
    GPIO_SetupPinOptions(BLINKY_LED_GPIO, GPIO_OUTPUT, GPIO_PUSHPULL); // LED 출력
    GPIO_WritePin(BLINKY_LED_GPIO, 0);      // LED 초기 OFF
    EDIS;
}

void initCAN(void) {
    // CANA 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR10.bit.CAN_A = 1;         // CAN 클럭 활성화 (CAN_A)

    EDIS;

    // CAN 초기화 모드 진입
    EALLOW;
    CanaRegs.CAN_CTL.bit.Init = 1;          // 초기화 모드
    CanaRegs.CAN_CTL.bit.CCE = 1;           // 비트 타이밍 설정 허용
    EDIS;

    // Bit Timing 설정 (1Mbps @ SYSCLK 200MHz)
    // CAN CLK = 200MHz / (BRP+1) = 20MHz, tq = 50ns
    // Bit Time = (1 + TSEG1 + TSEG2 + 3) tq = 23 tq = 1.15us (≈869kbps, 1Mbps 근사)
    EALLOW;
    CanaRegs.CAN_BTR.bit.BRP = 9;           // Baud rate prescaler: 10
    CanaRegs.CAN_BTR.bit.TSEG1 = 13;        // TSEG1 = 14 tq
    CanaRegs.CAN_BTR.bit.TSEG2 = 4;         // TSEG2 = 5 tq
    CanaRegs.CAN_BTR.bit.SJW = 3;           // SJW = 4 tq
    CanaRegs.CAN_BTR.bit.BRPE = 0;          // BRP Extension: 0 (미사용)
    EDIS;

    // 초기화 모드 종료
    EALLOW;
    CanaRegs.CAN_CTL.bit.CCE = 0;           // 비트 타이밍 설정 완료
    CanaRegs.CAN_CTL.bit.Init = 0;          // 정상 모드 진입
    CanaRegs.CAN_CTL.bit.ABO = 1;           // Auto-Bus-On 활성화
    EDIS;
}

void sendCANMessage(void) {
    // 메일박스 1 설정 (송신)
    EALLOW;
    CanaRegs.CAN_IF1CMD.bit.Arb = 1;        // Arbitration 필드
    CanaRegs.CAN_IF1CMD.bit.Control = 1;    // Control 필드
    CanaRegs.CAN_IF1CMD.bit.DATA_A = 1;     // Data A (0-3) - Data_A -> DATA_A
    CanaRegs.CAN_IF1CMD.bit.DATA_B = 1;     // Data B (4-7) - Data_B -> DATA_B
    CanaRegs.CAN_IF1ARB.bit.MsgVal = 1;     // 메일박스 유효
    CanaRegs.CAN_IF1ARB.bit.Xtd = 0;        // 표준 11비트 ID
    CanaRegs.CAN_IF1ARB.bit.ID = 0x123;     // CAN ID
    CanaRegs.CAN_IF1ARB.bit.Dir = 1;        // 송신
    CanaRegs.CAN_IF1MCTL.bit.DLC = 8;       // 데이터 길이 8바이트
    CanaRegs.CAN_IF1DATA.bit.Data_0 = 0x11; // 데이터 바이트
    CanaRegs.CAN_IF1DATA.bit.Data_1 = 0x22;
    CanaRegs.CAN_IF1DATA.bit.Data_2 = 0x33;
    CanaRegs.CAN_IF1DATA.bit.Data_3 = 0x44;
    CanaRegs.CAN_IF1DATB.bit.Data_4 = 0x55;
    CanaRegs.CAN_IF1DATB.bit.Data_5 = 0x66;
    CanaRegs.CAN_IF1DATB.bit.Data_6 = 0x77;
    CanaRegs.CAN_IF1DATB.bit.Data_7 = 0x88;
    CanaRegs.CAN_IF1CMD.bit.Mask = 0;       // 마스크 비활성화
    CanaRegs.CAN_IF1CMD.bit.TXRQST = 1;     // 송신 요청 - TxRqst -> TXRQST
    CanaRegs.CAN_IF1CMD.bit.MSG_NUM = 1;    // 메일박스 1
    EDIS;

    // 전송 완료 대기
    while(CanaRegs.CAN_IF1CMD.bit.Busy) { } // IF1CMD 전송 완료

    // 송신 완료 확인
    while(CanaRegs.CAN_TXRQ_X.bit.TxRqstReg1 & 0x1) { } // Mailbox 1 송신 완료 대기
}

설명:

  • 기능: CANA 모듈로 1Mbps, 표준 11비트 ID(0x123), 8바이트 데이터 송신
  • 설정: 보드레이트 1Mbps, 메일박스 1 송신, 데이터 0x11~0x88
  • GPIO: GPIO8(CANRXA), GPIO10(CANTXA), GPIO31(LED)
  • 출력: CAN 네트워크로 데이터 송신, 정상 동작 시 LED ON

5.2 예제 2: CAN 수신 및 필터링

// File: can_basic_receive.c
// Description: TMS320F28377D CANA 기본 수신 및 필터링 예제 (Bitfield 구조, driverlib GPIO)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

#define BLINKY_LED_GPIO 31

// 함수 프로토타입
void setupGpio(void);
void initCAN(void);
void receiveCANMessage(void);

void main(void) {
    // 시스템 초기화
    InitSysCtrl();                          // 시스템 클럭 및 PLL 초기화 (SYSCLK=200MHz)
    InitGpio();                             // GPIO 초기화
    setupGpio();                            // CAN 및 LED GPIO 설정
    DINT;                                   // 모든 인터럽트 비활성화
    InitPieCtrl();                          // PIE 초기화
    IER = 0x0000;                           // CPU 인터럽트 비활성화
    IFR = 0x0000;                           // 대기 중인 인터럽트 플래그 지우기
    InitPieVectTable();                     // PIE 벡터 테이블 초기화
    EINT;                                   // 글로벌 인터럽트 활성화
    ERTM;                                   // 실시간 인터럽트 활성화

    // CAN 초기화 및 메일박스 설정
    initCAN();

    // LED 초기 켜기
    GPIO_WritePin(BLINKY_LED_GPIO, 1);

    // 무한 루프
    for(;;) {
        // 에러 상태 확인
        if (CanaRegs.CAN_ES.bit.BOff || CanaRegs.CAN_ES.bit.EPass || CanaRegs.CAN_ES.bit.LEC != 0) {
            GPIO_WritePin(BLINKY_LED_GPIO, 0); // 에러 시 LED OFF
            // 필요 시 재초기화: initCAN();
        } else {
            receiveCANMessage(); // CAN 메시지 수신
        }
    }
}

void setupGpio(void) {
    EALLOW;
    // CAN GPIO 설정
    GPIO_SetupPinMux(8, GPIO_MUX_CPU1, 2);  // GPIO8: CANRXA
    GPIO_SetupPinMux(10, GPIO_MUX_CPU1, 2); // GPIO10: CANTXA
    // LED GPIO 설정
    GPIO_SetupPinMux(BLINKY_LED_GPIO, GPIO_MUX_CPU1, 0); // LED
    GPIO_SetupPinOptions(BLINKY_LED_GPIO, GPIO_OUTPUT, GPIO_PUSHPULL); // LED 출력
    GPIO_WritePin(BLINKY_LED_GPIO, 0);      // LED 초기 OFF
    EDIS;
}

void initCAN(void) {
    // CANA 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR10.bit.CAN_A = 1;      // CAN 클럭 활성화 (CAN_A)
    EDIS;

    // CAN 초기화 모드 진입
    EALLOW;
    CanaRegs.CAN_CTL.bit.Init = 1;          // 초기화 모드
    CanaRegs.CAN_CTL.bit.CCE = 1;           // 비트 타이밍 설정 허용
    EDIS;

    // Bit Timing 설정 (1Mbps @ SYSCLK 200MHz)
    // CAN CLK = 200MHz / (BRP+1) = 20MHz, tq = 50ns
    // Bit Time = (1 + TSEG1 + TSEG2) tq = 20 tq = 1us (1Mbps 정확)
    EALLOW;
    CanaRegs.CAN_BTR.bit.BRP = 9;           // Baud rate prescaler: 10
    CanaRegs.CAN_BTR.bit.TSEG1 = 13;        // TSEG1 = 14 tq
    CanaRegs.CAN_BTR.bit.TSEG2 = 4;         // TSEG2 = 5 tq
    CanaRegs.CAN_BTR.bit.SJW = 3;           // SJW = 4 tq
    CanaRegs.CAN_BTR.bit.BRPE = 0;          // BRP Extension: 0 (미사용)
    EDIS;

    // 메일박스 2 설정 (수신)
    EALLOW;
    CanaRegs.CAN_IF2CMD.bit.Arb = 1;        // Arbitration 필드
    CanaRegs.CAN_IF2CMD.bit.Control = 1;    // Control 필드
    CanaRegs.CAN_IF2CMD.bit.Mask = 1;       // Mask 필드
    CanaRegs.CAN_IF2ARB.bit.MsgVal = 1;     // 메일박스 유효
    CanaRegs.CAN_IF2ARB.bit.Xtd = 0;        // 표준 11비트 ID
    CanaRegs.CAN_IF2ARB.bit.ID = 0x123;     // CAN ID
    CanaRegs.CAN_IF2ARB.bit.Dir = 0;        // 수신
    CanaRegs.CAN_IF2MCTL.bit.DLC = 8;       // 데이터 길이 8바이트
    CanaRegs.CAN_IF2MCTL.bit.UMask = 1;     // 마스크 사용 활성화
    CanaRegs.CAN_IF2MCTL.bit.EoB = 1;       // 단일 메일박스
    CanaRegs.CAN_IF2MSK.bit.Msk = 0x7FF;    // ID 0x123만 수신 (11비트 마스크)
    CanaRegs.CAN_IF2MSK.bit.MXtd = 0;       // 표준 ID 마스크
    CanaRegs.CAN_IF2CMD.bit.MSG_NUM = 2;    // 메일박스 2
    while(CanaRegs.CAN_IF2CMD.bit.Busy);    // 쓰기 완료 대기
    EDIS;

    // 초기화 모드 종료
    EALLOW;
    CanaRegs.CAN_CTL.bit.CCE = 0;           // 비트 타이밍 설정 완료
    CanaRegs.CAN_CTL.bit.Init = 0;          // 정상 모드 진입
    CanaRegs.CAN_CTL.bit.ABO = 1;           // Auto-Bus-On 활성화
    EDIS;
}

void receiveCANMessage(void) {
    // 수신 대기 및 데이터 처리
    if (CanaRegs.CAN_IF2MCTL.bit.NewDat) {  // 새로운 데이터 확인
        GPIO_WritePin(BLINKY_LED_GPIO, !GPIO_ReadPin(BLINKY_LED_GPIO)); // LED 토글
        EALLOW;
        CanaRegs.CAN_IF2CMD.bit.DATA_A = 1;  // 데이터 읽기 설정
        CanaRegs.CAN_IF2CMD.bit.DATA_B = 1;
        CanaRegs.CAN_IF2CMD.bit.MSG_NUM = 2;
        while(CanaRegs.CAN_IF2CMD.bit.Busy); // 읽기 완료 대기
        Uint16 data[4];
        data[0] = CanaRegs.CAN_IF2DATA.all;  // 데이터 저장
        data[1] = CanaRegs.CAN_IF2DATB.all;
        CanaRegs.CAN_IF2MCTL.bit.NewDat = 0; // NewDat 플래그 클리어
        EDIS;
        // 디버깅: 수신 데이터 확인 (CCS Expressions 창에서 확인 가능)
        // 예: data[0] = (Data_0, Data_1), data[1] = (Data_4, Data_5)
    }
}

설명:

  • 기능: ID 0x123인 메시지만 수신하도록 필터링
  • 설정: 보드레이트 1Mbps, 메일박스 2 수신, LAM으로 ID 필터링
  • GPIO: GPIO8(CANRXA), GPIO10(CANTXA), GPIO31(LED)
  • 출력: 메시지 수신 시 LED 토글

5.3 예제 3: CAN 인터럽트 기반 수신

// File: can_interrupt_receive.c
// Description: TMS320F28377D CANA 인터럽트 기반 수신 예제 (Bitfield 구조, driverlib GPIO)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D
// Notes: 1Mbps CAN 수신, BLINKY_LED_GPIO로 상태 표시, 인터럽트 방식, F2837xD_can.h 비트필드 준수

#include "F28x_Project.h"

#define BLINKY_LED_GPIO 31

// 함수 프로토타입
void setupGpio(void);
void initCAN(void);
__interrupt void cana_isr(void);

// 인터럽트 서비스 루틴
__interrupt void cana_isr(void) {
    if (CanaRegs.CAN_IF2MCTL.bit.NewDat) {  // 새로운 데이터 확인
        GPIO_WritePin(BLINKY_LED_GPIO, !GPIO_ReadPin(BLINKY_LED_GPIO)); // LED 토글
        EALLOW;
        CanaRegs.CAN_IF2CMD.bit.DATA_A = 1;  // 데이터 읽기 설정
        CanaRegs.CAN_IF2CMD.bit.DATA_B = 1;
        CanaRegs.CAN_IF2CMD.bit.MSG_NUM = 2;
        while(CanaRegs.CAN_IF2CMD.bit.Busy); // 읽기 완료 대기
        Uint16 data[4];
        data[0] = CanaRegs.CAN_IF2DATA.all;  // 데이터 저장
        data[1] = CanaRegs.CAN_IF2DATB.all;
        CanaRegs.CAN_IF2MCTL.bit.NewDat = 0; // NewDat 플래그 클리어
        CanaRegs.CAN_IPEN_X.bit.IntPndReg1 = 0; // 메일박스 2 인터럽트 클리어
        EDIS;
        // 디버깅: 수신 데이터 확인 (CCS Expressions 창에서 확인 가능)
        // 예: data[0] = (Data_0, Data_1), data[1] = (Data_4, Data_5)
    }
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP9; // PIE 그룹 9 ACK
}

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

    // 인터럽트 벡터 설정
    EALLOW;
    PieVectTable.CANA0_INT = &cana_isr;     // CANA 인터럽트 벡터 설정
    EDIS;

    // CAN 초기화 및 메일박스 설정
    initCAN();

    // 인터럽트 활성화
    EALLOW;
    PieCtrlRegs.PIEIER9.bit.INTx1 = 1;      // PIE 그룹 9, CANA0 인터럽트 활성화
    IER |= M_INT9;                          // CPU 인터럽트 9 활성화
    EDIS;

    // LED 초기 켜기
    GPIO_WritePin(BLINKY_LED_GPIO, 1);

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

    // 무한 루프
    for(;;) {
        // 에러 상태 확인
        if (CanaRegs.CAN_ES.bit.BOff || CanaRegs.CAN_ES.bit.EPass || CanaRegs.CAN_ES.bit.LEC != 0) {
            GPIO_WritePin(BLINKY_LED_GPIO, 0); // 에러 시 LED OFF
            // 필요 시 재초기화: initCAN();
        }
    }
}

void setupGpio(void) {
    EALLOW;
    // CAN GPIO 설정
    GPIO_SetupPinMux(8, GPIO_MUX_CPU1, 2);  // GPIO8: CANRXA
    GPIO_SetupPinMux(10, GPIO_MUX_CPU1, 2); // GPIO10: CANTXA
    // LED GPIO 설정
    GPIO_SetupPinMux(BLINKY_LED_GPIO, GPIO_MUX_CPU1, 0); // LED
    GPIO_SetupPinOptions(BLINKY_LED_GPIO, GPIO_OUTPUT, GPIO_PUSHPULL); // LED 출력
    GPIO_WritePin(BLINKY_LED_GPIO, 0);      // LED 초기 OFF
    EDIS;
}

void initCAN(void) {
    // CANA 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR10.bit.CAN_A = 1;      // CAN 클럭 활성화 (CAN_A)
    EDIS;

    // CAN 초기화 모드 진입
    EALLOW;
    CanaRegs.CAN_CTL.bit.Init = 1;          // 초기화 모드
    CanaRegs.CAN_CTL.bit.CCE = 1;           // 비트 타이밍 설정 허용
    EDIS;

    // Bit Timing 설정 (1Mbps @ SYSCLK 200MHz)
    // CAN CLK = 200MHz / (BRP+1) = 20MHz, tq = 50ns
    // Bit Time = (1 + TSEG1 + TSEG2) tq = 20 tq = 1us (1Mbps 정확)
    EALLOW;
    CanaRegs.CAN_BTR.bit.BRP = 9;           // Baud rate prescaler: 10
    CanaRegs.CAN_BTR.bit.TSEG1 = 13;        // TSEG1 = 14 tq
    CanaRegs.CAN_BTR.bit.TSEG2 = 4;         // TSEG2 = 5 tq
    CanaRegs.CAN_BTR.bit.SJW = 3;           // SJW = 4 tq
    CanaRegs.CAN_BTR.bit.BRPE = 0;          // BRP Extension: 0 (미사용)
    EDIS;

    // 메일박스 2 설정 (수신)
    EALLOW;
    CanaRegs.CAN_IF2CMD.bit.Arb = 1;        // Arbitration 필드
    CanaRegs.CAN_IF2CMD.bit.Control = 1;    // Control 필드
    CanaRegs.CAN_IF2CMD.bit.Mask = 1;       // Mask 필드
    CanaRegs.CAN_IF2ARB.bit.MsgVal = 1;     // 메일박스 유효
    CanaRegs.CAN_IF2ARB.bit.Xtd = 0;        // 표준 11비트 ID
    CanaRegs.CAN_IF2ARB.bit.ID = 0x123;     // CAN ID
    CanaRegs.CAN_IF2ARB.bit.Dir = 0;        // 수신
    CanaRegs.CAN_IF2MCTL.bit.DLC = 8;       // 데이터 길이 8바이트
    CanaRegs.CAN_IF2MCTL.bit.UMask = 1;     // 마스크 사용 활성화
    CanaRegs.CAN_IF2MCTL.bit.EoB = 1;       // 단일 메일박스
    CanaRegs.CAN_IF2MCTL.bit.RxIE = 1;      // 수신 인터럽트 활성화
    CanaRegs.CAN_IF2MCTL.bit.RmtEn = 0;     // 원격 프레임 비활성화
    CanaRegs.CAN_IF2MSK.bit.Msk = 0x7FF;    // ID 0x123만 수신 (11비트 마스크)
    CanaRegs.CAN_IF2MSK.bit.MXtd = 0;       // 표준 ID 마스크
    CanaRegs.CAN_IF2CMD.bit.MSG_NUM = 2;    // 메일박스 2
    while(CanaRegs.CAN_IF2CMD.bit.Busy);    // 쓰기 완료 대기
    EDIS;

    // 초기화 모드 종료 및 인터럽트 활성화
    EALLOW;
    CanaRegs.CAN_CTL.bit.CCE = 0;           // 비트 타이밍 설정 완료
    CanaRegs.CAN_CTL.bit.Init = 0;          // 정상 모드 진입
    CanaRegs.CAN_CTL.bit.ABO = 1;           // Auto-Bus-On 활성화
    CanaRegs.CAN_CTL.bit.IE0 = 1;           // CAN 인터럽트 라인 0 활성화
    EDIS;
}

설명:

  • 기능: ID 0x123인 메시지를 인터럽트를 통해 수신
  • 설정: 보드레이트 1Mbps, 메일박스 2 수신, LAM으로 ID 필터링, 수신 인터럽트 활성화
  • GPIO: GPIO8(CANRXA), GPIO10(CANTXA), GPIO31(LED)
  • 출력: 메시지 수신 시 LED 토글

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 하드웨어 준비

  • CAN 핀: CANRXA(GPIO8), CANTXA(GPIO10)에 CAN 트랜시버 연결
  • LED: GPIO31에 LED 연결 (정상 동작 확인용)
  • CAN 네트워크: CAN 버스에 다른 노드 연결, 120Ω 종단 저항 확인

6.4 디버깅

  • CCS Expressions 창: CanARegs.CAN_ES, CanARegs.CAN_IF2MCTL 확인
  • 인터럽트 상태: CanARegs.CAN_MIL로 인터럽트 플래그 점검
  • 에러 확인: CanARegs.CAN_ES.bit.LEC로 에러 상태 모니터링
  • CAN 분석기: CAN 버스 데이터 확인용 CAN 분석기 사용

7. 추가 팁

  • 보드레이트 계산: 정확한 비트 타이밍을 위해 TI의 비트 타이밍 계산기 사용
  • 캘리브레이션: Device_cal() 호출로 클럭 보정
  • 노이즈 감소: CAN 트랜시버와 차동 신호 라인 점검
  • C2000Ware 참고: C:\ti\c2000\C2000Ware_x_xx_xx_xx\device_support\f2837xd\examples\cpu1\can
  • 문제 해결:
    • 송신 실패: CAN_ES.bit.TXOK, CAN 버스 연결 확인
    • 수신 실패: CAN_LAM, CAN_IF2ARB 설정 확인
    • 인터럽트 미작동: CAN_CTL.bit.IE0, PieCtrlRegs.PIEIER9 확인
  • TI 리소스: TI E2E 포럼, C2000Ware 예제

8. 결론

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

키워드: TMS320F28377D, CAN, C2000, 마이크로컨트롤러, Code Composer Studio, CAN 송신, CAN 수신, Bitfield, 인터럽트, 로컬 수락 마스크, 보드레이트