본문 바로가기
개발/TI_TMS320

TMS320F28069 eQEP 코드 예시 1

by 즐기며 2025. 9. 9.

TMS320F28069 eQEP GPIO20, GPIO21을 사용한 코드 예시

TMS320F28069의 eQEP 모듈은 GPIO 핀을 멀티플렉싱(MUX)하여 쿼드러처 엔코더 신호와 연결할 수 있습니다. GPIO20과 GPIO21은 eQEP2 모듈의 입력으로 매핑될 수 있습니다. 구체적으로:

  • GPIO20: eQEP2A (Channel A 신호, QEPxA)
  • GPIO21: eQEP2B (Channel B 신호, QEPxB)

이 핀들은 GPAMUX2 레지스터에서 MUX=3으로 설정하여 eQEP2 기능으로 활성화합니다. (참고: TMS320F28069 데이터시트 및 TRM SPRUH18A에 따라, GPIO20/21은 eQEP2A/B로 지원됩니다. Index 신호(QEPxI)는 GPIO22에 연결하는 것을 추천하나, 여기서는 A/B 채널만 사용한 기본 예시로 진행합니다.)

아래는 C2000Ware 라이브러리를 기반으로 한 초기화 코드 예시입니다. 이는 Code Composer Studio(CCS)에서 컴파일 가능하며, main() 함수 내에서 호출하세요. eQEP2를 쿼드러처 모드로 설정하고, 위치 카운터와 속도 측정을 활성화합니다. 인터럽트도 간단히 설정합니다.

1. 헤더 파일 포함 및 전역 선언

c
 
#include "F28x_Project.h"  // C2000 헤더 (DSP28x_Project.h 또는 F2806x_Device.h 포함)
#include "F2806x_EQep.h"   // eQEP 모듈 헤더

// eQEP2 관련 전역 변수 (예: 위치와 속도 저장)
Uint32 eqep2_position = 0;
float eqep2_speed = 0.0;

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

2. GPIO 설정 함수 (GPIO20, GPIO21을 eQEP2A/B로 설정)

c
 
void init_eqep2_gpio(void)
{
    EALLOW;  // 보호 레지스터 접근 허용

    // GPIO20 (eQEP2A) 설정
    GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 3;  // MUX=3: eQEP2A 기능으로 설정
    GpioCtrlRegs.GPAQSEL2.bit.GPIO20 = 0;  // 비동기 입력 모드 (SYSCLK 동기화)
    GpioCtrlRegs.GPAPUD.bit.GPIO20 = 0;   // 내부 풀업 활성화 (엔코더 신호 안정화)
    GpioCtrlRegs.GPAINV.bit.GPIO20 = 0;   // 입력 인버트 비활성화

    // GPIO21 (eQEP2B) 설정
    GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 3;  // MUX=3: eQEP2B 기능으로 설정
    GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 0;  // 비동기 입력 모드
    GpioCtrlRegs.GPAPUD.bit.GPIO21 = 0;   // 내부 풀업 활성화
    GpioCtrlRegs.GPAINV.bit.GPIO21 = 0;   // 입력 인버트 비활성화

    EDIS;  // 보호 레지스터 접근 비활성화
}

3. eQEP2 모듈 초기화 함수 (위치/속도 측정 설정)

c
 
void init_eqep2(void)
{
    // eQEP2 클럭 활성화 (SYSCLKOUT 기준, 90MHz 가정)
    SysCtrlRegs.PCLKCR0.bit.EQEP2 = 1;  // eQEP2 클럭 활성화

    // eQEP2 제어 레지스터 초기화
    EQep2Regs.QEPCTL.bit.FREE_SOFT = 2;  // FREE/SOFT 모드: 디버그 시 소프트 스톱
    EQep2Regs.QEPCTL.bit.PCRM = 0;       // Position Counter Reset Mode: 인덱스 시 리셋 비활성화 (Index 미연결 시)
    EQep2Regs.QEPCTL.bit.IEI = 0;        // Index Event Interrupt: 비활성화
    EQep2Regs.QEPCTL.bit.SEI = 0;        // Strobe Event Interrupt: 비활성화
    EQep2Regs.QEPCTL.bit.SWI = 0;        // Software Init: 초기화
    EQep2Regs.QEPCTL.bit.QPEN = 0;       // eQEP 모듈 비활성화 (아래에서 활성화)

    // 쿼드러처 디코더 제어
    EQep2Regs.QDECCTL.bit.QSRC = 00;     // Quadrature clock mode (A/B 신호 사용)
    EQep2Regs.QDECCTL.bit.IGATE = 0;     // Index gating 비활성화
    EQep2Regs.QDECCTL.bit.SWAP = 0;      // Channel A/B 스왑 비활성화
    EQep2Regs.QDECCTL.bit.XCR = 00;      // 2x resolution (기본 쿼드러처 모드, 4x로 하려면 10)

    // 위치 카운터 초기화 (0으로 리셋)
    EQep2Regs.QPOSINIT = 0;
    EQep2Regs.QEPCTL.bit.SWI = 1;        // 소프트웨어 초기화 (카운터 리셋)
    EQep2Regs.QPOSCNT = 0;               // 현재 위치 0으로 설정

    // Unit Timer 설정 (속도 측정용, 100Hz 업데이트 예시: SYSCLK 90MHz / 900000 = 100Hz)
    EQep2Regs.QUPRD = 900000;            // Unit Period: 90MHz / 900000 = 100Hz
    EQep2Regs.QEPCTL.bit.UTE = 1;        // Unit Timer Enable
    EQep2Regs.QEPCTL.bit.QPEN = 1;       // eQEP 모듈 활성화

    // 인터럽트 설정 (Unit Timer 이벤트 시 인터럽트)
    EQep2Regs.QEINT.bit.UTE = 1;         // Unit Time Event Interrupt Enable
    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;   // PIE Group 1, INT7 (eQEP2) Enable
    IER |= M_INT1;                       // CPU INT1 Enable
    PieCtrlRegs.PIECTRL.bit.ENPIE = 1;   // PIE Enable
}

4. 인터럽트 서비스 루틴 (ISR) - 위치와 속도 읽기

c
 
interrupt void eqep2_isr(void)
{
    // 위치 읽기 (32비트 카운터 값)
    eqep2_position = EQep2Regs.QPOSCNT;

    // 속도 계산 (캡처 기간 / Unit Period * 스케일링)
    // QCPRD: 펄스 간 캡처 시간 (오버플로우 시 0 속도 처리)
    if (EQep2Regs.QCPRD != 0xFFFF) {  // 오버플로우 체크 (16비트 캡처)
        eqep2_speed = (float)EQep2Regs.QUPRD / (float)EQep2Regs.QCPRD;  // RPM 또는 속도 단위 변환 필요
    } else {
        eqep2_speed = 0.0;  // 저속/정지 시 0
    }

    // 인터럽트 플래그 클리어
    EQep2Regs.QCLR.bit.INT = 1;    // Global Interrupt Clear
    EQep2Regs.QCLR.bit.UTE = 1;    // Unit Timer Event Clear

    // PIE 인터럽트 ACK
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

5. 메인 함수에서 사용 예시

c
 
void main(void)
{
    InitSysCtrl();  // 시스템 클럭 초기화 (90MHz)

    DINT;           // 글로벌 인터럽트 비활성화
    InitPieCtrl();  // PIE 컨트롤러 초기화
    IER = 0x0000;
    IFR = 0x0000;
    InitPieVectTable();  // 인터럽트 벡터 테이블 초기화

    // eQEP2 ISR 등록 (PIE Group 1, INT7)
    PieVectTable.EQEP2_INT = &eqep2_isr;

    init_eqep2_gpio();  // GPIO 설정
    init_eqep2();       // eQEP 모듈 설정

    EINT;              // 글로벌 인터럽트 활성화
    ERTM;              // 실시간 인터럽트 활성화

    // 메인 루프: 위치/속도 모니터링 (예: UART로 출력하거나 PID 제어에 사용)
    while(1)
    {
        // 예: 1초마다 위치/속도 출력 (SciaRegs로 UART 사용 가정)
        DELAY_US(1000000);  // 1초 딜레이
        // Scia_xmit(eqep2_position);  // 위치 전송 (별도 UART 코드 필요)
        // Scia_xmit(eqep2_speed);     // 속도 전송
    }
}

설명 및 주의사항

  • 동작 원리: GPIO20/21이 엔코더의 A/B 신호를 입력받아 eQEP2가 쿼드러처 모드로 위치(상대적 카운트)와 속도(펄스 간 시간 기반)를 계산합니다. 4x 해상도를 위해 QDECCTL.XCR=10으로 변경 가능.
  • 클럭 및 해상도: SYSCLK=90MHz 기준. 엔코더 PPR(Pulses Per Revolution)에 따라 QUPRD 조정 (예: 1000PPR 엔코더 시 속도 스케일링 필요).
  • Index/Strobe 미연결: GPIO22(GPIO22를 eQEP2I로 MUX=3 설정)와 GPIO23(eQEP2S)을 추가로 연결하면 절대 위치 참조 가능. 코드에 추가: GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 3; 등.
  • 문제 해결:
    • 오버플로우: 저속 시 QCPRD=0xFFFF 발생 → 속도=0 처리.
    • 인터럽트 누락: SCI 등 다른 모듈과 충돌 시 우선순위 조정 (PieCtrlRegs.PIEIER1).
    • 5V 엔코더: LaunchPad의 JP3 점퍼로 5V 공급, 하지만 GPIO는 3.3V tolerant이니 레벨 시프터 사용 추천.
  • 테스트: C2000Ware의 eqep_ex2_pos_speed 예제를 기반으로 수정. 실제 하드웨어(엔코더 연결)에서 디버깅하세요. 데이터시트(www.ti.com/product/TMS320F28069) 참조.