본문 바로가기
MCU/C2000

[TMS320F28335] ADC 사용법 : Bitfield 구조 활용 예제 코드

by linuxgo 2025. 8. 18.
반응형

1. TMS320F28335 ADC 모듈 개요

TI의 TMS320F28335는 C2000 Delfino 시리즈의 32비트 마이크로컨트롤러로, 고속 아날로그-디지털 변환(ADC)을 지원하여 모터 제어, 센서 데이터 수집, 전력 관리 등 다양한 애플리케이션에 적합합니다. ADC 모듈은 고속 샘플링, 트리거 소스 선택, 다중 채널 변환 기능을 제공합니다. 이 문서에서는 TMS320F28335 ADC 모듈의 설정 방법, Bitfield 구조를 활용한 레지스터 설정, 그리고 실용적인 예제 코드를 제공하여 초보자와 숙련된 개발자 모두 쉽게 활용할 수 있도록 돕습니다.

주요 사양

  • 해상도: 12비트
  • 샘플링 속도: 최대 12.5 MSPS (메가 샘플 per 초)
  • 입력 채널: 16개 아날로그 입력 채널 (ADCINA07, ADCINB07)
  • 변환 모드:
    • 단일 변환
    • 연속 변환
  • 트리거 소스:
    • 소프트웨어 트리거
    • ePWM 트리거 (SOCA, SOCB)
    • 외부 핀 트리거
  • 인터럽트: 변환 완료 시 인터럽트 지원
  • 샘플 앤 홀드: 80ns 샘플링 윈도우
  • 레지스터: ADCCTL1, ADCCTL2, ADCSOCxCTL, ADCINT 등 Bitfield 구조로 설정
  • 결과 저장: 16개 결과 레지스터 (ADCRESULT0~15)
  • 모듈 수: 단일 ADC 모듈, 2개의 SOC(Start of Conversion) 그룹 (SEQA, SEQB)

2. ADC Bitfield 설정 상세

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

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

  •    bit.RESET: ADC 소프트 리셋 (1: 리셋)
  •    bit.ADCENABLE: ADC 모듈 활성화 (1: 활성화)
  •    bit.ADCBGPWD: ADC 밴드갭 및 레퍼런스 전원 활성화 (1: 활성화)
  •    bit.ADCPWDN: ADC 아날로그 회로 전원 활성화 (1: 활성화)

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

  •    bit.CLKDIV2EN: ADC 클럭 분주비 (0: SYSCLK, 1: SYSCLK/2)
  •    bit.ADCNONOVERLAP: 비중첩 모드 (1: 활성화, SOC 간 충돌 방지)
  •    bit.INTMODEx: 인터럽트 모드 (x=1~8, 0: 변환 완료 시, 1: 연속)

2.3 ADCSOCxCTL (SOC 제어 레지스터, x=0~15)

  •    bit.CHSEL: 채널 선택 (015: ADCINA07, ADCINB0~7)
  •    bit.ACQPS: 샘플링 윈도우 크기 (0~63, 단위: SYSCLK 사이클)
  •    bit.TRIGSEL: 트리거 소스 선택 (0: 소프트웨어, 5: ePWM SOCA 등)

2.4 ADCINT (인터럽트 제어 레지스터)

  •    bit.INTxEN: 인터럽트 활성화 (x=1~8, 1: 활성화)
  •    bit.INTxCONT: 연속 인터럽트 모드 (1: 연속)
  •    bit.INTxSEL: 인터럽트 트리거 SOC 선택

3. ADC 설정 절차

  1. 시스템 초기화:
    •    InitSysCtrl()로 시스템 클럭과 PLL 초기화
    •    인터럽트 비활성화 및 PIE 초기화 (DINT, InitPieCtrl, InitPieVectTable)
  2. ADC 클럭 활성화:
    •    CpuSysRegs.PCLKCR0.bit.ADCENCLK = 1로 ADC 모듈 클럭 활성화
    •    보호된 레지스터 접근을 위해 EALLOW와 EDIS 사용
  3. ADC 전원 활성화:
    •    AdcRegs.ADCCTL1.bit.ADCBGPWD = 1로 밴드갭 및 레퍼런스 활성화
    •    AdcRegs.ADCCTL1.bit.ADCPWDN = 1로 아날로그 회로 전원 활성화
    •    AdcRegs.ADCCTL1.bit.ADCENABLE = 1로 ADC 모듈 활성화
  4. 샘플링 설정:
    •    AdcRegs.ADCCTL2.bit.CLKDIV2EN으로 클럭 분주 설정
    •    AdcRegs.ADCSOCxCTL.bit.ACQPS로 샘플링 윈도우 설정
  5. 채널 및 트리거 설정:
    •    AdcRegs.ADCSOCxCTL.bit.CHSEL로 변환 채널 선택
    •    AdcRegs.ADCSOCxCTL.bit.TRIGSEL로 트리거 소스 설정
  6. 인터럽트 설정 (필요 시):
    •    AdcRegs.ADCINT.bit.INTxEN으로 인터럽트 활성화
    •    AdcRegs.ADCINTSOCSELx로 인터럽트 트리거 SOC 선택
  7. 시퀀서 설정:
    •    AdcRegs.ADCSOCPRIORITY로 시퀀서 우선순위 설정
    •    AdcRegs.ADCCTL1.bit.INTPULSEPOS로 인터럽트 펄스 위치 설정
  8. 변환 시작:
    •    소프트웨어 트리거: AdcRegs.ADCSOCFRC1.bit.SOCx = 1
    •    ePWM 트리거: ePWM 모듈에서 SOCA/SOCB 설정

4. ADC 설정 고려사항

  • 클럭 설정: SYSCLK(150MHz)에서 ADC 클럭 분주 설정
  • 샘플링 윈도우: 최소 80ns (ACQPS ≥ 6 @ 150MHz)
  • 트리거 소스: ePWM 트리거 사용 시 동기화 확인
  • 인터럽트: 변환 완료 인터럽트로 데이터 처리 최적화
  • 결과 처리: ADCRESULTx 레지스터에서 12비트 데이터 읽기
  • 노이즈 방지: 아날로그 입력에 저역통과 필터 권장

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

아래는 TMS320F28335 ADC 모듈을 Bitfield 구조로 설정한 5개의 예제 코드입니다. GPIO와 ADC 설정은 별도의 함수로 분리되었으며, 각 라인에 상세한 주석이 추가되었습니다. Code Composer Studio(CCS)와 C2000Ware 환경에서 실행 가능합니다.

5.1 예제 1: 기본 ADC 변환 (소프트웨어 트리거)

// File: adc_basic_software.c
// Description: TMS320F28335 ADC 기본 변환 (소프트웨어 트리거) 예제
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28335

#include "F28x_Project.h"

volatile Uint16 adcResult; // ADC 변환 결과 저장 변수

// GPIO 설정 함수
void ConfigureGPIO(void) {
    EALLOW; // 보호된 레지스터 접근 허용
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0; // GPIO0을 일반 입력으로 설정 (ADCINA0)
    GpioCtrlRegs.GPADIR.bit.GPIO0 = 0; // GPIO0을 입력으로 설정
    GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // GPIO34를 출력으로 설정 (LED용)
    GpioDataRegs.GPBSET.bit.GPIO34 = 1; // GPIO34를 High로 설정하여 LED 켬
    EDIS; // 보호된 레지스터 접근 비허용
}

// ADC 설정 함수
void ConfigureADC(void) {
    EALLOW; // 보호된 레지스터 접근 허용
    CpuSysRegs.PCLKCR0.bit.ADCENCLK = 1; // ADC 모듈 클럭 활성화
    EDIS; // 보호된 레지스터 접근 비허용

    AdcRegs.ADCCTL1.bit.RESET = 1; // ADC 모듈 리셋
    AdcRegs.ADCCTL1.bit.ADCBGPWD = 1; // 밴드갭 및 레퍼런스 전원 활성화
    AdcRegs.ADCCTL1.bit.ADCPWDN = 1; // ADC 아날로그 회로 전원 활성화
    AdcRegs.ADCCTL1.bit.ADCENABLE = 1; // ADC 모듈 활성화
    AdcRegs.ADCCTL2.bit.CLKDIV2EN = 1; // ADC 클럭 분주비 SYSCLK/2 (75MHz)
    AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 인터럽트 펄스 위치: 변환 완료 시

    AdcRegs.ADCSOC0CTL.bit.CHSEL = 0; // SOC0: ADCINA0 채널 선택
    AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; // 샘플링 윈도우: 6 SYSCLK (80ns @ 150MHz)
    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 0; // 소프트웨어 트리거 선택

    AdcRegs.ADCINTSOCSEL1.bit.SOC0 = 0; // SOC0에 인터럽트 연결 비활성화
}

void main(void) {
    InitSysCtrl(); // 시스템 클럭(150MHz)과 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 컨트롤러 초기화
    IER = 0x0000; // CPU 인터럽트 레지스터 비활성화
    IFR = 0x0000; // 인터럽트 플래그 레지스터 클리어
    InitPieVectTable(); // PIE 인터럽트 벡터 테이블 초기화

    ConfigureGPIO(); // GPIO 설정 함수 호출
    ConfigureADC(); // ADC 설정 함수 호출

    while(1) {
        AdcRegs.ADCSOCFRC1.bit.SOC0 = 1; // SOC0 소프트웨어 트리거 시작
        while(AdcRegs.ADCINTFLG.bit.ADCINT1 == 0); // 변환 완료 대기
        adcResult = AdcRegs.ADCRESULT0; // 변환 결과 읽기
        AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // 인터럽트 플래그 클리어
        DELAY_US(1000); // 1ms 대기 (샘플링 주기 조정)
    }
}

설명:

  • 기능: ADCINA0 채널에서 소프트웨어 트리거로 단일 변환 수행, 결과 저장
  • 설정: ADC 클럭 75MHz, 샘플링 윈도우 80ns, ADCINA0 채널, 소프트웨어 트리거
  • GPIO: GPIO0(ADCINA0), GPIO34(LED)
  • 출력: adcResult에 12비트 ADC 값 저장, LED ON

5.2 예제 2: ePWM 트리거 ADC 변환

// File: adc_epwm_trigger.c
// Description: TMS320F28335 ADC ePWM 트리거 변환 예제
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28335

#include "F28x_Project.h"

volatile Uint16 adcResult; // ADC 변환 결과 저장 변수

// GPIO 설정 함수
void ConfigureGPIO(void) {
    EALLOW; // 보호된 레지스터 접근 허용
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0; // GPIO0을 ADCINA0으로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO0 = 0; // GPIO0을 입력으로 설정
    GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // GPIO34를 출력으로 설정 (LED용)
    GpioDataRegs.GPBSET.bit.GPIO34 = 1; // GPIO34를 High로 설정하여 LED 켬
    EDIS; // 보호된 레지스터 접근 비허용
}

// ePWM1 설정 함수 (ADC 트리거용)
void ConfigureEPWM1(void) {
    EALLOW; // 보호된 레지스터 접근 허용
    CpuSysRegs.PCLKCR1.bit.EPWM1 = 1; // ePWM1 모듈 클럭 활성화
    EDIS; // 보호된 레지스터 접근 비허용

    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // 타임-베이스 카운터를 업 카운트 모드로 설정
    EPwm1Regs.TBCTL.bit.CLKDIV = 0; // 클럭 분주비 1/1 (SYSCLK = 150MHz)
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 2; // 고속 클럭 분주비 1/2 (TBCLK = 75MHz)
    EPwm1Regs.TBPRD = 750; // 주기 레지스터 설정: 750 TBCLK = 10us (100kHz)
    EPwm1Regs.CMPA.bit.CMPA = 375; // 비교 레지스터 A 설정: 50% 듀티 사이클
    EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // TBCTR=0일 때 PWM_A 출력을 High로 설정
    EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // TBCTR=CMPA일 때 PWM_A 출력을 Low로 설정

    EPwm1Regs.ETSEL.bit.SOCAEN = 1; // SOCA 트리거 활성화
    EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO; // TBCTR=0일 때 SOCA 트리거 발생
    EPwm1Regs.ETPS.bit.SOCAPRD = 1; // 첫 번째 이벤트에서 SOCA 트리거 발생

    EPwm1Regs.TBCTL.bit.FREE_SOFT = 2; // Free run 모드
}

// ADC 설정 함수
void ConfigureADC(void) {
    EALLOW; // 보호된 레지스터 접근 허용
    CpuSysRegs.PCLKCR0.bit.ADCENCLK = 1; // ADC 모듈 클럭 활성화
    EDIS; // 보호된 레지스터 접근 비허용

    AdcRegs.ADCCTL1.bit.RESET = 1; // ADC 모듈 리셋
    AdcRegs.ADCCTL1.bit.ADCBGPWD = 1; // 밴드갭 및 레퍼런스 전원 활성화
    AdcRegs.ADCCTL1.bit.ADCPWDN = 1; // ADC 아날로그 회로 전원 활성화
    AdcRegs.ADCCTL1.bit.ADCENABLE = 1; // ADC 모듈 활성화
    AdcRegs.ADCCTL2.bit.CLKDIV2EN = 1; // ADC 클럭 분주비 SYSCLK/2 (75MHz)
    AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 인터럽트 펄스 위치: 변환 완료 시

    AdcRegs.ADCSOC0CTL.bit.CHSEL = 0; // SOC0: ADCINA0 채널 선택
    AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; // 샘플링 윈도우: 6 SYSCLK (80ns @ 150MHz)
    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // ePWM1 SOCA 트리거 선택

    AdcRegs.ADCINTSOCSEL1.bit.SOC0 = 0; // SOC0에 인터럽트 연결 비활성화
}

void main(void) {
    InitSysCtrl(); // 시스템 클럭(150MHz)과 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 컨트롤러 초기화
    IER = 0x0000; // CPU 인터럽트 레지스터 비활성화
    IFR = 0x0000; // 인터럽트 플래그 레지스터 클리어
    InitPieVectTable(); // PIE 인터럽트 벡터 테이블 초기화

    ConfigureGPIO(); // GPIO 설정 함수 호출
    ConfigureADC(); // ADC 설정 함수 호출
    ConfigureEPWM1(); // ePWM1 설정 함수 호출

    while(1) {
        while(AdcRegs.ADCINTFLG.bit.ADCINT1 == 0); // 변환 완료 대기
        adcResult = AdcRegs.ADCRESULT0; // 변환 결과 읽기
        AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // 인터럽트 플래그 클리어
    }
}

설명:

  • 기능: ePWM1 SOCA 트리거로 ADCINA0 채널에서 변환 수행, 결과 저장
  • 설정: ADC 클럭 75MHz, 샘플링 윈도우 80ns, ADCINA0 채널, ePWM1 SOCA 트리거 (100kHz)
  • GPIO: GPIO0(ADCINA0), GPIO34(LED)
  • 출력: adcResult에 12비트 ADC 값 저장, LED ON

5.3 예제 3: ADC 인터럽트 기반 다중 채널 변환

// File: adc_interrupt_multi.c
// Description: TMS320F28335 ADC 인터럽트 기반 다중 채널 변환 예제
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28335

#include "F28x_Project.h"

volatile Uint16 adcResults[2]; // ADCINA0, ADCINA1 변환 결과 저장 배열

// ADC 인터럽트 서비스 루틴
__interrupt void adc_isr(void) {
    adcResults[0] = AdcRegs.ADCRESULT0; // ADCINA0 결과 읽기
    adcResults[1] = AdcRegs.ADCRESULT1; // ADCINA1 결과 읽기
    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // 인터럽트 플래그 클리어
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // PIE 그룹 1 인터럽트 ACK
}

// GPIO 설정 함수
void ConfigureGPIO(void) {
    EALLOW; // 보호된 레지스터 접근 허용
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0; // GPIO0을 ADCINA0으로 설정
    GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 0; // GPIO1을 ADCINA1으로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO0 = 0; // GPIO0을 입력으로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO1 = 0; // GPIO1을 입력으로 설정
    GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // GPIO34를 출력으로 설정 (LED용)
    GpioDataRegs.GPBSET.bit.GPIO34 = 1; // GPIO34를 High로 설정하여 LED 켬
    EDIS; // 보호된 레지스터 접근 비허용
}

// ADC 설정 함수
void ConfigureADC(void) {
    EALLOW; // 보호된 레지스터 접근 허용
    CpuSysRegs.PCLKCR0.bit.ADCENCLK = 1; // ADC 모듈 클럭 활성화
    EDIS; // 보호된 레지스터 접근 비허용

    AdcRegs.ADCCTL1.bit.RESET = 1; // ADC 모듈 리셋
    AdcRegs.ADCCTL1.bit.ADCBGPWD = 1; // 밴드갭 및 레퍼런스 전원 활성화
    AdcRegs.ADCCTL1.bit.ADCPWDN = 1; // ADC 아날로그 회로 전원 활성화
    AdcRegs.ADCCTL1.bit.ADCENABLE = 1; // ADC 모듈 활성화
    AdcRegs.ADCCTL2.bit.CLKDIV2EN = 1; // ADC 클럭 분주비 SYSCLK/2 (75MHz)
    AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 인터럽트 펄스 위치: 변환 완료 시

    AdcRegs.ADCSOC0CTL.bit.CHSEL = 0; // SOC0: ADCINA0 채널 선택
    AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; // 샘플링 윈도우: 6 SYSCLK (80ns @ 150MHz)
    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 0; // 소프트웨어 트리거 선택

    AdcRegs.ADCSOC1CTL.bit.CHSEL = 1; // SOC1: ADCINA1 채널 선택
    AdcRegs.ADCSOC1CTL.bit.ACQPS = 6; // 샘플링 윈도우: 6 SYSCLK
    AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 0; // 소프트웨어 트리거 선택

    AdcRegs.ADCINT.bit.INT1EN = 1; // ADCINT1 인터럽트 활성화
    AdcRegs.ADCINTSOCSEL1.bit.SOC1 = 1; // SOC1 완료 시 ADCINT1 트리거
}

void main(void) {
    InitSysCtrl(); // 시스템 클럭(150MHz)과 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 컨트롤러 초기화
    IER = 0x0000; // CPU 인터럽트 레지스터 비활성화
    IFR = 0x0000; // 인터럽트 플래그 레지스터 클리어
    InitPieVectTable(); // PIE 인터럽트 벡터 테이블 초기화

    EALLOW; // 보호된 레지스터 접근 허용
    PieVectTable.ADCINT1 = &adc_isr; // ADCINT1 인터럽트 벡터를 ISR 함수에 연결
    EDIS; // 보호된 레지스터 접근 비허용

    ConfigureGPIO(); // GPIO 설정 함수 호출
    ConfigureADC(); // ADC 설정 함수 호출

    PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // PIE 그룹 1에서 ADCINT1 인터럽트 활성화
    IER |= M_INT1; // CPU 인터럽트 그룹 1 활성화

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

    while(1) {
        AdcRegs.ADCSOCFRC1.bit.SOC0 = 1; // SOC0 소프트웨어 트리거 시작
        AdcRegs.ADCSOCFRC1.bit.SOC1 = 1; // SOC1 소프트웨어 트리거 시작
    }
}

설명:

  • 기능: ADCINA0, ADCINA1 채널에서 소프트웨어 트리거로 다중 변환 수행, 인터럽트를 통해 결과 저장
  • 설정: ADC 클럭 75MHz, 샘플링 윈도우 80ns, ADCINA0/ADCINA1 채널, 소프트웨어 트리거, ADCINT1 활성화
  • GPIO: GPIO0(ADCINA0), GPIO1(ADCINA1), GPIO34(LED)
  • 출력: adcResults 배열에 12비트 ADC 값 저장, LED ON

5.4 예제 4: 연속 변환 모드 (시퀀서 사용)

// File: adc_sequential_continuous.c
// Description: TMS320F28335 ADC 연속 변환 모드 예제
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28335

#include "F28x_Project.h"

volatile Uint16 adcResults[4]; // ADCINA0~3 변환 결과 저장 배열

// ADC 인터럽트 서비스 루틴
__interrupt void adc_isr(void) {
    adcResults[0] = AdcRegs.ADCRESULT0; // ADCINA0 결과 읽기
    adcResults[1] = AdcRegs.ADCRESULT1; // ADCINA1 결과 읽기
    adcResults[2] = AdcRegs.ADCRESULT2; // ADCINA2 결과 읽기
    adcResults[3] = AdcRegs.ADCRESULT3; // ADCINA3 결과 읽기
    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // 인터럽트 플래그 클리어
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // PIE 그룹 1 인터럽트 ACK
}

// GPIO 설정 함수
void ConfigureGPIO(void) {
    EALLOW; // 보호된 레지스터 접근 허용
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0; // GPIO0을 ADCINA0으로 설정
    GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 0; // GPIO1을 ADCINA1으로 설정
    GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0; // GPIO2을 ADCINA2으로 설정
    GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 0; // GPIO3을 ADCINA3으로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO0 = 0; // GPIO0을 입력으로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO1 = 0; // GPIO1을 입력으로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO2 = 0; // GPIO2을 입력으로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO3 = 0; // GPIO3을 입력으로 설정
    GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // GPIO34를 출력으로 설정 (LED용)
    GpioDataRegs.GPBSET.bit.GPIO34 = 1; // GPIO34를 High로 설정하여 LED 켬
    EDIS; // 보호된 레지스터 접근 비허용
}

// ADC 설정 함수
void ConfigureADC(void) {
    EALLOW; // 보호된 레지스터 접근 허용
    CpuSysRegs.PCLKCR0.bit.ADCENCLK = 1; // ADC 모듈 클럭 활성화
    EDIS; // 보호된 레지스터 접근 비허용

    AdcRegs.ADCCTL1.bit.RESET = 1; // ADC 모듈 리셋
    AdcRegs.ADCCTL1.bit.ADCBGPWD = 1; // 밴드갭 및 레퍼런스 전원 활성화
    AdcRegs.ADCCTL1.bit.ADCPWDN = 1; // ADC 아날로그 회로 전원 활성화
    AdcRegs.ADCCTL1.bit.ADCENABLE = 1; // ADC 모듈 활성화
    AdcRegs.ADCCTL2.bit.CLKDIV2EN = 1; // ADC 클럭 분주비 SYSCLK/2 (75MHz)
    AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 인터럽트 펄스 위치: 변환 완료 시
    AdcRegs.ADCCTL1.bit.SEQ1MODE = 1; // 시퀀서 1 연속 모드 활성화

    AdcRegs.ADCSOC0CTL.bit.CHSEL = 0; // SOC0: ADCINA0 채널 선택
    AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; // 샘플링 윈도우: 6 SYSCLK (80ns @ 150MHz)
    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 0; // 소프트웨어 트리거 선택

    AdcRegs.ADCSOC1CTL.bit.CHSEL = 1; // SOC1: ADCINA1 채널 선택
    AdcRegs.ADCSOC1CTL.bit.ACQPS = 6; // 샘플링 윈도우: 6 SYSCLK
    AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 0; // 소프트웨어 트리거 선택

    AdcRegs.ADCSOC2CTL.bit.CHSEL = 2; // SOC2: ADCINA2 채널 선택
    AdcRegs.ADCSOC2CTL.bit.ACQPS = 6; // 샘플링 윈도우: 6 SYSCLK
    AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 0; // 소프트웨어 트리거 선택

    AdcRegs.ADCSOC3CTL.bit.CHSEL = 3; // SOC3: ADCINA3 채널 선택
    AdcRegs.ADCSOC3CTL.bit.ACQPS = 6; // 샘플링 윈도우: 6 SYSCLK
    AdcRegs.ADCSOC3CTL.bit.TRIGSEL = 0; // 소프트웨어 트리거 선택

    AdcRegs.ADCINT.bit.INT1EN = 1; // ADCINT1 인터럽트 활성화
    AdcRegs.ADCINTSOCSEL1.bit.SOC3 = 1; // SOC3 완료 시 ADCINT1 트리거
}

void main(void) {
    InitSysCtrl(); // 시스템 클럭(150MHz)과 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 컨트롤러 초기화
    IER = 0x0000; // CPU 인터럽트 레지스터 비활성화
    IFR = 0x0000; // 인터럽트 플래그 레지스터 클리어
    InitPieVectTable(); // PIE 인터럽트 벡터 테이블 초기화

    EALLOW; // 보호된 레지스터 접근 허용
    PieVectTable.ADCINT1 = &adc_isr; // ADCINT1 인터럽트 벡터를 ISR 함수에 연결
    EDIS; // 보호된 레지스터 접근 비허용

    ConfigureGPIO(); // GPIO 설정 함수 호출
    ConfigureADC(); // ADC 설정 함수 호출

    PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // PIE 그룹 1에서 ADCINT1 인터럽트 활성화
    IER |= M_INT1; // CPU 인터럽트 그룹 1 활성화

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

    AdcRegs.ADCSOCFRC1.bit.SOC0 = 1; // SOC0 소프트웨어 트리거 시작 (연속 모드 시작)
}

설명:

  • 기능: ADCINA0~3 채널에서 연속 변환 모드로 다중 변환 수행, 인터럽트를 통해 결과 저장
  • 설정: ADC 클럭 75MHz, 샘플링 윈도우 80ns, ADCINA0~3 채널, 소프트웨어 트리거, 시퀀서 연속 모드, ADCINT1 활성화
  • GPIO: GPIO03(ADCINA03), GPIO34(LED)
  • 출력: adcResults 배열에 12비트 ADC 값 저장, LED ON

5.5 예제 5: 외부 핀 트리거 ADC 변환

// File: adc_external_trigger.c
// Description: TMS320F28335 ADC 외부 핀 트리거 변환 예제
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28335

#include "F28x_Project.h"

volatile Uint16 adcResult; // ADC 변환 결과 저장 변수

// GPIO 설정 함수
void ConfigureGPIO(void) {
    EALLOW; // 보호된 레지스터 접근 허용
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0; // GPIO0을 ADCINA0으로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO0 = 0; // GPIO0을 입력으로 설정
    GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0; // GPIO12를 일반 입력으로 설정 (외부 트리거)
    GpioCtrlRegs.GPADIR.bit.GPIO12 = 0; // GPIO12를 입력으로 설정
    GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // GPIO34를 출력으로 설정 (LED용)
    GpioDataRegs.GPBSET.bit.GPIO34 = 1; // GPIO34를 High로 설정하여 LED 켬
    EDIS; // 보호된 레지스터 접근 비허용
}

// ADC 설정 함수
void ConfigureADC(void) {
    EALLOW; // 보호된 레지스터 접근 허용
    CpuSysRegs.PCLKCR0.bit.ADCENCLK = 1; // ADC 모듈 클럭 활성화
    EDIS; // 보호된 레지스터 접근 비허용

    AdcRegs.ADCCTL1.bit.RESET = 1; // ADC 모듈 리셋
    AdcRegs.ADCCTL1.bit.ADCBGPWD = 1; // 밴드갭 및 레퍼런스 전원 활성화
    AdcRegs.ADCCTL1.bit.ADCPWDN = 1; // ADC 아날로그 회로 전원 활성화
    AdcRegs.ADCCTL1.bit.ADCENABLE = 1; // ADC 모듈 활성화
    AdcRegs.ADCCTL2.bit.CLKDIV2EN = 1; // ADC 클럭 분주비 SYSCLK/2 (75MHz)
    AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 인터럽트 펄스 위치: 변환 완료 시

    AdcRegs.ADCSOC0CTL.bit.CHSEL = 0; // SOC0: ADCINA0 채널 선택
    AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; // 샘플링 윈도우: 6 SYSCLK (80ns @ 150MHz)
    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 1; // 외부 핀 트리거 (GPIO12, ADCTRIG1)

    AdcRegs.ADCINTSOCSEL1.bit.SOC0 = 0; // SOC0에 인터럽트 연결 비활성화
}

void main(void) {
    InitSysCtrl(); // 시스템 클럭(150MHz)과 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 컨트롤러 초기화
    IER = 0x0000; // CPU 인터럽트 레지스터 비활성화
    IFR = 0x0000; // 인터럽트 플래그 레지스터 클리어
    InitPieVectTable(); // PIE 인터럽트 벡터 테이블 초기화

    ConfigureGPIO(); // GPIO 설정 함수 호출
    ConfigureADC(); // ADC 설정 함수 호출

    while(1) {
        while(AdcRegs.ADCINTFLG.bit.ADCINT1 == 0); // 변환 완료 대기
        adcResult = AdcRegs.ADCRESULT0; // 변환 결과 읽기
        AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // 인터럽트 플래그 클리어
    }
}

설명:

  • 기능: GPIO12(ADCTRIG1) 외부 핀 트리거로 ADCINA0 채널에서 변환 수행, 결과 저장
  • 설정: ADC 클럭 75MHz, 샘플링 윈도우 80ns, ADCINA0 채널, 외부 핀 트리거
  • GPIO: GPIO0(ADCINA0), GPIO12(ADCTRIG1), GPIO34(LED)
  • 출력: adcResult에 12비트 ADC 값 저장, LED ON

6. 사용 방법

6.1 환경 설정

  • C2000Ware 설치: C:\ti\c2000\C2000Ware_x_xx_xx_xx
  • CCS 프로젝트: TMS320F28335 타겟으로 프로젝트 생성, F28x_Project.h 포함
  • 링커 파일: device_support\f2833x 폴더에서 링커 파일 추가

6.2 코드 실행

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

6.3 하드웨어 준비

  • ADC 입력: ADCINA03 핀에 아날로그 신호(03.3V) 연결
  • LED: GPIO34에 LED 연결
  • ePWM 트리거: 예제 2의 경우 ePWM1 SOCA 트리거 확인
  • 외부 트리거: 예제 5의 경우 GPIO12에 트리거 신호 연결

6.4 디버깅

  • CCS Expressions 창: AdcRegs.ADCRESULT0~`AdcRegs.ADCRESULT3` 확인
  • 인터럽트 상태: AdcRegs.ADCINTFLG로 인터럽트 플래그 점검
  • 샘플링 확인: 오실로스코프로 ADC 입력 신호와 트리거 동기화 확인

7. 추가 팁

  • 캘리브레이션: ADC 사용 전 Device_cal() 호출 권장
  • 노이즈 감소: 아날로그 입력에 저역통과 필터 사용
  • C2000Ware 참고: C:\ti\c2000\C2000Ware_x_xx_xx_xx\device_support\f2833x\examples\cpu1\adc
  • 문제 해결:
    •    ADC 출력 없음: ADCCTL1.bit.ADCENABLE, ADCSOCxCTL.bit.TRIGSEL 확인
    •    인터럽트 실패: ADCINT.bit.INTxEN, PieCtrlRegs.PIEIER1 확인
    •    부정확한 결과: ADCSOCxCTL.bit.ACQPS 값 및 아날로그 입력 범위(0~3.3V) 확인
  • TI 리소스: TI E2E 포럼, C2000Ware 예제

8. 결론

이 문서는 TMS320F28335 ADC 모듈의 설정 방법과 Bitfield 구조를 활용한 예제 코드를 제공하여 다양한 애플리케이션에 적용 가능하도록 구성했습니다.

키워드: TMS320F28335, ADC, C2000, 아날로그-디지털 변환, 마이크로컨트롤러, Code Composer Studio, ePWM 트리거, 인터럽트, 다중 채널 변환, 연속 변환, 외부 트리거, 샘플링 윈도우

반응형