반응형
1. 개요
이 문서는 TI TMS320F280049C DSP를 활용하여 전압 모드 제어(VMC) 기반 동기 벅 컨버터를 설계하는 절차를 설명합니다. 설계는 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)
- 통신:
- 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: 전체 제어 루프(VMC, 소프트 스타트, 보호, 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. 소프트웨어 설계 (VMC)
소프트웨어는 VMC를 구현하며, 단일 전압 루프, 소프트 스타트, 보호, 복구 로직, SCI 통신을 포함하고, LEVEL 매크로로 단계별 검증을 지원하며, TI DCL 라이브러리를 사용하지 않고 순수 C로 PI 제어기를 구현하였습니다.
2.2.1. 공통 설정
- 시스템 클럭: 100 MHz.
- PWM: 200 kHz, TBPRD = 500, 50 ns 데드밴드, CMPA로 듀티비 제어.
- ADC: 12비트, ePWM1 SOCA 트리거.
- SCI: 115200 baud, GPIO28/29, 인터럽트 기반.
- 소프트 스타트: 10 ms, UART로 조정.
- PI 게인: powerSUITE로 튜닝 ($K_p = 0.5$, $K_i = 0.01$).
- LEVEL 정의:
- LEVEL_1: GPIO 및 PWM 초기화, 고정 듀티(50%) 출력.
- LEVEL_2: ADC 초기화, 센싱 데이터 SCI 전송.
- LEVEL_3: SCI 초기화, 테스트 메시지 송수신.
- LEVEL_4: 타이머 초기화, 주기적 플래그 토글.
- LEVEL_5: 전체 제어 루프(VMC, 소프트 스타트, 보호, SCI).
2.2.2. VMC 구현 (vmc_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_D (0.5f / SOFT_START_STEPS_DEFAULT) // 소프트 스타트 듀티비 증가량
#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, duty; // 출력 전압(V), 전류(A), 온도 전압(V), 제어 오차, PWM 듀티비
float vref = VREF_DEFAULT; // 목표 전압 (V, UART로 동적 조정)
float iref_max = IREF_MAX_DEFAULT; // 최대 전류 제한 (A, UART로 동적 조정)
float duty_soft = 0.0f; // 소프트 스타트용 듀티비 (0에서 0.5까지 증가)
float integral = 0.0f; // PI 제어기 적분 항
uint16_t soft_start_steps = SOFT_START_STEPS_DEFAULT; // 소프트 스타트 주기 수 (UART로 조정)
float soft_start_step_d; // 소프트 스타트 듀티비 증가량 (1/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 데드타임, CMPA로 듀티비 제어
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.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.ZRO = AQ_CLEAR; // 타이머 0에서 PWM 출력 클리어 (저측)
EPwm1Regs.AQCTLB.bit.CAU = AQ_SET; // CMPA에서 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_d = 0.5f / soft_start_steps; // 소프트 스타트 증가량 재계산
soft_start_counter = 0; // 소프트 스타트 카운터 초기화
soft_start_complete = false; // 소프트 스타트 재시작
duty_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_d = 0.5f / soft_start_steps; // 증가량 재계산
soft_start_counter = 0; // 소프트 스타트 카운터 초기화
soft_start_complete = false; // 소프트 스타트 재시작
duty_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_d = 0.5f / 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 인터럽트 서비스 루틴: 전압, 전류, 온도 센싱 및 VMC 제어
__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
// 소프트 스타트 처리: 듀티비를 0에서 0.5까지 10ms 동안 선형 증가
if (!soft_start_complete) {
soft_start_counter++; // 소프트 스타트 카운터 증가
duty_soft += soft_start_step_d; // 듀티비 증가
if (soft_start_counter >= soft_start_steps) { // 소프트 스타트 완료 확인
duty_soft = 0.5f; // 최종 듀티비 설정 (최대 50%)
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%
CPUTimer0Regs.TCR.bit.TSS = 0; // 복구 타이머 시작
recovery_trigger = true; // 복구 트리거 활성화
} else if (!fault) { // 정상 상태에서 VMC 제어
// 전압 루프: 목표 전압(vref)에 대한 PI 제어
error = vref - vout; // 전압 오차 계산
duty = pi_update(error, &integral, KP, KI, UMAX, UMIN); // PI 제어로 듀티비 계산
// 소프트 스타트 적용
if (!soft_start_complete) {
if (duty > duty_soft) duty = duty_soft;
}
// 듀티비를 PWM 레지스터 값으로 변환
uint16_t cmpa = (uint16_t)(duty * TBPRD); // 듀티비를 CMPA 값으로 변환
EPwm1Regs.CMPA.bit.CMPA = cmpa; // CMPA 업데이트 (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; // 소프트 스타트 카운터 초기화
duty_soft = 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 (전체 제어):
- 전체 제어 루프(VMC, 소프트 스타트, 보호, 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$ 기준).
3. 테스트 및 디버깅
- 하드웨어: PWM (200 kHz), ADC, SCI (115200 baud) 확인.
- 소프트웨어: CCS로 변수(vout, iout, temp, duty, 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.
- 빌드: vmc_control.c.
- 링커: F28004x_Headers_nonBIOS.cmd.
- 인터럽트: INT_ADCA1, INT_TINT0, INT_SCIA_RX.
5. 추가 고려사항
- 핀 충돌: SCI-A와 SPI 확인.
- EMC: 스너버 회로 최적화.
- 통신 확장: 추가 프로토콜 (예: CAN) 고려.
- 제어 최적화: 부하 조건에 따라 $K_p$, $K_i$ 조정.
반응형
'MCU > C2000' 카테고리의 다른 글
[TI C2000]TI TMS320F280049C DSP를 적용한 동기 벅 컨버터 설계 - PCMC (0) | 2025.08.21 |
---|---|
[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 |