본문 바로가기
Power Electronics/DC-DC변환

TI C2000 DSP를 사용한 PSFB 컨버터 2차측 동기 정류 디지털 제어기 설계

by linuxgo 2025. 8. 26.
반응형

1. 서론

Phase-Shifted Full-Bridge (PSFB) 컨버터는 고효율 절연형 DC-DC 변환기로, 제로 전압 스위칭(ZVS)을 통해 스위칭 손실을 줄여 고전력 애플리케이션에 적합합니다. 2차측 동기 정류(SR)를 적용하면 전도 손실을 최소화할 수 있습니다. TI의 C2000 DSP(F28379D)를 사용하여 고속 PWM, ADC, CLA를 활용한 정밀한 디지털 제어를 구현합니다. 본 문서는 PSFB 컨버터의 2차측 동기 정류 디지털 제어기를 설계하며, 위상 천이 제어(Phase-Shift Control)를 적용합니다. UART를 통한 RUN/STOP 제어, 외부 스위치 입력, 소프트 스타트, 과전압/과전류 보호(OVP/OCP)를 포함합니다.

2. 설계 요구사항

  • 입력 전압 (\( V_{in} \)): 300V ~ 400V
  • 출력 전압 (\( V_{out} \)): 48V
  • 출력 전류 (\( I_{out} \)): 10A
  • 스위칭 주파수 (\( f_{sw} \)): 100kHz
  • 샘플링 주기 (\( T_s \)): 5μs (PWM 동기화)
  • 제어 모드: 위상 천이 제어
  • 제어 방식: 위상 천이 변조 및 2차측 동기 정류
  • 하드웨어 플랫폼: TI Delfino F28379D LaunchPad (200MHz) + 커스터마이징된 PSFB 보드
  • 성능 목표:
    • 출력 전압 리플: \( \Delta V_{out} \leq 480 \, \text{mV} \) (1% 이하)
    • 과도 응답 시간: \( \leq 200 \, \mu \text{s} \) (부하/전압 스텝 응답)
    • 위상 마진: \( 45^\circ \sim 60^\circ \)
    • 대역폭: 약 10kHz (\( f_{sw}/10 \))
  • 추가 요구사항:
    • ADC: 12비트, 3.3V 기준
    • PWM: Phase-Shift 모드, 200MHz 시스템 클럭
    • 안정성: 위상 천이 제한 (\( 0^\circ \sim 180^\circ \)), ADC 입력 보호
    • 디버깅: UART (SCIA, 115200 baud)로 \( V_{out}, I_{out} \), 상태 모니터링
    • 보호: 과전압 (\( V_{out} > 52.8 \, \text{V} \)), 과전류 (\( I_{out} > 15 \, \text{A} \))
    • 기능: UART 명령 ('R'/'S'), 외부 스위치 (GPIO4), 소프트 스타트 (20ms)
    • 최적화: CLA로 PI 연산, IQmath로 고정소수점 연산, Pre-warping

3. PSFB 설계 절차

3.1 입력/출력 사양 정의

출력 전력 계산: 출력 전압과 전류를 곱하여 전력을 구합니다.

\[ P_{out} = V_{out} \times I_{out} \]

대입: \( V_{out} = 48 \, \text{V} \), \( I_{out} = 10 \, \text{A} \)

\[ P_{out} = 48 \times 10 = 480 \, \text{W} \]

입력 전력 계산: 효율을 고려하여 입력 전력을 구합니다. 효율 \( \eta = 0.95 \) (95%) 가정.

\[ P_{in} = \frac{P_{out}}{\eta} \]

\[ P_{in} = \frac{480}{0.95} \approx 505.2632 \, \text{W} \]

최소 입력 전압에서의 입력 전류 계산: RMS 전류를 계산하기 위해 최소 입력 전압을 사용합니다.

최소 입력 전압: \( V_{in,min} = 300 \, \text{V} \). AC RMS로 변환 시 \( V_{in,min} / \sqrt{2} \).

\[ V_{in,min,rms} = \frac{V_{in,min}}{\sqrt{2}} = \frac{300}{\sqrt{2}} \approx 212.1320 \, \text{V} \]

\[ I_{in,rms} = \frac{P_{in}}{V_{in,min,rms}} \]

\[ I_{in,rms} = \frac{505.2632}{212.1320} \approx 2.3818 \, \text{A} \]

3.2 트랜스포머 설계

3.2.1 턴 비율 (\( n \))

PSFB 컨버터에서 트랜스포머 턴 비율은 입력 전압과 출력 전압의 비율로 결정됩니다.

\[ n = \frac{V_{in,min}}{V_{out}} \]

대입: \( V_{in,min} = 300 \, \text{V} \), \( V_{out} = 48 \, \text{V} \)

\[ n = \frac{300}{48} = 6.25 \]

실제 설계에서는 정수비를 선호하므로, 가장 가까운 정수비로 조정.

선택: \( n = 6 \) (6:1).

3.2.2 코어 및 턴 수

페라이트 코어 선택: ETD49 (N87 재질). 코어 사양: \( A_e = 2.11 \times 10^{-4} \, \text{m}^2 \), \( l_e = 0.114 \, \text{m} \).

턴 비율에 따라 턴 수 결정: \( n = \frac{N_1}{N_2} = 6 \).

선택: \( N_1 = 36 \), \( N_2 = 6 \).

3.2.3 자화 인덕턴스 (\( L_m \))

자화 인덕턴스 목표: \( L_m = 500 \, \mu \text{H} \). 에어 갭을 통해 인덕턴스 조정.

\[ L_m = \frac{\mu_0 N_1^2 A_e}{l_g + \frac{l_e}{\mu_r}} \]

이를 재배열하여 에어 갭 \( l_g \)를 구합니다.

\[ l_g = \frac{\mu_0 N_1^2 A_e}{L_m} - \frac{l_e}{\mu_r} \]

파라미터 대입: \( \mu_0 = 4\pi \times 10^{-7} \, \text{H/m} \), \( N_1 = 36 \), \( A_e = 2.11 \times 10^{-4} \, \text{m}^2 \), \( l_e = 0.114 \, \text{m} \), \( \mu_r = 2000 \), \( L_m = 500 \times 10^{-6} \, \text{H} \).

1단계: 첫 번째 항 계산

\[ \frac{\mu_0 N_1^2 A_e}{L_m} = \frac{(4\pi \times 10^{-7}) \times 36^2 \times (2.11 \times 10^{-4})}{500 \times 10^{-6}} \]

\[ = \frac{(1.256637 \times 10^{-6}) \times 1296 \times (2.11 \times 10^{-4})}{5 \times 10^{-4}} \]

\[ = \frac{3.4366 \times 10^{-4}}{5 \times 10^{-4}} \approx 0.68732 \, \text{m} \]

2단계: 두 번째 항 계산

\[ \frac{l_e}{\mu_r} = \frac{0.114}{2000} = 5.7 \times 10^{-5} \, \text{m} \]

3단계: 에어 갭 계산

\[ l_g = 0.68732 - 5.7 \times 10^{-5} \approx 0.68675 \, \text{mm} \]

결과: 실제 구현에서 에어 갭을 약 0.7mm로 조정하여 \( L_m \approx 500 \, \mu \text{H} \)를 얻습니다.

3.2.4 와이어 선택

스킨 효과를 고려하여 적절한 와이어 선택.

1차측 전류: \( I_{1,rms} \approx 2.38 \, \text{A} \). AWG 20 선택 (충분한 전류 용량).

2차측 전류: \( I_{2,rms} \approx 10 \, \text{A} \). AWG 14, Litz wire 권장 (스킨 효과 최소화).

3.3 출력 인덕터 설계

인덕터 값 및 리플 전류 계산: 출력 인덕터는 리플 전류를 제한합니다.

인덕터 값: \( L_o = 100 \, \mu \text{H} \).

\[ \Delta I_L = \frac{V_{out} \cdot (1 - D_{max})}{f_{sw} \cdot L_o} \]

최대 듀티 사이클 \( D_{max} \approx 0.8 \) (PSFB에서 일반적인 값).

대입: \( V_{out} = 48 \, \text{V} \), \( f_{sw} = 100000 \, \text{Hz} \), \( L_o = 100 \times 10^{-6} \, \text{H} \).

\[ \Delta I_L = \frac{48 \cdot (1 - 0.8)}{100000 \cdot 100 \times 10^{-6}} \]

\[ = \frac{48 \cdot 0.2}{10 \times 10^{-3}} = \frac{9.6}{0.01} = 0.96 \, \text{A} \]

3.4 출력 커패시터 설계

출력 커패시터는 리플 전압을 제한합니다. 목표: \( \Delta V_{out} \leq 480 \, \text{mV} \).

PSFB 컨버터에서 일반적인 출력 리플 공식 사용.

\[ C_{out} = \frac{\Delta I_L}{8 \cdot f_{sw} \cdot \Delta V_{out}} \]

대입: \( \Delta I_L = 0.96 \, \text{A} \), \( f_{sw} = 100000 \, \text{Hz} \), \( \Delta V_{out} = 0.48 \, \text{V} \).

\[ C_{out} = \frac{0.96}{8 \cdot 100000 \cdot 0.48} \]

\[ = \frac{0.96}{384000} \approx 2.5 \times 10^{-6} \, \text{F} = 2.5 \, \mu \text{F} \]

PSFB의 current doubler 구조를 고려하면, 효과적인 주파수가 \( 2 f_{sw} \)로 증가하므로 공식 수정.

\[ C_{out} = \frac{\Delta I_L}{4 \cdot f_{sw} \cdot \Delta V_{out}} \]

\[ = \frac{0.96}{4 \cdot 100000 \cdot 0.48} = \frac{0.96}{192000} \approx 5 \times 10^{-6} \, \text{F} = 5 \, \mu \text{F} \]

안정성과 ESR을 고려하여 여유 있게 선택: \( C_{out} = 1000 \, \mu \text{F} \), ESR \( \leq 5 \, \text{m}\Omega \) (예: Panasonic EEH-ZA1J101P). 이는 TI 가이드(SLUP414)에서 권장하는 안전 마진과 일치.

3.5 스위치 및 정류기

1차측 및 2차측 스위치와 드라이버 선택.

1차측 MOSFET: N-채널, 600V, 20A (TI CSD19536KCS), ePWM1A/B, ePWM2A/B (GPIO0~3).

2차측 SR MOSFET: N-채널, 100V, 50A (TI CSD19535KCS), ePWM3A/B (GPIO4~5), 데드타임 100ns.

게이트 드라이버: UCC27211, 4A 듀얼 채널.

3.6 센싱 및 제어 회로

출력 전압 센싱: 분압기를 사용하여 ADC 입력 범위(0~3.3V)로 변환.

\[ V_{sense} = V_{out} \times \frac{R_2}{R_1 + R_2} \]

ADC 기준 전압 3.3V에 맞추기 위해 \( R_1 = 100 \, \text{k}\Omega \), \( R_2 = 3.3 \, \text{k}\Omega \).

\[ V_{sense} = 48 \times \frac{3.3 \times 10^3}{100 \times 10^3 + 3.3 \times 10^3} \]

\[ = 48 \times \frac{3.3}{103.3} \approx 48 \times 0.03195 \approx 1.5336 \, \text{V} \]

ADC 입력: ADCINA0 (GPIO6).

출력 전류 센싱: 션트 저항 사용.

\[ V_{shunt} = I_{out} \times R_{shunt} \]

대입: \( I_{out} = 10 \, \text{A} \), \( R_{shunt} = 0.005 \, \Omega \).

\[ V_{shunt} = 10 \times 0.005 = 0.05 \, \text{V} \]

ADC 입력: ADCINA1 (GPIO7), CMPSS1 사용.

외부 스위치 및 UART 설정.

외부 스위치: GPIO8, 풀업 10kΩ, Low=RUN, High=STOP.

UART: SCIA, GPIO28(TX), GPIO29(RX), 115200 baud.

3.7 하드웨어 플랫폼

사용 하드웨어 및 테스트 장비.

F28379D LaunchPad: 200MHz, 12비트 ADC, 16채널 PWM, CLA.

PSFB 보드: 풀-브릿지 MOSFET, SR MOSFET, \( L_o = 100 \, \mu \text{H} \), \( C_{out} = 1000 \, \mu \text{F} \).

4. 아날로그 모델링

4.1 State-Space 평균화 모델

상태 변수 정의: 인덕터 전류 (\( i_L \)), 출력 전압 (\( v_{out} \)).

\[ \frac{di_L}{dt} = \frac{1}{L_o} \left( \frac{V_{in}}{n} \cdot D_{eff} - v_{out} \right) \]

\[ \frac{dv_{out}}{dt} = \frac{1}{C_{out}} \left( i_L - \frac{v_{out}}{R} \right) \]

매트릭스 형태로 표현.

\[ \frac{d}{dt} \begin{bmatrix} i_L \\ v_{out} \end{bmatrix} = \begin{bmatrix} 0 & -\frac{1}{L_o} \\ \frac{1}{C_{out}} & -\frac{1}{R C_{out}} \end{bmatrix} \begin{bmatrix} i_L \\ v_{out} \end{bmatrix} + \begin{bmatrix} \frac{D_{eff}}{n L_o} \\ 0 \end{bmatrix} V_{in} \]

4.2 소신호 모델

위상 천이에 대한 소신호 전달 함수를 유도합니다.

\[ G_{vd}(s) = \frac{\hat{v}_{out}(s)}{\hat{d}(s)} = \frac{V_{in} / n}{s^2 L_o C_{out} + s \frac{L_o}{R} + 1} \]

파라미터 대입: \( V_{in} = 300 \, \text{V} \), \( n = 6 \), \( L_o = 100 \times 10^{-6} \, \text{H} \), \( C_{out} = 1000 \times 10^{-6} \, \text{F} \), \( R = 4.8 \, \Omega \).

1단계: 분자 계산

\[ \frac{V_{in}}{n} = \frac{300}{6} = 50 \]

2단계: 분모 계산

\[ L_o C_{out} = (100 \times 10^{-6}) \times (1000 \times 10^{-6}) = 10^{-7} \]

\[ \frac{L_o}{R} = \frac{100 \times 10^{-6}}{4.8} \approx 2.0833 \times 10^{-5} \]

\[ G_{vd}(s) = \frac{50}{10^{-7} s^2 + 2.0833 \times 10^{-5} s + 1} \]

4.3 MATLAB 모델링

MATLAB을 사용한 전달 함수 모델링 및 시각화.

% PSFB 컨버터 플랜트 모델
Vin = 300; n = 6; Lo = 100e-6; Co = 1000e-6; R = 4.8;
Gvd = tf(Vin/n, [Lo*Co, Lo/R, 1]);
figure; bode(Gvd); grid on;
figure; step(Gvd); grid on;

5. 디지털 제어기 설계

5.1 아날로그 PI 제어기

PI 제어기 설계: 비례항과 적분항으로 구성.

\[ G_c(s) = K_p + \frac{K_i}{s} = \frac{K_p s + K_i}{s} \]

MATLAB pidTuner를 사용하여 튜닝: 목표 대역폭 10kHz, 위상 마진 45°~60°.

\[ K_p = 0.15, \quad K_i = 1500 \]

5.2 이산화 (Tustin 변환 with Pre-warping)

Pre-warping을 적용하여 아날로그 PI 제어기를 이산화합니다.

Pre-warping 주파수: \( \omega_p = 2 \pi \times 10000 \, \text{rad/s} \).

\[ \omega_p = 2 \pi \times 10000 \approx 62831.8531 \, \text{rad/s} \]

Tustin 변환: \( s = \frac{2}{T_s} \cdot \frac{z - 1}{z + 1} \). Pre-warping 적용 시:

\[ s = \frac{\omega_p}{\tan(\omega_p T_s / 2)} \cdot \frac{z - 1}{z + 1} \]

대입: \( T_s = 5 \times 10^{-6} \, \text{s} \).

\[ \omega_p T_s = 62831.8531 \times 5 \times 10^{-6} \approx 0.314159265 \]

\[ \frac{\omega_p T_s}{2} \approx 0.157079632 \]

\[ \tan\left(\frac{\omega_p T_s}{2}\right) = \tan(0.157079632) \approx 0.1583844 \]

\[ s \approx \frac{62831.8531}{0.1583844} \cdot \frac{z - 1}{z + 1} \approx 396693.5 \cdot \frac{z - 1}{z + 1} \]

아날로그 PI 제어기 \( G_c(s) = \frac{0.15 s + 1500}{s} \)를 이산화.

\[ G_c(s) = \frac{0.15 s + 1500}{s} \]

Tustin 변환을 적용하여 \( s \)를 대입:

\[ G_c(z) = \frac{0.15 \cdot \left(396693.5 \cdot \frac{z - 1}{z + 1}\right) + 1500}{\left(396693.5 \cdot \frac{z - 1}{z + 1}\right)} \]

분자 정리:

\[ \text{분자} = 0.15 \cdot 396693.5 \cdot \frac{z - 1}{z + 1} + 1500 \]

\[ = 59504.025 \cdot \frac{z - 1}{z + 1} + 1500 \]

\[ = \frac{59504.025 (z - 1) + 1500 (z + 1)}{z + 1} \]

\[ = \frac{59504.025 z - 59504.025 + 1500 z + 1500}{z + 1} \]

\[ = \frac{(59504.025 + 1500) z + (-59504.025 + 1500)}{z + 1} \]

\[ = \frac{61004.025 z - 58004.025}{z + 1} \]

분모는 \( s = 396693.5 \cdot \frac{z - 1}{z + 1} \)이므로:

\[ \text{분모} = 396693.5 \cdot \frac{z - 1}{z + 1} \]

전체 전달 함수:

\[ G_c(z) = \frac{\frac{61004.025 z - 58004.025}{z + 1}}{\frac{396693.5 (z - 1)}{z + 1}} = \frac{61004.025 z - 58004.025}{396693.5 (z - 1)} \]

\[ = \frac{\frac{61004.025}{396693.5} z - \frac{58004.025}{396693.5}}{z - 1} \approx \frac{0.15374 z - 0.14621}{z - 1} \]

간략화하여 사용: \( G_c(z) \approx \frac{0.153 z - 0.147}{z - 1} \).

차분 방정식:

\[ u[n] = u[n-1] + 0.153 e[n] - 0.147 e[n-1] \]

Ts = 5e-6;
Gc = tf([0.15 1500], [1 0]);
Gc_d = c2d(Gc, Ts, 'tustin', 'PrewarpFrequency', 2*pi*10000);
[num, den] = tfdata(Gc_d, 'v');

5.3 2차측 SR 설계

동기 정류를 위한 전류 제로 크로싱 감지 및 데드타임 설정.

CMPSS로 전류 제로 크로싱 감지.

데드타임: 100ns (200MHz에서 20 클럭).

위상 천이 제한: \( 0^\circ \sim 180^\circ \).

dead_time = 100e-9;
phi_min = 0; phi_max = 180;
t = 0:1e-9:1e-5;
pwm = square(2*pi*100e3*t, 50);
pwm_sr = [zeros(1, dead_time/1e-9) pwm(1:end-dead_time/1e-9)];
plot(t, pwm, t, pwm_sr);

6. TI C2000 DSP 구현

F28379D를 사용한 PSFB 컨버터 제어 코드.

#include "F28x_Project.h" // F28379D 헤더 파일: 시스템 레지스터 및 함수 정의
#include "IQmathLib.h"    // 고정소수점 연산을 위한 IQmath 라이브러리

// 상수 정의: 시스템 파라미터 및 제어 설정
#define VREF _IQ(48.0)            // 출력 전압 기준값: 48V
#define KP _IQ(0.15)              // PI 제어기 비례 게인
#define KI _IQ(1500.0)            // PI 제어기 적분 게인
#define TS _IQ(0.000005)          // 샘플링 주기: 5us (200kHz)
#define ADC_VREF _IQ(3.3)         // ADC 기준 전압: 3.3V
#define ADC_MAX _IQ(4095.0)       // 12비트 ADC 최대값: 4095
#define FSW _IQ(100000.0)         // 스위칭 주파수: 100kHz
#define PHI_MAX _IQ(180.0)        // 최대 위상 천이: 180도
#define DEAD_TIME _IQ(0.0000001)  // 데드타임: 100ns
#define SHUNT_R _IQ(0.005)        // 션트 저항: 5mΩ
#define V_OVP _IQ(52.8)           // 과전압 보호 임계값: 52.8V
#define V_OVP_HYST _IQ(50.0)      // 과전압 히스테리시스: 50V
#define I_OCP _IQ(15.0)           // 과전류 보호 임계값: 15A
#define I_OCP_HYST _IQ(13.0)      // 과전류 히스테리시스: 13A
#define SOFT_START_TIME _IQ(0.02) // 소프트 스타트 시간: 20ms
#define SOFT_START_STEPS 4000     // 소프트 스타트 단계 수: 4000
#define FAULT_RECOVERY_TIME 2000  // FAULT 복구 대기 시간: 2초 (2000ms)
#define DEBOUNCE_COUNT 10         // 스위치 디바운싱 카운트
#define V_SCALE _IQ(16.0)         // 전압 분압비: 1/16
#define I_GAIN _IQ(10.0)          // 전류 증폭기 이득: 10

// 전역 변수: 시스템 상태 및 제어 변수
volatile _iq Vout = _IQ(0.0);         // 현재 출력 전압 (IQ 포맷)
volatile _iq Iout = _IQ(0.0);         // 현재 출력 전류 (IQ 포맷)
volatile _iq error = _IQ(0.0);        // PI 제어기 오차
volatile _iq phi = _IQ(0.0);          // 현재 위상 천이 각도
volatile _iq error_prev = _IQ(0.0);   // 이전 오차 (PI 제어용)
volatile _iq phi_prev = _IQ(0.0);     // 이전 위상 천이 각도
volatile Uint16 error_count = 0;       // ADC 에러 카운터
volatile Uint16 system_state = 0;      // 시스템 상태 (0: STOP, 1: RUN, 2: FAULT)
volatile Uint16 soft_start_count = 0;  // 소프트 스타트 카운터
volatile _iq phi_target = _IQ(0.0);    // 목표 위상 천이 각도
volatile Uint16 fault_recovery_count = 0; // FAULT 복구 카운터
volatile Uint16 debounce_count = 0;    // 스위치 디바운싱 카운터
volatile Uint16 last_switch_state = 1; // GPIO8 이전 상태 (1: High)

// CLA 메모리 할당: 고속 연산을 위한 CLA 데이터
#pragma DATA_SECTION(CLA_Vout, "Cla1DataRam0");  // CLA용 출력 전압
#pragma DATA_SECTION(CLA_Iout, "Cla1DataRam0");  // CLA용 출력 전류
#pragma DATA_SECTION(CLA_error, "Cla1DataRam0"); // CLA용 오차
#pragma DATA_SECTION(CLA_phi, "Cla1DataRam0");   // CLA용 위상 천이
volatile _iq CLA_Vout, CLA_Iout, CLA_error, CLA_phi;

// 함수 프로토타입 (CLA 태스크)
__interrupt void cla_task1_isr(void);

// 시스템 초기화: 클럭, 인터럽트, 메모리 설정
void initSystem(void) {
    InitSysCtrl();                   // 시스템 클럭 및 PLL 초기화 (200MHz)
    DINT;                            // 글로벌 인터럽트 비활성화
    InitPieCtrl();                   // PIE (Peripheral Interrupt Expansion) 초기화
    IER = 0x0000; IFR = 0x0000;     // 인터럽트 레지스터 초기화
    InitPieVectTable();              // 인터럽트 벡터 테이블 설정
    InitCla();                       // CLA (Control Law Accelerator) 초기화
}

// GPIO 초기화: PWM, ADC, 외부 스위치, UART 핀 설정
void initGPIO(void) {
    EALLOW;                          // 보호된 레지스터 접근 허용
    // PWM 출력 (ePWM1, ePWM2: 1차측, ePWM3: 2차측 SR)
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; GpioCtrlRegs.GPADIR.bit.GPIO0 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0; // ePWM1A
    GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; GpioCtrlRegs.GPADIR.bit.GPIO1 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0; // ePWM1B
    GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1; GpioCtrlRegs.GPADIR.bit.GPIO2 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO2 = 0; // ePWM2A
    GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 1; GpioCtrlRegs.GPADIR.bit.GPIO3 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO3 = 0; // ePWM2B
    GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 1; GpioCtrlRegs.GPADIR.bit.GPIO4 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO4 = 0; // ePWM3A
    GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 1; GpioCtrlRegs.GPADIR.bit.GPIO5 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO5 = 0; // ePWM3B
    // ADC 입력
    GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 0; GpioCtrlRegs.GPADIR.bit.GPIO6 = 0; GpioCtrlRegs.GPAQSEL1.bit.GPIO6 = 0; // ADCINA0
    GpioCtrlRegs.GPAMUX1.bit.GPIO7 = 0; GpioCtrlRegs.GPADIR.bit.GPIO7 = 0; GpioCtrlRegs.GPAQSEL1.bit.GPIO7 = 0; // ADCINA1
    // 외부 스위치
    GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 0; GpioCtrlRegs.GPADIR.bit.GPIO8 = 0; GpioCtrlRegs.GPAPUD.bit.GPIO8 = 1; // GPIO8
    // UART (SCIA)
    GpioCtrlRegs.GPBMUX1.bit.GPIO28 = 1; GpioCtrlRegs.GPBDIR.bit.GPIO28 = 1; // SCIA TX
    GpioCtrlRegs.GPBMUX1.bit.GPIO29 = 1; GpioCtrlRegs.GPBDIR.bit.GPIO29 = 0; // SCIA RX
    EDIS;                            // 보호된 레지스터 접근 비활성화
}

// ADC 초기화: 전압/전류 센싱을 위한 설정
void initADC(void) {
    EALLOW;
    AdcaRegs.ADCCTL2.bit.PRESCALE = 8;                   // ADC 클럭 분주: 200MHz/8 = 25MHz
    AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0;                   // SOC0: ADCINA0 (전압 센싱)
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = 14;                  // 샘플링 윈도우: 14 클럭
    AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5;                 // 트리거: ePWM1 SOCA
    AdcaRegs.ADCSOC1CTL.bit.CHSEL = 1;                   // SOC1: ADCINA1 (전류 센싱)
    AdcaRegs.ADCSOC1CTL.bit.ACQPS = 14;                  // 샘플링 윈도우: 14 클럭
    AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 5;                 // 트리거: ePWM1 SOCA
    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0;               // 인터럽트: SOC0 완료 시
    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1;                 // ADC 인터럽트 1 활성화
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;               // 인터럽트 플래그 초기화
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;                // 인터럽트 펄스 위치 설정
    AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;                   // ADC 전원 활성화
    DELAY_US(1000);                                     // ADC 안정화 대기: 1ms
    EDIS;
}

// PWM 초기화: 1차측 풀-브릿지 및 2차측 SR PWM 설정
void initPWM(void) {
    EALLOW;
    // ePWM1 설정 (1차측 풀-브릿지 상단)
    EPwm1Regs.TBCTL.bit.CTRMODE = 0;                    // 업카운트 모드
    EPwm1Regs.TBCTL.bit.PHSEN = 1;                      // 페이즈 동기화 활성화
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 1;                  // 고속 클럭 분주: 200MHz
    EPwm1Regs.TBCTL.bit.CLKDIV = 0;                     // 클럭 분주: 1
    EPwm1Regs.TBPRD = (Uint16)(200e6 / (2 * _IQtoF(FSW))); // 주기: 100kHz
    EPwm1Regs.CMPA.bit.CMPA = EPwm1Regs.TBPRD / 2;      // 듀티 사이클: 50%
    EPwm1Regs.TBCTR = 0;                                // 타이머 카운터 초기화
    EPwm1Regs.ETSEL.bit.SOCAEN = 1;                     // SOCA 활성화 (ADC 트리거)
    EPwm1Regs.ETSEL.bit.SOCASEL = 1;                    // SOCA 트리거: 카운터=0
    EPwm1Regs.ETPS.bit.SOCAPRD = 1;                     // SOCA 주기: 매 사이클
    EPwm1Regs.DBCTL.bit.OUT_MODE = 3;                   // 데드밴드 활성화
    EPwm1Regs.DBRED.bit.DBRED = (Uint16)(_IQtoF(DEAD_TIME) * 200e6); // 상승 데드타임: 100ns
    EPwm1Regs.DBFED.bit.DBFED = (Uint16)(_IQtoF(DEAD_TIME) * 200e6); // 하강 데드타임: 100ns
    EPwm2Regs = EPwm1Regs;                              // ePWM2: ePWM1과 동일 설정 (1차측 하단)
    // ePWM3 설정 (2차측 SR)
    EPwm3Regs = EPwm1Regs;                              // 기본 설정 복사
    EPwm3Regs.TBPHS.bit.TBPHS = EPwm1Regs.TBPRD / 4;    // SR 위상: 90도 지연 (1/4 주기)
    EPwm1Regs.TBCTL.bit.FREE_SOFT = 2;                  // 프리-런 모드
    // ePWM4 설정 (타이머: 상태 전송용)
    EPwm4Regs.TBCTL.bit.CTRMODE = 0;                    // 업카운트 모드
    EPwm4Regs.TBCTL.bit.HSPCLKDIV = 7;                  // 200MHz / 7 = 약 28.57MHz
    EPwm4Regs.TBCTL.bit.CLKDIV = 7;                     // 28.57MHz / 128 ≈ 223kHz
    EPwm4Regs.TBPRD = 44643;                            // 200ms 주기 (223kHz / 44643)
    EPwm4Regs.ETSEL.bit.INTEN = 1;                      // 인터럽트 활성화
    EPwm4Regs.ETSEL.bit.INTSEL = 1;                     // 인터럽트: 카운터=0
    EPwm4Regs.ETPS.bit.INTPRD = 1;                      // 인터럽트 주기: 매 사이클
    EDIS;
}

// CMPSS 초기화: 2차측 SR 전류 제로 크로싱 감지
void initCMPSS(void) {
    EALLOW;
    Cmpss1Regs.COMPCTL.bit.COMPDACE1 = 1;               // 비교기 1 활성화
    Cmpss1Regs.COMPCTL.bit.COMPHSOURCE = 0;             // 하이 사이드 소스: DAC
    Cmpss1Regs.COMPDACCTL.bit.DACSOURCE = 0;            // DAC 소스: 내부 DAC
    Cmpss1Regs.DACHVALS.bit.DACVAL = 2048;              // DAC 기준: 1.65V (오프셋 고려)
    Cmpss1Regs.COMPCTL.bit.ASYNCHEN = 1;                // 비동기 출력 활성화
    Cmpss1Regs.COMPSTSCLR.bit.HLATCHCLR = 1;            // 래치 클리어
    EPwm3Regs.ETSEL.bit.SOCAEN = 1;                     // CMPSS 트리거로 SR 동기화
    EPwm3Regs.ETSEL.bit.SOCASEL = 4;                    // SOCA: CMPSS 이벤트
    EDIS;
}

// CLA 초기화: PI 제어 연산을 위한 CLA 설정
void initCLA(void) {
    EALLOW;
    Cla1Regs.MVECT1 = (Uint16)((Uint32)&cla_task1_isr); // CLA 태스크 1 인터럽트 벡터
    Cla1Regs.MCTL.bit.IACKE = 1;                        // CLA 인터럽트 활성화
    Cla1Regs.MIER.bit.MINT1 = 1;                        // 태스크 1 인터럽트 활성화
    EDIS;
}

// UART 초기화: 디버깅 및 상태 모니터링 (115200 baud)
void initUART(void) {
    EALLOW;
    SciaRegs.SCICCR.all = 0x0007;                       // 8비트 데이터, 패리티 없음, 1 스톱 비트
    SciaRegs.SCICTL1.all = 0x0003;                      // 송수신 활성화
    SciaRegs.SCIHBAUD.all = 0x0000;                     // Baud rate: 115200
    SciaRegs.SCILBAUD.all = 216;                        // Baud rate 설정
    SciaRegs.SCICTL2.bit.RXBKINTENA = 1;                // 수신 인터럽트 활성화
    SciaRegs.SCICTL1.all = 0x0023;                      // UART 활성화
    EDIS;
}

// UART 데이터 전송: 전압/전류 데이터 전송
void scia_xmit(_iq data) {
    Uint16 val = (Uint16)(_IQtoF(data) * 1000);         // IQ 포맷을 정수로 변환 (mV 단위)
    while (SciaRegs.SCIFFTX.bit.TXFFST != 0);           // 송신 버퍼가 비어질 때까지 대기
    SciaRegs.SCITXBUF.all = val;                        // 데이터 전송
}

// UART 상태 전송: 시스템 상태 전송
void scia_xmit_status(Uint16 status) {
    while (SciaRegs.SCIFFTX.bit.TXFFST != 0);           // 송신 버퍼가 비어질 때까지 대기
    SciaRegs.SCITXBUF.all = status;                     // 상태 전송 (0: STOP, 1: RUN, 2: FAULT)
}

// 소프트 스타트: 부팅 시 전류 충격 방지를 위한 위상 천이 점진적 증가
void softStart(void) {
    if (soft_start_count < SOFT_START_STEPS) {          // 소프트 스타트 진행 중
        phi = _IQmpy(_IQdiv(_IQ(soft_start_count), _IQ(SOFT_START_STEPS)), phi_target); // 선형적으로 위상 증가
        Uint16 phase = (Uint16)(_IQtoF(phi) * EPwm1Regs.TBPRD / 360.0); // 위상 천이 계산
        EPwm2Regs.TBPHS.bit.TBPHS = phase;             // ePWM2 위상 업데이트
        soft_start_count++;                             // 카운터 증가
    } else {
        phi = phi_target;                               // 목표 위상으로 전환
        Uint16 phase = (Uint16)(_IQtoF(phi) * EPwm1Regs.TBPRD / 360.0); // 최종 위상
        EPwm2Regs.TBPHS.bit.TBPHS = phase;              // ePWM2 업데이트
    }
}

// 보호 기능: 과전압/과전류 감지 및 시스템 정지
void checkProtection(void) {
    static Uint16 fault_active = 0;
    if (_IQtoF(Vout) > _IQtoF(V_OVP) || _IQtoF(Iout) > _IQtoF(I_OCP)) { // OVP/OCP 조건 확인
        updateSystemState(2);                                // FAULT 상태로 전환
        fault_active = 1;
        fault_recovery_count = 0;
        EALLOW;
        EPwm1Regs.TBCTL.bit.CTRMODE = 3; EPwm1Regs.CMPA.bit.CMPA = 0; // PWM1 정지
        EPwm2Regs.TBCTL.bit.CTRMODE = 3; EPwm2Regs.CMPA.bit.CMPA = 0; // PWM2 정지
        EPwm3Regs.TBCTL.bit.CTRMODE = 3; EPwm3Regs.CMPA.bit.CMPA = 0; // PWM3 정지
        soft_start_count = 0; phi = _IQ(0.0); phi_prev = _IQ(0.0); // 변수 초기화
        EDIS;
    } else if (fault_active && _IQtoF(Vout) < _IQtoF(V_OVP_HYST) && _IQtoF(Iout) < _IQtoF(I_OCP_HYST)) {
        fault_recovery_count++;
        if (fault_recovery_count > FAULT_RECOVERY_TIME / 5) { // 2초 대기 (5us 주기 기준)
            fault_active = 0;
            updateSystemState(0);                            // STOP 상태로 복구
        }
    }
}

// 시스템 상태 업데이트: RUN/STOP/FAULT 상태 관리
void updateSystemState(Uint16 new_state) {
    if (new_state == system_state) return;               // 동일 상태면 무시
    system_state = new_state;                            // 상태 업데이트
    EALLOW;
    if (system_state == 1) {                             // RUN 상태
        EPwm1Regs.TBCTL.bit.CTRMODE = 0;                 // PWM1 활성화
        EPwm2Regs.TBCTL.bit.CTRMODE = 0;                 // PWM2 활성화
        EPwm3Regs.TBCTL.bit.CTRMODE = 0;                 // PWM3 활성화
        soft_start_count = 0; phi = _IQ(0.0);            // 소프트 스타트 초기화
    } else {                                             // STOP 또는 FAULT
        EPwm1Regs.TBCTL.bit.CTRMODE = 3; EPwm1Regs.CMPA.bit.CMPA = 0; // PWM1 정지
        EPwm2Regs.TBCTL.bit.CTRMODE = 3; EPwm2Regs.CMPA.bit.CMPA = 0; // PWM2 정지
        EPwm3Regs.TBCTL.bit.CTRMODE = 3; EPwm3Regs.CMPA.bit.CMPA = 0; // PWM3 정지
        soft_start_count = 0; phi = _IQ(0.0); phi_prev = _IQ(0.0); // 변수 초기화
    }
    EDIS;
    scia_xmit_status(system_state);                      // 상태 UART 전송
}

// 인터럽트 초기화: ADC, CLA, UART, ePWM4 인터럽트 설정
void initInterrupts(void) {
    EALLOW;
    PieVectTable.ADCA1_INT = &adc_isr;                   // ADC 인터럽트 벡터
    PieVectTable.CLA1_1_INT = &cla_task1_isr;            // CLA 태스크 1 벡터
    PieVectTable.SCIA_RX_INT = &scia_rx_isr;             // UART 수신 벡터
    PieVectTable.EPWM4_INT = &epwm4_isr;                 // ePWM4 인터럽트 (타이머)
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1;                   // ADC 인터럽트 활성화
    PieCtrlRegs.PIEIER11.bit.INTx1 = 1;                  // CLA 인터럽트 활성화
    PieCtrlRegs.PIEIER9.bit.INTx1 = 1;                   // UART 인터럽트 활성화
    PieCtrlRegs.PIEIER3.bit.INTx4 = 1;                   // ePWM4 인터럽트 활성화
    IER |= M_INT1 | M_INT3 | M_INT9 | M_INT11;           // CPU 인터럽트 활성화
    EDIS;
}

// ADC 인터럽트: 전압/전류 센싱 및 보호 로직
__interrupt void adc_isr(void) {
    static _iq Vout_filt = _IQ(0.0), Iout_filt = _IQ(0.0);
    _iq Vout_raw = _IQmpy(_IQ(AdcaResult.ADCRESULT0), _IQdiv(ADC_VREF, ADC_MAX)) * V_SCALE; // 분압비 반영
    _iq Iout_raw = _IQmpy(_IQ(AdcaResult.ADCRESULT1), _IQdiv(ADC_VREF, _IQmpy(ADC_MAX, SHUNT_R))) / I_GAIN; // 증폭기 이득 반영
    // 이동평균 필터 (4샘플)
    Vout_filt = _IQmpy(_IQ(0.75), Vout_filt) + _IQmpy(_IQ(0.25), Vout_raw);
    Iout_filt = _IQmpy(_IQ(0.75), Iout_filt) + _IQmpy(_IQ(0.25), Iout_raw);
    if (_IQtoF(Vout_filt) < 0.0f || _IQtoF(Vout_filt) > 60.0f || 
        _IQtoF(Iout_filt) < 0.0f || _IQtoF(Iout_filt) > 20.0f) {
        error_count++;
        if (error_count > 10) { // 10회 이상 에러 시 초기화
            Vout = _IQ(0.0); Iout = _IQ(0.0);
            error_count = 0;
        }
    } else {
        Vout = Vout_filt; Iout = Iout_filt;
        error_count = 0; // 정상 데이터 시 에러 카운터 리셋
    }
    CLA_Vout = Vout; CLA_Iout = Iout;                   // CLA로 데이터 전달
    checkProtection();                                  // 과전압/과전류 보호 확인
    if (system_state == 1) {                            // RUN 상태에서
        softStart();                                    // 소프트 스타트 실행
        Cla1Regs.MIFRC.bit.INT1 = 1;                    // CLA 태스크 트리거
    }
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;              // 인터럽트 플래그 클리어
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;             // PIE 그룹 ACK
}

// UART 수신 인터럽트: 'R' (RUN), 'S' (STOP) 명령 처리
__interrupt void scia_rx_isr(void) {
    Uint16 rx_data = SciaRegs.SCIRXBUF.all;            // 수신 데이터 읽기
    if (rx_data == 'R' && system_state == 0) {         // 'R' 명령: STOP → RUN
        updateSystemState(1);
    } else if (rx_data == 'S' && system_state == 1) {  // 'S' 명령: RUN → STOP
        updateSystemState(0);
    }
    SciaRegs.SCIFFRX.bit.RXFFOVRCLR = 1;              // 오버플로우 클리어
    SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1;              // 수신 인터럽트 클리어
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;            // PIE 그룹 ACK
}

// ePWM4 인터럽트: 200ms 주기 상태 전송
__interrupt void epwm4_isr(void) {
    scia_xmit(Vout); scia_xmit(Iout); scia_xmit_status(system_state);
    EPwm4Regs.ETFRC.bit.INT = 1;                       // 인터럽트 플래그 클리어
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;            // PIE 그룹 ACK
}

// 메인 함수: 시스템 초기화 및 메인 루프
void main(void) {
    initSystem();                                      // 시스템 초기화
    initGPIO();                                        // GPIO 설정
    initADC();                                         // ADC 설정
    initPWM();                                         // PWM 설정
    initCMPSS();                                       // CMPSS 설정
    initCLA();                                         // CLA 설정
    initUART();                                        // UART 설정
    initInterrupts();                                  // 인터럽트 설정
    EALLOW; EINT; ERTM; EDIS;                         // 글로벌 인터럽트 활성화
    updateSystemState(0);                              // 초기 상태: STOP
    while(1) {                                         // 메인 루프
        // 외부 스위치 (GPIO8)로 RUN/STOP 제어 (디바운싱 포함)
        Uint16 current_switch = GpioDataRegs.GPADAT.bit.GPIO8;
        if (current_switch != last_switch_state) {
            debounce_count++;
            if (debounce_count >= DEBOUNCE_COUNT) {
                if (current_switch == 0 && system_state == 0) {
                    updateSystemState(1);              // Low: RUN
                } else if (current_switch == 1 && system_state == 1) {
                    updateSystemState(0);              // High: STOP
                }
                last_switch_state = current_switch;
                debounce_count = 0;
            }
        } else {
            debounce_count = 0;
        }
    }
}
#include "F28x_Project.h" // F28379D 헤더 파일: 시스템 레지스터 및 함수 정의
#include "IQmathLib.h"    // 고정소수점 연산을 위한 IQmath 라이브러리

// 외부 변수 선언 (main.c에서 정의)
extern volatile _iq VREF;
extern volatile _iq KP;
extern volatile _iq KI;
extern volatile _iq TS;
extern volatile _iq PHI_MAX;
extern volatile _iq CLA_Vout;
extern volatile _iq CLA_Iout;
extern volatile _iq CLA_error;
extern volatile _iq CLA_phi;
extern volatile _iq phi_prev;
extern volatile _iq error_prev;
extern volatile _iq phi_target;
extern volatile Uint16 system_state;
extern volatile Uint16 soft_start_count;
extern volatile Uint16 SOFT_START_STEPS;

// CLA 태스크: PI 제어 및 위상 천이 업데이트
__interrupt void cla_task1_isr(void)
{
    if (system_state != 1) { // RUN 상태가 아니면 종료
        Cla1Regs.MIRUN.bit.INT1 = 0; // CLA 인터럽트 클리어
        return;
    }
    CLA_error = _IQmpy(VREF - CLA_Vout, _IQ(1.0)); // 오차 계산: Vref - Vout
    // PI 제어기: u[n] = u[n-1] + KP*e[n] + KI*TS*(e[n])
    _iq integral = phi_prev + _IQmpy(KI * TS, CLA_error); // 적분 항
    // Anti-windup: 적분기 제한
    if (integral > PHI_MAX) integral = PHI_MAX;
    if (integral < _IQ(0.0)) integral = _IQ(0.0);
    CLA_phi = integral + _IQmpy(KP, CLA_error); // PI 출력
    // 위상 천이 제한: 0° ~ 180°
    if (CLA_phi > PHI_MAX) CLA_phi = PHI_MAX;
    if (CLA_phi < _IQ(0.0)) CLA_phi = _IQ(0.0);
    // 소프트 스타트 완료 후 PWM 위상 업데이트
    if (soft_start_count >= SOFT_START_STEPS) {
        Uint16 phase = (Uint16)(_IQtoF(CLA_phi) * EPwm1Regs.TBPRD / 360.0); // 위상 천이 계산
        EPwm2Regs.TBPHS.bit.TBPHS = phase; // ePWM2 위상 업데이트
        phi_target = CLA_phi; // 목표 위상 업데이트
    }
    Cmpss1Regs.DACHVALS.bit.DACVAL = 2048; // SR 제로 크로싱 기준 (1.65V)
    error_prev = CLA_error; phi_prev = CLA_phi; // 이전 값 업데이트
    Cla1Regs.MIRUN.bit.INT1 = 0; // CLA 인터럽트 클리어
}
/* F28379D 메모리 맵 및 섹션 할당 */
MEMORY
{
PAGE 0 :   /* 프로그램 메모리 (Flash 및 RAM) */
   BEGIN      : origin = 0x000000, length = 0x000002  /* 부트 시작 주소 */
   BOOT_RSVD  : origin = 0x000002, length = 0x0001AE  /* 부트 ROM 예약 */
   RAMM0      : origin = 0x0001B0, length = 0x000250  /* RAM M0 */
   RAMM1      : origin = 0x000400, length = 0x000400  /* RAM M1 */
   RAMLS0     : origin = 0x008000, length = 0x000800  /* RAM LS0 */
   RAMLS1     : origin = 0x008800, length = 0x000800  /* RAM LS1 */
   RAMLS2     : origin = 0x009000, length = 0x000800  /* RAM LS2 */
   RAMLS3     : origin = 0x009800, length = 0x000800  /* RAM LS3 */
   RAMLS4     : origin = 0x00A000, length = 0x000800  /* RAM LS4 */
   RAMLS5     : origin = 0x00A800, length = 0x000800  /* RAM LS5 */
   FLASH0     : origin = 0x080000, length = 0x080000  /* Flash 섹터 (512KB) */
   RESET      : origin = 0x3FFFC0, length = 0x000002  /* 리셋 벡터 */

PAGE 1 :   /* 데이터 메모리 */
   RAMD0      : origin = 0x00B000, length = 0x000800  /* RAM D0 */
   RAMD1      : origin = 0x00B800, length = 0x000800  /* RAM D1 */
   RAMGS0     : origin = 0x00C000, length = 0x001000  /* RAM GS0 */
   RAMGS1     : origin = 0x00D000, length = 0x001000  /* RAM GS1 */
   Cla1DataRam0 : origin = 0x001480, length = 0x000380 /* CLA 데이터 RAM */
   Cla1DataRam1 : origin = 0x001800, length = 0x000800 /* CLA 데이터 RAM (추가) */
   Cla1ProgRam  : origin = 0x010000, length = 0x008000 /* CLA 프로그램 RAM */
}

/* 섹션 할당 */
SECTIONS
{
   /* 코드 섹션 */
   .text            : > FLASH0, PAGE = 0       /* 프로그램 코드 (Flash) */
   .cinit           : > FLASH0, PAGE = 0       /* 초기화 데이터 */
   .pinit           : > FLASH0, PAGE = 0       /* 전역 객체 초기화 */
   .switch          : > FLASH0, PAGE = 0       /* 스위치 테이블 */
   .reset           : > RESET,  PAGE = 0, TYPE = DSECT /* 리셋 벡터 (DSECT: 링커에서만 사용) */
   
   /* 데이터 섹션 */
   .stack           : > RAMM0,  PAGE = 0       /* 스택 (RAM M0) */
   .ebss            : > RAMD0,  PAGE = 1       /* 전역/정적 변수 */
   .econst          : > FLASH0, PAGE = 0       /* 상수 데이터 */
   .esysmem         : > RAMD1,  PAGE = 1       /* 동적 메모리 할당 */
   
   /* CLA 섹션 */
   Cla1Prog         : > Cla1ProgRam, PAGE = 0  /* CLA 프로그램 코드 */
   Cla1DataRam0     : > Cla1DataRam0, PAGE = 1 /* CLA 데이터 RAM */
   
   /* IQmath 섹션 */
   IQmath           : > FLASH0, PAGE = 0       /* IQmath 함수 */
   IQmathTables     : > FLASH0, PAGE = 0       /* IQmath 테이블 */
   
   /* 인터럽트 벡터 */
   .intvecs         : > RAMM1,  PAGE = 0       /* PIE 벡터 테이블 */
}

/* CLA 태스크 벡터 */
Cla1Task1 : Cla1Prog, PAGE = 0

/* 링커 옵션 */
--stack_size=0x300
--heap_size=0x100
--entry_point=code_start

/* 부트 코드 */
code_start:
    LB  main        ; main 함수로 점프

7. 시뮬레이션 및 검증

7.1 MATLAB/Simulink 시뮬레이션

시뮬레이션 파라미터 및 테스트 설정.

파라미터: \( L_o = 100 \, \mu \text{H} \), \( C_{out} = 1000 \, \mu \text{F} \), \( R = 4.8 \, \Omega \).

제어기: Discrete Transfer Function [0.153, -0.147], [1, -1].

테스트: 부하 스텝 (5A → 10A), 전압 스텝 (48V → 50V), 소프트 스타트 (20ms).

기준: 리플 \( \leq 480 \, \text{mV} \), 과도 응답 \( \leq 200 \, \mu \text{s} \), 위상 마진 \( \geq 45^\circ \).

7.2 하드웨어 테스트

하드웨어 테스트 절차.

장비: F28379D LaunchPad, PSFB 보드, 400V/5A 전원, 오실로스코프, 4.8Ω 부하.

절차:

  1. CCS v12로 빌드/플래시.
  2. Simulink External Mode로 \( K_p \), \( K_i \), 위상 천이 튜닝.
  3. UART로 \( V_{out}, I_{out} \), 상태 모니터링 ('R'/'S' 명령).
  4. 외부 스위치 (GPIO8)로 RUN/STOP 테스트.
  5. 소프트 스타트, OVP, OCP 확인.

기준: \( V_{out} = 48 \, \text{V} \pm 480 \, \text{mV} \), 위상 마진 \( \geq 45^\circ \), 과도 응답 \( \leq 200 \, \mu \text{s} \).

8. 참고 자료

  • TI 문서: TIDM-1001, SLUA901, SPRUHM8I, C2000Ware Digital Power SDK.
  • Infineon: "Design Guide for Phase-Shifted Full-Bridge Converter".
  • IEEE 논문: Sabate, J.A., 1990; Chen, W., 2006.
  • MATLAB: Power Electronics Control Design, C2000 Microcontroller Blockset.
반응형