본문 바로가기
MCU/C2000

[TI C2000]TI TMS320F280049C DSP를 적용한 동기 벅 컨버터 설계 - PCMC

by linuxgo 2025. 8. 21.
반응형

1. 개요

이 문서는 TI TMS320F280049C 마이크로컨트롤러(MCU)를 활용하여 피크 전류 모드 제어(PCMC) 기반 동기 벅 컨버터를 설계하는 절차를 설명합니다. 설계는 Power ON 소프트 스타트, 경사 보상, 과전류(OCP), 과전압(OVP), 과열(OTP) 보호, 타이머 기반 복구 로직, SCI(UART) 통신을 통한 모니터링 및 설정 기능을 포함합니다. LEVEL 매크로를 사용하여 PWM, ADC, SCI, 타이머, 전체 제어 루프를 단계별로 검증할 수 있으며, TI DCL 라이브러리를 사용하지 않고 순수 C로 PI 제어기를 구현합니다.

1.1. 설계 사양

  • 입력 전압: 12 V ~ 24 V
  • 출력 전압: 5 V (UART로 조정 가능)
  • 출력 전류: 최대 3 A (UART로 제한 설정 가능)
  • 스위칭 주파수: 200 kHz
  • MCU: TMS320F280049C (100 MHz SYSCLK)
  • GPIO 핀:
    • ePWM1A (GPIO0): 고측 MOSFET
    • ePWM1B (GPIO1): 저측 MOSFET
    • ADCINA0 (핀 16): 출력 전압 피드백
    • ADCINA1 (핀 17): 인덕터 전류 피드백
    • ADCINA2 (핀 18): 온도 센서 (NTC 서미스터)
    • SCIRXDA (GPIO28): UART 수신
    • SCITXDA (GPIO29): UART 송신
  • ADC: 12비트, 3.3 V 기준
  • 션트 저항: 10 mΩ
  • 증폭 게인: 10배
  • 보호 임계값:
    • OCP: 3.5 A (UART로 조정 가능)
    • OVP: 5.5 V
    • OTP: ~85°C (NTC 전압 2 V, 10 kΩ NTC 및 10 kΩ 분압 저항 기준)
  • 소프트 스타트: 10 ms (2000 스위칭 주기, UART로 조정 가능)
  • 복구 타이머: 1초 후 재시작 (Timer0)
  • 경사 보상 (PCMC): 램프 기울기 0.5 A/µs
  • 통신:
    • SCI-A, 115200 baud, 8-N-1
    • 모니터링: MONITOR:V=<전압>,I=<전류>,T=<온도>,F=<상태>
    • 설정: VSET:<값>, ISET:<값>, SSET:<값>
  • 검증 레벨:
    • LEVEL_1: GPIO 및 PWM 테스트
    • LEVEL_2: ADC 테스트
    • LEVEL_3: SCI 테스트
    • LEVEL_4: 타이머 및 복구 로직 테스트
    • LEVEL_5: 전체 제어 루프(PCMC, 소프트 스타트, 경사 보상, 보호, SCI)
  • 개발 환경: CCS, C2000Ware
  • 참고 자료: TI TIDM-DC-DC-BUCK, C2000Ware 예제

2. 설계 절차

2.1. 하드웨어 설계

2.1.1. 전력단 구성

  • MOSFET: N-채널 MOSFET (예: CSD18532Q5B, 60 V, 100 A), 낮은 $R_{ds(on)}$과 빠른 스위칭.
  • 인덕터 ($L$):
    리플 전류($\Delta I_L$)를 출력 전류의 30%로 설정:
    $$ \Delta I_L = 0.3 \cdot I_{out} = 0.3 \cdot 3 = 0.9 , \text{A} $$
    인덕터 값 계산:
    $$ L = \frac{V_{in} - V_{out}}{f_{sw} \cdot \Delta I_L} \cdot \frac{V_{out}}{V_{in}} $$
    최악 조건($V_{in} = 24 , \text{V}$, $V_{out} = 5 , \text{V}$, $f_{sw} = 200 , \text{kHz}$):
    $$ L = \frac{24 - 5}{200 \cdot 10^3 \cdot 0.9} \cdot \frac{5}{24} \approx 10 , \mu\text{H} $$
    선택: 10 µH, 정격 전류 3 A 이상.
  • 출력 커패시터 ($C_{out}$):
    출력 전압 리플($\Delta V_{out}$)을 50 mV 미만으로:
    $$ C_{out} = \frac{\Delta I_L}{8 \cdot f_{sw} \cdot \Delta V_{out}} $$
    계산:
    $$ C_{out} = \frac{0.9}{8 \cdot 200 \cdot 10^3 \cdot 0.05} \approx 112.5 , \mu\text{F} $$
    선택: 100 µF, 저ESR 커패시터.
  • 션트 저항: 10 mΩ, 전력 등급:
    $$ P = I_{out}^2 \cdot R_{shunt} = 3^2 \cdot 0.01 = 0.09 , \text{W} $$
    선택: 0.25 W 이상.
  • 게이트 드라이버: UCC27211, 50 ns 데드타임.

2.1.2. 신호 조절

  • 전압 피드백:
    분압 저항으로 ADC 범위(0~3.3 V) 조정:
    $$ V_{out_{ADC}} = V_{out} \cdot \frac{R_2}{R_1 + R_2} $$
    $R_1 = 10 , \text{k}\Omega$, $R_2 = 15 , \text{k}\Omega$:
    $$ V_{out_{ADC}} = 5 \cdot \frac{15}{10 + 15} = 3 , \text{V} $$
  • 전류 피드백:
    션트 전압 증폭($G_I = 10$):
    $$ V_{ADC} = I_{out} \cdot R_{shunt} \cdot G_I = I_{out} \cdot 0.01 \cdot 10 $$
    $I_{out} = 3 , \text{A}$:
    $$ V_{ADC} = 0.3 , \text{V} $$
  • 온도 피드백: NTC 10 kΩ, 85°C에서 ~2 V.

2.1.3. 핀 배치

  • GPIO0 (ePWM1A), GPIO1 (ePWM1B), ADCINA0/1/2 (핀 16/17/18).
  • GPIO28 (SCIRXDA), GPIO29 (SCITXDA).

2.1.4. 하드웨어 주의사항

  • 핀 충돌: SCI-A (GPIO28/29)와 SPI 충돌 확인 (SPRSP45).
  • EMC: 스너버 회로, 짧은 트레이스.
  • UART: 3.3 V TTL, 외부 RS-232 변환기(예: MAX3232) 필요 시 사용.

2.2. 소프트웨어 설계 (PCMC)

소프트웨어는 PCMC를 구현하며, 전류 및 전압 루프, 소프트 스타트, 경사 보상, 보호, 복구 로직, SCI 통신을 포함하고, LEVEL 매크로로 단계별 검증을 지원하고 TI DCL 라이브러리를 사용하지 않고 순수 C로 PI 제어기를 구현되었습니다

2.2.1. 공통 설정

  • 시스템 클럭: 100 MHz.
  • PWM: 200 kHz, TBPRD = 500, 50 ns 데드밴드.
  • ADC: 12비트, ePWM1 SOCA 트리거.
  • SCI: 115200 baud, GPIO28/29, 인터럽트 기반.
  • 소프트 스타트: 10 ms, UART로 조정.
  • PI 게인: powerSUITE로 튜닝 ($K_p = 0.5$, $K_i = 0.01$).
  • 경사 보상 (PCMC):
    $$ m_a = 0.5 , \text{A}/\mu\text{s}, \quad m_2 = \frac{V_{out}}{L} = 0.5 , \text{A}/\mu\text{s} $$
  • LEVEL 정의:
    • LEVEL_1: GPIO 및 PWM 초기화, 고정 듀티(50%) 출력.
    • LEVEL_2: ADC 초기화, 센싱 데이터 SCI 전송.
    • LEVEL_3: SCI 초기화, 테스트 메시지 송수신.
    • LEVEL_4: 타이머 초기화, 주기적 플래그 토글.
    • LEVEL_5: 전체 제어 루프(PCMC, 소프트 스타트, 경사 보상, 보호, SCI).

2.2.2. PCMC 구현 (pcmc_control.c)

코드

#include "F28x_project.h" // TI C2000 헤더 파일: 레지스터 정의 및 DriverLib 포함

// 단계별 검증을 위한 LEVEL 매크로 정의 (1~5)
#define LEVEL 5 // 검증 레벨 설정: 1(PWM), 2(ADC), 3(SCI), 4(타이머), 5(전체)

// 설정 파라미터 정의 (매크로 상수)
#define VREF_DEFAULT 5.0f      // 기본 목표 출력 전압 (5V, UART로 조정 가능)
#define VOVP 5.5f              // 과전압 보호 임계값 (5.5V)
#define IREF_MAX_DEFAULT 3.5f  // 기본 피크 전류 제한 (3.5A, UART로 조정 가능)
#define TEMP_MAX 2.0f          // 과열 보호 임계값 (NTC 전압 2V, 약 85°C)
#define ADC_VREF 3.3f          // ADC 기준 전압 (3.3V, 12비트 ADC)
#define PWM_FREQ 200000        // PWM 스위칭 주파수 (200kHz)
#define TBPRD 500              // PWM 주기 레지스터 값 (100MHz / 200kHz = 500)
#define SHUNT_R 0.01f          // 션트 저항 값 (10mΩ, 전류 센싱용)
#define GAIN_I 10.0f           // 전류 증폭 게인 (10배, INA240 등 사용)
#define ADC_SCALE (ADC_VREF / 4096.0f) // ADC 스케일링 인자 (12비트: 3.3V / 4096)
#define RECOVERY_TIME 100000000 // 복구 타이머 주기 (1초, 100MHz SYSCLK 기준)
#define SOFT_START_STEPS_DEFAULT 2000 // 기본 소프트 스타트 주기 수 (10ms, 200kHz)
#define SOFT_START_STEP_I (3.0f / SOFT_START_STEPS_DEFAULT) // 소프트 스타트 전류 증가량
#define SLOPE_MA 0.5f          // 경사 보상 기울기 (0.5 A/µs, 서브하모닉 발진 방지)
#define TS (1.0f / PWM_FREQ)   // 스위칭 주기 (µs, 200kHz 기준)
#define SCI_BAUD 115200        // SCI(UART) 통신 속도 (115200 baud)
#define SCI_LSPCLK 25000000    // SCI용 저속 클럭 (25MHz)
#define KP 0.5f                // PI 제어기 비례 게인 (powerSUITE로 튜닝)
#define KI 0.01f               // PI 제어기 적분 게인 (powerSUITE로 튜닝)
#define UMAX 0.95f             // PI 출력 최대 제한 (95%)
#define UMIN 0.05f             // PI 출력 최소 제한 (5%)

// 전역 변수 선언
float vout, iout, temp, error, iref; // 출력 전압(V), 전류(A), 온도 전압(V), 제어 오차, 전류 기준(A)
float vref = VREF_DEFAULT;           // 목표 전압 (V, UART로 동적 조정)
float iref_max = IREF_MAX_DEFAULT;   // 피크 전류 제한 (A, UART로 동적 조정)
float iref_soft = 0.0f;              // 소프트 스타트용 전류 기준 (A, 0에서 3A까지 증가)
float ramp = 0.0f;                   // 경사 보상 램프 신호 (A)
float integral = 0.0f;               // PI 제어기 적분 항
uint16_t soft_start_steps = SOFT_START_STEPS_DEFAULT; // 소프트 스타트 주기 수 (UART로 조정)
float soft_start_step_i;              // 소프트 스타트 전류 증가량 (A/step)
volatile uint16_t adc_vout, adc_iout, adc_temp; // ADC 변환 결과 (전압, 전류, 온도)
volatile bool fault = false;          // 보호 동작 플래그 (OCP, OVP, OTP 발생 시 true)
volatile bool recovery_trigger = false; // 복구 타이머 트리거 플래그
volatile uint16_t soft_start_counter = 0; // 소프트 스타트 진행 카운터
volatile bool soft_start_complete = false; // 소프트 스타트 완료 플래그
char rx_buffer[32];                  // SCI 수신 버퍼 (최대 32바이트, 설정 명령 저장)
volatile uint16_t rx_index = 0;       // 수신 버퍼 현재 인덱스
volatile bool rx_complete = false;    // 수신 완료 플래그 (CR/LF 수신 시 true)
char tx_buffer[64];                  // SCI 송신 버퍼 (모니터링 데이터 전송용)
volatile bool level_test_flag = false; // LEVEL_4 테스트용 플래그 (타이머 토글)

// PI 제어기 함수: 수동으로 PI 제어 구현
float pi_update(float error, float *integral, float kp, float ki, float umax, float umin) {
    // 비례 항 계산
    float p_term = kp * error;
    // 적분 항 계산
    float i_term = *integral + ki * error * TS; // TS는 샘플링 주기 (1/200kHz)
    // 안티-와인드업: 적분 항 제한
    if (i_term > umax) i_term = umax;
    if (i_term < umin) i_term = umin;
    *integral = i_term; // 적분 항 업데이트
    // PI 출력 계산
    float output = p_term + i_term;
    // 출력 제한
    if (output > umax) output = umax;
    if (output < umin) output = umin;
    return output;
}

// GPIO 초기화 함수: PWM, ADC, SCI 핀 설정
void init_GPIO(void) {
    EALLOW; // 보호 레지스터 접근 허용
    // ePWM1A (GPIO0): 고측 MOSFET 제어 (PWM 출력)
    GpioCtrlRegs.GPAGMUX.bit.GPIO0 = 0; // GPIO0을 기본 GPIO로 설정
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // GPIO0을 ePWM1A로 설정
    // ePWM1B (GPIO1): 저측 MOSFET 제어 (PWM 출력)
    GpioCtrlRegs.GPAGMUX.bit.GPIO1 = 0; // GPIO1을 기본 GPIO로 설정
    GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // GPIO1을 ePWM1B로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO0 = 1;  // GPIO0 출력 설정
    GpioCtrlRegs.GPADIR.bit.GPIO1 = 1;  // GPIO1 출력 설정
    GpioCtrlRegs.GPAPUD.bit.GPIO0 = 1;  // GPIO0 풀업 저항 활성화
    GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1;  // GPIO1 풀업 저항 활성화
#if LEVEL >= 2
    // ADCINA0 (핀 16): 출력 전압 센싱
    GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 0; // GPIO16을 ADC로 설정
    GpioCtrlRegs.GPAPUD.bit.GPIO16 = 1;  // 풀업 저항 활성화
    // ADCINA1 (핀 17): 인덕터 전류 센싱
    GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 0; // GPIO17을 ADC로 설정
    GpioCtrlRegs.GPAPUD.bit.GPIO17 = 1;  // 풀업 저항 활성화
    // ADCINA2 (핀 18): 온도 센싱 (NTC 서미스터)
    GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 0; // GPIO18을 ADC로 설정
    GpioCtrlRegs.GPAPUD.bit.GPIO18 = 1;  // 풀업 저항 활성화
#endif
#if LEVEL >= 3
    // SCI-A (GPIO28: RX, GPIO29: TX): UART 통신
    GpioCtrlRegs.GPBMUX1.bit.GPIO28 = 1; // GPIO28을 SCIRXDA로 설정
    GpioCtrlRegs.GPBMUX1.bit.GPIO29 = 1; // GPIO29를 SCITXDA로 설정
    GpioCtrlRegs.GPBDIR.bit.GPIO28 = 0;  // GPIO28 입력 (RX)
    GpioCtrlRegs.GPBDIR.bit.GPIO29 = 1;  // GPIO29 출력 (TX)
    GpioCtrlRegs.GPBPUD.bit.GPIO28 = 1;  // 풀업 저항 활성화
    GpioCtrlRegs.GPBPUD.bit.GPIO29 = 1;  // 풀업 저항 활성화
#endif
    EDIS; // 보호 레지스터 접근 비활성화
}

// ePWM 초기화 함수: 200kHz PWM, 50ns 데드타임, CMPB로 전류 제어
void init_ePWM(void) {
    EALLOW; // 보호 레지스터 접근 허용
    CpuSysRegs.PCLKCR2.bit.EPWM1 = 1; // ePWM1 모듈 클럭 활성화
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Up-Down 카운트 모드
    EPwm1Regs.TBPRD = TBPRD; // PWM 주기 설정 (500 = 100MHz / 200kHz)
    EPwm1Regs.CMPA.bit.CMPA = TBPRD / 2; // LEVEL_1 테스트용 고정 듀티 50%
    EPwm1Regs.CMPB.bit.CMPB = 0; // 초기 전류 비교값 0
    EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // 데드밴드 활성화
    EPwm1Regs.DBRED.bit.DBRED = 5; // 상승 에지 지연 (50ns)
    EPwm1Regs.DBFED.bit.DBFED = 5; // 하강 에지 지연 (50ns)
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // 고속 클럭 분주 1
    EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1; // 클럭 분주 1
    EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // 타이머 0에서 PWM 출력 설정
    EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // CMPA에서 PWM 출력 클리어
    EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR; // CMPB에서 PWM 출력 클리어 (전류 제어)
#if LEVEL >= 2
    EPwm1Regs.ETSEL.bit.SOCAEN = 1; // SOCA 트리거 활성화 (ADC 트리거용)
    EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO; // 타이머 0에서 SOCA 발생
    EPwm1Regs.ETPS.bit.SOCAPRD = 1; // 매 주기마다 SOCA 발생
#endif
    EDIS; // 보호 레지스터 접근 비활성화
}

// ADC 초기화 함수: 전압, 전류, 온도 센싱 설정
void init_ADC(void) {
#if LEVEL >= 2
    EALLOW; // 보호 레지스터 접근 허용
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 인터럽트 펄스 위치 설정
    AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; // ADC 전원 활성화
    AdcaRegs.ADCCTL2.bit.PRESCALE = 2; // ADC 클럭 분주 (SYSCLK/4)
    AdcaRegs.ADCCTL1.bit.ADCBGPWD = 1; // 밴드갭 회로 전원 활성화
    AdcaRegs.ADCCTL1.bit.ADCREFPWD = 1; // 기준 전압 전원 활성화
    AdcaRegs.ADCCTL1.bit.REFSEL = 0; // 내부 3.3V 기준 전압 선택
    // ADC SOC0: 출력 전압 센싱 (ADCINA0)
    AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; // 채널 ADCINA0 선택
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = 15; // 샘플링 윈도우 (15 SYSCLK)
    AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // ePWM1 SOCA로 트리거
    // ADC SOC1: 인덕터 전류 센싱 (ADCINA1)
    AdcaRegs.ADCSOC1CTL.bit.CHSEL = 1; // 채널 ADCINA1 선택
    AdcaRegs.ADCSOC1CTL.bit.ACQPS = 15;
    AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 5;
    // ADC SOC2: 온도 센싱 (ADCINA2)
    AdcaRegs.ADCSOC2CTL.bit.CHSEL = 2; // 채널 ADCINA2 선택
    AdcaRegs.ADCSOC2CTL.bit.ACQPS = 15;
    AdcaRegs.ADCSOC2CTL.bit.TRIGSEL = 5;
    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 2; // SOC2 완료 시 인터럽트 발생
    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; // ADCINT1 활성화
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // 인터럽트 플래그 초기화
    EDIS; // 보호 레지스터 접근 비활성화
#endif
}

// SCI 초기화 함수: UART 통신 설정 (115200 baud, 8-N-1)
void init_SCI(void) {
#if LEVEL >= 3
    EALLOW; // 보호 레지스터 접근 허용
    CpuSysRegs.PCLKCR7.bit.SCI_A = 1; // SCI-A 모듈 클럭 활성화
    SciaRegs.SCICCR.all = 0x0007; // 8비트 데이터, 1 스톱 비트, 패리티 없음
    SciaRegs.SCICTL1.bit.SWRESET = 0; // SCI 리셋
    SciaRegs.SCICTL1.bit.RXENA = 1; // 수신 활성화
    SciaRegs.SCICTL1.bit.TXENA = 1; // 송신 활성화
    SciaRegs.SCICTL2.bit.RXBKINTENA = 1; // 수신 인터럽트 활성화
    // Baud rate 계산: 115200 = LSPCLK / ((BRR + 1) * 8), LSPCLK = 25MHz
    SciaRegs.SCIHBAUD.all = 0; // 상위 바우드 레지스터
    SciaRegs.SCILBAUD.all = 26; // 하위 바우드 레지스터 (BRR = 26)
    SciaRegs.SCICTL1.bit.SWRESET = 1; // SCI 활성화
    EDIS; // 보호 레지스터 접근 비활성화
#endif
}

// 타이머 초기화 함수: 복구 로직용 1초 타이머 설정
void init_timer(void) {
#if LEVEL >= 4
    EALLOW; // 보호 레지스터 접근 허용
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0; // 타이머 클럭 동기화 비활성화
    CPUTimer0Regs.TCR.bit.TSS = 1; // 타이머 정지
    CPUTimer0Regs.PRD.all = RECOVERY_TIME - 1; // 1초 주기 (100MHz 기준)
    CPUTimer0Regs.TCR.bit.TRB = 1; // 주기 리로드
    CPUTimer0Regs.TCR.bit.TIE = 1; // 타이머 인터럽트 활성화
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1; // 타이머 클럭 동기화 활성화
    EDIS; // 보호 레지스터 접근 비활성화
#endif
}

// SCI 송신 함수: 문자열 데이터를 UART로 전송
void sci_transmit(char *data) {
#if LEVEL >= 3
    // 입력 문자열의 각 문자를 순회하며 전송
    while (*data != '\0') {
        while (SciaRegs.SCIFFTX.bit.TXFFST >= 4); // TX FIFO가 가득 찰 때까지 대기
        SciaRegs.SCITXBUF.all = *data++; // 문자 전송
    }
    while (SciaRegs.SCIFFTX.bit.TXFFST != 0); // 전송 완료 대기
#endif
}

// 모니터링 데이터 전송 함수: 전압, 전류, 온도, 보호 상태 전송
void send_monitoring_data(void) {
#if LEVEL >= 3
    // 모니터링 데이터 포맷: MONITOR:V=5.00,I=2.50,T=1.80,F=0
    sprintf(tx_buffer, "MONITOR:V=%.2f,I=%.2f,T=%.2f,F=%d\r\n", vout, iout, temp, fault);
    sci_transmit(tx_buffer); // SCI로 데이터 전송
#endif
}

// SCI 수신 데이터 처리 함수: UART로 수신된 설정 명령 처리
void process_sci_data(void) {
#if LEVEL >= 3
    if (!rx_complete) return; // 수신 완료 플래그 확인
    rx_complete = false; // 플래그 초기화
    // 테스트 명령 처리 (LEVEL_3 테스트용)
    if (strncmp(rx_buffer, "TEST:", 5) == 0) {
        sprintf(tx_buffer, "LEVEL_3: ECHO=%s\r\n", &rx_buffer[5]); // 수신 데이터 에코
        sci_transmit(tx_buffer);
    }
#if LEVEL >= 5
    // 목표 전압 설정 (예: VSET:4.5)
    else if (strncmp(rx_buffer, "VSET:", 5) == 0) {
        float new_vref = atof(&rx_buffer[5]); // 문자열을 부동소수점으로 변환
        if (new_vref >= 1.0f && new_vref <= 5.0f) { // 유효 범위(1.0~5.0V) 확인
            vref = new_vref; // 목표 전압 업데이트
            soft_start_step_i = 3.0f / soft_start_steps; // 소프트 스타트 증가량 재계산
            soft_start_counter = 0; // 소프트 스타트 카운터 초기화
            soft_start_complete = false; // 소프트 스타트 재시작
            iref_soft = 0.0f; // 소프트 스타트 전류 기준 초기화
            integral = 0.0f; // PI 적분 항 초기화
        }
    }
    // 전류 제한 설정 (예: ISET:3.0)
    else if (strncmp(rx_buffer, "ISET:", 5) == 0) {
        float new_iref_max = atof(&rx_buffer[5]); // 문자열을 부동소수점으로 변환
        if (new_iref_max >= 1.0f && new_iref_max <= 4.0f) { // 유효 범위(1.0~4.0A) 확인
            iref_max = new_iref_max; // 전류 제한 업데이트
        }
    }
    // 소프트 스타트 시간 설정 (예: SSET:3000)
    else if (strncmp(rx_buffer, "SSET:", 5) == 0) {
        uint16_t new_steps = atoi(&rx_buffer[5]); // 문자열을 정수로 변환
        if (new_steps >= 1000 && new_steps <= 4000) { // 유효 범위(5~20ms) 확인
            soft_start_steps = new_steps; // 소프트 스타트 주기 업데이트
            soft_start_step_i = 3.0f / soft_start_steps; // 증가량 재계산
            soft_start_counter = 0; // 소프트 스타트 카운터 초기화
            soft_start_complete = false; // 소프트 스타트 재시작
            iref_soft = 0.0f; // 소프트 스타트 전류 기준 초기화
            integral = 0.0f; // PI 적분 항 초기화
        }
    }
#endif
    rx_index = 0; // 수신 버퍼 인덱스 초기화
    memset(rx_buffer, 0, sizeof(rx_buffer)); // 수신 버퍼 클리어
#endif
}

// 메인 함수: 시스템 초기화 및 무한 루프
void main(void) {
    InitSysCtrl(); // 시스템 클럭 초기화 (100MHz SYSCLK)
    DINT; // 전역 인터럽트 비활성화
    init_GPIO(); // GPIO 초기화 (PWM, ADC, SCI 핀 설정)
    init_ePWM(); // ePWM 초기화 (200kHz PWM 설정)
    init_ADC();  // ADC 초기화 (전압, 전류, 온도 센싱)
    init_SCI();  // SCI 초기화 (115200 baud UART)
    init_timer(); // 타이머 초기화 (복구 로직용)
#if LEVEL >= 5
    soft_start_step_i = 3.0f / soft_start_steps; // 소프트 스타트 전류 증가량 초기화
#endif
    Interrupt_initModule(); // 인터럽트 모듈 초기화
#if LEVEL >= 2
    Interrupt_register(INT_ADCA1, &adc_isr); // ADC 인터럽트 등록
    Interrupt_enable(INT_ADCA1); // ADC 인터럽트 활성화
#endif
#if LEVEL >= 4
    Interrupt_register(INT_TINT0, &timer_isr); // 타이머 인터럽트 등록
    Interrupt_enable(INT_TINT0); // 타이머 인터럽트 활성화
#endif
#if LEVEL >= 3
    Interrupt_register(INT_SCIA_RX, &sci_rx_isr); // SCI 수신 인터럽트 등록
    Interrupt_enable(INT_SCIA_RX); // SCI 수신 인터럽트 활성화
#endif
    EINT; // 전역 인터럽트 활성화
    ERTM; // 실시간 모드 활성화
    while(1) {
#if LEVEL == 1
        sprintf(tx_buffer, "LEVEL_1: PWM OK\r\n"); // PWM 테스트 메시지
        sci_transmit(tx_buffer);
#elif LEVEL == 2
        sprintf(tx_buffer, "LEVEL_2: ADC V=%.2f, I=%.2f, T=%.2f\r\n", vout, iout, temp); // ADC 테스트 메시지
        sci_transmit(tx_buffer);
#elif LEVEL == 3
        process_sci_data(); // SCI 테스트: 에코 응답
#elif LEVEL == 4
        sprintf(tx_buffer, "LEVEL_4: TIMER FLAG=%d\r\n", level_test_flag); // 타이머 테스트 메시지
        sci_transmit(tx_buffer);
#elif LEVEL == 5
        process_sci_data(); // SCI 설정 명령 처리
        send_monitoring_data(); // 모니터링 데이터 전송
#endif
    }
}

// ADC 인터럽트 서비스 루틴: 전압, 전류, 온도 센싱 및 PCMC 제어
__interrupt void adc_isr(void) {
#if LEVEL >= 2
    adc_vout = AdcaResultRegs.ADCRESULT0; // ADCINA0: 출력 전압 ADC 값
    adc_iout = AdcaResultRegs.ADCRESULT1; // ADCINA1: 인덕터 전류 ADC 값
    adc_temp = AdcaResultRegs.ADCRESULT2; // ADCINA2: 온도 ADC 값
    vout = (float)adc_vout * ADC_SCALE; // 전압 변환 (ADC 값 → V)
    iout = (float)adc_iout * ADC_SCALE / (SHUNT_R * GAIN_I); // 전류 변환 (ADC 값 → A)
    temp = (float)adc_temp * ADC_SCALE; // 온도 전압 변환 (V, NTC 기준)
#if LEVEL >= 5
    // 소프트 스타트 처리: 전류 기준을 0A에서 3A까지 10ms 동안 선형 증가
    if (!soft_start_complete) {
        soft_start_counter++; // 소프트 스타트 카운터 증가
        iref_soft += soft_start_step_i; // 전류 기준 증가
        if (soft_start_counter >= soft_start_steps) { // 소프트 스타트 완료 확인
            iref_soft = 3.0f; // 최종 전류 기준 설정
            soft_start_complete = true; // 완료 플래그 설정
        }
    }
    // 보호 조건 확인: OCP, OVP, OTP
    if (vout > VOVP || iout > iref_max || temp > TEMP_MAX) {
        fault = true; // 보호 동작 플래그 설정
        EPwm1Regs.TBCTL.bit.SWFSYNC = 1; // PWM 강제 정지
        EPwm1Regs.CMPA.bit.CMPA = 0; // PWM 듀티 0%
        EPwm1Regs.CMPB.bit.CMPB = 0; // 전류 비교값 0
        CPUTimer0Regs.TCR.bit.TSS = 0; // 복구 타이머 시작
        recovery_trigger = true; // 복구 트리거 활성화
    } else if (!fault) { // 정상 상태에서 PCMC 제어
        // 외부 전압 루프: 목표 전압(vref)에 대한 PI 제어
        error = vref - vout; // 전압 오차 계산
        iref = pi_update(error, &integral, KP, KI, UMAX, UMIN); // PI 제어로 전류 기준 계산
        if (iref > iref_max) iref = iref_max; // 전류 기준 제한
        if (iref < 0.0f) iref = 0.0f;
        // 경사 보상: 서브하모닉 발진 방지
        ramp += SLOPE_MA * TS; // 램프 신호 증가 (0.5 A/µs * 주기)
        if (ramp > iref_max) ramp = 0.0f; // 주기마다 램프 리셋
        float iref_comp = iref_soft < iref ? iref_soft : iref; // 소프트 스타트 전류 제한
        iref_comp += ramp; // 경사 보상 적용
        // 내부 전류 루프: CMPB로 전류 제어
        uint16_t cmpb = (uint16_t)(iref_comp * SHUNT_R * GAIN_I / ADC_SCALE); // 전류 기준을 ADC 단위로 변환
        EPwm1Regs.CMPB.bit.CMPB = cmpb; // CMPB 업데이트 (PWM 종료 지점)
    }
#endif
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // ADC 인터럽트 플래그 클리어
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1); // 인터럽트 그룹 확인
#endif
}

// 타이머 인터럽트 서비스 루틴: 보호 후 복구 로직 및 테스트 플래그 토글
__interrupt void timer_isr(void) {
#if LEVEL >= 4
    level_test_flag = !level_test_flag; // LEVEL_4 테스트용 플래그 토글
#if LEVEL >= 5
    if (recovery_trigger) { // 복구 트리거 활성화 시
        adc_vout = AdcaResultRegs.ADCRESULT0; // 최신 전압 ADC 값
        adc_iout = AdcaResultRegs.ADCRESULT1; // 최신 전류 ADC 값
        adc_temp = AdcaResultRegs.ADCRESULT2; // 최신 온도 ADC 값
        vout = (float)adc_vout * ADC_SCALE; // 전압 변환
        iout = (float)adc_iout * ADC_SCALE / (SHUNT_R * GAIN_I); // 전류 변환
        temp = (float)adc_temp * ADC_SCALE; // 온도 전압 변환
        if (vout <= VOVP && iout <= iref_max && temp <= TEMP_MAX) { // 보호 조건 해제 확인
            fault = false; // 보호 플래그 초기화
            recovery_trigger = false; // 복구 트리거 비활성화
            CPUTimer0Regs.TCR.bit.TSS = 1; // 타이머 정지
            EPwm1Regs.TBCTL.bit.SWFSYNC = 0; // PWM 재시작
            soft_start_counter = 0; // 소프트 스타트 카운터 초기화
            iref_soft = 0.0f; // 소프트 스타트 전류 기준 초기화
            ramp = 0.0f; // 경사 보상 램프 초기화
            integral = 0.0f; // PI 적분 항 초기화
        }
    }
#endif
    CPUTimer0Regs.TCR.bit.TIF = 1; // 타이머 인터럽트 플래그 클리어
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP2); // 인터럽트 그룹 확인
#endif
}

// SCI 수신 인터럽트 서비스 루틴: UART 데이터 수신 처리
__interrupt void sci_rx_isr(void) {
#if LEVEL >= 3
    char data = SciaRegs.SCIRXBUF.all; // 수신된 데이터 읽기
    if (data == '\r' || data == '\n') { // CR 또는 LF 수신 시
        rx_buffer[rx_index] = '\0'; // 문자열 종료
        rx_complete = true; // 수신 완료 플래그 설정
    } else if (rx_index < sizeof(rx_buffer) - 1) { // 버퍼 오버플로우 방지
        rx_buffer[rx_index++] = data; // 데이터 저장
    }
    SciaRegs.SCIFFRX.bit.RXFIFORESET = 0; // RX FIFO 리셋
    SciaRegs.SCIFFRX.bit.RXFIFORESET = 1; // RX FIFO 재활성화
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9); // 인터럽트 그룹 확인
#endif
}

2.3. 보호 회로

  • OCP: $I_{out} >$ iref_max (UART로 조정).
  • OVP: $V_{out} > 5.5 , \text{V}$.
  • OTP: NTC 전압 > 2 V.
  • 복구 로직: 1초 후 조건 확인 및 소프트 스타트 재시작.

2.4. 통신 프로토콜

  • 모니터링: MONITOR:V=<전압>,I=<전류>,T=<온도>,F=<상태> (예: MONITOR:V=5.00,I=2.50,T=1.80,F=0).
  • 설정:
    • VSET:<값>: 목표 전압 (1.0~5.0 V).
    • ISET:<값>: 피크 전류 제한 (1.0~4.0 A).
    • SSET:<값>: 소프트 스타트 주기 (1000~4000).
  • 테스트: TEST:<문자열> (LEVEL_3에서 에코 응답).
  • 호스트: Tera Term 또는 Python 스크립트.

2.5. 단계별 검증 절차

  • LEVEL_1 (PWM 테스트):
    • GPIO 및 ePWM 초기화.
    • 고정 50% 듀티 PWM 출력 (GPIO0/1).
    • SCI로 LEVEL_1: PWM OK 전송.
    • 검증: 오실로스코프로 PWM 파형 확인 (200 kHz, 50% 듀티).
  • LEVEL_2 (ADC 테스트):
    • ADC 초기화 및 센싱 (전압, 전류, 온도).
    • SCI로 LEVEL_2: ADC V=%.2f, I=%.2f, T=%.2f 전송.
    • 검증: CCS 디버거로 vout, iout, temp 확인, SCI 출력 확인.
  • LEVEL_3 (SCI 테스트):
    • SCI 초기화 및 송수신.
    • TEST:<문자열> 수신 시 에코 응답 (LEVEL_3: ECHO=<문자열>).
    • 검증: Tera Term으로 TEST:hello 전송, 에코 응답 확인.
  • LEVEL_4 (타이머 테스트):
    • 타이머 초기화, 1초 주기로 level_test_flag 토글.
    • SCI로 LEVEL_4: TIMER FLAG=%d 전송.
    • 검증: CCS로 level_test_flag 주기적 토글 확인, SCI 출력 확인.
  • LEVEL_5 (전체 제어):
    • 전체 제어 루프(PCMC, 소프트 스타트, 경사 보상, 보호, SCI) 활성화.
    • 검증: 모니터링 데이터 확인, VSET, ISET, SSET 명령으로 설정 변경, 보호/복구 동작 확인, 경사 보상으로 서브하모닉 발진 방지 확인.

2.6. 소프트웨어 주의사항

  • LEVEL 설정: LEVEL 매크로를 1~5로 변경하여 테스트.
  • SCI 설정: GPIO28/29와 SPI 충돌 확인 (SPRSP45).
  • UART: 수신 버퍼 크기 제한.
  • 인터럽트: INT_SCIA_RX, INT_ADCA1, INT_TINT0 우선순위 확인.
  • PI 튜닝: powerSUITE로 $K_p$, $K_i$ 튜닝 ($K_p = 0.5$, $K_i = 0.01$ 기준).
  • 경사 보상: $m_a = 0.5 , \text{A}/\mu\text{s}$로 서브하모닉 발진 방지.

3. 테스트 및 디버깅

  • 하드웨어: PWM (200 kHz), ADC, SCI (115200 baud) 확인.
  • 소프트웨어: CCS로 변수(vout, iout, temp, iref, ramp, integral) 모니터링, UART 명령 테스트.
  • 보호 및 복구: OCP, OVP, OTP 트리거 및 복구 확인.
  • 경사 보상: 오실로스코프로 전류 파형 확인 (서브하모닉 발진 없음).
  • LEVEL별 테스트:
    • LEVEL_1: PWM 파형.
    • LEVEL_2: ADC 데이터.
    • LEVEL_3: SCI 에코.
    • LEVEL_4: 타이머 플래그.
    • LEVEL_5: 전체 동작 및 경사 보상.

4. 프로젝트 설정 (CCS)

  • C2000Ware: C:/ti/c2000/C2000Ware_5_XX_XX_XX.
  • 빌드: pcmc_control.c.
  • 링커: F28004x_Headers_nonBIOS.cmd.
  • 인터럽트: INT_ADCA1, INT_TINT0, INT_SCIA_RX.

5. 추가 고려사항

  • 핀 충돌: SCI-A와 SPI 확인.
  • EMC: 스너버 회로 최적화.
  • 통신 확장: 추가 프로토콜 (예: CAN) 고려.
  • 경사 보상 최적화: $m_a$ 값을 부하 조건에 따라 조정.
반응형