본문 바로가기
MCU/C2000

TMS320F28377D DSP GPIO 사용법 : Bitfield 구조 활용 예제 코드(수정)

by linuxgo 2025. 8. 6.

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를 사용하려면 다음 단계를 따라야 합니다:

  1. 클럭 활성화: GPIO 모듈에 시스템 클럭 공급.
  2. 핀 다중화 설정: GPxGMUXn, GPxMUXn 레지스터로 GPIO 또는 주변 장치 선택.
  3. 입출력 방향 설정: GPxDIR로 입력/출력 지정.
  4. 데이터 읽기/쓰기: GPxDAT, GPxSET, GPxCLEAR로 핀 상태 제어.
  5. 추가 설정: 풀업/풀다운, 입력 한정, 인터럽트 설정.

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 사용법을 익혀봅시다. 각 코드에는 상세 주석을 추가해 동작을 명확히 설명합니다.

tms320f28377d 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로 다중화.
  • TBPRDCMPA: 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을 참고해 프로젝트를 확장해 보세요.