본문 바로가기
MCU/C2000

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

by linuxgo 2025. 8. 6.

TI의 TMS320F28377D는 C2000 Delfino 시리즈의 강력한 32비트 마이크로컨트롤러로, 모터 제어, 전력 변환, 센서 데이터 수집과 같은 실시간 제어 애플리케이션에 최적화되어 있습니다. 특히, ADC(아날로그-디지털 컨버터) 모듈은 고속, 고정밀 아날로그 신호 변환을 제공하여 다양한 산업 응용 분야에서 핵심적인 역할을 합니다. 이 글에서는 TMS320F28377D ADC 모듈의 상세한 설정 방법, Bitfield 구조를 활용한 레지스터 설정, 그리고 실용적인 예제 코드를 제공하여 초보자와 숙련된 개발자 모두가 쉽게 활용할 수 있도록 돕겠습니다.

1. TMS320F28377D ADC 모듈 개요

TMS320F28377D는 4개의 독립적인 ADC 모듈(ADCA, ADCB, ADCC, ADCD)을 포함하며, 각 모듈은 고속 및 고정밀 변환을 지원합니다. 아래는 주요 사양입니다:

  • 해상도:
    • 단일 입력(Single-Ended): 12비트 (0~4095)
    • 차동 입력(Differential): 16비트 (0~65535)
  • 샘플링 속도: 최대 12.5 MSPS (12비트 모드)
  • 채널: 모듈당 8개 단일 입력 또는 4개 차동 입력 쌍, 총 24개 아날로그 입력 핀(ADCIN)
  • 입력 범위:
    • 단일 입력: 0V ~ 3.3V (VREFHI 기준)
    • 차동 입력: ±1.65V (VREFHI = 3.3V, 공통 모드 전압 1.65V)
  • 참조 전압: 내부(2.5V/3.0V) 또는 외부(VREFHI/VREFLO) 선택 가능
  • 샘플 앤 홀드(S+H): 각 채널별 독립 S+H 회로로 동시 샘플링 지원

주요 기능:

  • 시퀀서: 두 개의 8-state 시퀀서(SEQ1, SEQ2) 또는 16-state 캐스케이드 모드
  • 트리거: 소프트웨어, ePWM, 타이머, 외부 GPIO 등
  • PPB(Post-Processing Block): 오프셋 보정, 스케일링, 비교 기능
  • DMA: CPU 부하 없이 고속 데이터 전송
  • 인터럽트: ADCINT1/2로 변환 완료 시 알림

2. ADC Bitfield 설정 상세

TMS320F28377D의 ADC 레지스터는 Bitfield 구조로 정의되어 있어, F2837xD_adc.h 헤더 파일을 통해 접근합니다. Bitfield는 레지스터의 개별 비트를 명확히 설정하고 가독성을 높이는 장점이 있습니다. 주요 레지스터와 Bitfield는 다음과 같습니다:

2.1 ADCCTL1 (ADC 제어 레지스터 1)

  • bit.INTPULSEPOS: 인터럽트 펄스 타이밍 (0: 변환 시작 시, 1: 변환 완료 시)
  • bit.ADCENABLE: ADC 모듈 활성화 (1: 활성화)
  • bit.ADCPWDN: ADC 전원 활성화 (1: 켜기)
  • bit.ADCBSY: ADC 상태 (1: 변환 중)

2.2 ADCCTL2 (ADC 제어 레지스터 2)

  • bit.PRESCALE: ADC 클럭 분주비 (예: 6 = SYSCLK/6)
  • bit.RESOLUTION: 해상도 (0: 12비트, 1: 16비트)
  • bit.SIGNALMODE: 입력 모드 (0: 단일 입력, 1: 차동 입력)

2.3 ADCSOCxCTL (SOC 제어 레지스터)

  • bit.CHSEL: 변환 채널 (0~15, 단일 입력은 채널 번호, 차동 입력은 쌍 번호)
  • bit.ACQPS: 샘플링 창 크기 (6~511 SYSCLK 사이클)
  • bit.TRIGSEL: 트리거 소스 (0: 소프트웨어, 5: ePWM1 SOCA 등)

2.4 ADCINTSEL1N2 (인터럽트 선택)

  • bit.INT1SEL: ADCINT1 트리거 SOC (0~15)
  • bit.INT1E: ADCINT1 활성화 (1: 활성화)
  • bit.INT1CONT: 연속 인터럽트 (1: 연속)

2.5 ADCPPBxCONFIG 및 ADCPPBxOFFCAL

  • bit.CONFIG: PPB와 연결할 SOC (0~15)
  • bit.OFFCAL: 오프셋 보정 값 (-1024~+1023)

Bitfield 사용 이점:

  • 명확한 비트 단위 설정으로 실수 감소
  • 코드 가독성 및 유지보수성 향상
  • F2837xD_adc.h에서 제공하는 구조체로 직관적 접근

3. ADC 설정 고려사항

  • 클럭 설정: 시스템 클럭(200MHz)을 분주하여 ADC 클럭 설정 (예: PRESCALE = 6 → 33.33MHz)
  • 입력 회로: 저항(Rs ≤ 50Ω), 커패시터(Cs ≈ 300pF)로 신호 컨디셔닝
  • VREFHI/VREFLO: 3.3V 이하, 안정적인 전원 공급
  • 샘플링 시간(ACQPS): 입력 회로 RC 시정수에 맞게 설정 (예: 15~25 SYSCLK)
  • 캘리브레이션: 부팅 시 Device_cal() 호출로 오프셋 보정

4. 실용적인 ADC 예제 코드 (Bitfield 구조)

아래는 TMS320F28377D ADC를 Bitfield 구조로 설정한 4개의 실용적인 예제 코드입니다. 각 예제는 독립적인 파일로 구성되며, Code Composer Studio(CCS)와 C2000Ware 환경에서 실행 가능합니다.

TMS320F28377D ADC

4.1 예제 1: 단일 입력 소프트웨어 트리거

ADCINA0에서 12비트 단일 입력 변환을 소프트웨어로 트리거합니다.

// File: adc_single_software.c
// Description: TMS320F28377D ADC 단일 입력(ADCINA0) 소프트웨어 트리거 예제 (Bitfield 구조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D
// C2000Ware Version: 6.0.0.0

#include "F28x_Project.h"

// ADC 인터럽트 핸들러 선언
interrupt void adc_isr(void);

// ADC 결과 저장용 전역 변수
volatile Uint16 adcResult = 0;

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    Device_cal(); // ADC 캘리브레이션 호출 (오프셋 보정)

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

    // ADC 인터럽트 벡터 등록
    EALLOW;
    PieVectTable.ADCA1_INT = &adc_isr; // ADCINT1 인터럽트 핸들러 등록
    EDIS;

    // ADC 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR13.bit.ADC_A = 1; // ADCA 모듈 클럭 활성화
    EDIS;

    // ADC 전원 설정 및 안정화 대기
    EALLOW;
    AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; // ADC 코어 전원 켜기
    EDIS;
    DELAY_US(1000); // 1ms (1000μs) 대기

    // ADC 모듈 설정 (Bitfield 사용)
    EALLOW;
    AdcaRegs.ADCCTL2.bit.PRESCALE = 6; // ADC 클럭 = SYSCLK(200MHz) / 6 = 33.33MHz
    AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); // 12비트, 단일 입력 모드
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 변환 완료 시 인터럽트 펄스 발생
    EDIS;

    // SOC0 설정: ADCINA0 채널
    EALLOW;
    AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; // ADCINA0 채널 선택
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = 15; // 샘플링 창 = 15 SYSCLK 사이클 (75ns at 200MHz)
    AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 0; // 소프트웨어 트리거
    EDIS;

    // ADC 인터럽트 설정
    EALLOW;
    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0; // SOC0 완료 시 ADCINT1 발생
    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; // ADCINT1 활성화
    AdcaRegs.ADCINTSEL1N2.bit.INT1CONT = 1; // 연속 인터럽트 모드 활성화
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // ADCINT1 플래그 초기화
    EDIS;

    // 인터럽트 활성화
    EALLOW;
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // PIE 그룹 1, ADCINT1 활성화
    IER |= M_INT1; // CPU 인터럽트 1 활성화
    EINT; // 글로벌 인터럽트 활성화
    EDIS;

    // 무한 루프: 소프트웨어 트리거로 반복 변환
    for(;;) {
        AdcaRegs.ADCSOCFRC1.bit.SOC0 = 1; // SOC0 강제 시작
        DELAY_US(1000); // 변환 간 간격 (1ms 대기)
    }
}

// ADC 인터럽트 서비스 루틴
interrupt void adc_isr(void) {
    adcResult = AdcaResultRegs.ADCRESULT0; // ADC 결과 읽기 (0~4095)
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // 인터럽트 플래그 초기화
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // PIE 그룹 1 ACK
}

설명: 이 코드는 ADCINA0에서 단일 입력(12비트)을 소프트웨어로 트리거하여 변환합니다. 초보자가 ADC의 기본 동작을 이해하는 데 적합합니다.

4.2 예제 2: 차동 입력 ePWM 트리거

ADCINA0/ADCINA1 차동 쌍에서 16비트 변환을 ePWM1으로 트리거합니다.

// File: adc_differential_epwm.c
// Description: TMS320F28377D ADC 차동 입력(ADCINA0/ADCINA1) ePWM 트리거 예제 (Bitfield 구조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D
// C2000Ware Version: 6.0.0.0

#include "F28x_Project.h"

// ADC 인터럽트 핸들러 선언
interrupt void adc_isr(void);

// ADC 결과 저장용 전역 변수
volatile Uint16 adcResult = 0;

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    InitGpio();
    Device_cal(); // ADC 캘리브레이션 호출 (오프셋 보정)

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

    // ADC 인터럽트 벡터 등록
    EALLOW;
    PieVectTable.ADCA1_INT = &adc_isr; // ADCINT1 인터럽트 핸들러 등록
    EDIS;

    // ADC 및 ePWM 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR13.bit.ADC_A = 1; // ADCA 모듈 클럭 활성화
    CpuSysRegs.PCLKCR2.bit.EPWM1 = 1; // ePWM1 모듈 클럭 활성화
    EDIS;

    // ePWM1 설정: ADC 트리거용
    EALLOW;
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // 카운트 업 모드
    EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; // 주기 레지스터 섀도우 모드
    EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // 동기화 비활성화
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 1; // TBCLK = SYSCLK / 1
    EPwm1Regs.TBCTL.bit.CLKDIV = 0; // TBCLK = SYSCLK (200MHz)
    EPwm1Regs.TBPRD = 1000; // PWM 주기 = 1000 TBCLK = 5μs (200MHz)
    EPwm1Regs.ETSEL.bit.SOCAEN = 1; // SOCA 트리거 활성화
    EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO; // 주기 매칭 시 트리거
    EPwm1Regs.ETPS.bit.SOCAPRD = 1; // 첫 번째 이벤트에서 트리거
    EPwm1Regs.TBCTL.bit.FREE_SOFT = 2; // Free run 모드
    EDIS;

    // ADC 전원 설정 및 안정화 대기
    EALLOW;
    AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; // ADC 코어 전원 켜기
    EDIS;
    DELAY_US(1000); // 1ms (1000μs) 대기

    // ADC 모듈 설정 (Bitfield 사용)
    EALLOW;
    AdcaRegs.ADCCTL2.bit.PRESCALE = 6; // ADC 클럭 = SYSCLK(200MHz) / 6 = 33.33MHz
    AdcSetMode(ADC_ADCA, ADC_RESOLUTION_16BIT, ADC_SIGNALMODE_DIFFERENTIAL); // 16비트, 차동 입력 모드
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 변환 완료 시 인터럽트 펄스 발생
    EDIS;

    // SOC0 설정: 차동 쌍 ADCINA0/ADCINA1
    EALLOW;
    AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; // 차동 쌍 A0/A1 선택
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = 25; // 샘플링 창 = 25 SYSCLK 사이클 (125ns at 200MHz)
    AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // ePWM1 SOCA 트리거
    EDIS;

    // ADC 인터럽트 설정
    EALLOW;
    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0; // SOC0 완료 시 ADCINT1 발생
    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; // ADCINT1 활성화
    AdcaRegs.ADCINTSEL1N2.bit.INT1CONT = 1; // 연속 인터럽트 모드 활성화
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // ADCINT1 플래그 초기화
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // PIE 그룹 1, ADCINT1 활성화
    IER |= M_INT1; // CPU 인터럽트 1 활성화
    EDIS;

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

    // 무한 루프: ePWM 트리거에 의해 ADC 변환 자동 수행
    for(;;) {
        // ISR에서 결과 처리, 필요 시 추가 로직 삽입
    }
}

// ADC 인터럽트 서비스 루틴
interrupt void adc_isr(void) {
    adcResult = AdcaResultRegs.ADCRESULT0; // 차동 입력 결과 읽기 (0~65535)
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // 인터럽트 플래그 초기화
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // PIE 그룹 1 ACK
}

설명: 이 코드는 차동 입력(16비트)을 ePWM1 트리거로 변환하며, 모터 제어와 같은 주기적 변환 애플리케이션에 적합합니다.

4.3 예제 3: 다중 채널 시퀀싱 및 PPB

ADCINA0과 ADCINA1에서 순차 변환하고, PPB로 오프셋 보정을 수행합니다.

// File: adc_multi_ppb.c
// Description: TMS320F28377D ADC 다중 채널(ADCINA0, ADCINA1) 및 PPB 예제 (Bitfield 구조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D
// C2000Ware Version: 6.0.0.0

#include "F28x_Project.h"

// ADC 인터럽트 핸들러 선언
interrupt void adc_isr(void);

// ADC 결과 저장용 전역 변수
volatile Uint16 adcResult0 = 0; // SOC0 결과 (ADCINA0)
volatile Uint16 adcResult1 = 0; // SOC1 결과 (ADCINA1)
volatile Uint16 ppbResult = 0; // PPB1 보정된 결과

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    InitGpio(); // GPIO 초기화
    Device_cal(); // ADC 캘리브레이션 호출 (오프셋 보정)

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

    // ADC 인터럽트 벡터 등록
    EALLOW;
    PieVectTable.ADCA1_INT = &adc_isr; // ADCINT1 인터럽트 핸들러 등록
    EDIS;

    // ADC 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR13.bit.ADC_A = 1; // ADCA 모듈 클럭 활성화
    EDIS;

    // ADC 전원 설정 및 안정화 대기
    EALLOW;
    AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; // ADC 코어 전원 켜기
    EDIS;
    DELAY_US(1000); // 1ms (1000μs) 대기

    // ADC 모듈 설정 (Bitfield 사용)
    EALLOW;
    AdcaRegs.ADCCTL2.bit.PRESCALE = 6; // ADC 클럭 = SYSCLK(200MHz) / 6 = 33.33MHz
    AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); // 12비트, 단일 입력 모드
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 변환 완료 시 인터럽트 펄스 발생
    EDIS;

    // SOC0, SOC1 설정: ADCINA0, ADCINA1
    EALLOW;
    AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; // SOC0: ADCINA0
    AdcaRegs.ADCSOC1CTL.bit.CHSEL = 1; // SOC1: ADCINA1
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = 15; // 샘플링 창 = 15 SYSCLK 사이클 (75ns at 200MHz)
    AdcaRegs.ADCSOC1CTL.bit.ACQPS = 15; // 샴플링 창 = 15 SYSCLK 사이클
    AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 0; // 소프트웨어 트리거
    AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 0; // 소프트웨어 트리거
    EDIS;

    // PPB 설정: SOC0에 오프셋 보정
    EALLOW;
    AdcaRegs.ADCPPB1CONFIG.bit.CONFIG = 0; // PPB1을 SOC0에 연결
    AdcaRegs.ADCPPB1OFFCAL.bit.OFFCAL = 10; // 오프셋 보정 값 = 10
    EDIS;

    // ADC 인터럽트 설정
    EALLOW;
    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 1; // SOC1 완료 시 ADCINT1 발생
    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; // ADCINT1 활성화
    AdcaRegs.ADCINTSEL1N2.bit.INT1CONT = 1; // 연속 인터럽트 모드 활성화
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // ADCINT1 플래그 초기화
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // PIE 그룹 1, ADCINT1 활성화
    IER |= M_INT1; // CPU 인터럽트 1 활성화
    EDIS;

    // 글로벌 인터럽트 및 실시간 디버깅 활성화
    EINT; // 글로벌 인터럽트 활성화
    ERTM; // 실시간 디버깅 모드 활성화

    // 무한 루프: 소프트웨어 트리거로 반복 변환
    for(;;) {
        EALLOW;
        AdcaRegs.ADCSOCFRC1.bit.SOC0 = 1; // SOC0 강제 시작
        AdcaRegs.ADCSOCFRC1.bit.SOC1 = 1; // SOC1 강제 시작
        EDIS;
        DELAY_US(1000); // 변환 간 간격 (1ms 대기)
    }
}

// ADC 인터럽트 서비스 루틴
interrupt void adc_isr(void) {
    adcResult0 = AdcaResultRegs.ADCRESULT0; // SOC0 결과 (ADCINA0)
    adcResult1 = AdcaResultRegs.ADCRESULT1; // SOC1 결과 (ADCINA1)
    ppbResult = AdcaResultRegs.ADCPPB1RESULT.all; // PPB1 보정된 결과 (16비트)
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // 인터럽트 플래그 초기화
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // PIE 그룹 1 ACK
}

설명: 이 코드는 다중 채널(ADCINA0, ADCINA1)을 순차적으로 변환하고, PPB로 오프셋 보정을 수행합니다. 다중 센서 데이터 처리에 유용합니다.

4.4 예제 4: DMA를 사용한 연속 데이터 수집

ADC 결과를 DMA를 통해 메모리 버퍼로 전송하여 연속 데이터 수집을 수행합니다.

// File: adc_dma_continuous.c
// Description: TMS320F28377D ADC DMA를 사용한 연속 데이터 수집 예제 (Bitfield 구조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D
// C2000Ware Version: 6.0.0.0

#include "F28x_Project.h"

// DMA 인터럽트 핸들러 선언
interrupt void dma_isr(void);

// ADC 결과 저장용 전역 변수
volatile Uint16 adcData[16]; // ADC 결과를 저장할 메모리 버퍼
volatile Uint16 dmaComplete = 0; // DMA 전송 완료 플래그

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    InitGpio(); // GPIO 초기화
    InitEPwm1Gpio(); // ePWM1 GPIO 초기화 (GPIO0/1을 ePWM1A/1B로 설정)
    Device_cal(); // ADC 캘리브레이션 호출 (오프셋 보정)

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

    // DMA 인터럽트 벡터 등록
    EALLOW;
    PieVectTable.DMA_CH1_INT = &dma_isr; // DMA CH1 인터럽트 핸들러 등록
    EDIS;

    // ADC 및 DMA 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR13.bit.ADC_A = 1; // ADCA 모듈 클럭 활성화
    CpuSysRegs.PCLKCR0.bit.DMA = 1; // DMA 모듈 클럭 활성화
    EDIS;

    // ADC 전원 설정 및 안정화 대기
    EALLOW;
    AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; // ADC 코어 전원 켜기
    EDIS;
    DELAY_US(1000); // 1ms (1000μs) 대기

    // ADC 모듈 설정 (Bitfield 사용)
    EALLOW;
    AdcaRegs.ADCCTL2.bit.PRESCALE = 6; // ADC 클럭 = SYSCLK(200MHz) / 6 = 33.33MHz
    AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); // 12비트, 단일 입력 모드
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 변환 완료 시 인터럽트 펄스 발생
    EDIS;

    // SOC0 설정: ADCINA0 채널
    EALLOW;
    AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; // ADCINA0 채널 선택
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = 15; // 샘플링 창 = 15 SYSCLK 사이클 (75ns at 200MHz)
    AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // ePWM1 SOCA 트리거
    EDIS;

    // ADC 인터럽트 설정
    EALLOW;
    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0; // SOC0 완료 시 ADCINT1 발생
    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; // ADCINT1 활성화
    AdcaRegs.ADCINTSEL1N2.bit.INT1CONT = 1; // 연속 인터럽트 모드 활성화
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // ADCINT1 플래그 초기화
    EDIS;

    // DMA 설정
    DMAInitialize(); // DMA 초기화
    EALLOW;
    DMACH1AddrConfig(&adcData[0], &AdcaResultRegs.ADCRESULT0); // 소스(ADC 결과) 및 대상(버퍼) 설정
    DMACH1BurstConfig(0, 1, 1); // 버스트 크기 = 1, 소스/대상 스텝 = 1
    DMACH1TransferConfig(15, 1, 1); // 16개 샘플 전송, 소스/대상 증분
    DMACH1ModeConfig(16, 1, 0, 1, 0, 0, 0, 0, 1, 1); // ADCINT1 트리거, 연속 모드, 16비트, 인터럽트 활성화
    IER |= M_INT7; // CPU 인터럽트 7 활성화
    EDIS;
    StartDMACH1(); // DMA 시작

    // ePWM1 설정: ADC 트리거용
    EALLOW;
    CpuSysRegs.PCLKCR2.bit.EPWM1 = 1; // ePWM1 클럭 활성화
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // 카운트 업 모드
    EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; // 주기 레지스터 섀도우 모드
    EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // 동기화 비활성화
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 1; // TBCLK = SYSCLK / 1
    EPwm1Regs.TBCTL.bit.CLKDIV = 0; // TBCLK = SYSCLK (200MHz)
    EPwm1Regs.TBPRD = 1000; // PWM 주기 = 1000 TBCLK = 5μs (200MHz)
    EPwm1Regs.ETSEL.bit.SOCAEN = 1; // SOCA 트리거 활성화
    EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO; // 주기 매칭 시 트리거
    EPwm1Regs.ETPS.bit.SOCAPRD = 1; // 첫 번째 이벤트에서 트리거
    EPwm1Regs.TBCTL.bit.FREE_SOFT = 2; // Free run 모드
    EDIS;

    // 글로벌 인터럽트 및 실시간 디버깅 활성화
    EINT; // 글로벌 인터럽트 활성화
    ERTM; // 실시간 디버깅 모드 활성화

    // 무한 루프: DMA가 데이터를 adcData 배열에 저장
    for(;;) {
        // DMA 완료 플래그 확인, 필요 시 추가 로직 삽입
    }
}

// DMA 인터럽트 서비스 루틴
interrupt void dma_isr(void) {
    dmaComplete = 1; // DMA 전송 완료 플래그 설정
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP7; // PIE 그룹 7 ACK
}

설명: 이 코드는 ADC 결과를 DMA를 통해 메모리 버퍼로 전송하여 고속 데이터 수집을 구현합니다. 실시간 데이터 로깅에 적합합니다.

5. 사용 방법

5.1 환경 설정

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

5.2 코드 실행

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

5.3 하드웨어 준비

  • ADC 입력: ADCINA0, ADCINA1에 0~3.3V 아날로그 신호 연결
  • 차동 입력: 공통 모드 전압 1.65V 유지 (예: THS4531 오피앰프)
  • VREFHI: 3.3V 안정적인 전원 연결

5.4 디버깅

  • CCS의 Expressions 창에서 AdcaResultRegs, adcData 확인
  • AdcaRegs.ADCINTFLG로 변환 상태 점검
  • 레지스터(AdcaRegs.ADCCTL1, AdcaRegs.ADCSOC0CTL) 모니터링

6. 추가 팁

  • 캘리브레이션: 부팅 시 Device_cal() 호출로 오프셋 보정
  • 노이즈 감소: 아날로그/디지털 접지 분리, VREFHI에 저노이즈 레귤레이터 사용
  • C2000Ware 참고: C:\ti\c2000\C2000Ware_x_xx_xx_xx\device_support\f2837xd\examples\cpu1\adc
  • 문제 해결:
    • 변환 결과 없음: AdcaRegs.ADCSOCxCTL.bit.TRIGSEL, ACQPS 확인
    • DMA 오류: DMACH1AddrConfig, DMACH1ModeConfig 설정 점검
  • TI 리소스: TI E2E 포럼, C2000Ware 예제

7. 결론

이 문서는 TMS320F28377D ADC 모듈의 설정 방법과 Bitfield 구조를 활용한 예제 코드를 제공하여, 초보자부터 숙련된 개발자까지 쉽게 활용할 수 있도록 구성했습니다. 단일 입력, 차동 입력, 다중 채널 시퀀싱, DMA를 사용한 예제를 통해 다양한 애플리케이션에 적용 가능합니다.