본문 바로가기
MCU/C2000

TMS320F28377D DSP PWM 출력 설정: Bitfield 구조 활용 예제 코드

by linuxgo 2025. 8. 5.
반응형

소개

Texas Instruments의 TMS320F28377D는 고성능 C2000 시리즈 마이크로컨트롤러로, PWM(펄스 폭 변조) 신호 생성에 자주 사용됩니다. 이 글에서는 ePWM 모듈을 활용해 20kHz 주파수와 50% 듀티 사이클로 PWM 신호를 생성하는 방법을 bitfield 구조를 사용해 상세히 설명합니다.

왜 Bitfield를 사용하나요?

Bitfield 구조는 레지스터의 특정 비트를 직관적으로 조작할 수 있어 코드 가독성과 유지보수성을 높입니다. TMS320F28377D의 레지스터는 bitfield로 정의되어 있어, PWM 설정 시 명확하고 효율적인 코드를 작성할 수 있습니다. 이 글에서는 F28x_Project.h 헤더를 사용하며, 각 비트 필드의 역할과 설정 이유를 주석으로 자세히 설명합니다.

전제 조건

  • 개발 환경: Code Composer Studio(CCS) 및 C2000Ware 설치
  • 하드웨어: TMS320F28377D 기반 보드
  • 시스템 클럭: 200MHz 가정
  • 목표: 20kHz PWM, 50% 듀티 사이클, GPIO0를 ePWM1A로 설정

예제 코드

아래는 ePWM1 모듈을 설정하는 C 코드로, bitfield를 활용해 레지스터를 조작합니다. 각 설정은 주석으로 상세히 설명됩니다.

#include "F28x_Project.h" // TMS320F28377D의 레지스터 및 기본 정의를 포함하는 표준 헤더 파일

// 함수 프로토타입 선언
void InitSystem(void);   // 시스템 클럭 및 ePWM 모듈 초기화
void Setup_ePWM1(void);  // ePWM1 모듈 설정
void Gpio_select(void);  //(GPIO 핀 설정

// 메인 함수
void main(void)
{
    InitSystem();   // 시스템 초기화: 클럭 설정 및 ePWM 모듈 활성화
    Gpio_select();  // GPIO0를 ePWM1A 출력 핀으로 설정
    Setup_ePWM1();  // ePWM1을 20kHz, 50% 듀티 사이클로 설정

    while(1)        // 무한 루프: PWM 출력 지속
    {
        // 필요 시 추가 제어 로직 삽입
    }
}

// 시스템 초기화 함수
void InitSystem(void)
{
    EALLOW; // 보호된 레지스터 접근 허용 (EALLOW는 CPU 레지스터 접근 제어 비트를 설정)

    /* PCLKCR0.TBCLKSYNC: 타이머 베이스 클럭 동기화 비활성화
     * - 비트 필드: CpuSysRegs.PCLKCR0.bit.TBCLKSYNC (1비트)
     * - 역할: 모든 ePWM 모듈의 타이머 베이스 클럭 동기화를 제어
     * - 설정 이유: 초기 설정 중 동기화로 인한 예기치 않은 동작 방지
     * - 0 = 동기화 비활성화, 1 = 동기화 활성화
     */
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;

    /* PCLKCR2.EPWM1: ePWM1 모듈 클럭 활성화
     * - 비트 필드: CpuSysRegs.PCLKCR2.bit.EPWM1 (1비트)
     * - 역할: ePWM1 모듈에 시스템 클럭 공급 제어
     * - 설정 이유: ePWM1 모듈을 사용하기 위해 클럭 활성화
     * - 0 = 클럭 비활성화, 1 = 클럭 활성화
     */
    CpuSysRegs.PCLKCR2.bit.EPWM1 = 1;

    EDIS;   // 보호된 레지스터 접근 비활성화
}

// GPIO 설정 함수
void Gpio_select(void)
{
    EALLOW; // 보호된 레지스터 접근 허용

    /* GPAMUX1.GPIO0: GPIO0를 ePWM1A로 설정
     * - 비트 필드: GpioCtrlRegs.GPAMUX1.bit.GPIO0 (2비트)
     * - 역할: GPIO0의 다중화 기능 선택
     * - 설정 값: 1 = ePWM1A 출력 (PWM 신호 출력용)
     * - 다른 값: 0 (GPIO), 2 (SDAA), 3 (TZ1) 등
     * - 설정 이유: GPIO0를 ePWM1A 출력 핀으로 사용
     */
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;

    /* GPADIR.GPIO0: GPIO0를 출력으로 설정
     * - 비트 필드: GpioCtrlRegs.GPADIR.bit.GPIO0 (1비트)
     * - 역할: GPIO0의 입출력 방향 설정
     * - 설정 값: 1 = 출력 (PWM 신호를 외부로 출력)
     * - 계획 이유: PWM 신호를 출력하기 위해 GPIO0를 출력 모드로 설정
     */
    GpioCtrlRegs.GPADIR.bit.GPIO0 = 1;

    EDIS;   // 보호된 레지스터 접근 비활성화
}

// ePWM1 설정 함수: 20kHz 주파수, 50% 듀티 사이클
void Setup_ePWM1(void)
{
    // 시스템 클럭 및 PWM 주파수 정의
    #define SYSCLK 200000000UL  // 시스템 클럭: 200MHz
    #define PWM_FREQ 20000UL    // 목표 PWM 주파수: 20kHz
    #define TBPRD (SYSCLK / (2 * PWM_FREQ)) // 타임 베이스 주기 = 5000 (20kHz)

    EALLOW; // 보호된 레지스터 접근 허용

    /* TBCTL.CTRMODE: 타이머 카운터 모드 설정
     * - 비트 필드: EPwm1Regs.TBCTL.bit.CTRMODE (2비트)
     * - 역할: 타이머 베이스의 카운트 동작 모드 선택
     * - 설정 값: TB_COUNT_UP (0) = 업카운트 모드
     * - 다른 값: 1 (다운카운트), 2 (업-다운카운트), 3 (정지)
     * - 설정 이유: 단순한 PWM 신호 생성을 위해 업카운트 모드 선택
     */
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;

    /* TBCTL.PHSEN: 페이즈 로딩 활성화/비활성화
     * - 비트 필드: EPwm1Regs.TBCTL.bit.PHSEN (1비트)
     * - 역할: 동기화 신호를 통한 페이즈 로딩 제어
     * - 설정 값: TB_DISABLE (0) = 페이즈 로딩 비활성화
     * - 설정 이유: 단일 PWM 모듈 사용 시 페이즈 동기화 불필요
     */
    EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;

    /* TBCTL.HSPCLKDIV: 고속 클럭 분주 설정
     * - 비트 필드: EPwm1Regs.TBCTL.bit.HSPCLKDIV (3비트)
     * - 역할: 타임 베이스 클럭의 고속 분주 설정
     * - 설정 값: TB_DIV1 (0) = 분주 없음 (1:1)
     * - 다른 값: 1 (/2), 2 (/4), ..., 7 (/14)
     * - 설정 이유: 최대 해상도를 위해 클럭 분주 비활성화
     */
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;

    /* TBCTL.CLKDIV: 클럭 분주 설정
     * - 비트 필드: EPwm1Regs.TBCTL.bit.CLKDIV (3비트)
     * - 역할: 타임 베이스 클럭의 기본 분주 설정
     * - 설정 값: TB_DIV1 (0) = 분주 없음 (1:1)
     * - 설정 이유: 최대 해상도를 위해 클럭 분주 비활성화
     */
    EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

    /* TBPRD: 타임 베이스 주기 설정
     * - 레지스터: EPwm1Regs.TBPRD (16비트)
     * - 역할: PWM 주기를 결정 (주기 = (TBPRD + 1) * TBCLK)
     * - 설정 값: 5000 (TBPRD = SYSCLK / (2 * PWM_FREQ))
     * - 계산: 200MHz / (2 * 20kHz) = 5000 (20kHz 주파수)
     * - 설정 이유: 20kHz PWM 신호 생성
     */
    EPwm1Regs.TBPRD = TBPRD;

    /* CMPA.CMPA: 비교 레지스터 A 설정
     * - 비트 필드: EPwm1Regs.CMPA.bit.CMPA (16비트)
     * - 역할: PWM 듀티 사이클을 결정 (듀티 = CMPA / (TBPRD + 1))
     * - 설정 값: TBPRD / 2 = 2500 (50% 듀티 사이클)
     * - 설정 이유: PWM 신호의 듀티 사이클을 50%로 설정
     */
    EPwm1Regs.CMPA.bit.CMPA = TBPRD / 2;

    /* AQCTLA.ZRO: 카운터 0에서의 동작 설정
     * - 비트 필드: EPwm1Regs.AQCTLA.bit.ZRO (2비트)
     * - 역할: 타이머 카운터가 0일 때 PWM 출력 동작 정의
     * - 설정 값: AQ_SET (2) = 출력 HIGH 설정
     * - 설정 이유: PWM 주기 시작 시 출력을 HIGH로 설정
     */
    EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;

    /* AQCTLA.CAU: CMPA 업카운트 시 동작 설정
     * - 비트 필드: EPwm1Regs.AQCTLA.bit.CAU (2비트)
     * - 역할: 타이머가 CMPA 값과 일치할 때 PWM 출력 동작 정의
     * - 설정 값: AQ_CLEAR (1) = 출력 LOW 설정
     * - 설정 이유: 듀티 사이클 종료 시점에서 출력을 LOW로 설정
     */
    EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;

    /* DBCTL.OUT_MODE: 데드밴드 출력 모드 설정
     * - 비트 필드: EPwm1Regs.DBCTL.bit.OUT_MODE (2비트)
     * - 역할: 데드밴드 모듈의 출력 활성화/비활성화
     * - 설정 값: DB_DISABLE (0) = 데드밴드 비활성화
     * - 설정 이유: 단일 PWM 신호 생성 시 데드밴드 불필요
     */
    EPwm1Regs.DBCTL.bit.OUT_MODE = DB_DISABLE;

    EDIS; // 보호된 레지스터 접근 비활성화

    /* PCLKCR0.TBCLKSYNC: 타이머 베이스 클럭 동기화 활성화
     * - 비트 필드: CpuSysRegs.PCLKCR0.bit.TBCLKSYNC (1비트)
     * - 역할: ePWM 모듈의 타이머 베이스 클럭 동기화
     * - 설정 값: 1 = 동기화 활성화
     * - 설정 이유: 설정 완료 후 PWM 타이머 시작을 위해 동기화 활성화
     */
    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;
}

코드 설명

1. 시스템 초기화 (InitSystem)

  • 목적: 시스템 클럭과 ePWM 모듈을 초기화.
  • 주요 bitfield:
    •    PCLKCR0.TBCLKSYNC: 타이머 베이스 클럭 동기화 비활성화로 설정 충돌 방지.
    •    PCLKCR2.EPWM1: ePWM1 모듈 클럭 활성화.

2. GPIO 설정 (Gpio_select)

  • 목적: GPIO0를 ePWM1A 출력 핀으로 설정.
  • 주요 bitfield:
    •    GPAMUX1.GPIO0: GPIO0를 ePWM1A로 설정.
    •    GPADIR.GPIO0: GPIO0를 출력 모드로 설정.

3. ePWM 설정 (Setup_ePWM1)

  • 목적: 20kHz 주파수와 50% 듀티 사이클로 PWM 신호 생성.
  • 주요 bitfield:
    •    TBCTL.CTRMODE: 업카운트 모드로 설정.
    •    TBCTL.PHSEN: 페이즈 로딩 비활성화.
    •    TBCTL.HSPCLKDIVTBCTL.CLKDIV: 클럭 분주 비활성화로 최대 해상도.
    •    TBPRD: PWM 주기를 5000으로 설정 (20kHz).
    •    CMPA.CMPA: 듀티 사이클을 50%로 설정 (2500).
    •    AQCTLA.ZROAQCTLA.CAU: PWM 파형의 HIGH/LOW 동작 정의.
    •    DBCTL.OUT_MODE: 데드밴드 비활성화.

Bitfield의 장점

  • 명확성: 비트 단위로 레지스터 조작이 가능해 코드 의도가 명확.
  • 효율성: 비트 마스크 연산 대비 간결한 코드 작성.
  • 유지보수성: bitfield 이름이 레지스터 구조를 반영해 가독성 향상.
  • 오류 방지: 잘못된 비트 조작 가능성 감소.

디버깅 및 테스트

  1. 레지스터 확인: CCS 디버그 모드에서 EPwm1Regs, GpioCtrlRegs 값을 확인.
  2. 오실로스코프: GPIO0에서 20kHz, 50% 듀티 사이클 PWM 신호 측정.
  3. C2000Ware 설정: 프로젝트에 F28x_Project.h와 링커 파일(F28377D.cmd) 포함.

추가 팁

  • 시스템 클럭: 200MHz가 아닌 경우 SYSCLK 값을 조정.
  • 확장 기능: 인터럽트(ETSEL), 데드밴드(DBCTL), 동기화(TBPHS) 추가 가능.
  • 문제 해결: 컴파일 오류 시 C2000Ware 경로와 헤더 파일 확인.

결론

이 예제는 TMS320F28377D에서 bitfield 구조를 활용해 PWM 출력을 설정하는 방법을 보여줍니다. 상세 주석과 구조화된 코드는 초보자와 숙련자 모두에게 유용하며, C2000 마이크로컨트롤러 프로그래밍을 배우는 데 훌륭한 출발점입니다. 

반응형