Texas Instruments의 TMS320F28377D는 C2000 시리즈 마이크로컨트롤러로, 실시간 제어 애플리케이션에 최적화된 강력한 디바이스입니다. 이 글에서는 GPIO(General Purpose Input/Output)의 설정 방법, 주요 레지스터, 그리고 상세 주석이 포함된 실용적인 예제 코드를 제공합니다. 초보자도 쉽게 따라 할 수 있도록 단계별로 설명하며, LED 제어, 버튼 입력, 인터럽트, PWM 다중화 예제를 포함합니다.
1. TMS320F28377D GPIO 개요
TMS320F28377D는 최대 169개의 GPIO 핀을 제공하며, 각 핀은 입력, 출력, 또는 주변 장치(SPI, I2C, PWM 등)로 설정 가능합니다. 주요 특징은 다음과 같습니다:
- 다중화(Multiplexing): GPIO 핀을 일반 입출력 또는 특정 기능으로 설정.
- 입력 한정(Qualification): 노이즈 방지를 위한 샘플링 메커니즘.
- 인터럽트 지원: 특정 핀에서 이벤트를 감지해 인터럽트 발생.
- 전기적 특성: 3.3V TTL 레벨, 일부 핀은 5V 입력 지원.
이 가이드는 Code Composer Studio(CCS)와 F28x_Project.h
헤더를 기준으로 작성되었습니다.
2. GPIO 설정 단계
GPIO를 사용하려면 다음 단계를 따라야 합니다:
- 클럭 활성화: GPIO 모듈에 시스템 클럭 공급.
- 핀 다중화 설정:
GPxGMUXn
,GPxMUXn
레지스터로 GPIO 또는 주변 장치 선택. - 입출력 방향 설정:
GPxDIR
로 입력/출력 지정. - 데이터 읽기/쓰기:
GPxDAT
,GPxSET
,GPxCLEAR
로 핀 상태 제어. - 추가 설정: 풀업/풀다운, 입력 한정, 인터럽트 설정.
3. 주요 GPIO 레지스터
레지스터 | 설명 | 주요 비트 예시 |
GPxGMUXn | 상위 다중화 설정 | GPIO11: 비트 6-7 (0 = GPIO) |
GPxMUXn | 하위 다중화 설정 | GPIO11: 비트 6-7 (0 = GPIO) |
GPxDIR | 입출력 방향 설정 | 0 = 입력, 1 = 출력 |
GPxDAT | 핀 상태 읽기/쓰기 | GPIO11: 비트 11 |
GPxSET | 핀을 High로 설정 | GPIO11: 비트 11 |
GPxCLEAR | 핀을 Low로 설정 | GPIO11: 비트 11 |
GPxPUD | 풀업/풀다운 저항 설정 | 0 = 풀업 활성화, 1 = 비활성화 |
4. 다양한 예제 코드
다양한 시나리오를 통해 GPIO 사용법을 익혀봅시다. 각 코드에는 상세 주석을 추가해 동작을 명확히 설명합니다.
4.1. LED 깜빡이기
GPIO11을 출력으로 설정해 LED를 1초 간격으로 깜빡입니다.
#include "F28x_Project.h"
// 깜빡일 LED가 연결된 GPIO 핀 번호를 정의합니다.
// Defines the GPIO pin number connected to the LED to blink.
#define BLINKY_LED_GPIO 11
void main(void)
{
// 시스템 클럭 및 주변 장치 초기화
// Initializes system clock and peripherals.
InitSysCtrl();
// GPIO 모듈의 클럭을 활성화하고 기본 설정을 초기화합니다.
// Initializes GPIO module by enabling its clock and setting up default configurations.
InitGpio();
// GPIO11 핀의 다중화(mux) 설정을 GPIO 기능(0)으로 지정합니다.
// Sets the multiplexing (mux) configuration of GPIO11 pin to GPIO function (0).
GPIO_SetupPinMux(BLINKY_LED_GPIO, GPIO_MUX_CPU1, 0);
// GPIO11 핀의 옵션을 출력(OUTPUT)으로 설정하고, 푸시풀(PUSHPULL) 모드로 지정합니다.
// Sets the options for GPIO11 pin to output (OUTPUT) and push-pull (PUSHPULL) mode.
GPIO_SetupPinOptions(BLINKY_LED_GPIO, GPIO_OUTPUT, GPIO_PUSHPULL);
// CPU 인터럽트를 비활성화합니다.
// Disables CPU interrupts.
DINT;
// PIE 컨트롤러 초기화
// Initializes the PIE controller.
InitPieCtrl();
// CPU의 IER(Interrupt Enable Register)과 IFR(Interrupt Flag Register)을 초기화합니다.
// Initializes the CPU's IER (Interrupt Enable Register) and IFR (Interrupt Flag Register).
IER = 0x0000;
IFR = 0x0000;
// PIE 벡터 테이블을 기본 주소로 초기화합니다.
// Initializes the PIE vector table to default addresses.
InitPieVectTable();
// 전역 인터럽트를 활성화합니다.
// Enables global interrupts.
EINT;
// 실시간 모드(Real-Time Mode)에서 인터럽트를 활성화합니다.
// Enables interrupts in Real-Time Mode.
ERTM;
for(;;) // 무한 루프
{
// GPIO11 핀을 Low(0)로 설정하여 LED를 켭니다.
// Sets GPIO11 pin to Low (0) to turn on the LED.
GPIO_WritePin(BLINKY_LED_GPIO, 0);
// 1초 지연
// Delays for 1 second.
DELAY_US(1000000);
// GPIO11 핀을 High(1)로 설정하여 LED를 끕니다.
// Sets GPIO11 pin to High (1) to turn off the LED.
GPIO_WritePin(BLINKY_LED_GPIO, 1);
// 1초 지연
// Delays for 1 second.
DELAY_US(1000000);
}
}
설명:
InitSysCtrl()
: 시스템 클럭과 주변 장치를 초기화.EALLOW
/EDIS
: 보호된 레지스터 수정 시 필요.GPASET
/GPACLEAR
: LED를 켜고 끄는 데 사용.DELAY_US
: 정확한 타이밍을 위해 마이크로초 단위 지연.
4.2. 버튼 입력 읽기
GPIO12(버튼) 상태에 따라 GPIO11(LED)을 제어합니다.
#include "F28x_Project.h"
// LED 및 버튼 GPIO 핀 번호를 정의합니다.
// Defines the GPIO pin numbers for the LED and the button.
#define BLINKY_LED_GPIO 11
#define BUTTON_GPIO 12
void main(void)
{
// 시스템 클럭 및 주변 장치 초기화
// Initializes system clock and peripherals.
InitSysCtrl();
// GPIO 모듈 초기화
// Initializes the GPIO module.
InitGpio();
// LED(GPIO11) 설정
// LED (GPIO11) configuration
// 핀 다중화를 GPIO 기능으로 설정
// Set pin multiplexing to GPIO function.
GPIO_SetupPinMux(BLINKY_LED_GPIO, GPIO_MUX_CPU1, 0);
// 핀을 출력, 푸시풀 모드로 설정
// Set pin to output, push-pull mode.
GPIO_SetupPinOptions(BLINKY_LED_GPIO, GPIO_OUTPUT, GPIO_PUSHPULL);
// 버튼(GPIO12) 설정
// Button (GPIO12) configuration
// 핀 다중화를 GPIO 기능으로 설정
// Set pin multiplexing to GPIO function.
GPIO_SetupPinMux(BUTTON_GPIO, GPIO_MUX_CPU1, 0);
// 핀을 입력, 풀업 저항 활성화, 퀄리피케이션 필터 활성화(3-sample)로 설정
// Set pin to input, enable pull-up resistor, and enable qualification filter (3-sample).
GPIO_SetupPinOptions(BUTTON_GPIO, GPIO_INPUT, GPIO_PULLUP | GPIO_QUAL3);
// 인터럽트 관련 설정
// Interrupt-related settings
DINT;
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
EINT;
ERTM;
while(1) // 무한 루프
{
// 버튼 핀(GPIO12)의 상태를 읽습니다.
// Reads the state of the button pin (GPIO12).
if(GPIO_ReadPin(BUTTON_GPIO) == 0) { // 버튼이 눌렸을 때 (Low)
// LED 핀(GPIO11)을 High로 설정하여 LED를 켭니다.
// Sets the LED pin (GPIO11) to High to turn on the LED.
GPIO_WritePin(BLINKY_LED_GPIO, 1);
} else { // 버튼이 눌리지 않았을 때 (High)
// LED 핀(GPIO11)을 Low로 설정하여 LED를 끕니다.
// Sets the LED pin (GPIO11) to Low to turn off the LED.
GPIO_WritePin(BLINKY_LED_GPIO, 0);
}
}
}
설명:
GPAQSEL1
: 3-샘플 한정으로 버튼 입력의 노이즈 제거.GPAPUD
: 내부 풀업 저항을 활성화해 버튼이 눌리지 않은 상태에서 High 유지.- 버튼이 눌리면
GPADAT
에서 Low를 감지해 LED 제어.
4.3. 인터럽트로 LED 토글
GPIO12의 하강 엣지로 인터럽트를 발생시켜 GPIO11의 LED를 토글합니다.
#include "F28x_Project.h"
// LED 및 버튼 GPIO 핀 번호를 정의합니다.
// Defines the GPIO pin numbers for the LED and the button.
#define LED_GPIO_PIN 11
#define BUTTON_GPIO_PIN 12
// 인터럽트 서비스 루틴 함수를 선언합니다.
// Declares the interrupt service routine function.
__interrupt void xint1_isr(void);
void main(void)
{
// 시스템 초기화
// System initialization
InitSysCtrl();
InitGpio();
// LED 핀(GPIO11)을 출력으로 설정합니다.
// Configures the LED pin (GPIO11) as an output.
GPIO_SetupPinMux(LED_GPIO_PIN, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(LED_GPIO_PIN, GPIO_OUTPUT, GPIO_PUSHPULL);
// 버튼 핀(GPIO12)을 입력으로 설정하고 인터럽트를 활성화합니다.
// Configures the button pin (GPIO12) as an input and enables its interrupt.
GPIO_SetupPinMux(BUTTON_GPIO_PIN, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(BUTTON_GPIO_PIN, GPIO_INPUT, GPIO_PULLUP | GPIO_QUAL3);
// XINT1 인터럽트 설정
// XINT1 interrupt configuration
// XINT1 인터럽트 소스로 GPIO12를 선택합니다.
// Selects GPIO12 as the XINT1 interrupt source.
GPIO_SetupXINT1Gpio(BUTTON_GPIO_PIN); // GPIO_SetupXINT1Pin 함수를 변경했습니다.
// XINT1 인터럽트의 트리거 극성(polarity)을 하강 엣지(falling edge)로 설정합니다.
// Sets the trigger polarity of the XINT1 interrupt to a falling edge.
XintRegs.XINT1CR.bit.POLARITY = 0;
// XINT1 인터럽트를 활성화합니다.
// Enables the XINT1 interrupt.
XintRegs.XINT1CR.bit.ENABLE = 1;
// 인터럽트 관련 설정
// Interrupt-related settings
DINT;
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
EINT;
ERTM;
// PIE 컨트롤러를 활성화하고, 그룹 1의 XINT1 인터럽트를 활성화합니다.
// Enables the PIE controller and the XINT1 interrupt in group 1.
PieCtrlRegs.PIECTRL.bit.ENPIE = 1;
PieCtrlRegs.PIEIER1.bit.INTx4 = 1;
while(1); // 메인 루프에서 인터럽트 대기
}
// XINT1 인터럽트 서비스 루틴 (ISR)
// XINT1 Interrupt Service Routine (ISR)
__interrupt void xint1_isr(void)
{
// GPIO11의 상태를 토글합니다. (비트 필드 사용)
// Toggles the state of GPIO11. (using bit-fields)
GpioDataRegs.GPATOGGLE.bit.GPIO11 = 1;
// PIE 인터럽트 플래그를 클리어하여 다음 인터럽트를 허용합니다.
// Clears the PIE interrupt flag to allow the next interrupt.
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
설명:
GPIOXINT1SEL
: GPIO12를 XINT1 인터럽트 소스로 선택.XINT1CR
: 하강 엣지 트리거와 인터럽트 활성화 설정.PIEACK
: 인터럽트 플래그를 클리어해 다음 인터럽트 처리 가능.
4.4. PWM으로 다중화
GPIO0을 ePWM1A로 설정해 PWM 신호를 출력합니다.
#include "F28x_Project.h" // C2000 헤더 파일 포함
// PWM 주파수와 듀티 사이클을 위한 정의
// Definitions for PWM frequency and duty cycle
// SYSCLKOUT = 200MHz
#define TBPRD_VALUE 1000 // PWM 주기 레지스터 값
#define CMPA_VALUE 500 // 비교 레지스터 값 (50% 듀티)
void InitEPwm1(void) {
EALLOW; // 보호된 레지스터 접근 허용 (Enable access to protected registers)
// ePWM1 모듈 클럭 활성화 (수정된 부분)
// Activate ePWM1 module clock (modified part)
CpuSysRegs.PCLKCR2.bit.EPWM1 = 1;
// GPIO0 핀을 ePWM1A 기능으로 다중화 설정
// Configure GPIO0 pin multiplexing for ePWM1A function
GpioCtrlRegs.GPAGMUX1.bit.GPIO0 = 0; // 상위 다중화: GPIO0 설정
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // 하위 다중화: ePWM1A로 설정
// ePWM1 모듈 레지스터 설정
// Configure ePWM1 module registers
EPwm1Regs.TBPRD = TBPRD_VALUE; // PWM 주기 설정
EPwm1Regs.TBPHS.all = 0; // 위상 초기화
EPwm1Regs.TBCTL.bit.CTRMODE = 0; // 타이머 업 카운트 모드
EPwm1Regs.TBCTL.bit.CLKDIV = 0; // 클럭 분주기 설정
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; // 고속 클럭 분주기 설정
EPwm1Regs.CMPA.bit.CMPA = CMPA_VALUE; // 비교값 설정
// 액션 퀄리파이어(Action Qualifier) 설정
// Action Qualifier configuration
EPwm1Regs.AQCTLA.bit.ZRO = 2; // 카운터가 0일 때 EPWM1A를 High로 설정
EPwm1Regs.AQCTLA.bit.CAU = 1; // 카운터가 CMPA에 도달할 때 EPWM1A를 Low로 설정
EDIS; // 보호된 레지스터 접근 비활성화
}
void main(void) {
// 시스템 및 인터럽트 초기화
// System and interrupt initialization
InitSysCtrl();
InitGpio();
// ePWM1 초기화 함수 호출
// Call ePWM1 initialization function
InitEPwm1();
DINT;
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
EINT;
ERTM;
while(1) {
// 무한 루프
// Infinite loop
}
}
설명:
GPAMUX1
: GPIO0을 ePWM1A로 다중화.TBPRD
와CMPA
: PWM 주기와 듀티 사이클 설정.AQCTLA
: PWM 출력의 High/Low 전환 타이밍 설정.
5. 디버깅 팁
- 다중화 충돌: 데이터시트의 "GPIO Muxed Pins" 테이블(Table 8-12)을 확인해 핀이 다른 주변 장치에 할당되지 않았는지 점검.
- 타이밍 문제: 빠른 GPIO 토글 시
NOP
명령어 또는DELAY_US
로 타이밍 조정. - 레지스터 확인: CCS의 레지스터 뷰에서
GPxDAT
,GPxDIR
값을 확인. - 하드웨어 점검: 오실로스코프 또는 로직 애널라이저로 핀 상태 모니터링.
- 초기화 상태: 리셋 후 GPIO는 고임피던스(High-Z) 상태이므로 명시적 초기화 필수.
6. 추가 자료
- TI Technical Reference Manual (TRM): GPIO 챕터 (Section 8)에서 레지스터 상세 정보 확인.
- TI ControlSUITE: 샘플 코드와 드라이버 라이브러리 제공.
- TI E2E 포럼: GPIO 관련 문제 해결 사례 검색.
- 데이터시트: "GPIO Muxed Pins" 테이블(Table 8-12)로 다중화 설정 확인.
7. 마무리
이 문서는 TMS320F28377D GPIO를 활용한 LED 제어, 버튼 입력, 인터럽트, PWM 출력 예제를 상세 주석과 함께 제공했습니다. 초보자도 쉽게 따라 할 수 있도록 단계별로 구성했으며, 데이터시트와 TRM을 참고해 프로젝트를 확장해 보세요.
'MCU > C2000' 카테고리의 다른 글
TI C2000 Lockstep 완벽 정리: 기능 안전을 위한 필수 기술 (0) | 2025.08.06 |
---|---|
TMS320F28377D DSP SCI 사용법: Bitfield 구조 활용 예제 코드(수정) (0) | 2025.08.06 |
TMS320F28377D DSP ADC 트리거 모드 사용: Bitfield 구조 활용(수정) (0) | 2025.08.06 |
TMS320F28377D DSP ADC 사용법 : Bitfield 구조 활용 예제 코드(수정) (0) | 2025.08.06 |
TMS320F28377D DSP CPU 타이머 사용법 :Bitfield 구조 활용 예제 코드(수정) (0) | 2025.08.06 |
TMS320F28377D DSP CCS 프로젝트 설정 및 기본 프로그램 (0) | 2025.08.06 |
TMS320F28377D DSP Half-Bridge PWM 설정: 비트필드 예제 (0) | 2025.08.05 |
TI C2000 DSP ELF 파일 구조 분석 및 CCS 확인 방법 (0) | 2025.08.02 |