본문 바로가기
MCU/C2000

[TMS320F28377D] 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 환경에서 실행 가능합니다.

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

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

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

#include "F28x_Project.h"

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

    // ADC 클럭 활성화
    EALLOW; // 보호된 레지스터 접근 허용
    CpuSysRegs.PCLKCR13.bit.ADC_A = 1; // ADCA 모듈 클럭 활성화
    EDIS; // 보호된 레지스터 접근 비활성화

    // ADC 모듈 설정 (Bitfield 사용)
    AdcaRegs.ADCCTL2.bit.PRESCALE = 6; // ADC 클럭 = SYSCLK(200MHz) / 6
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 변환 완료 시 인터럽트 펄스 발생
    AdcaRegs.ADCCTL2.bit.RESOLUTION = 0; // 12비트 해상도
    AdcaRegs.ADCCTL2.bit.SIGNALMODE = 0; // 단일 입력 모드
    AdcaRegs.ADCCTL1.bit.ADCENABLE = 1; // ADC 모듈 활성화
    AdcaRegs.ADCCTL1.bit.ADCPWDN = 1; // ADC 전원 활성화

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

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

    // ADC 변환 시작
    AdcaRegs.ADCSOCFRC1.bit.SOC0 = 1; // SOC0 강제 시작

    // 변환 완료 대기 및 결과 읽기
    while (AdcaRegs.ADCINTFLG.bit.ADCINT1 == 0); // 인터럽트 플래그 대기
    Uint16 result = AdcaResultRegs.ADCRESULT0; // ADC 결과 읽기 (0~4095)

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

설명: 이 코드는 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

#include "F28x_Project.h"

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

    // ADC 및 ePWM 클럭 활성화
    EALLOW; // 보호된 레지스터 접근 허용
    CpuSysRegs.PCLKCR13.bit.ADC_A = 1; // ADCA 모듈 클럭 활성화
    CpuSysRegs.PCLKCR2.bit.EPWM1 = 1; // ePWM1 모듈 클럭 활성화
    EDIS; // 보호된 레지스터 접근 비활성화

    // ePWM1 설정: ADC 트리거용
    EPwm1Regs.TBPRD = 1000; // PWM 주기 = 1000 TBCLK
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // 카운트 업 모드
    EPwm1Regs.ETSEL.bit.SOCAEN = 1; // SOCA 트리거 활성화
    EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO; // 주기 매칭 시 트리거
    EPwm1Regs.ETPS.bit.SOCAPRD = 1; // 첫 번째 이벤트에서 트리거

    // ADC 모듈 설정: 차동 입력 (Bitfield 사용)
    AdcaRegs.ADCCTL2.bit.PRESCALE = 6; // ADC 클럭 = SYSCLK / 6
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 변환 완료 시 인터럽트 펄스
    AdcaRegs.ADCCTL2.bit.RESOLUTION = 1; // 16비트 해상도
    AdcaRegs.ADCCTL2.bit.SIGNALMODE = 1; // 차동 입력 모드
    AdcaRegs.ADCCTL1.bit.ADCENABLE = 1; // ADC 모듈 활성화
    AdcaRegs.ADCCTL1.bit.ADCPWDN = 1; // ADC 전원 활성화

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

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

    // ePWM 시작
    EPwm1Regs.TBCTL.bit.FREE_SOFT = 2; // Free run 모드

    // 변환 완료 대기 및 결과 읽기
    while (AdcaRegs.ADCINTFLG.bit.ADCINT1 == 0); // 인터럽트 플래그 대기
    Uint16 result = AdcaResultRegs.ADCRESULT0; // 차동 입력 결과 읽기 (0~65535)

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

설명: 이 코드는 차동 입력(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

#include "F28x_Project.h"

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

    // ADC 클럭 활성화
    EALLOW; // 보호된 레지스터 접근 허용
    CpuSysRegs.PCLKCR13.bit.ADC_A = 1; // ADCA 모듈 클럭 활성화
    EDIS; // 보호된 레지스터 접근 비활성화

    // ADC 모듈 설정 (Bitfield 사용)
    AdcaRegs.ADCCTL2.bit.PRESCALE = 6; // ADC 클럭 = SYSCLK / 6
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 변환 완료 시 인터럽트 펄스
    AdcaRegs.ADCCTL2.bit.RESOLUTION = 0; // 12비트 해상도
    AdcaRegs.ADCCTL2.bit.SIGNALMODE = 0; // 단일 입력 모드
    AdcaRegs.ADCCTL1.bit.ADCENABLE = 1; // ADC 모듈 활성화
    AdcaRegs.ADCCTL1.bit.ADCPWDN = 1; // ADC 전원 활성화

    // 시퀀서 설정: ADCINA0, ADCINA1 순차 변환
    AdcaRegs.ADCCHSELSEQ1.bit.CONV00 = 0; // SOC0: ADCINA0
    AdcaRegs.ADCCHSELSEQ1.bit.CONV01 = 1; // SOC1: ADCINA1
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = 15; // 샘플링 창 = 15 SYSCLK 사이클
    AdcaRegs.ADCSOC1CTL.bit.ACQPS = 15; // 샘플링 창 = 15 SYSCLK 사이클
    AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 0; // 소프트웨어 트리거
    AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 0; // 소프트웨어 트리거

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

    // ADC 인터럽트 설정
    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 1; // SOC1 완료 시 ADCINT1 발생
    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; // ADCINT1 활성화
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // ADCINT1 플래그 초기화

    // ADC 변환 시작
    AdcaRegs.ADCSOCFRC1.bit.SOC0 = 1; // SOC0 강제 시작
    AdcaRegs.ADCSOCFRC1.bit.SOC1 = 1; // SOC1 강제 시작

    // 변환 완료 대기 및 결과 읽기
    while (AdcaRegs.ADCINTFLG.bit.ADCINT1 == 0); // 인터럽트 플래그 대기
    Uint16 result0 = AdcaResultRegs.ADCRESULT0; // SOC0 결과 (ADCINA0)
    Uint16 result1 = AdcaResultRegs.ADCRESULT1; // SOC1 결과 (ADCINA1)
    Uint16 ppb_result = AdcaResultRegs.ADCPPB1RESULT; // PPB 보정된 결과

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

설명: 이 코드는 다중 채널(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

#include "F28x_Project.h"

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

    // ADC 및 DMA 클럭 활성화
    EALLOW; // 보호된 레지스터 접근 허용
    CpuSysRegs.PCLKCR13.bit.ADC_A = 1; // ADCA 모듈 클럭 활성화
    CpuSysRegs.PCLKCR0.bit.DMA = 1; // DMA 모듈 클럭 활성화
    EDIS; // 보호된 레지스터 접근 비활성화

    // ADC 모듈 설정 (Bitfield 사용)
    AdcaRegs.ADCCTL2.bit.PRESCALE = 6; // ADC 클럭 = SYSCLK / 6
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 변환 완료 시 인터럽트 펄스
    AdcaRegs.ADCCTL2.bit.RESOLUTION = 0; // 12비트 해상도
    AdcaRegs.ADCCTL2.bit.SIGNALMODE = 0; // 단일 입력 모드
    AdcaRegs.ADCCTL1.bit.ADCENABLE = 1; // ADC 모듈 활성화
    AdcaRegs.ADCCTL1.bit.ADCPWDN = 1; // ADC 전원 활성화

    // SOC0 설정: ADCINA0 채널
    AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; // ADCINA0 채널 선택
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = 15; // 샘플링 창 = 15 SYSCLK 사이클
    AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // ePWM1 SOCA 트리거

    // DMA 설정
    Uint16 adcData[16]; // ADC 결과를 저장할 메모리 버퍼
    DMAInitialize(); // DMA 초기화
    DMACH1AddrConfig(&adcData[0], &AdcaResultRegs.ADCRESULT0); // 소스(ADC 결과) 및 대상(버퍼) 설정
    DMACH1BurstConfig(0, 1, 1); // 버스트 크기 = 1
    DMACH1TransferConfig(15, 1, 1); // 16개 샘플 전송
    DMACH1ModeConfig(ADCINT1, PERINT_ENABLE, 0, 0, 0, 0); // ADCINT1로 트리거
    StartDMACH1(); // DMA 시작

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

    // ePWM1 설정: ADC 트리거용
    EALLOW;
    CpuSysRegs.PCLKCR2.bit.EPWM1 = 1; // ePWM1 클럭 활성화
    EPwm1Regs.TBPRD = 1000; // PWM 주기 = 1000 TBCLK
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // 카운트 업 모드
    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;

    for(;;); // 무한 루프 (DMA가 데이터를 adcData 배열에 저장)
}

설명: 이 코드는 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를 사용한 예제를 통해 다양한 애플리케이션에 적용 가능합니다.

반응형