본문 바로가기
MCU/C2000

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

3.1. LED 깜빡이기

GPIO11을 출력으로 설정해 LED를 1초 간격으로 깜빡입니다.

#include "F28x_Project.h" // C2000 헤더 파일 포함 (레지스터 정의 등)

void main(void) {
    InitSysCtrl(); // 시스템 클럭, PLL, 주변 장치 초기화

    // GPIO 클럭 활성화
    EALLOW; // 보호된 레지스터 접근 허용
    SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1; // GPIO 모듈 클럭 활성화
    EDIS; // 보호된 레지스터 접근 비활성화

    // GPIO11 설정 (출력)
    EALLOW; // 보호된 레지스터 접근 허용
    GpioCtrlRegs.GPAGMUX1.bit.GPIO11 = 0; // 상위 다중화: GPIO로 설정
    GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 0;  // 하위 다중화: GPIO로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO11 = 1;   // GPIO11을 출력으로 설정 (1=출력)
    GpioCtrlRegs.GPAPUD.bit.GPIO11 = 0;   // 내부 풀업 저항 활성화
    EDIS; // 보호된 레지스터 접근 비활성화

    while(1) { // 무한 루프
        GpioDataRegs.GPASET.bit.GPIO11 = 1;   // GPIO11을 High로 설정 (LED 켜기)
        DELAY_US(1000000);                    // 1초 대기 (마이크로초 단위)
        GpioDataRegs.GPACLEAR.bit.GPIO11 = 1; // GPIO11을 Low로 설정 (LED 끄기)
        DELAY_US(1000000);                    // 1초 대기
    }
}

설명:

  • InitSysCtrl(): 시스템 클럭과 주변 장치를 초기화.
  • EALLOW/EDIS: 보호된 레지스터 수정 시 필요.
  • GPASET/GPACLEAR: LED를 켜고 끄는 데 사용.
  • DELAY_US: 정확한 타이밍을 위해 마이크로초 단위 지연.

3.2. 버튼 입력 읽기

GPIO12(버튼) 상태에 따라 GPIO11(LED)을 제어합니다.

#include "F28x_Project.h" // C2000 헤더 파일 포함

void main(void) {
    InitSysCtrl(); // 시스템 클럭 및 주변 장치 초기화

    // GPIO 클럭 활성화
    EALLOW; // 보호된 레지스터 접근 허용
    SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1; // GPIO 모듈 클럭 활성화
    EDIS; // 보호된 레지스터 접근 비활성화

    // GPIO11 설정: 출력 (LED)
    EALLOW; // 보호된 레지스터 접근 허용
    GpioCtrlRegs.GPAGMUX1.bit.GPIO11 = 0; // 상위 다중화: GPIO로 설정
    GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 0;  // 하위 다중화: GPIO로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO11 = 1;   // GPIO11을 출력으로 설정
    GpioCtrlRegs.GPAPUD.bit.GPIO11 = 0;   // 내부 풀업 저항 활성화
    EDIS; // 보호된 레지스터 접근 비활성화

    // GPIO12 설정: 입력 (버튼)
    EALLOW; // 보호된 레지스터 접근 허용
    GpioCtrlRegs.GPAGMUX1.bit.GPIO12 = 0; // 상위 다중화: GPIO로 설정
    GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0;  // 하위 다중화: GPIO로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO12 = 0;   // GPIO12를 입력으로 설정 (0=입력)
    GpioCtrlRegs.GPAPUD.bit.GPIO12 = 0;   // 내부 풀업 저항 활성화
    GpioCtrlRegs.GPAQSEL1.bit.GPIO12 = 1; // 3-샘플 한정: 노이즈 방지
    EDIS; // 보호된 레지스터 접근 비활성화

    while(1) { // 무한 루프
        if(GpioDataRegs.GPADAT.bit.GPIO12 == 0) { // 버튼이 눌림 (Low)
            GpioDataRegs.GPASET.bit.GPIO11 = 1;   // LED 켜기
        } else { // 버튼이 눌리지 않음 (High)
            GpioDataRegs.GPACLEAR.bit.GPIO11 = 1; // LED 끄기
        }
    }
}

설명:

  • GPAQSEL1: 3-샘플 한정으로 버튼 입력의 노이즈 제거.
  • GPAPUD: 내부 풀업 저항을 활성화해 버튼이 눌리지 않은 상태에서 High 유지.
  • 버튼이 눌리면 GPADAT에서 Low를 감지해 LED 제어.

3.3. 인터럽트로 LED 토글

GPIO12의 하강 엣지로 인터럽트를 발생시켜 GPIO11의 LED를 토글합니다.

#include "F28x_Project.h" // C2000 헤더 파일 포함

interrupt void xint1_isr(void); // 인터럽트 서비스 루틴 선언

void main(void) {
    InitSysCtrl(); // 시스템 클럭 및 주변 장치 초기화

    // GPIO 클럭 활성화
    EALLOW; // 보호된 레지스터 접근 허용
    SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1; // GPIO 모듈 클럭 활성화
    EDIS; // 보호된 레지스터 접근 비활성화

    // GPIO11 설정: 출력 (LED)
    EALLOW; // 보호된 레지스터 접근 허용
    GpioCtrlRegs.GPAGMUX1.bit.GPIO11 = 0; // 상위 다중화: GPIO로 설정
    GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 0;  // 하위 다중화: GPIO로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO11 = 1;   // GPIO11을 출력으로 설정
    GpioCtrlRegs.GPAPUD.bit.GPIO11 = 0;   // 내부 풀업 저항 활성화
    EDIS; // 보호된 레지스터 접근 비활성화

    // GPIO12 설정: 입력 (인터럽트)
    EALLOW; // 보호된 레지스터 접근 허용
    GpioCtrlRegs.GPAGMUX1.bit.GPIO12 = 0; // 상위 다중화: GPIO로 설정
    GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0;  // 하위 다중화: GPIO로 설정
    GpioCtrlRegs.GPADIR.bit.GPIO12 = 0;   // GPIO12를 입력으로 설정
    GpioCtrlRegs.GPAPUD.bit.GPIO12 = 0;   // 내부 풀업 저항 활성화
    GpioCtrlRegs.GPAQSEL1.bit.GPIO12 = 1; // 3-샘플 한정: 노이즈 방지
    EDIS; // 보호된 레지스터 접근 비활성화

    // XINT1 인터럽트 설정
    EALLOW; // 보호된 레지스터 접근 허용
    GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL = 12; // GPIO12를 XINT1에 매핑
    XintRegs.XINT1CR.bit.POLARITY = 0;         // 하강 엣지 트리거 (버튼 누름)
    XintRegs.XINT1CR.bit.ENABLE = 1;           // XINT1 인터럽트 활성화
    EDIS; // 보호된 레지스터 접근 비활성화

    // 인터럽트 벡터 테이블 설정
    EINT; // 글로벌 인터럽트 활성화
    ERTM; // 실시간 인터럽트 활성화
    PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // PIE(Peripheral Interrupt Expansion) 활성화
    PieCtrlRegs.PIEIER1.bit.INTx4 = 1; // XINT1 인터럽트 활성화 (그룹 1)

    while(1); // 무한 루프 (인터럽트 대기)
}

// XINT1 인터럽트 서비스 루틴
interrupt void xint1_isr(void) {
    GpioDataRegs.GPATOGGLE.bit.GPIO11 = 1; // GPIO11 상태 토글 (LED 켜기/끄기)
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // 인터럽트 플래그 클리어 (재인터럽트 허용)
}

설명:

  • GPIOXINT1SEL: GPIO12를 XINT1 인터럽트 소스로 선택.
  • XINT1CR: 하강 엣지 트리거와 인터럽트 활성화 설정.
  • PIEACK: 인터럽트 플래그를 클리어해 다음 인터럽트 처리 가능.

3.4. PWM으로 다중화

GPIO0을 ePWM1A로 설정해 PWM 신호를 출력합니다.

#include "F28x_Project.h" // C2000 헤더 파일 포함

void InitEPwm1(void) {
    EALLOW; // 보호된 레지스터 접근 허용
    SysCtrlRegs.PCLKCR2.bit.EPWM1 = 1; // ePWM1 모듈 클럭 활성화
    GpioCtrlRegs.GPAGMUX1.bit.GPIO0 = 0; // 상위 다중화: GPIO0 설정
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;  // 하위 다중화: ePWM1A로 설정
    EPwm1Regs.TBPRD = 1000; // PWM 주기 설정 (SYSCLK / (TBPRD * 2))
    EPwm1Regs.TBPHS.all = 0; // 위상 초기화
    EPwm1Regs.TBCTL.bit.CTRMODE = 0; // 타이머 업 카운트 모드
    EPwm1Regs.CMPA.bit.CMPA = 500; // 듀티 사이클 50% 설정
    EPwm1Regs.AQCTLA.bit.ZRO = 2; // 타이머 0에서 High로 설정
    EPwm1Regs.AQCTLA.bit.CAU = 1; // CMPA에서 Low로 설정
    EDIS; // 보호된 레지스터 접근 비활성화
}

void main(void) {
    InitSysCtrl(); // 시스템 클럭 및 주변 장치 초기화
    InitEPwm1(); // ePWM1 초기화 함수 호출
    while(1); // 무한 루프 (PWM 출력 지속)
}

설명:

  • GPAMUX1: GPIO0을 ePWM1A로 다중화.
  • TBPRDCMPA: PWM 주기와 듀티 사이클 설정.
  • AQCTLA: PWM 출력의 High/Low 전환 타이밍 설정.

4. 주요 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 = 비활성화

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을 참고해 프로젝트를 확장해 보세요. 

반응형