본문 바로가기
MCU/C2000

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

by linuxgo 2025. 8. 17.

1. TMS320F28377D eCAP 모듈 개요

TI의 TMS320F28377D는 C2000 Delfino 시리즈의 32비트 마이크로컨트롤러로, eCAP(Enhanced Capture) 모듈은 펄스 폭, 주기, 듀티 사이클 측정과 같은 고속 캡처 애플리케이션에 최적화되어 있습니다. eCAP 모듈은 타이밍 이벤트를 정밀하게 캡처하고, 속도 측정, 엔코더 인터페이스, 또는 PWM 신호 분석에 유용합니다. 이 문서에서는 eCAP 모듈의 설정 방법, Bitfield 구조를 활용한 레지스터 설정, 그리고 실용적인 예제 코드를 제공하여 초보자와 숙련된 개발자 모두가 쉽게 활용할 수 있도록 돕겠습니다.

주요 사양

  • 모듈 수: 최대 6개의 독립적인 eCAP 모듈(eCAP1~eCAP6)
  • 클럭 소스: 시스템 클럭(SYSCLK, 최대 200MHz)
  • 타이머: 32비트 타임-베이스 카운터
  • 캡처 이벤트: 최대 4개의 타임스탬프 이벤트 저장
  • 모드:
    • 캡처 모드: 상승/하강 에지에서 타임스탬프 캡처
    • APWM 모드: 비대칭 PWM 신호 생성
  • 주요 기능:
    • 펄스 폭/주기/듀티 측정
    • 절대/델타 타임 캡처
    • 인터럽트 지원 (캡처 이벤트, 오버플로우 등)
    • 동기화 지원
  • 입력: 외부 핀 또는 내부 신호 입력
  • 인터럽트: 캡처 이벤트, 카운터 오버플로우, 주기 매칭 등

2. eCAP Bitfield 설정 상세

eCAP 레지스터는 Bitfield 구조로 정의되어 있으며, F2837xD_ecap.h 헤더 파일을 통해 접근합니다. 주요 레지스터는 다음과 같습니다:

2.1 ECCTL1 (캡처 제어 레지스터 1)

  • bit.CAPxPOL: 캡처 이벤트 극성 (0: 상승 에지, 1: 하강 에지)
  • bit.CTRRSTx: 캡처 이벤트 시 카운터 리셋 (0: 유지, 1: 리셋)
  • bit.CAPLDEN: 캡처 로드 활성화 (1: 활성화)
  • bit.PRESCALE: 입력 신호 프리스케일 (031, 분주비 162)

2.2 ECCTL2 (캡처 제어 레지스터 2)

  • bit.CONT_ONESHT: 연속/원샷 모드 (0: 연속, 1: 원샷)
  • bit.STOP_WRAP: 캡처 이벤트 래핑 (0~3, 최대 4개 이벤트)
  • bit.TSCTRSTOP: 타임-베이스 카운터 동작 (1: 활성화)
  • bit.APWMPOL: APWM 모드 극성 (0: High, 1: Low)
  • bit.CAP_APWM: 모드 선택 (0: 캡처, 1: APWM)

2.3 ECEINT (인터럽트 제어 레지스터)

  • bit.CEVTx: 캡처 이벤트 인터럽트 활성화 (1: 활성화)
  • bit.CTROVF: 카운터 오버플로우 인터럽트 활성화
  • bit.CTR_PRD: 주기 매칭 인터럽트 활성화

2.4 TSCTR, CAPx (타임-베이스 및 캡처 레지스터)

  • TSCTR: 32비트 타임-베이스 카운터
  • CAP1~CAP4: 캡처 이벤트 타임스탬프 저장

Bitfield 사용 이점:

  • 비트 단위로 명확한 설정 가능
  • 코드 가독성과 유지보수성 향상
  • F2837xD_ecap.h를 통해 직관적 접근

3. eCAP 설정 절차

eCAP 모듈을 효과적으로 설정하려면 다음 단계를 따릅니다:

  1. 시스템 초기화:
    •   InitSysCtrl()로 시스템 클럭과 PLL 초기화.
    •   인터럽트 비활성화 및 PIE 초기화 (DINT, InitPieCtrl, InitPieVectTable).
  2. eCAP 클럭 활성화:
    •   CpuSysRegs.PCLKCR3.bit.ECAPx = 1로 원하는 eCAP 모듈(x=1~6) 클럭 활성화.
    •   보호된 레지스터 접근을 위해 EALLOW와 EDIS 사용.
  3. GPIO 설정:
    •  eCAP 입력 핀 설정 (예: GPIO5를 eCAP1 입력으로 설정).
  4. 타임-베이스(TSCTR) 설정:
    •   ECCTL2.bit.TSCTRSTOP = 1로 카운터 시작.
    •   ECCTL1.bit.PRESCALE로 입력 신호 분주 설정.
  5. 캡처 모드 설정:
    •   ECCTL1.bit.CAPxPOL로 상승/하강 에지 선택.
    •   ECCTL1.bit.CTRRSTx로 카운터 리셋 여부 설정.
    •   ECCTL2.bit.CONT_ONESHT로 연속/원샷 모드 선택.
    •   ECCTL2.bit.STOP_WRAP로 캡처 이벤트 수 설정.
  6. 인터럽트 설정 (필요 시):
    •   ECEINT.bit.CEVTx = 1로 캡처 이벤트 인터럽트 활성화.
    •   ECFLG로 인터럽트 플래그 확인 및 클리어.
  7. APWM 모드 설정 (필요 시):
    •   ECCTL2.bit.CAP_APWM = 1로 APWM 모드 활성화.
    •   CAP1과 CAP2로 주기 및 비교 값 설정.
  8. 모듈 실행:
    •   ECCTL2.bit.TSCTRSTOP = 1로 캡처 또는 PWM 출력 시작.

4. eCAP 설정 고려사항

  • 클럭 설정: SYSCLK(200MHz)에서 입력 신호 프리스케일 설정.
  • 캡처 해상도: 32비트 타임-베이스로 고해상도 타임스탬프 제공.
  • 입력 신호: 외부 핀 입력 시 노이즈 필터링 고려.
  • 인터럽트: 캡처 이벤트 또는 오버플로우 인터럽트로 실시간 처리.
  • APWM 모드: PWM 신호 생성 시 주기와 듀티 설정에 주의.

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

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

tms320f28377D eCap

5.1 예제 1: 기본 캡처 모드 (펄스 폭 측정)

// File: ecap_basic_capture.c
// Description: TMS320F28377D eCAP 펄스 폭 측정 예제 (Bitfield 구조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

#define BLINKY_LED_GPIO  31
volatile Uint32 pulse_width = 0; // 펄스 폭 저장

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    InitGpio();

    // GPIO 설정
    EALLOW;
    InitECap1Gpio(5);
    GPIO_SetupPinOptions(5, GPIO_INPUT, GPIO_ASYNC);
    GPIO_SetupPinMux(BLINKY_LED_GPIO, GPIO_MUX_CPU1, 0);
    GPIO_SetupPinOptions(BLINKY_LED_GPIO, GPIO_OUTPUT, GPIO_PUSHPULL);
    EDIS;

    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 초기화
    IER = 0x0000; // CPU 인터럽트 비활성화
    IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
    InitPieVectTable(); // PIE 벡터 테이블 초기화


    // eCAP1 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR3.bit.ECAP1 = 1; // eCAP1 모듈 클럭 활성화
    EDIS;

    // eCAP1 설정 (Bitfield 사용)
    ECap1Regs.ECEINT.all = 0; // 모든 인터럽트 비활성화
    ECap1Regs.ECCLR.all = 0xFFFF; // 모든 인터럽트 플래그 클리어
    ECap1Regs.ECCTL1.bit.CAP1POL = 1; // 하강 에지 캡처
    ECap1Regs.ECCTL1.bit.CAP2POL = 0; // 상승 에지 캡처
    ECap1Regs.ECCTL1.bit.CTRRST1 = 1; // 첫 번째 이벤트에서 카운터 리셋
    ECap1Regs.ECCTL1.bit.CTRRST2 = 0; // 두 번째 이벤트에서 카운터 유지
    ECap1Regs.ECCTL1.bit.CAPLDEN = 1; // 캡처 로드 활성화
    ECap1Regs.ECCTL1.bit.PRESCALE = 0; // 프리스케일 1/1
    ECap1Regs.ECCTL2.bit.CONT_ONESHT = 0; // 연속 모드
    ECap1Regs.ECCTL2.bit.STOP_WRAP = 1; // 2개 이벤트 캡처
    ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1; // 타임-베이스 카운터 시작


    // 펄스 폭 계산
    while(1)
    {
        if(ECap1Regs.ECFLG.bit.CEVT2)
        { // 두 번째 이벤트 발생 확인
            pulse_width = ECap1Regs.CAP2; // 펄스 폭 (타임스탬프)
            ECap1Regs.ECCLR.bit.CEVT2 = 1; // 플래그 클리어
        }
    }
}

설명:

  • 기능: eCAP1을 사용하여 입력 신호의 펄스 폭 측정.
  • 설정: 하강 에지(CAP1)와 상승 에지(CAP2)에서 타임스탬프 캡처, 연속 모드, 프리스케일 1/1.
  • GPIO: GPIO5(eCAP1 입력), GPIO31(LED).
  • 출력: pulse_width 변수에 펄스 폭 저장, 정상 동작 시 LED ON.

5.2 예제 2: 인터럽트 기반 주기 측정

// File: ecap_basic_capture.c
// Description: TMS320F28377D eCAP 펄스 폭 측정 예제 (함수 및 구조 참조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

// 전역 변수 (Global Variables)
volatile Uint32 rising_edge_capture = 0;   // 펄스 상승 에지 캡처 값 (Rising edge capture value)
volatile Uint32 falling_edge_capture = 0;  // 펄스 하강 에지 캡처 값 (Falling edge capture value)
volatile Uint32 pulse_width = 0;           // 최종 펄스 폭 값 (Final pulse width value)

// 함수 프로토타입 (Function Prototypes)
void initECap(void);
void initGPIO(void);

void main(void) {
    // 1. 시스템 초기화 (System Initialization)
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화 (Initialize system clock and PLL)
    InitGpio();
    DINT;          // 모든 인터럽트 비활성화 (Disable all interrupts)
    InitPieCtrl(); // PIE 초기화 (Initialize PIE)
    IER = 0x0000;  // CPU 인터럽트 비활성화 (Disable CPU interrupts)
    IFR = 0x0000;  // 대기 중인 인터럽트 플래그 지우기 (Clear pending interrupt flags)
    InitPieVectTable(); // PIE 벡터 테이블 초기화 (Initialize PIE vector table)

    // 2. 주변장치 초기화 함수 호출 (Call Peripheral Initialization Functions)
    initGPIO();
    initECap();

    // 3. 펄스 폭 계산 무한 루프 (Infinite loop for pulse width calculation)
    while(1)
    {
        // 두 번째 캡처 이벤트(하강 에지)가 발생했는지 확인
        if(ECap1Regs.ECFLG.bit.CEVT2)
        {
            // 펄스 폭은 하강 에지 캡처 값(CAP2)에서 상승 에지 캡처 값(CAP1)을 뺀 값입니다.
            rising_edge_capture = ECap1Regs.CAP1;
            falling_edge_capture = ECap1Regs.CAP2;
            pulse_width = falling_edge_capture - rising_edge_capture;
            
            // 캡처 이벤트 플래그 클리어
            ECap1Regs.ECCLR.bit.CEVT2 = 1; 
            ECap1Regs.ECCLR.bit.CEVT1 = 1;
            
            // 다음 이벤트 캡처를 위해 전체 인터럽트 플래그도 클리어
            ECap1Regs.ECCLR.bit.INT = 1;
        }
    }
}

// eCAP 모듈 초기화 함수 (eCAP Module Initialization Function)
void initECap(void) {
    EALLOW;
    CpuSysRegs.PCLKCR3.bit.ECAP1 = 1; // eCAP1 모듈 클럭 활성화 (Enable eCAP1 module clock)
    EDIS;
    
    // eCAP1 설정 (eCAP1 Configuration)
    ECap1Regs.ECEINT.all = 0;            // 모든 인터럽트 비활성화 (Disable all interrupts)
    ECap1Regs.ECCLR.all = 0xFFFF;        // 모든 인터럽트 플래그 클리어 (Clear all interrupt flags)
    
    // 캡처 모드 설정 (Capture Mode Settings)
    ECap1Regs.ECCTL1.bit.CAP1POL = 0;    // 첫 번째 이벤트: 상승 에지 캡처 (1st event: Capture on rising edge)
    ECap1Regs.ECCTL1.bit.CAP2POL = 1;    // 두 번째 이벤트: 하강 에지 캡처 (2nd event: Capture on falling edge)
    ECap1Regs.ECCTL1.bit.CTRRST1 = 1;    // 첫 번째 이벤트에서 카운터 리셋 (Reset counter on 1st event)
    ECap1Regs.ECCTL1.bit.CTRRST2 = 0;    // 두 번째 이벤트에서 카운터 유지 (Keep counter on 2nd event)
    ECap1Regs.ECCTL1.bit.CAPLDEN = 1;    // 캡처 로드 활성화 (Enable capture load)
    ECap1Regs.ECCTL1.bit.PRESCALE = 0;   // 프리스케일 1/1 (Prescale 1/1)
    
    ECap1Regs.ECCTL2.bit.CONT_ONESHT = 0;// 연속 모드 (Continuous mode)
    ECap1Regs.ECCTL2.bit.STOP_WRAP = 1;  // 2개 이벤트 캡처 후 멈춤 (Stop after 2 events capture)
    ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1;  // 타임-베이스 카운터 시작 (Start time-base counter)
}

// GPIO 초기화 함수 (GPIO Initialization Function)
void initGPIO(void) {
    EALLOW;
    // GPIO5를 eCAP1 입력으로 설정 (Set GPIO5 to eCAP1 input)
    // GPIO 다중화 레지스터를 직접 조작하는 방법
    GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 3;
    // GPIO5 핀을 입력으로 설정 (Set GPIO5 as input)
    GpioCtrlRegs.GPADIR.bit.GPIO5 = 0;
    EDIS;
}

설명:

  • 기능: eCAP1을 사용하여 입력 신호의 주기를 인터럽트를 통해 측정.
  • 설정: 상승 에지(CAP1, CAP2)에서 타임스탬프 캡처, 연속 모드, 인터럽트 활성화.
  • GPIO: GPIO5(eCAP1 입력), GPIO31(LED).
  • 출력: period 변수에 주기 저장, 정상 동작 시 LED ON.

5.3 예제 3: APWM 모드 (PWM 생성)

// File: ecap_apwm.c
// Description: TMS320F28377D eCAP APWM 모드 예제 (함수 및 구조 참조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

// 함수 프로토타입 (Function Prototypes)
void initECapAPWM(void);
void initGPIO(void);

#define BLINKY_LED_GPIO 31

void main(void) {
    // 1. 시스템 초기화 (System Initialization)
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화 (Initialize system clock and PLL)
    DINT;          // 모든 인터럽트 비활성화 (Disable all interrupts)
    InitPieCtrl(); // PIE 초기화 (Initialize PIE)
    IER = 0x0000;  // CPU 인터럽트 비활성화 (Disable CPU interrupts)
    IFR = 0x0000;  // 대기 중인 인터럽트 플래그 지우기 (Clear pending interrupt flags)
    InitPieVectTable(); // PIE 벡터 테이블 초기화 (Initialize PIE vector table)

    // 2. 주변장치 초기화 함수 호출 (Call Peripheral Initialization Functions)
    initGPIO();
    initECapAPWM();

    // 3. 무한 루프 (Infinite loop)
    for(;;);
}

// eCAP 모듈 APWM 모드 초기화 함수 (eCAP APWM Mode Initialization Function)
void initECapAPWM(void) {
    EALLOW;
    CpuSysRegs.PCLKCR3.bit.ECAP1 = 1; // eCAP1 모듈 클럭 활성화 (Enable eCAP1 module clock)
    // 클럭 소스 설정: SYSCLK를 eCAP 타임베이스 카운터의 소스로 사용
    ECap1Regs.ECCTL2.bit.SYNCI_EN = 1; // 동기 입력 활성화 (Enable sync input)
    ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1; // 타임-베이스 카운터 시작 (Start time-base counter)
    
    // eCAP1 APWM 설정 (eCAP1 APWM Configuration)
    ECap1Regs.ECCTL2.bit.CAP_APWM = 1;  // APWM 모드 활성화 (Enable APWM mode)
    ECap1Regs.ECCTL2.bit.APWMPOL = 0;   // Active High (Active high)
    
    // 주기 및 듀티 사이클 설정 (Set period and duty cycle)
    ECap1Regs.CAP1 = 2000;              // 주기 = 2000 SYSCLK (100kHz = 200MHz/2000) (Period = 2000 SYSCLK)
    ECap1Regs.CAP2 = 1000;              // 50% 듀티 (50% duty cycle)
    EDIS;
}

// GPIO 초기화 함수 (GPIO Initialization Function)
void initGPIO(void) {
    EALLOW;
    
    // GPIO5를 eCAP1 출력으로 설정
    // 함수를 사용하여 GPIO5 설정
    GPIO_SetupPinMux(5, GPIO_MUX_CPU1, 3);
    GPIO_SetupPinOptions(5, GPIO_OUTPUT, GPIO_PUSHPULL);
    
    // GPIO31 (LED) 설정
    // 이 코드 블록은 APWM 예제에서 필요하지 않으므로 삭제합니다.
    GPIO_SetupPinMux(BLINKY_LED_GPIO, GPIO_MUX_CPU1, 0);
    GPIO_SetupPinOptions(BLINKY_LED_GPIO, GPIO_OUTPUT, GPIO_PUSHPULL);
    
    EDIS;
}

설명:

  • 기능: eCAP1을 APWM 모드로 사용하여 100kHz, 50% 듀티 사이클 PWM 신호 생성.
  • 설정: APWM 모드, 주기 2000(100kHz @ 200MHz), 듀티 1000(50%).
  • GPIO: GPIO5(eCAP1 출력), GPIO31(LED).
  • 출력: GPIO5에 PWM 신호 출력, 정상 동작 시 LED ON.

5.4 예제 4: 쿼드러처 엔코더 펄스(QEP) 방향 및 속도 측정

// File: ecap_qep_capture.c
// Description: TMS320F28377D eCAP QEP 신호 방향 및 속도 측정 예제 (함수 및 구조 참조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

// 전역 변수 (Global Variables)
volatile Uint32 pulse_count = 0;  // 펄스 카운트 (Pulse count)
volatile int direction = 0;       // 1: 정방향, -1: 역방향 (1: forward, -1: reverse)

// 함수 프로토타입 (Function Prototypes)
void initECap_QEP(void);
void initGPIO_QEP(void);

// eCAP1 인터럽트 서비스 루틴 (eCAP1 Interrupt Service Routine)
__interrupt void ecap1_isr(void) {
    if(ECap1Regs.ECFLG.bit.CEVT1) { // A상 상승 에지 캡처 이벤트 (A-phase rising edge capture event)
        // B상 핀의 상태를 확인하여 회전 방향 결정 (Check B-phase pin state to determine direction)
        if(GpioDataRegs.GPADAT.bit.GPIO7) { // B상 신호가 HIGH이면 역방향 (If B-phase is HIGH, direction is reverse)
            direction = -1;
        } else { // B상 신호가 LOW이면 정방향 (If B-phase is LOW, direction is forward)
            direction = 1;
        }
        pulse_count++; // 펄스 카운트 증가 (Increment pulse count)
        ECap1Regs.ECCLR.bit.CEVT1 = 1; // 플래그 클리어 (Clear flag)
    }
    
    ECap1Regs.ECCLR.bit.INT = 1; // 전체 인터럽트 플래그 클리어 (Clear global interrupt flag)
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP4; // PIE ACK 클리어 (Clear PIE ACK)
}

void main(void) {
    // 1. 시스템 초기화 (System Initialization)
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화 (Initialize system clock and PLL)
    DINT;          // 모든 인터럽트 비활성화 (Disable all interrupts)
    InitPieCtrl(); // PIE 초기화 (Initialize PIE)
    IER = 0x0000;  // CPU 인터럽트 비활성화 (Disable CPU interrupts)
    IFR = 0x0000;  // 대기 중인 인터럽트 플래그 지우기 (Clear pending interrupt flags)
    InitPieVectTable(); // PIE 벡터 테이블 초기화 (Initialize PIE vector table)

    // 2. 주변장치 초기화 함수 호출 (Call Peripheral Initialization Functions)
    initGPIO_QEP();
    initECap_QEP();

    // 3. 인터럽트 설정 (Interrupt Configuration)
    EALLOW;
    PieVectTable.ECAP1_INT = &ecap1_isr; // eCAP1 인터럽트 벡터 설정 (Set eCAP1 interrupt vector)
    EDIS;
    
    ECap1Regs.ECEINT.bit.CEVT1 = 1; // 첫 번째 캡처 이벤트 인터럽트 활성화 (Enable interrupt on 1st capture event)
    PieCtrlRegs.PIEIER4.bit.INTx1 = 1; // PIE 그룹 4, eCAP1 인터럽트 활성화 (Enable PIE group 4, eCAP1 interrupt)
    IER |= M_INT4; // CPU 인터럽트 4 활성화 (Enable CPU interrupt 4)
    EINT; // 글로벌 인터럽트 활성화 (Enable global interrupts)
    
    // 4. 무한 루프 (Infinite loop)
    for(;;);
}

// eCAP 모듈 초기화 함수 (eCAP Module Initialization Function)
void initECap_QEP(void) {
    EALLOW;
    CpuSysRegs.PCLKCR3.bit.ECAP1 = 1; // eCAP1 모듈 클럭 활성화 (Enable eCAP1 module clock)
    EDIS;
    
    // eCAP1 설정 (eCAP1 Configuration)
    ECap1Regs.ECEINT.all = 0;          // 모든 인터럽트 비활성화 (Disable all interrupts)
    ECap1Regs.ECCLR.all = 0xFFFF;      // 모든 인터럽트 플래그 클리어 (Clear all interrupt flags)
    
    // 캡처 모드 설정 (Capture Mode Settings)
    ECap1Regs.ECCTL1.bit.CAP1POL = 0;  // 첫 번째 이벤트: 상승 에지 캡처 (1st event: Capture on rising edge)
    ECap1Regs.ECCTL1.bit.CTRRST1 = 0;  // 카운터 리셋 비활성화 (Disable counter reset)
    ECap1Regs.ECCTL1.bit.CAPLDEN = 1;  // 캡처 로드 활성화 (Enable capture load)
    ECap1Regs.ECCTL1.bit.PRESCALE = 0; // 프리스케일 1/1 (Prescale 1/1)
    
    ECap1Regs.ECCTL2.bit.CONT_ONESHT = 0; // 연속 모드 (Continuous mode)
    ECap1Regs.ECCTL2.bit.STOP_WRAP = 0; // 1개 이벤트 캡처 (Capture 1 event)
    ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1; // 타임-베이스 카운터 시작 (Start time-base counter)
}

// GPIO 초기화 함수 (GPIO Initialization Function)
void initGPIO_QEP(void) {
    EALLOW;
    
    // GPIO5 (eCAP1A)를 입력으로 설정 (Set GPIO5 (eCAP1A) as input)
    GPIO_SetupPinMux(5, GPIO_MUX_CPU1, 3);
    GPIO_SetupPinOptions(5, GPIO_INPUT, GPIO_ASYNC);
    
    // GPIO7 (eCAP1B)를 입력으로 설정 (Set GPIO7 (eCAP1B) as input)
    GPIO_SetupPinMux(7, GPIO_MUX_CPU1, 0); // GPIO7은 GPIOA-GPAMUX1 레지스터의 비트 7-8을 사용하여 설정
    GPIO_SetupPinOptions(7, GPIO_INPUT, GPIO_ASYNC);
    
    // GPIO31 (LED)를 출력으로 설정 (Set GPIO31 (LED) as output)
    GPIO_SetupPinMux(31, GPIO_MUX_CPU1, 0);
    GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSHPULL);
    EDIS;
}

설명:

  • 기능: eCAP1을 사용하여 쿼드러처 엔코더의 A상 펄스를 캡처하고, B상 상태를 확인하여 회전 방향 및 펄스 수를 계산.
  • 설정: 상승 에지(CAP1)에서 캡처, 연속 모드, 인터럽트 활성화.
  • GPIO: GPIO5(eCAP1 입력, A상), GPIO7(B상 입력), GPIO31(LED).
  • 출력: pulse_count에 펄스 수, direction에 회전 방향 저장, 정상 동작 시 LED ON.

5.5 예제 5: 다중 eCAP 모듈 동기화

// File: ecap_synchronization.c
// Description: TMS320F28377D eCAP 다중 모듈 동기화 예제 (함수 및 구조 참조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

// 전역 변수 (Global Variables)
volatile Uint32 pulse_width1 = 0; // eCAP1 펄스 폭 (eCAP1 pulse width)
volatile Uint32 pulse_width2 = 0; // eCAP2 펄스 폭 (eCAP2 pulse width)

// 함수 프로토타입 (Function Prototypes)
void initGPIO(void);
void initECapMaster(void);
void initECapSlave(void);

void main(void) {
    // 1. 시스템 초기화 (System Initialization)
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화 (Initialize system clock and PLL)
    DINT;          // 모든 인터럽트 비활성화 (Disable all interrupts)
    InitPieCtrl(); // PIE 초기화 (Initialize PIE)
    IER = 0x0000;  // CPU 인터럽트 비활성화 (Disable CPU interrupts)
    IFR = 0x0000;  // 대기 중인 인터럽트 플래그 지우기 (Clear pending interrupt flags)
    InitPieVectTable(); // PIE 벡터 테이블 초기화 (Initialize PIE vector table)

    // 2. 주변장치 초기화 함수 호출 (Call Peripheral Initialization Functions)
    initGPIO();
    initECapMaster();
    initECapSlave();

    // 3. 펄스 폭 계산 무한 루프 (Infinite loop for pulse width calculation)
    while(1) {
        if(ECap1Regs.ECFLG.bit.CEVT2) { // eCAP1 두 번째 이벤트 (eCAP1 second event)
            pulse_width1 = ECap1Regs.CAP2 - ECap1Regs.CAP1; // 펄스 폭 계산 및 저장 (Calculate and store pulse width)
            ECap1Regs.ECCLR.bit.CEVT2 = 1; // 플래그 클리어 (Clear flag)
        }
        if(ECap2Regs.ECFLG.bit.CEVT2) { // eCAP2 두 번째 이벤트 (eCAP2 second event)
            pulse_width2 = ECap2Regs.CAP2 - ECap2Regs.CAP1; // 펄스 폭 계산 및 저장 (Calculate and store pulse width)
            ECap2Regs.ECCLR.bit.CEVT2 = 1; // 플래그 클리어 (Clear flag)
        }
    }
}

// GPIO 초기화 함수 (GPIO Initialization Function)
void initGPIO(void) {
    EALLOW;
    // GPIO5를 eCAP1 입력으로 설정 (Set GPIO5 to eCAP1 input)
    GPIO_SetupPinMux(5, GPIO_MUX_CPU1, 3);
    GPIO_SetupPinOptions(5, GPIO_INPUT, GPIO_ASYNC);

    // GPIO7을 eCAP2 입력으로 설정 (Set GPIO7 to eCAP2 input)
    GPIO_SetupPinMux(7, GPIO_MUX_CPU1, 3);
    GPIO_SetupPinOptions(7, GPIO_INPUT, GPIO_ASYNC);

    // GPIO31 (LED)를 출력으로 설정 (Set GPIO31 (LED) as output)
    GPIO_SetupPinMux(31, GPIO_MUX_CPU1, 0);
    GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSHPULL);
    EDIS;
}

// eCAP1 (Master) 초기화 함수 (eCAP1 Master Initialization Function)
void initECapMaster(void) {
    EALLOW;
    CpuSysRegs.PCLKCR3.bit.ECAP1 = 1; // eCAP1 모듈 클럭 활성화 (Enable eCAP1 module clock)
    EDIS;

    ECap1Regs.ECEINT.all = 0;        // 모든 인터럽트 비활성화 (Disable all interrupts)
    ECap1Regs.ECCLR.all = 0xFFFF;    // 모든 인터럽트 플래그 클리어 (Clear all interrupt flags)

    // 캡처 모드 설정 (Capture Mode Settings)
    ECap1Regs.ECCTL1.bit.CAP1POL = 0; // 상승 에지 캡처 (Capture on rising edge)
    ECap1Regs.ECCTL1.bit.CAP2POL = 1; // 하강 에지 캡처 (Capture on falling edge)
    ECap1Regs.ECCTL1.bit.CTRRST1 = 1; // 첫 번째 이벤트에서 카운터 리셋 (Reset counter on 1st event)
    ECap1Regs.ECCTL1.bit.CTRRST2 = 0; // 두 번째 이벤트에서 카운터 유지 (Keep counter on 2nd event)
    ECap1Regs.ECCTL1.bit.CAPLDEN = 1; // 캡처 로드 활성화 (Enable capture load)
    ECap1Regs.ECCTL1.bit.PRESCALE = 0; // 프리스케일 1/1 (Prescale 1/1)
    
    ECap1Regs.ECCTL2.bit.CONT_ONESHT = 0; // 연속 모드 (Continuous mode)
    ECap1Regs.ECCTL2.bit.STOP_WRAP = 1; // 2개 이벤트 캡처 (Capture 2 events)
    ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1; // 타임-베이스 카운터 시작 (Start time-base counter)
    
    // 동기화 출력 설정 (Synchronization Output Configuration)
    // 0: 동기화 출력 비활성화, 1: 이벤트1, 2: 이벤트2, 3: 이벤트3, 4: 이벤트4
    ECap1Regs.ECCTL2.bit.SYNCO_SEL = 0; // 동기화 출력 비활성화 (Disable sync output)
}

// eCAP2 (Slave) 초기화 함수 (eCAP2 Slave Initialization Function)
void initECapSlave(void) {
    EALLOW;
    CpuSysRegs.PCLKCR3.bit.ECAP2 = 1; // eCAP2 모듈 클럭 활성화 (Enable eCAP2 module clock)
    EDIS;

    ECap2Regs.ECEINT.all = 0;        // 모든 인터럽트 비활성화 (Disable all interrupts)
    ECap2Regs.ECCLR.all = 0xFFFF;    // 모든 인터럽트 플래그 클리어 (Clear all interrupt flags)

    // 캡처 모드 설정 (Capture Mode Settings)
    ECap2Regs.ECCTL1.bit.CAP1POL = 0; // 상승 에지 캡처 (Capture on rising edge)
    ECap2Regs.ECCTL1.bit.CAP2POL = 1; // 하강 에지 캡처 (Capture on falling edge)
    ECap2Regs.ECCTL1.bit.CTRRST1 = 1; // 첫 번째 이벤트에서 카운터 리셋 (Reset counter on 1st event)
    ECap2Regs.ECCTL1.bit.CTRRST2 = 0; // 두 번째 이벤트에서 카운터 유지 (Keep counter on 2nd event)
    ECap2Regs.ECCTL1.bit.CAPLDEN = 1; // 캡처 로드 활성화 (Enable capture load)
    ECap2Regs.ECCTL1.bit.PRESCALE = 0; // 프리스케일 1/1 (Prescale 1/1)
    
    ECap2Regs.ECCTL2.bit.CONT_ONESHT = 0; // 연속 모드 (Continuous mode)
    ECap2Regs.ECCTL2.bit.STOP_WRAP = 1; // 2개 이벤트 캡처 (Capture 2 events)

    // 동기화 입력 설정 (Synchronization Input Configuration)
    ECap2Regs.ECCTL2.bit.SYNCI_EN = 1; // 동기화 입력 활성화 (Enable sync input)
    ECap2Regs.ECCTL2.bit.TSCTRSTOP = 0; // 동기화 입력 시 카운터 시작 (Start counter on sync input)
}

설명:

  • 기능: eCAP1과 eCAP2를 동기화하여 두 입력 신호의 펄스 폭을 동시에 측정.
  • 설정: eCAP1(Master)에서 동기화 신호 출력, eCAP2(Slave)에서 동기화 입력 활성화, 하강/상승 에지 캡처, 연속 모드.
  • GPIO: GPIO5(eCAP1 입력), GPIO7(eCAP2 입력), GPIO31(LED).
  • 출력: pulse_width1, pulse_width2에 각각 펄스 폭 저장, 정상 동작 시 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 하드웨어 준비

  • 캡처 입력: GPIO5(eCAP1 입력), GPIO7(eCAP2 입력 또는 QEP B상)에 펄스 신호 연결 (예: PWM 또는 엔코더 신호).
  • APWM 출력: GPIO5에 오실로스코프 연결.
  • LED: GPIO31에 LED 연결 (정상 동작 확인용).

6.4 디버깅

  • CCS의 Expressions 창에서 ECapxRegs.TSCTR, ECapxRegs.CAPx 확인.
  • ECapxRegs.ECFLG로 이벤트 플래그 점검.
  • 레지스터(ECapxRegs.ECCTL1, ECapxRegs.ECCTL2) 모니터링.

7. 추가 팁

  • 캘리브레이션: Device_cal() 호출로 클럭 보정.
  • 노이즈 감소: 입력 신호에 저역통과 필터 사용.
  • C2000Ware 참고: C:\ti\c2000\C2000Ware_x_xx_xx_xx\device_support\f2837xd\examples\cpu1\ecap.
  • 문제 해결:
    • 캡처 실패: ECCTL1.bit.CAPxPOL, ECCTL2.bit.STOP_WRAP 확인.
    • 인터럽트 실패: ECEINT, PIEIER4 설정 확인.
    • APWM 출력 없음: ECCTL2.bit.CAP_APWM, CAP1 설정 확인.
  • TI 리소스: TI E2E 포럼, C2000Ware 예제.

8. 결론

이 문서는 TMS320F28377D eCAP 모듈의 설정 방법과 Bitfield 구조를 활용한 예제 코드를 제공하여, 펄스 폭 측정, 주기 측정, APWM 신호 생성, 쿼드러처 엔코더 처리, 다중 모듈 동기화 등 다양한 애플리케이션에 적용 가능하도록 구성했습니다. 초보자와 숙련된 개발자 모두에게 유용한 참고 자료가 될 것입니다.

키워드: TMS320F28377D, eCAP, C2000, 캡처, APWM, 마이크로컨트롤러, Code Composer Studio, 펄스 폭, 주기 측정, 쿼드러처 엔코더, 동기화, 인터럽트, 타임스탬프