본문 바로가기
MCU/C2000

[TMS320F28388D] ePWM 사용법: DriverLib API로 ePWM 설정 및 코드

by linuxgo 2025. 8. 16.
반응형

 

이 문서에서는 Texas Instruments의 TMS320F28388D 마이크로컨트롤러에서 ePWM(Enhanced Pulse Width Modulation) 모듈을 DriverLib API를 사용하여 설정하고 사용하는 방법을 상세히 다룹니다. C2000 시리즈의 고성능 마이크로컨트롤러인 TMS320F28388D의 ePWM 모듈을 활용하여 PWM 신호를 생성하는 방법을 배우고, 다양한 독립적인 예제 코드를 통해 실제 구현 방법을 익힐 수 있습니다. 각 코드에는 상세한 주석이 포함되어 있으며, Code Composer Studio(CCS) 환경에서 실행 가능합니다.

1. TMS320F28388D ePWM 개요

TMS320F28388D는 Texas Instruments의 C2000 시리즈에 속하는 고성능 32비트 마이크로컨트롤러로, 최대 16개의 ePWM 모듈을 제공합니다. ePWM 모듈은 모터 제어, 전력 변환, 조명 제어 등 정밀한 PWM 신호 생성이 필요한 실시간 제어 애플리케이션에 최적화되어 있습니다.

ePWM 모듈의 주요 특징

  • 타임 베이스(Time-Base): 각 ePWM 모듈은 독립적인 타이머를 기반으로 PWM 신호를 생성하며, 주기와 듀티 사이클을 정밀하게 제어 가능.
  • 카운터 모드: Up, Down, Up-Down 모드 지원.
  • PWM 출력: 각 모듈은 두 개의 독립적인 출력(A, B)을 제공하며, 상보적 출력(Complementary PWM) 및 데드밴드(Deadband) 설정 가능.
  • 트리거 이벤트: ADC 변환 트리거(SOCA, SOCB), 인터럽트, 또는 외부 동기화 신호 생성 가능.
  • 고급 기능: 데드밴드 제어, 트립 존(Trip Zone), 이벤트 트리거, 고해상도 PWM(HRPWM) 지원.
  • 클럭: 시스템 클럭(최대 200MHz)을 기반으로 동작하며, 프리스케일러를 통해 주파수 조정 가능.

DriverLib API는 하드웨어 레지스터를 직접 조작하는 대신 추상화된 함수를 제공하여 ePWM 설정을 간소화합니다.

2. 주요 ePWM DriverLib API 함수

아래는 TMS320F28388D의 ePWM 모듈을 제어하기 위해 자주 사용되는 DriverLib API 함수와 그 사용 방법입니다.

2.1. ePWM 기본 설정 관련 함수

  • EPWM_setTimeBasePeriod(base, period)
    • 설명: PWM 주기를 설정합니다. 주기는 클럭 사이클 단위로 지정.
    • 매개변수: base (ePWM 모듈의 베이스 주소), period (타이머 주기 값, 0~65535).
    • 사용 예: 100kHz PWM 주기를 위해 200MHz 클럭에서 period=2000 설정.
  • EPWM_setCounterMode(base, mode)
    • 설명: 타이머 카운터 동작 모드를 설정합니다.
    • 매개변수: mode (EPWM_COUNTER_MODE_UP, EPWM_COUNTER_MODE_DOWN, EPWM_COUNTER_MODE_UP_DOWN).
  • EPWM_setClockPrescaler(base, prescaler, highSpeedPrescaler)
    • 설명: ePWM 모듈의 클럭 분주를 설정합니다.
    • 매개변수: prescaler (클럭 분주 값), highSpeedPrescaler (HRPWM용).
  • EPWM_enableModule(base): ePWM 모듈 활성화.
  • EPWM_disableModule(base): ePWM 모듈 비활성화.

2.2. PWM 출력 설정 관련 함수

  • EPWM_setActionQualifierAction(base, output, event, action)
    • 설명: 특정 이벤트에서 PWM 출력(A/B)의 동작을 설정.
    • 매개변수: output (EPWM_AQ_OUTPUT_A/B), event (예: EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO), action (예: EPWM_AQ_OUTPUT_HIGH).
  • EPWM_setCompareA(base, value): 비교 레지스터 A(CMPA) 값을 설정하여 듀티 사이클 제어.
  • EPWM_setCompareB(base, value): 비교 레지스터 B(CMPB) 값 설정.

2.3. ADC 트리거 관련 함수

  • EPWM_enableADCTrigger(base, soc): ADC 트리거(SOCA/SOCB) 활성화.
  • EPWM_setADCTriggerSource(base, soc, source): ADC 트리거 발생 조건 설정.
  • EPWM_setADCTriggerEventPrescale(base, soc, prescale): 트리거 프리스케일러 설정.

2.4. 인터럽트 관련 함수

  • EPWM_enableInterrupt(base): ePWM 인터럽트 활성화.
  • EPWM_setInterruptSource(base, source): 인터럽트 발생 조건 설정.
  • EPWM_clearInterruptStatus(base): 인터럽트 플래그 지우기.
  • Interrupt_register(intNumber, handler): 인터럽트 서비스 루틴(ISR) 등록.

2.5. 데드밴드 및 트립 존 관련 함수

  • EPWM_enableDeadBandModule(base): 데드밴드 모듈 활성화.
  • EPWM_setDeadBandDelay(base, risingDelay, fallingDelay): 상승/하강 에지 데드밴드 지연 시간 설정.
  • EPWM_enableTripZone(base, tripSource): 트립 존 활성화.

2.6. HRPWM 관련 함수

  • EPWM_enableHRPWM(base): 고해상도 PWM 모듈 활성화.
  • EPWM_setHRPWMCompareValue(base, value): HRPWM 비교 값 설정.

3. ePWM 설정 및 동작 원리

  1. 시스템 초기화: 시스템 클럭과 GPIO 초기화(Device_init(), Device_initGPIO()), 인터럽트 모듈 초기화.
  2. ePWM 모듈 설정: 클럭 활성화, 타임 베이스 주기, 카운터 모드, PWM 출력 동작 설정.
  3. ADC 트리거 또는 인터럽트 설정(선택): ADC 트리거 설정 또는 인터럽트 활성화.
  4. 데드밴드 및 트립 존 설정(선택): 데드밴드 및 트립 존 설정.
  5. ePWM 활성화: ePWM 모듈 활성화.

4. ePWM 예제 코드

아래는 독립적인 ePWM 예제 코드로, C2000Ware의 DriverLib를 기반으로 작성되었습니다. GPIO 설정은 별도의 initGPIO() 함수로 분리되어 있으며, 모든 코드는 CCS에서 바로 실행 가능합니다.

4.1. 예제 1: 기본 PWM 신호 생성

ePWM1을 사용하여 100kHz, 50% 듀티 사이클의 PWM 신호를 생성합니다.


#include "driverlib.h"
#include "device.h"

// 디버깅용 상태 변수
volatile uint32_t pwmStatus = 0; // 0: 초기화 완료, 1: PWM 동작 중, 0xFFFF: 오류

// GPIO 초기화 함수
void initGPIO(void)
{
    // GPIO0을 ePWM1A로 설정 (EPWM1A는 기본적으로 GPIO0에 매핑)
    GPIO_setPinConfig(GPIO_0_EPWM1A);         // GPIO0을 ePWM1A로 멀티플렉싱
    GPIO_setDirectionMode(0, GPIO_DIR_MODE_OUT); // 출력 모드 설정
    GPIO_setPadConfig(0, GPIO_PULL_UP);        // 풀업 저항 활성화 (외부 회로에 따라 조정 가능)
    
    // 디버깅용 LED 설정 (LAUNCHXL-F28379D 기준, GPIO31=LED)
    GPIO_setPinConfig(GPIO_31_GPIO31);        // GPIO31을 일반 GPIO로 설정
    GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT); // 출력 모드 설정
    GPIO_setPadConfig(31, GPIO_PULL_UP);       // 풀업 저항 활성화
    GPIO_writePin(31, 0);                     // 초기 LED OFF
}

// ePWM1 초기화 함수
void initEPWM(void)
{
    // ePWM1 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
    
    // 주기 설정: 100kHz PWM (200MHz / 2000 = 100kHz)
    // 주기 = (시스템 클럭) / (원하는 PWM 주파수 * 클럭 분주)
    EPWM_setTimeBasePeriod(EPWM1_BASE, 2000);
    
    // 카운터 모드 설정: Up 카운터
    EPWM_setCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
    
    // PWM_A 동작 설정: 카운터=0일 때 HIGH, CMPA에서 LOW
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO, EPWM_AQ_OUTPUT_HIGH);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_UP, EPWM_AQ_OUTPUT_LOW);
    
    // 듀티 사이클 50% 설정 (CMPA = period/2)
    EPWM_setCompareA(EPWM1_BASE, 1000);
    
    // ePWM 모듈 활성화
    EPWM_enableModule(EPWM1_BASE);
    
    // 상태 업데이트: PWM 동작 중
    pwmStatus = 1;
}

void main(void)
{
    // 시스템 클럭 및 주변 장치 초기화
    // PLL, Watchdog, 주변 장치 클럭 설정
    Device_init();
    
    // GPIO 기본 초기화
    Device_initGPIO();
    
    // ePWM 관련 GPIO 설정
    initGPIO();
    
    // 인터럽트 모듈 초기화 (확장성을 위해 포함, 본 예제에서는 사용 안 함)
    Interrupt_initModule();
    Interrupt_initVectorTable();
    
    // 시스템 클럭 확인 (디버깅용)
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
    if (sysClockHz != 200000000) // 200MHz가 아닌 경우 오류 플래그 설정
    {
        pwmStatus = 0xFFFF; // 오류 상태
        GPIO_writePin(31, 0); // LED OFF로 오류 표시
        ESTOP0; // 디버깅용 정지 (CCS에서 브레이크포인트로 확인 가능)
    }
    
    // ePWM1 초기화
    initEPWM();
    
    // ePWM 초기화 오류 확인
    if (pwmStatus != 1)
    {
        pwmStatus = 0xFFFF; // 초기화 실패
        GPIO_writePin(31, 0); // LED OFF로 오류 표시
        ESTOP0; // 디버깅용 정지
    }
    
    // 글로벌 인터럽트 활성화 (확장성을 위해 포함)
    EINT;
    
    // 저전력 모드 방지: Watchdog 활성화 (실시간 애플리케이션용)
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
    SysCtl_serviceWatchdog();
    
    // 무한 루프: PWM 신호는 하드웨어로 자동 생성
    for(;;)
    {
        // 디버깅용: 상태 표시 (GPIO31 LED로 상태 출력)
        GPIO_writePin(31, (pwmStatus == 1) ? 1 : 0); // 정상 동작 시 LED ON
        
        // 1초 대기 (디버깅 및 CPU 부하 감소)
        DEVICE_DELAY_US(1000000);
    }
}
    

설명:

  • 기능: ePWM1의 PWM_A 출력으로 100kHz, 50% 듀티 사이클 PWM 신호 생성.
  • 설정: Up 카운터, 주기 2000(100kHz @ 200MHz), CMPA=1000(50% 듀티).
  • GPIO: GPIO0(ePWM1A), GPIO31(LED).
  • 출력: GPIO0(ePWM1A)에 PWM 신호 출력, 정상 동작 시 LED ON.

4.2. 예제 2: 인터럽트를 사용한 듀티 사이클 동적 변경

ePWM1의 인터럽트를 사용하여 PWM 듀티 사이클을 동적으로 변경합니다.


#include "driverlib.h"
#include "device.h"

// 디버깅용 상태 변수
volatile uint32_t pwmStatus = 0; // 0: 초기화 완료, 1: PWM 동작 중, 0xFFFF: 오류

// 듀티 사이클 저장 변수 (초기 25% 듀티)
volatile uint16_t dutyCycle = 500;

// GPIO 초기화 함수
void initGPIO(void)
{
    // GPIO0을 ePWM1A로 설정
    GPIO_setPinConfig(GPIO_0_EPWM1A);
    GPIO_setDirectionMode(0, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(0, GPIO_PULL_UP);
    
    // 디버깅용 LED 설정 (GPIO31)
    GPIO_setPinConfig(GPIO_31_GPIO31);
    GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(31, GPIO_PULL_UP);
    GPIO_writePin(31, 0); // 초기 LED OFF
}

// 인터럽트 서비스 루틴 (ISR)
__interrupt void epwm1ISR(void)
{
    // 듀티 사이클 증가 (0~100% 순환)
    dutyCycle += 100;
    if (dutyCycle > 2000) dutyCycle = 0; // 주기 초과 시 초기화
    
    // CMPA 업데이트로 듀티 사이클 변경
    EPWM_setCompareA(EPWM1_BASE, dutyCycle);
    
    // 인터럽트 플래그 지우기
    EPWM_clearInterruptStatus(EPWM1_BASE);
    
    // PIE 인터럽트 ACK
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    
    // 상태 업데이트
    pwmStatus = 1;
}

void initEPWM(void)
{
    // ePWM1 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
    
    // 주기 설정: 100kHz PWM
    EPWM_setTimeBasePeriod(EPWM1_BASE, 2000);
    EPWM_setCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
    
    // PWM_A 동작 설정
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO, EPWM_AQ_OUTPUT_HIGH);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_UP, EPWM_AQ_OUTPUT_LOW);
    
    // 초기 듀티 사이클 설정
    EPWM_setCompareA(EPWM1_BASE, dutyCycle);
    
    // 인터럽트 설정: 카운터=0일 때 발생
    EPWM_setInterruptSource(EPWM1_BASE, EPWM_INT_TBCTR_ZERO);
    EPWM_enableInterrupt(EPWM1_BASE);
    
    // ePWM 모듈 활성화
    EPWM_enableModule(EPWM1_BASE);
}

void main(void)
{
    // 시스템 클럭 및 주변 장치 초기화
    Device_init();
    
    // GPIO 기본 초기화
    Device_initGPIO();
    
    // ePWM 관련 GPIO 설정
    initGPIO();
    
    // 인터럽트 모듈 초기화
    Interrupt_initModule();
    Interrupt_initVectorTable();
    
    // ePWM1 인터럽트 ISR 등록
    Interrupt_register(INT_EPWM1, &epwm1ISR);
    
    // 시스템 클럭 확인
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
    if (sysClockHz != 200000000)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // ePWM1 초기화
    initEPWM();
    
    // ePWM 초기화 오류 확인
    if (pwmStatus != 1)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // 글로벌 인터럽트 활성화
    EINT;
    
    // Watchdog 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
    SysCtl_serviceWatchdog();
    
    // 무한 루프
    for(;;)
    {
        // 디버깅용: 상태 표시
        GPIO_writePin(31, (pwmStatus == 1) ? 1 : 0);
        DEVICE_DELAY_US(1000000);
    }
}
    

설명:

  • 기능: 100kHz PWM 신호 생성, 인터럽트를 통해 듀티 사이클을 0~100%로 동적 변경.
  • 인터럽트: 카운터=0일 때 ISR에서 CMPA 업데이트.
  • GPIO: GPIO0(ePWM1A), GPIO31(LED).
  • 결과: 듀티 사이클이 주기적으로 변화, 정상 동작 시 LED ON.

4.3. 예제 3: ADC 트리거를 위한 ePWM 설정

ePWM1의 SOCA 신호를 사용하여 ADC 변환을 트리거합니다.


#include "driverlib.h"
#include "device.h"

// 디버깅용 상태 변수
volatile uint32_t pwmStatus = 0;

// ADC 결과 저장 버퍼
#define RESULTS_BUFFER_SIZE 256
uint16_t adcResults[RESULTS_BUFFER_SIZE];
volatile uint16_t index = 0;

// GPIO 초기화 함수
void initGPIO(void)
{
    // GPIO0을 ePWM1A로 설정
    GPIO_setPinConfig(GPIO_0_EPWM1A);
    GPIO_setDirectionMode(0, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(0, GPIO_PULL_UP);
    
    // 디버깅용 LED 설정 (GPIO31)
    GPIO_setPinConfig(GPIO_31_GPIO31);
    GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(31, GPIO_PULL_UP);
    GPIO_writePin(31, 0);
}

// ADC 인터럽트 서비스 루틴
__interrupt void adcA1ISR(void)
{
    // ADC 변환 결과 읽기
    adcResults[index] = ADC_readResult(ADCA_BASE, ADC_SOC_NUMBER0);
    
    // 인덱스 증가 및 버퍼 오버플로우 방지
    index++;
    if (index >= RESULTS_BUFFER_SIZE) index = 0;
    
    // 인터럽트 플래그 지우기
    ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
    
    // PIE 인터럽트 ACK
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
    
    // 상태 업데이트
    pwmStatus = 1;
}

void initEPWM(void)
{
    // ePWM1 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
    
    // 주기 설정: 100kHz PWM
    EPWM_setTimeBasePeriod(EPWM1_BASE, 2000);
    EPWM_setCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
    
    // PWM_A 동작 설정
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO, EPWM_AQ_OUTPUT_HIGH);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_UP, EPWM_AQ_OUTPUT_LOW);
    
    // 듀티 사이클 50% 설정
    EPWM_setCompareA(EPWM1_BASE, 1000);
    
    // SOCA 트리거 설정: 카운터=0일 때 발생
    EPWM_enableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
    EPWM_setADCTriggerSource(EPWM1_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_ZERO);
    EPWM_setADCTriggerEventPrescale(EPWM1_BASE, EPWM_SOC_A, 1);
    
    // ePWM 모듈 활성화
    EPWM_enableModule(EPWM1_BASE);
}

void main(void)
{
    // 시스템 클럭 및 주변 장치 초기화
    Device_init();
    
    // GPIO 기본 초기화
    Device_initGPIO();
    
    // ePWM 및 ADC 관련 GPIO 설정
    initGPIO();
    
    // 인터럽트 모듈 초기화
    Interrupt_initModule();
    Interrupt_initVectorTable();
    
    // ADC 인터럽트 ISR 등록
    Interrupt_register(INT_ADCA_1, &adcA1ISR);
    
    // 시스템 클럭 확인
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
    if (sysClockHz != 200000000)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // ADC 설정: 50MHz 클럭, 12비트, ePWM1_SOCA 트리거
    ADC_setPrescaler(ADCA_BASE, ADC_CLK_DIV_4_0);
    ADC_setVREF(ADCA_BASE, ADC_REFERENCE_INTERNAL, ADC_REFERENCE_3_3V);
    ADC_setMode(ADCA_BASE, ADC_RESOLUTION_12BIT, ADC_MODE_SINGLE_ENDED);
    ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM1_SOCA, ADC_CH_ADCIN0, 15);
    ADC_setInterruptSOCTrigger(ADCA_BASE, ADC_SOC_NUMBER0, ADC_INT_NUMBER1);
    ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);
    ADC_enableConverter(ADCA_BASE);
    
    // ADC 안정화를 위해 1ms 지연
    DEVICE_DELAY_US(1000);
    
    // ePWM1 초기화
    initEPWM();
    
    // ePWM 초기화 오류 확인
    if (pwmStatus != 1)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // 글로벌 인터럽트 활성화
    EINT;
    
    // Watchdog 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
    SysCtl_serviceWatchdog();
    
    // 무한 루프
    for(;;)
    {
        // 디버깅용: 상태 표시
        GPIO_writePin(31, (pwmStatus == 1) ? 1 : 0);
        DEVICE_DELAY_US(1000000);
    }
}
    

설명:

  • 기능: ePWM1의 SOCA 신호로 ADC-A의 ADCIN0 채널 변환 트리거.
  • ePWM 설정: 100kHz PWM, 카운터=0일 때 SOCA 트리거.
  • ADC 설정: 12비트, ePWM1_SOCA 트리거.
  • GPIO: GPIO0(ePWM1A), GPIO31(LED).
  • 결과: ADC 변환 결과는 adcResults 버퍼에 저장, 정상 동작 시 LED ON.

4.4. 예제 4: 데드밴드를 사용한 상보 PWM

ePWM1의 PWM_A와 PWM_B를 상보적으로 설정하고 데드밴드를 적용합니다.


#include "driverlib.h"
#include "device.h"

// 디버깅용 상태 변수
volatile uint32_t pwmStatus = 0;

// GPIO 초기화 함수
void initGPIO(void)
{
    // GPIO0을 ePWM1A로 설정
    GPIO_setPinConfig(GPIO_0_EPWM1A);
    GPIO_setDirectionMode(0, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(0, GPIO_PULL_UP);
    
    // GPIO1을 ePWM1B로 설정
    GPIO_setPinConfig(GPIO_1_EPWM1B);
    GPIO_setDirectionMode(1, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(1, GPIO_PULL_UP);
    
    // 디버깅용 LED 설정 (GPIO31)
    GPIO_setPinConfig(GPIO_31_GPIO31);
    GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(31, GPIO_PULL_UP);
    GPIO_writePin(31, 0);
}

void initEPWM(void)
{
    // ePWM1 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
    
    // 주기 설정: 100kHz PWM
    EPWM_setTimeBasePeriod(EPWM1_BASE, 2000);
    EPWM_setCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
    
    // PWM_A 동작 설정
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO, EPWM_AQ_OUTPUT_HIGH);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_UP, EPWM_AQ_OUTPUT_LOW);
    
    // PWM_B 동작 설정 (상보 출력)
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO, EPWM_AQ_OUTPUT_LOW);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_UP, EPWM_AQ_OUTPUT_HIGH);
    
    // 듀티 사이클 50% 설정
    EPWM_setCompareA(EPWM1_BASE, 1000);
    
    // 데드밴드 설정: 100ns (20 사이클 @ 200MHz)
    EPWM_enableDeadBandModule(EPWM1_BASE);
    EPWM_setDeadBandDelay(EPWM1_BASE, 20, 20); // 상승/하강 에지 지연
    
    // ePWM 모듈 활성화
    EPWM_enableModule(EPWM1_BASE);
    
    // 상태 업데이트
    pwmStatus = 1;
}

void main(void)
{
    // 시스템 클럭 및 주변 장치 초기화
    Device_init();
    
    // GPIO 기본 초기화
    Device_initGPIO();
    
    // ePWM 관련 GPIO 설정
    initGPIO();
    
    // 인터럽트 모듈 초기화 (확장성을 위해 포함)
    Interrupt_initModule();
    Interrupt_initVectorTable();
    
    // 시스템 클럭 확인
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
    if (sysClockHz != 200000000)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // ePWM1 초기화
    initEPWM();
    
    // ePWM 초기화 오류 확인
    if (pwmStatus != 1)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // 글로벌 인터럽트 활성화
    EINT;
    
    // Watchdog 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
    SysCtl_serviceWatchdog();
    
    // 무한 루프
    for(;;)
    {
        // 디버깅용: 상태 표시
        GPIO_writePin(31, (pwmStatus == 1) ? 1 : 0);
        DEVICE_DELAY_US(1000000);
    }
}
    

설명:

  • 기능: ePWM1의 PWM_A와 PWM_B로 상보 PWM 신호 생성, 100ns 데드밴드 적용.
  • 설정: 100kHz PWM, 50% 듀티, 데드밴드 모듈 활성화.
  • GPIO: GPIO0(ePWM1A), GPIO1(ePWM1B), GPIO31(LED).
  • 출력: PWM_A와 PWM_B는 상보적이며, 스위칭 충돌 방지를 위해 100ns 지연, 정상 동작 시 LED ON.
  • 용도: 모터 드라이버 또는 인버터 제어에 적합.

4.5. 예제 5: 동기화된 다중 ePWM 모듈

ePWM1과 ePWM2를 동기화하여 동일한 주기로 PWM 신호를 생성합니다.


#include "driverlib.h"
#include "device.h"

// 디버깅용 상태 변수
volatile uint32_t pwmStatus = 0;

// GPIO 초기화 함수
void initGPIO(void)
{
    // GPIO0을 ePWM1A로 설정
    GPIO_setPinConfig(GPIO_0_EPWM1A);
    GPIO_setDirectionMode(0, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(0, GPIO_PULL_UP);
    
    // GPIO2을 ePWM2A로 설정
    GPIO_setPinConfig(GPIO_2_EPWM2A);
    GPIO_setDirectionMode(2, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(2, GPIO_PULL_UP);
    
    // 디버깅용 LED 설정 (GPIO31)
    GPIO_setPinConfig(GPIO_31_GPIO31);
    GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(31, GPIO_PULL_UP);
    GPIO_writePin(31, 0);
}

// ePWM1 및 ePWM2 초기화 함수
void initEPWM(void)
{
    // ePWM1, ePWM2 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM2);
    
    // ePWM1 주기 설정: 100kHz PWM
    EPWM_setTimeBasePeriod(EPWM1_BASE, 2000);
    EPWM_setCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
    
    // ePWM2 주기 설정: ePWM1과 동일
    EPWM_setTimeBasePeriod(EPWM2_BASE, 2000);
    EPWM_setCounterMode(EPWM2_BASE, EPWM_COUNTER_MODE_UP);
    
    // ePWM2를 ePWM1과 동기화
    EPWM_enablePhaseShift(EPWM2_BASE);
    EPWM_setPhaseShift(EPWM2_BASE, 0); // 위상 지연 없음
    EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO);
    EPWM_setSyncInSource(EPWM2_BASE, EPWM_SYNC_IN_SRC_EPWM1SYNCO);
    
    // ePWM1 PWM_A 동작 설정
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO, EPWM_AQ_OUTPUT_HIGH);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_UP, EPWM_AQ_OUTPUT_LOW);
    EPWM_setCompareA(EPWM1_BASE, 1000); // 50% 듀티
    
    // ePWM2 PWM_A 동작 설정 (ePWM1과 동일 듀티)
    EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO, EPWM_AQ_OUTPUT_HIGH);
    EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_UP, EPWM_AQ_OUTPUT_LOW);
    EPWM_setCompareA(EPWM2_BASE, 1000);
    
    // ePWM 모듈 활성화
    EPWM_enableModule(EPWM1_BASE);
    EPWM_enableModule(EPWM2_BASE);
    
    // 상태 업데이트
    pwmStatus = 1;
}

void main(void)
{
    // 시스템 클럭 및 주변 장치 초기화
    Device_init();
    
    // GPIO 기본 초기화
    Device_initGPIO();
    
    // ePWM 관련 GPIO 설정
    initGPIO();
    
    // 인터럽트 모듈 초기화
    Interrupt_initModule();
    Interrupt_initVectorTable();
    
    // 시스템 클럭 확인
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
    if (sysClockHz != 200000000)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // ePWM1, ePWM2 초기화
    initEPWM();
    
    // 초기화 오류 확인
    if (pwmStatus != 1)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // 글로벌 인터럽트 활성화
    EINT;
    
    // Watchdog 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
    SysCtl_serviceWatchdog();
    
    // 무한 루프
    for(;;)
    {
        // 디버깅용: 상태 표시
        GPIO_writePin(31, (pwmStatus == 1) ? 1 : 0);
        DEVICE_DELAY_US(1000000);
    }
}
    

설명:

  • 기능: ePWM1과 ePWM2를 동기화하여 100kHz, 50% 듀티 사이클 PWM 신호 생성.
  • 설정: ePWM1이 마스터, ePWM2가 동기화된 슬레이브. 동일 주기 및 듀티.
  • GPIO: GPIO0(ePWM1A), GPIO2(ePWM2A), GPIO31(LED).
  • 출력: 동기화된 PWM 신호 출력, 정상 동작 시 LED ON.
  • 용도: 다상 모터 제어 또는 동기화된 전력 변환.

4.6. 예제 6: HRPWM(고해상도 PWM)

ePWM1에서 HRPWM을 사용하여 나노초 단위의 정밀 듀티 사이클을 제어합니다.


#include "driverlib.h"
#include "device.h"

// 디버깅용 상태 변수
volatile uint32_t pwmStatus = 0;

// GPIO 초기화 함수
void initGPIO(void)
{
    // GPIO0을 ePWM1A로 설정
    GPIO_setPinConfig(GPIO_0_EPWM1A);
    GPIO_setDirectionMode(0, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(0, GPIO_PULL_UP);
    
    // 디버깅용 LED 설정 (GPIO31)
    GPIO_setPinConfig(GPIO_31_GPIO31);
    GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(31, GPIO_PULL_UP);
    GPIO_writePin(31, 0);
}

// ePWM1 HRPWM 초기화 함수
void initEPWM(void)
{
    // ePWM1 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
    
    // 주기 설정: 100kHz PWM (200MHz / 2000 = 100kHz)
    EPWM_setTimeBasePeriod(EPWM1_BASE, 2000);
    EPWM_setCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
    
    // PWM_A 동작 설정
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO, EPWM_AQ_OUTPUT_HIGH);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_UP, EPWM_AQ_OUTPUT_LOW);
    
    // 듀티 사이클 50% 설정 (CMPA = period/2)
    EPWM_setCompareA(EPWM1_BASE, 1000);
    
    // HRPWM 활성화
    EPWM_enableHRPWM(EPWM1_BASE);
    EPWM_setHRPWMCompareValue(EPWM1_BASE, EPWM_HRCMP_A, 8); // 8 MEP 스텝 추가 (약 40ns @ 200MHz)
    
    // ePWM 모듈 활성화
    EPWM_enableModule(EPWM1_BASE);
    
    // 상태 업데이트
    pwmStatus = 1;
}

void main(void)
{
    // 시스템 클럭 및 주변 장치 초기화
    Device_init();
    
    // GPIO 기본 초기화
    Device_initGPIO();
    
    // ePWM 관련 GPIO 설정
    initGPIO();
    
    // 인터럽트 모듈 초기화
    Interrupt_initModule();
    Interrupt_initVectorTable();
    
    // 시스템 클럭 확인
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
    if (sysClockHz != 200000000)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // ePWM1 초기화
    initEPWM();
    
    // 초기화 오류 확인
    if (pwmStatus != 1)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // 글로벌 인터럽트 활성화
    EINT;
    
    // Watchdog 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
    SysCtl_serviceWatchdog();
    
    // 무한 루프
    for(;;)
    {
        // 디버깅용: 상태 표시
        GPIO_writePin(31, (pwmStatus == 1) ? 1 : 0);
        DEVICE_DELAY_US(1000000);
    }
}
    

설명:

  • 기능: ePWM1에서 HRPWM을 사용하여 100kHz, 약 50%+40ns 듀티 사이클 PWM 신호 생성.
  • 설정: HRPWM 활성화, MEP(Micro Edge Positioner)로 정밀 제어.
  • GPIO: GPIO0(ePWM1A), GPIO31(LED).
  • 출력: 정밀 PWM 신호 출력, 정상 동작 시 LED ON.
  • 용도: 고정밀 전력 변환 또는 고속 스위칭 애플리케이션.

4.7. 예제 7: 트립 존(Trip Zone) 설정

외부 트립 신호로 ePWM1을 비활성화하는 보호 기능을 구현합니다.


#include "driverlib.h"
#include "device.h"

// 디버깅용 상태 변수
volatile uint32_t pwmStatus = 0;

// GPIO 초기화 함수
void initGPIO(void)
{
    // GPIO0을 ePWM1A로 설정
    GPIO_setPinConfig(GPIO_0_EPWM1A);
    GPIO_setDirectionMode(0, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(0, GPIO_PULL_UP);
    
    // GPIO12를 TZ1(트립 존 입력)으로 설정
    GPIO_setPinConfig(GPIO_12_TZ1);
    GPIO_setDirectionMode(12, GPIO_DIR_MODE_IN);
    GPIO_setPadConfig(12, GPIO_PULL_UP);
    
    // 디버깅용 LED 설정 (GPIO31)
    GPIO_setPinConfig(GPIO_31_GPIO31);
    GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(31, GPIO_PULL_UP);
    GPIO_writePin(31, 0);
}

// 트립 존 인터럽트 서비스 루틴
__interrupt void tripZoneISR(void)
{
    // 트립 이벤트 발생 시 PWM 출력 비활성화
    EPWM_forceTripZoneEvent(EPWM1_BASE, EPWM_TZ_FORCE_EVENT_CBC);
    
    // 상태 업데이트
    pwmStatus = 0xFFFF; // 트립 발생
    
    // 인터럽트 플래그 지우기
    EPWM_clearTripZoneFlag(EPWM1_BASE, EPWM_TZ_INTERRUPT_CBC);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP2);
}

void initEPWM(void)
{
    // ePWM1 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
    
    // 주기 설정: 100kHz PWM
    EPWM_setTimeBasePeriod(EPWM1_BASE, 2000);
    EPWM_setCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
    
    // PWM_A 동작 설정
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO, EPWM_AQ_OUTPUT_HIGH);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_UP, EPWM_AQ_OUTPUT_LOW);
    
    // 듀티 사이클 50% 설정
    EPWM_setCompareA(EPWM1_BASE, 1000);
    
    // 트립 존 설정: TZ1 활성화, 트립 시 출력 LOW
    EPWM_enableTripZone(EPWM1_BASE, EPWM_TZ_SIGNAL_CBC1);
    EPWM_setTripZoneAction(EPWM1_BASE, EPWM_TZ_ACTION_EVENT_TZA, EPWM_TZ_ACTION_LOW);
    
    // 트립 존 인터럽트 활성화
    EPWM_enableTripZoneInterrupt(EPWM1_BASE, EPWM_TZ_INTERRUPT_CBC);
    
    // ePWM 모듈 활성화
    EPWM_enableModule(EPWM1_BASE);
    
    // 상태 업데이트
    pwmStatus = 1;
}

void main(void)
{
    // 시스템 클럭 및 주변 장치 초기화
    Device_init();
    
    // GPIO 기본 초기화
    Device_initGPIO();
    
    // ePWM 및 트립 존 관련 GPIO 설정
    initGPIO();
    
    // 인터럽트 모듈 초기화
    Interrupt_initModule();
    Interrupt_initVectorTable();
    
    // 트립 존 인터럽트 ISR 등록
    Interrupt_register(INT_EPWM1_TZ, &tripZoneISR);
    
    // 시스템 클럭 확인
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
    if (sysClockHz != 200000000)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // ePWM1 초기화
    initEPWM();
    
    // 초기화 오류 확인
    if (pwmStatus != 1)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // 글로벌 인터럽트 활성화
    EINT;
    
    // Watchdog 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
    SysCtl_serviceWatchdog();
    
    // 무한 루프
    for(;;)
    {
        // 디버깅용: 상태 표시
        GPIO_writePin(31, (pwmStatus == 1) ? 1 : 0);
        DEVICE_DELAY_US(1000000);
    }
}
    

설명:

  • 기능: ePWM1의 PWM_A 출력으로 100kHz, 50% 듀티 사이클 PWM 신호 생성, TZ1 트립 신호로 출력 비활성화.
  • 설정: 트립 존(TZ1) 활성화, 트립 시 PWM_A LOW.
  • GPIO: GPIO0(ePWM1A), GPIO12(TZ1), GPIO31(LED).
  • 출력: 트립 이벤트 발생 시 PWM 출력 중단, LED OFF.
  • 용도: 모터 제어 시 과전류/과열 보호.

4.8. 예제 8: Up-Down 카운터 모드 PWM

ePWM1을 Up-Down 카운터 모드로 설정하여 대칭 PWM 신호를 생성합니다.


#include "driverlib.h"
#include "device.h"

// 디버깅용 상태 변수
volatile uint32_t pwmStatus = 0;

// GPIO 초기화 함수
void initGPIO(void)
{
    // GPIO0을 ePWM1A로 설정
    GPIO_setPinConfig(GPIO_0_EPWM1A);
    GPIO_setDirectionMode(0, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(0, GPIO_PULL_UP);
    
    // 디버깅용 LED 설정 (GPIO31)
    GPIO_setPinConfig(GPIO_31_GPIO31);
    GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(31, GPIO_PULL_UP);
    GPIO_writePin(31, 0);
}

// ePWM1 초기화 함수 (Up-Down 모드)
void initEPWM(void)
{
    // ePWM1 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
    
    // 주기 설정: 100kHz PWM (200MHz / (2 * 1000) = 100kHz, Up-Down 모드)
    // Up-Down 모드에서는 주기가 TBPRD * 2로 계산
    EPWM_setTimeBasePeriod(EPWM1_BASE, 1000);
    EPWM_setCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN);
    
    // PWM_A 동작 설정: CMPA에서 HIGH/LOW 전환
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_UP, EPWM_AQ_OUTPUT_HIGH);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_DOWN, EPWM_AQ_OUTPUT_LOW);
    
    // 듀티 사이클 50% 설정 (CMPA = period/2)
    EPWM_setCompareA(EPWM1_BASE, 500);
    
    // ePWM 모듈 활성화
    EPWM_enableModule(EPWM1_BASE);
    
    // 상태 업데이트
    pwmStatus = 1;
}

void main(void)
{
    // 시스템 클럭 및 주변 장치 초기화
    Device_init();
    
    // GPIO 기본 초기화
    Device_initGPIO();
    
    // ePWM 관련 GPIO 설정
    initGPIO();
    
    // 인터럽트 모듈 초기화
    Interrupt_initModule();
    Interrupt_initVectorTable();
    
    // 시스템 클럭 확인
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
    if (sysClockHz != 200000000)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // ePWM1 초기화
    initEPWM();
    
    // 초기화 오류 확인
    if (pwmStatus != 1)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // 글로벌 인터럽트 활성화
    EINT;
    
    // Watchdog 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
    SysCtl_serviceWatchdog();
    
    // 무한 루프
    for(;;)
    {
        // 디버깅용: 상태 표시
        GPIO_writePin(31, (pwmStatus == 1) ? 1 : 0);
        DEVICE_DELAY_US(1000000);
    }
}
    

설명:

  • 기능: ePWM1의 PWM_A 출력으로 100kHz, 50% 듀티 사이클 대칭 PWM 신호 생성.
  • 설정: Up-Down 카운터 모드, 주기 1000(100kHz @ 200MHz), CMPA=500.
  • GPIO: GPIO0(ePWM1A), GPIO31(LED).
  • 출력: 대칭 PWM 신호 출력, 정상 동작 시 LED ON.
  • 용도: 모터 제어, 인버터에서 대칭 PWM 필요 시 적합.

4.9. 예제 9: 페이즈 시프트 PWM

ePWM1과 ePWM2를 동기화하되, 90도 페이즈 차이로 PWM 신호를 생성합니다.


#include "driverlib.h"
#include "device.h"

// 디버깅용 상태 변수
volatile uint32_t pwmStatus = 0;

// GPIO 초기화 함수
void initGPIO(void)
{
    // GPIO0을 ePWM1A로 설정
    GPIO_setPinConfig(GPIO_0_EPWM1A);
    GPIO_setDirectionMode(0, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(0, GPIO_PULL_UP);
    
    // GPIO2을 ePWM2A로 설정
    GPIO_setPinConfig(GPIO_2_EPWM2A);
    GPIO_setDirectionMode(2, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(2, GPIO_PULL_UP);
    
    // 디버깅용 LED 설정 (GPIO31)
    GPIO_setPinConfig(GPIO_31_GPIO31);
    GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(31, GPIO_PULL_UP);
    GPIO_writePin(31, 0);
}

// ePWM1 및 ePWM2 초기화 함수 (페이즈 시프트)
void initEPWM(void)
{
    // ePWM1, ePWM2 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM2);
    
    // ePWM1 주기 설정: 100kHz PWM
    EPWM_setTimeBasePeriod(EPWM1_BASE, 2000);
    EPWM_setCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
    
    // ePWM2 주기 설정: ePWM1과 동일
    EPWM_setTimeBasePeriod(EPWM2_BASE, 2000);
    EPWM_setCounterMode(EPWM2_BASE, EPWM_COUNTER_MODE_UP);
    
    // ePWM2를 ePWM1과 동기화, 90도 페이즈 시프트 (2000 * 0.25 = 500)
    EPWM_enablePhaseShift(EPWM2_BASE);
    EPWM_setPhaseShift(EPWM2_BASE, 500); // 90도 위상 지연
    EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO);
    EPWM_setSyncInSource(EPWM2_BASE, EPWM_SYNC_IN_SRC_EPWM1SYNCO);
    
    // ePWM1 PWM_A 동작 설정
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO, EPWM_AQ_OUTPUT_HIGH);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_UP, EPWM_AQ_OUTPUT_LOW);
    EPWM_setCompareA(EPWM1_BASE, 1000); // 50% 듀티
    
    // ePWM2 PWM_A 동작 설정
    EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO, EPWM_AQ_OUTPUT_HIGH);
    EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_UP, EPWM_AQ_OUTPUT_LOW);
    EPWM_setCompareA(EPWM2_BASE, 1000);
    
    // ePWM 모듈 활성화
    EPWM_enableModule(EPWM1_BASE);
    EPWM_enableModule(EPWM2_BASE);
    
    // 상태 업데이트
    pwmStatus = 1;
}

void main(void)
{
    // 시스템 클럭 및 주변 장치 초기화
    Device_init();
    
    // GPIO 기본 초기화
    Device_initGPIO();
    
    // ePWM 관련 GPIO 설정
    initGPIO();
    
    // 인터럽트 모듈 초기화
    Interrupt_initModule();
    Interrupt_initVectorTable();
    
    // 시스템 클럭 확인
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
    if (sysClockHz != 200000000)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // ePWM1, ePWM2 초기화
    initEPWM();
    
    // 초기화 오류 확인
    if (pwmStatus != 1)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // 글로벌 인터럽트 활성화
    EINT;
    
    // Watchdog 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
    SysCtl_serviceWatchdog();
    
    // 무한 루프
    for(;;)
    {
        // 디버깅용: 상태 표시
        GPIO_writePin(31, (pwmStatus == 1) ? 1 : 0);
        DEVICE_DELAY_US(1000000);
    }
}
    

설명:

  • 기능: ePWM1과 ePWM2를 동기화하되, 90도 페이즈 차이로 100kHz, 50% 듀티 사이클 PWM 신호 생성.
  • 설정: ePWM1이 마스터, ePWM2가 90도 위상 지연 슬레이브.
  • GPIO: GPIO0(ePWM1A), GPIO2(ePWM2A), GPIO31(LED).
  • 출력: 페이즈 시프트 PWM 신호 출력, 정상 동작 시 LED ON.
  • 용도: 다상 전력 변환, 3상 인버터 제어.

4.10. 예제 10: PWM 주파수 동적 변경

인터럽트를 사용하여 ePWM1의 PWM 주파수를 동적으로 변경합니다.


#include "driverlib.h"
#include "device.h"

// 디버깅용 상태 변수
volatile uint32_t pwmStatus = 0;

// 주기 저장 변수 (초기 100kHz, TBPRD=2000)
volatile uint16_t pwmPeriod = 2000;

// GPIO 초기화 함수
void initGPIO(void)
{
    // GPIO0을 ePWM1A로 설정
    GPIO_setPinConfig(GPIO_0_EPWM1A);
    GPIO_setDirectionMode(0, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(0, GPIO_PULL_UP);
    
    // 디버깅용 LED 설정 (GPIO31)
    GPIO_setPinConfig(GPIO_31_GPIO31);
    GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(31, GPIO_PULL_UP);
    GPIO_writePin(31, 0);
}

// 인터럽트 서비스 루틴 (ISR)
__interrupt void epwm1ISR(void)
{
    // 주기 변경: 100kHz → 50kHz → 25kHz 순환
    if (pwmPeriod == 2000) // 100kHz
    {
        pwmPeriod = 4000; // 50kHz
        EPWM_setCompareA(EPWM1_BASE, 2000); // 50% 듀티 유지
    }
    else if (pwmPeriod == 4000) // 50kHz
    {
        pwmPeriod = 8000; // 25kHz
        EPWM_setCompareA(EPWM1_BASE, 4000); // 50% 듀티 유지
    }
    else // 25kHz
    {
        pwmPeriod = 2000; // 100kHz로 복귀
        EPWM_setCompareA(EPWM1_BASE, 1000); // 50% 듀티 유지
    }
    
    // 주기 업데이트
    EPWM_setTimeBasePeriod(EPWM1_BASE, pwmPeriod);
    
    // 인터럽트 플래그 지우기
    EPWM_clearInterruptStatus(EPWM1_BASE);
    
    // PIE 인터럽트 ACK
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    
    // 상태 업데이트
    pwmStatus = 1;
}

void initEPWM(void)
{
    // ePWM1 클럭 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
    
    // 초기 주기 설정: 100kHz PWM
    EPWM_setTimeBasePeriod(EPWM1_BASE, pwmPeriod);
    EPWM_setCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
    
    // PWM_A 동작 설정
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO, EPWM_AQ_OUTPUT_HIGH);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, 
                                 EPWM_AQ_OUTPUT_ON_TIMEBASE_CMPA_UP, EPWM_AQ_OUTPUT_LOW);
    
    // 초기 듀티 사이클 50% 설정
    EPWM_setCompareA(EPWM1_BASE, pwmPeriod / 2);
    
    // 인터럽트 설정: 카운터=0일 때 발생
    EPWM_setInterruptSource(EPWM1_BASE, EPWM_INT_TBCTR_ZERO);
    EPWM_enableInterrupt(EPWM1_BASE);
    
    // ePWM 모듈 활성화
    EPWM_enableModule(EPWM1_BASE);
}

void main(void)
{
    // 시스템 클럭 및 주변 장치 초기화
    Device_init();
    
    // GPIO 기본 초기화
    Device_initGPIO();
    
    // ePWM 관련 GPIO 설정
    initGPIO();
    
    // 인터럽트 모듈 초기화
    Interrupt_initModule();
    Interrupt_initVectorTable();
    
    // ePWM1 인터럽트 ISR 등록
    Interrupt_register(INT_EPWM1, &epwm1ISR);
    
    // 시스템 클럭 확인
    uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
    if (sysClockHz != 200000000)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // ePWM1 초기화
    initEPWM();
    
    // 초기화 오류 확인
    if (pwmStatus != 1)
    {
        pwmStatus = 0xFFFF;
        GPIO_writePin(31, 0);
        ESTOP0;
    }
    
    // 글로벌 인터럽트 활성화
    EINT;
    
    // Watchdog 활성화
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
    SysCtl_serviceWatchdog();
    
    // 무한 루프
    for(;;)
    {
        // 디버깅용: 상태 표시
        GPIO_writePin(31, (pwmStatus == 1) ? 1 : 0);
        DEVICE_DELAY_US(1000000);
    }
}
    

설명:

  • 기능: ePWM1의 PWM_A 출력으로 100kHz, 50kHz, 25kHz 주파수를 순환하며 PWM 신호 생성.
  • 설정: 인터럽트로 TBPRD 업데이트, 50% 듀티 유지.
  • GPIO: GPIO0(ePWM1A), GPIO31(LED).
  • 출력: 주파수 변화 PWM 신호 출력, 정상 동작 시 LED ON.
  • 용도: 가변 주파수 드라이브, 조명 제어.

5. 추가 고려 사항

  • 주기와 듀티 계산: PWM 주기는 TBPRD = (SYSCLK / (PWM_FREQ * CLKDIV))로 계산. Up-Down 모드에서는 TBPRD * 2. 예: 200MHz 클럭, 100kHz PWM → TBPRD=2000(Up), 1000(Up-Down).
  • HRPWM: 고해상도 PWM은 나노초 단위 정밀 제어를 제공. 보정 필요 시 HRPWM_calibrateMEP 호출.
  • 데드밴드: 모터 제어 시 스위칭 충돌 방지를 위해 필수.
  • GPIO 설정: initGPIO() 함수로 ePWM 관련 핀 설정을 분리하여 코드 가독성과 유지보수성 향상.
  • C2000Ware: 예제 코드는 C2000Ware의 DriverLib 기반. C:\ti\c2000에 설치.
  • 디버깅: Code Composer Studio의 .syscfg 툴로 ePWM 및 GPIO 설정 시각적 구성 가능.

키워드: TMS320F28388D, ePWM, DriverLib, C2000, PWM, 마이크로컨트롤러, Code Composer Studio, ADC 트리거, 데드밴드, 상보 PWM, HRPWM, 트립 존, 동기화, 페이즈 시프트, Up-Down 카운터

반응형