반응형
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$ 값을 부하 조건에 따라 조정.
반응형
'MCU > C2000' 카테고리의 다른 글
[TI C2000]TMS320F280049C DSP를 적용한 동기 벅 컨버터 설계 절차-VMC (0) | 2025.08.20 |
---|---|
[TMS320F28335] CAN, I2C, McBSP 사용법 : Bitfield 구조 활용 예제 코드 (0) | 2025.08.19 |
[TMS320F28335] DMA 사용법 : Bitfield 구조 활용 예제 코드 (0) | 2025.08.19 |
[TMS320F28335] eQEP 및 eCAP 사용법 : Bitfield 구조 활용 예제 코드 (0) | 2025.08.19 |
[TMS320F28335] XINTF 사용법 : Bitfield 구조 활용 예제 코드 (0) | 2025.08.19 |
[TMS320F28335] ADC 사용법 : Bitfield 구조 활용 예제 코드 (0) | 2025.08.18 |
[TMS320F28335] ePWM 사용법 : Bitfield 구조 활용 예제 코드 (1) | 2025.08.18 |
[TMS320F28377D] DC-DC 변환 토포롤로지별 ePWM 생성 방법: Bitfield 구조 활용 예제 코드 (1) | 2025.08.18 |