1.1 서론
TI C2000 패밀리는 전력 변환 디지털 제어 분야의 표준 플랫폼으로 30년 가까이 자리해왔다. 그 최신 세대인 TMS320F28P65x는 전력전자 응용에 특화된 핵심 기능들을 대폭 강화하였으며, 본서는 이 디바이스를 기준 플랫폼으로 삼는다.
F28P65x 핵심 차별점:
- 36채널 HRPWM: 150ps 분해능, 전 채널 MINDB(최소 데드밴드)·ICL(금지조합차단)·DE(다이오드 에뮬레이션) 내장
- ADC 하드웨어 가속: SYSCLK에서 직접 유도되는 클록, 16-bit/12-bit 소프트웨어 선택, 최대 128배 오버샘플링
- 듀얼코어 + CLA: CPU1/CPU2 각 200 MIPS + CLA 코프로세서, 록스텝 안전 옵션
- 기능안전 인증: ISO 26262 ASIL B / IEC 61508 SIL 2
1.2 디바이스 패밀리 개요
1.2.1 파트번호 체계
| 파트번호 | 코어 구성 | EtherCat | 록스텝 | 비고 |
| F28P650DK | CPU1+CLA, CPU2 | ○ | ○ | 본서 기준 |
| F28P650SK | CPU1+CLA | ○ | — | 싱글코어 |
| F28P659DK-Q1 | CPU1+CLA, CPU2 | — | ○ | 차량용 Q1 |
1.2.2 핵심 사양
| 항목 | 사양 |
| CPU 코어 | C28x × 2, 각 200 MIPS |
| CLA | CPU1.CLA, 200 MIPS |
| FPU | IEEE 754 단정밀도(32-bit) |
| ePWM | 36채널 (전 채널 150ps HRPWM) |
| ADC | 3개 모듈(A/B/C), 16/12-bit 소프트웨어 선택 |
| Flash | 최대 5뱅크, 부팅 시 CPU1/CPU2 동적 할당 |
| RAM | LS×10 + GS×5 + 전용(M0/M1/Dx) + MSGRAM |
| 기능안전 | ISO 26262 ASIL B / IEC 61508 SIL 2 |
1.3 C28x 프로세서 코어
1.3.1 부동소수점 유닛(FPU)
F28P65x의 FPU는 IEEE 754 단정밀도(32-bit) 부동소수점을 지원한다. 8개의 32-bit 결과 레지스터(R0H~R7H), 상태 레지스터(STF), 반복블록 레지스터(RB)가 추가되며, RB를 제외한 모든 FPU 레지스터는 섀도잉되어 고우선순위 인터럽트에서 빠른 컨텍스트 전환이 가능하다.
1.3.2 TMU — 명령어별 사이클
| 명령어 | C 등가 연산 | 사이클 |
| MPY2PIF32 | a = b × 2π | 2/3 |
| DIV2PIF32 | a = b / 2π | 2/3 |
| DIVF32 | a = b/c | 5 |
| SQRTF32 | a = sqrt(b) | 5 |
| SINPUF32 | a = sin(b×2π) | 4 |
| COSPUF32 | a = cos(b×2π) | 4 |
| ATANPUF32 | a = atan(b)/2π | 4 |
| QUADF32 | ATANPU2 보조 | 5 |
IEXP2F32(지수), LOG2F32(로그) 명령어로 비선형 PID(NLPID)의 거듭제곱 연산을 약 300사이클(라이브러리 에뮬레이션)에서 10사이클 미만으로 단축한다.
FOC Park 변환:
$$\begin{bmatrix} V_d \ V_q \end{bmatrix} = \begin{bmatrix} \cos\theta_r & \sin\theta_r \ -\sin\theta_r & \cos\theta_r \end{bmatrix} \begin{bmatrix} V_\alpha \ V_\beta \end{bmatrix}, \qquad \theta_{PU} = \frac{\theta_{rad}}{2\pi}$$
SINPUF32+COSPUF32 사용 시 최대 8사이클(@200MHz, 40ns)이며, 이는 C 표준 sinf()/cosf()(약 50~80사이클) 대비 대폭 단축된 수치다.
1.3.3 VCRC 유닛
| CRC 종류 | 다항식 |
| CRC8 | 0x07 |
| CRC16 | 0x8005 / 0x1021 |
| CRC24 | 0x5D6DCB |
| CRC32 | 0x04C11DB7 / 0x1EDC6F41 |
바이트당 1사이클(표준 다항식) 또는 3사이클(사용자 정의 다항식)로 연산한다.
1.4 클록 시스템

그림 1-1. 클록 분배 트리
1.4.1 클록 소스 4종
| 소스 | 주파수 | 용도 |
| INTOSC2 | 10 MHz | 리셋 기본값, Boot ROM 구동 |
| INTOSC1 | 10 MHz | Watchdog/MCD 백업 전용 |
| XTAL | 사용자 결정 | 외부 수정/레조네이터(X1/X2, GPIO220/221) |
| AUXCLKIN | 사용자 결정 | GPIO133, USB/CAN/통신용 |
클록 소스는 CLKSRCCTL1[OSCCLKSRCSEL] 레지스터로 선택한다: 00=INTOSC2(기본), 01=XTAL, 10=INTOSC1.
설계 규칙: 클록 소스 변경 시 SYSPLLMULT가 자동으로 0이 되며 PLL이 바이패스된다. 다음 SYSPLLMULT 쓰기 전 최소 10 OSCCLK 사이클을 대기해야 한다.
1.4.2 SYSPLLMULT 레지스터와 PLL 주파수 공식
| 비트 | 필드 | 의미 |
| 28:24 | REFDIV | 실제 분주비 = REFDIV + 1 |
| 20:16 | ODIV | 실제 분주비 = ODIV + 1 (레지스터값 1 이상 권장) |
| 7:0 | IMULT | 레지스터 값 자체가 배율(1~127) |
PLL 주파수 공식:
$$\boxed{f_{PLLRAWCLK} = f_{OSCCLK} \times \frac{IMULT}{(REFDIV+1)\times(ODIV+1)}}$$
SYSPLLMULT 레지스터는 쓰기 후 다음 쓰기까지 69 SYSCLK 사이클의 지연이 필요하다.
설계 예 — XTAL 20MHz로 SYSCLK 200MHz를 만드는 경우:
먼저 PLLRAWCLK를 400MHz로 설정한 뒤 SYSCLKDIVSEL로 ÷2하여 200MHz를 얻는다. REFDIV=0(실제÷1), ODIV=1(실제÷2)로 두면:
$$400\text{MHz} = 20\text{MHz} \times \frac{IMULT}{(0+1)\times(1+1)} \Rightarrow IMULT=40$$
| 레지스터 | 기록값 | 의미 |
| IMULT | 40 | 배율 ×40 |
| REFDIV | 0 | 실제 분주비 1 |
| ODIV | 1 | 실제 분주비 2 |
설계에서는 위 절차를 직접 구현하는 C2000Ware Driverlib의 SysCtl_setClock() 함수 사용이 권장된다.
1.4.3 시스템 PLL 설정 절차
1. PLLCLKEN=0, 120사이클 대기 5. SYSPLLMULT 32-bit 동시기록
2. PLLEN=0, 60사이클 대기 (다음쓰기까지 69 SYSCLK 대기)
3. OSCCLKSRCSEL 선택, 300사이클 대기 6. SYSPLLSTS.LOCKS=1 폴링
4. PLLSYSCLKDIV=0(÷1, 최고속) 7. DCC로 PLLRAWCLK 검증
8. 분주를 한 단계 높여 재설정
1.4.4 클록 도메인
| 도메인 | 적용대상 |
| PLLSYSCLK | 시스템 제어 레지스터, GS0-4 RAM, IPC |
| CPUx.CPUCLK | CPU, 코프로세서, 전용RAM(M0/M1/Dx), Flash래퍼 |
| CPUx.SYSCLK | CLA, DMA, ePIE, LS0-9 RAM |
| PERx.SYSCLK | ADC, CMPSS, DAC, eCAP, eQEP, EPWM/HRPWM 등 |
| PERx.LSPCLK | SPI, SCI |
| AUXPLLCLK | USB(60MHz 고정) |
1.5 메모리 아키텍처

그림 1-2. 메모리 분류 전체도
1.5.1 메모리 분류 4종
| 분류 | RAM | 접근 주체 |
| 전용(Dedicated) | M0, M1, Dx | 해당 CPU만 |
| 로컬 공유(LSx) | LS0~LS9 (10개) | CPU + 해당 CPU의 CLA |
| 글로벌 공유(GSx) | GS0~GS4 (5개) | CPU + 양쪽 CPU의 DMA |
| 메시지(MSGRAM) | — | CPU1↔CPU2 통신 전용 |
1.5.2 확인된 정확한 주소
| 블럭 | 주소 범위 | 크기 |
| LS0 | 0x8000–0x87FF | 2 KW |
| LS1 | 0x8800–0x8FFF | 2 KW |
| D2(CPU2 로컬) | 0x8000–0x9FFF | 8 KW |
| D3(CPU2 로컬) | 0xA000–0xCFFF | 12 KW |
LS2~LS9, GS0~GS4 개별 주소 및 Flash 뱅크 정확한 크기는 데이터시트(SPRSP69D)의 메모리맵 표 또는 C2000Ware 링커 .cmd 예제 파일에서 확인한다.
1.5.3 전용 RAM(Dx)의 소유권
D0-D1은 CPU1 전용으로 고정되어 있다. D2-D5는 MCUCNF1 레지스터 설정에 따라 CPU1 또는 CPU2 중 한쪽에 동적으로 매핑된다.
1.5.4 메모리 에러 보호
| 항목 | 내용 |
| 전용/LSx RAM | ECC(SECDED), 단일비트 정정 |
| GSx 등 공유 RAM | Parity, 정정 불가 시 NMI 발생 |
| 초기화 | INIT 비트 세트 후 INITDONE 폴링 필수. 완료 전 해당 RAM 접근 금지 |
1.5.5 Flash — 뱅크 구성과 Wait State
Flash는 최대 5개 뱅크(Bank0~4)로 구성되며, 부팅 시점에 CPU1 또는 CPU2에 동적으로 할당된다(BANKxMUXSEL 레지스터). 두 CPU가 서로 다른 뱅크를 동시에 읽을 수 있고, 한 뱅크를 프로그램/소거하는 동안 다른 뱅크는 읽기가 가능하다.
Wait State 공식:
$$\boxed{RWAIT = \lceil f_{SYSCLK}/f_{FCLK} - 1 \rceil}, \qquad t_{access}=(RWAIT+1)\times T_{SYSCLK}$$
| 항목 | 값 |
| 리셋 기본값 | RWAIT = 15(최악 케이스) |
| USER-OTP 접근 | 11 SYSCLK 사이클 고정 |
| Flash 설정 코드 | 반드시 RAM에서 실행 |
Prefetch(128-bit 단위 선읽기)와 Data Cache(128-bit, 데이터 읽기 전용)는 리셋 시 비활성화 상태이며, Flash_enablePrefetch()/Flash_enableCache() Driverlib 함수로 활성화한다. 두 기능 모두 RWAIT=0일 때는 자동으로 우회된다.
1.6 인터럽트 시스템 — PIE
1.6.1 3단계 전파 구조
인터럽트는 주변장치 → PIE → CPU의 3단계를 모두 통과해야 처리된다.
① 주변장치: 고유 신호 발생, 상태 레지스터로 원인 구분
② PIE: PIEIER(인에이블)/PIEIFR(플래그)/PIEACK(그룹마스크) — 그룹당 16채널, 낮은 채널 우선
③ CPU: IER/IFR/INTM(ST1 레지스터 비트) — IER/INTM 쓰기는 원자적(atomic)
인터럽트 엔트리 시퀀스(11단계):
1. PIEIFRx.y 래치 7. 파이프라인 D2 이후 명령어 완료
2. PIEIERx.y 확인 시 전파 8. 컨텍스트 스택 저장
3. PIEACK 확인 후 세트 9. IFR/IER 클리어, INTM 세트
4. IFR.x 래치 10. PIE에서 ISR 벡터 페치, PIEIFRx.y 클리어
5. IER.x 확인 시 전파 11. ISR로 분기
6. INTM 클리어 시 CPU 수신
1.6.2 인터럽트 레이턴시
| 종류 | 최소 latency | 200MHz 환산 |
| 내부 주변장치(ePWM 등) | 14 사이클 | 70 ns |
| 외부 GPIO(XINT) | 16 사이클 | 80 ns |
20kHz 제어 루프(50μs) 대비 내부 인터럽트 레이턴시 비율은 $70\text{ns}/50\mu\text{s}=0.14%$로 무시 가능한 수준이다. C28x RPT(반복) 명령어로 생성된 루프는 인터럽트가 불가능하므로, ISR 내에서 긴 RPT 루프 사용에 주의해야 한다.
1.6.3 인터럽트 비활성화 절차
1. DINT(전역 비활성화) 4. 해당 PIE 그룹 IFR 클리어
2. PIEIER 비트 클리어 5. 해당 PIE 그룹 PIEACK 클리어
3. 5 사이클 대기 6. EINT(전역 재활성화)
중요: PIEIFR 비트는 소프트웨어에서 절대 직접 클리어해서는 안 된다. read/modify/write 동작 중 들어오는 인터럽트가 유실될 수 있기 때문이다. PIEIFR을 안전하게 클리어하는 유일한 방법은 CPU가 해당 인터럽트를 실제로 처리(ISR 실행)하는 것이다.
1.6.4 PIE 채널 매핑 — 전력 제어 관련
| PIE | 그룹 매핑 | 비고 |
| INT2.y | EPWM1_TZ ~ EPWM16_TZ | ePWM Trip-Zone(보호) |
| INT3.y | EPWM1 ~ EPWM16 | ePWM 주기 인터럽트 — 제어 루프 핵심 |
| INT4.y | ECAP1~7, FSI | — |
| INT5.y | EQEP1~4, CLB1~4, SDFM1/2 | — |
1.7 ePWM 모듈
1.7.1 PWM 주기·주파수 공식
$$\text{업/다운 단일카운트}: T_{PWM}=(TBPRD+1)\times T_{TBCLK}$$
$$\text{대칭 업다운카운트}: T_{PWM}=2\times TBPRD \times T_{TBCLK}$$
설계 예 — TBCLK 100MHz, 20kHz 대칭 PWM:
$$TBPRD = \frac{100\times10^6}{2\times20\times10^3} = 2500$$
1.7.2 데드밴드
$$FED=DBFED\times T_{TBCLK}, \qquad RED=DBRED\times T_{TBCLK}$$
10-bit 레지스터이며, half-cycle 모드 사용 시 분주값이 절반이 된다.
1.7.3 Trip-Zone
각 ePWM 모듈은 6개의 트립존 입력(TZ1~TZ6)을 가진다.
| 신호 | 소스 |
| TZ1-3 | GPIO 입력 X-BAR |
| TZ4 | EQEPx 에러(반전) |
| TZ5 | 시스템 클록 실패 로직 |
| TZ6 | CPU EMUSTOP(에뮬레이션 정지) |
트립 발생 시 출력은 High/Low/High-impedance/무동작 중 선택 가능하며, One-Shot(영구 정지)과 Cycle-By-Cycle(자동 복귀) 두 가지 모드를 지원한다.
1.7.4 MINDB / ICL
MINDB(Minimum Dead-Band): 신호의 하강 에지를 검출한 후 BLOCK 신호를 생성하여 반대편 신호의 천이를 차단함으로써, 게이트 드라이버 내부 지연을 보상하는 최소 데드타임을 하드웨어가 보장한다.
ICL(Illegal Combo Logic): 3입력(IN1/IN2/IN3) LUT(Look-Up Table) 구조로, 정의된 조합에 따라 출력을 강제한다. 기본값은 바이패스이며, 활성화 시에만 동작한다. 매트릭스 컨버터나 3레벨 NPC 인버터의 금지된 스위칭 조합을 하드웨어 수준에서 차단하는 데 사용된다.
1.7.5 다중 ePWM 모듈 클록 동기화
1. 개별 ePWM 모듈 클록 활성화
2. TBCLKSYNC = 0 → 모든 ePWM 타임베이스 클록 정지
3. 프리스케일러 값 및 원하는 ePWM 모드 설정
4. TBCLKSYNC = 1 → 모든 ePWM 타임베이스 클록을 동시에 시작
동기화를 위해서는 각 ePWM 모듈의 프리스케일러 비트가 동일하게 설정되어야 한다.
1.8 ADC 모듈
1.8.1 모듈 구성과 클록
ADC-A/B/C 3개 모듈을 가지며, 각각 16-bit 또는 12-bit 분해능을 소프트웨어로 선택할 수 있다.
ADC 변환 클록(ADCCLK)은 SYSCLK에서 직접 유도되며, ADCCTL2 레지스터의 PRESCALE 필드로 분주비를 결정한다.
1.8.2 PRESCALE — 분주비 환산표
| PRESCALE | 분주비 | PRESCALE | 분주비 |
| 0 | ÷1 | 8 | ÷5 |
| 2 | ÷2 | 9 | ÷5.5 |
| 3 | ÷2.5 | 10 | ÷6 |
| 4 | ÷3 | 11 | ÷6.5 |
| 5 | ÷3.5 | 12 | ÷7 |
| 6 | ÷4 | 13 | ÷7.5 |
| 7 | ÷4.5 | 14, 15 | ÷8, ÷8.5 |
1.8.3 변환 시간
12-bit 모드에서는 약 10.5 ADCCLK 사이클, 16-bit 모드에서는 약 29.5 ADCCLK 사이클이 소요된다.
| PRESCALE | 분주비 | 12-bit 변환시간(SYSCLK 사이클) | 16-bit |
| 0 | ÷1 | 11 | 31 |
| 6 | ÷4 | 41 | 119 |
| 15 | ÷8.5 | 86 | 252 |
200MHz, PRESCALE=0, 12-bit 기준 변환시간: $11/200\text{MHz}=55\text{ns}$
1.8.4 샘플홀드(S+H) 윈도우
$$t_{S+H} = (ACQPS+1)\times T_{SYSCLK}$$
S+H 시간은 최소 1 ADCCLK 주기와 데이터시트가 규정하는 최소 S+H 시간을 모두 충족해야 한다.
1.8.5 전원 인가 절차
1. PCLKCR13에서 해당 ADC 클록 활성화
2. ADCCTL2.PRESCALE에 원하는 분주비 설정
3. ADCCTL1.ADCPWDNZ=1로 전원 ON
4. 샘플링 전 지연 (정확한 시간은 데이터시트 참조)
1.8.6 설정 시 주의사항
ADC 분해능은 반드시 Driverlib ADC_setMode() 함수를 통해 설정해야 한다. 이 함수가 내부적으로 올바른 트림(trim) 값을 함께 로드하기 때문이며, ADCCTL2 레지스터를 직접 조작해서는 안 된다.
1.9 Driverlib 기반 코드 구현
1.9.1 시스템 클록 초기화
/*==============================================================================
* 파일 : sys_init.c
* 목적 : TMS320F28P650DK SYSCLK 200MHz 초기화
*============================================================================*/
#include "driverlib.h"
#include "device.h"
/*--- 방법 A: Device_init() — 신규 프로젝트 권장 ---
* 내부에서 SysCtl_setClock(), ADC 트림 로드(Device_cal()),
* Flash wait state 자동 설정을 일괄 처리한다. */
void System_Init(void)
{
Device_init();
Device_initGPIO();
}
/*--- 방법 B: SysCtl_setClock() 직접 호출 ---
* XTAL 20MHz -> SYSCLK 200MHz:
* PLLRAWCLK = 20MHz x IMULT / [(REFDIV+1)x(ODIV+1)] = 400MHz
* REFDIV=0(실제÷1), ODIV=1(실제÷2) -> IMULT=40
* 이후 SYSCLKDIVSEL=÷2 적용 -> SYSCLK = 200MHz */
void System_Init_Manual(void)
{
SysCtl_setClock(SYSCTL_OSCSRC_XTAL |
SYSCTL_IMULT(40) |
SYSCTL_REFDIV(1) |
SYSCTL_ODIV(2) |
SYSCTL_SYSDIV(2) |
SYSCTL_PLL_ENABLE);
Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES);
SysCtl_setEPWMClockDivider(SYSCTL_EPWMCLK_DIV_2);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ADCA);
}
1.9.2 ePWM1 초기화 — 20kHz 상보 PWM
/*==============================================================================
* 파일 : epwm_init.c
* 목적 : ePWM1 20kHz 대칭 PWM, 상보 출력, 데드밴드, ADC/ISR 트리거
*============================================================================*/
#include "driverlib.h"
#include "device.h"
#define EPWM1_TBPRD 2500U /* 100MHz/(2x20kHz)=2500 */
#define EPWM1_DEADBAND 20U /* 200ns @ TBCLK=100MHz */
void EPWM1_Init(void)
{
/*--- 타임베이스 ---*/
EPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
EPWM_setTimeBasePeriod(EPWM1_BASE, EPWM1_TBPRD);
EPWM_setTimeBaseCounter(EPWM1_BASE, 0U);
EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN);
/*--- 카운터 비교 ---*/
EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, EPWM1_TBPRD/2);
EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE, EPWM_COUNTER_COMPARE_A,
EPWM_COMP_LOAD_ON_CNTR_ZERO);
/*--- 액션 퀄리파이어: 업카운트 CMPA→HIGH, 다운카운트 CMPA→LOW ---*/
EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
/*--- 데드밴드: FED=DBFED×TTBCLK, RED=DBRED×TTBCLK ---*/
EPWM_setDeadBandDelayMode(EPWM1_BASE, EPWM_DB_RED, true);
EPWM_setDeadBandDelayPolarity(EPWM1_BASE, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH);
EPWM_setDeadBandDelayMode(EPWM1_BASE, EPWM_DB_FED, true);
EPWM_setDeadBandDelayPolarity(EPWM1_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
EPWM_setRisingEdgeDelay(EPWM1_BASE, EPWM1_DEADBAND);
EPWM_setFallingEdgeDelay(EPWM1_BASE, EPWM1_DEADBAND);
/*--- ADC SOC 및 ISR 트리거: 카운터=0 시점 ---*/
EPWM_setADCTriggerSource(EPWM1_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_ZERO);
EPWM_setADCTriggerEventPrescale(EPWM1_BASE, EPWM_SOC_A, 1U);
EPWM_enableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
EPWM_setInterruptSource(EPWM1_BASE, EPWM_INT_TBCTR_ZERO);
EPWM_setInterruptEventCount(EPWM1_BASE, 1U);
EPWM_enableInterrupt(EPWM1_BASE);
}
1.9.3 ADC 초기화
/*==============================================================================
* 파일 : adc_init.c
* 목적 : ADCA 12-bit Single-ended 초기화, ePWM1 SOCA 트리거
*============================================================================*/
#include "driverlib.h"
#include "device.h"
void ADCA_Init(void)
{
ADC_enableConverter(ADCA_BASE);
DEVICE_DELAY_US(1000U); /* 전원 ON 후 안정화 대기 */
/* 분해능은 반드시 ADC_setMode()로 설정 (트림값 동시 로드) */
ADC_setMode(ADCA_BASE, ADC_RESOLUTION_12BIT, ADC_MODE_SINGLE_ENDED);
/* PRESCALE=2 → ÷2.0 분주 */
ADC_setPrescaler(ADCA_BASE, ADC_CLK_DIV_2_0);
/* SOC0: ePWM1 SOCA 트리거, S+H=(ACQPS+1)×T_SYSCLK */
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0,
ADC_TRIGGER_EPWM1_SOCA, ADC_CH_ADCIN0, 15U);
ADC_setInterruptSource(ADCA_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER0);
ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
}
/* 12-bit 전압 변환: V = raw/4096 × VREFHI */
float ADCA_Read_12bit(void)
{
uint16_t raw = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0);
return ((float)raw / 4096.0f) * 3.3f;
}
1.9.4 인터럽트 초기화 및 제어 루프 ISR
/*==============================================================================
* 파일 : main_cpu1.c
* 목적 : CPU1 메인 — 시스템 초기화 + 20kHz 제어 루프 ISR
*============================================================================*/
#include "driverlib.h"
#include "device.h"
volatile float g_v_bus = 0.0f, g_duty = 0.5f, g_setpoint = 48.0f;
__interrupt void epwm1_isr(void);
void main(void)
{
Device_init();
Device_initGPIO();
GPIO_setPadConfig(0U, GPIO_PIN_TYPE_STD);
GPIO_setPinConfig(GPIO_0_EPWM1_A);
GPIO_setPadConfig(1U, GPIO_PIN_TYPE_STD);
GPIO_setPinConfig(GPIO_1_EPWM1_B);
Interrupt_initModule();
Interrupt_initVectorTable();
Interrupt_register(INT_EPWM1, &epwm1_isr);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ADCA);
SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
EPWM1_Init();
ADCA_Init();
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
Interrupt_enable(INT_EPWM1);
Interrupt_enableGlobal();
ERTM;
while(1)
{
/* 백그라운드: 통신, CPU2 IPC 등 비실시간 처리 */
}
}
/* 제어 루프 ISR — 실행 주기 20kHz(50μs), 최소 레이턴시 14사이클(70ns) */
__interrupt void epwm1_isr(void)
{
/*--- ADC 결과 읽기 ---*/
uint16_t adc_raw = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0);
g_v_bus = ((float)adc_raw / 4096.0f) * 3.3f;
/*--- 제어 알고리즘 삽입 위치 (이후 장에서 구현) ---*/
/*--- PWM 듀티비 업데이트 ---*/
uint16_t cmpa = (uint16_t)(g_duty * (float)EPWM1_TBPRD);
if(cmpa > EPWM1_TBPRD) cmpa = EPWM1_TBPRD;
EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, cmpa);
/*--- [필수①] ePWM ET 인터럽트 플래그 클리어 ---*/
EPWM_clearEventTriggerInterruptFlag(EPWM1_BASE);
/*--- [필수②] ePIE 그룹3 ACK 클리어 ---
* PIEIFR 비트는 절대 직접 클리어하지 않는다.
* PIEACK 클리어만이 안전한 방법이다. */
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
}
1.10 개발 환경 구성
1.10.1 필수 소프트웨어
| 도구 | 권장 버전 | 용도 |
| Code Composer Studio | 12.x 이상 | IDE, 디버거, Flash 프로그래머 |
| C2000Ware | 5.x 이상 | F28P65x Driverlib, 예제, 문서 |
| TI C28x CGT Compiler | 22.6 이상 | C/C++ → C28x 기계어 |
| LAUNCHXL-F28P65X | — | 평가 보드 |
1.10.2 컴파일러 핵심 옵션
[Optimization]
-O2 : 최적화 레벨 2
[Advanced Options]
--fp_mode=relaxed : FPU 활성화
--tmu_support=tmu0 : TMU 삼각함수 가속
[Predefined Symbols]
CPU1
_LAUNCHXL_F28P65X
[Linker]
${C2000WARE}/driverlib/f28p65x/driverlib/Debug/driverlib.lib
참고문헌
- Texas Instruments, TMS320F28P65x Real-Time Microcontrollers Technical Reference Manual, SPRUIZ1B, July 2023 – Revised August 2024.
- Texas Instruments, TMS320F28P65x Real-Time Microcontrollers Data Sheet, SPRSP69D, Revised August 2025.
- Texas Instruments, F28P65x Peripheral Driver Library API Guide, v5.04.00.00.
- Texas Instruments, TMS320C28x CPU and Instruction Set Reference Guide.
- Texas Instruments, TMS320C28x Extended Instruction Sets Technical Reference Manual.
'Power Electronics' 카테고리의 다른 글
| 디지탈 전력변환-제5장 고속 제어 루프 설계 — CLA, DMA, 루프 타이밍 최적화 (0) | 2026.06.30 |
|---|---|
| 디지탈 전력변환-제4장 통신 주변장치 — SPI, I2C, CAN, UART (0) | 2026.06.29 |
| 디지탈 전력변환 -제3장 전력변환 보호·위치 측정 주변장치 — CMPSS, DAC, eQEP, SDFM (0) | 2026.06.21 |
| 디지탈 전력변환-제2장 CCS + C2000Ware 개발환경 및 F28P65x 프로젝트 구성 (0) | 2026.06.21 |
| NE555를 사용한 DC to AC 인버터 회로 (0) | 2026.03.08 |
| MATLAB Simulink에서 Nonlinear Transformer 모델링 가이드 (0) | 2025.08.22 |