1. TMS320F28388D eQEP 개요
TMS320F28388D는 Texas Instruments의 C2000 시리즈에 속하는 고성능 32비트 마이크로컨트롤러로, 최대 4개의 eQEP(Enhanced Quadrature Encoder Pulse) 모듈을 제공합니다. eQEP 모듈은 로터리 인코더 또는 리니어 인코더를 사용하여 모터의 위치, 속도, 방향을 정밀하게 측정하는 데 최적화되어 있습니다. 이는 모터 제어, 로보틱스, 산업 자동화 등에서 필수적인 기능을 제공합니다.
eQEP 모듈의 주요 특징
- 쿼드러처 디코딩: A, B, I(인덱스) 신호를 분석하여 위치와 방향을 감지.
- 위치 카운터: 32비트 카운터로 고해상도 위치 추적 가능.
- 속도 계산: 단위 시간당 펄스 수 또는 펄스 간 시간을 통해 속도 계산.
- 인덱스 및 스트로브: 인덱스 펄스로 절대 위치 동기화, 스트로브 신호로 특정 이벤트 감지.
- 타이머: 참조 클럭을 사용하여 주기적 속도 계산 및 인터럽트 생성.
- 에러 감지: 쿼드러처 신호의 위상 오류 감지.
- 클럭: 시스템 클럭(최대 200MHz)을 기반으로 동작, 프리스케일러로 조정 가능.
DriverLib API는 복잡한 레지스터 조작을 추상화하여 eQEP 설정을 간소화합니다.
2. 주요 eQEP DriverLib API 함수
아래는 TMS320F28388D의 eQEP 모듈을 제어하기 위해 자주 사용되는 DriverLib API 함수입니다.
2.1. eQEP 기본 설정 관련 함수
- EQEP_enableModule(base): eQEP 모듈을 활성화하여 동작 시작.
- EQEP_disableModule(base): eQEP 모듈을 비활성화하여 동작 중지.
- EQEP_setDecoderConfig(base, config): 쿼드러처 디코더 설정(4x/2x 디코딩, A/B 신호 스왑 여부).
- EQEP_setPositionCounterConfig(base, mode, maxCount): 위치 카운터 동작 모드(리셋 조건) 및 최대 카운트 설정.
- EQEP_setPositionInitMode(base, initMode): 위치 카운터 초기화 조건(예: 인덱스 펄스) 설정.
2.2. 속도 계산 관련 함수
- EQEP_enableUnitTimer(base, period): 단위 타이머 활성화 및 주기 설정(속도 계산용).
- EQEP_setCaptureConfig(base, prescale, eventPrescindale): 캡처 유닛 설정(펄스 간 시간 측정).
- EQEP_enableCompare(base, value): 위치 비교 이벤트 설정.
2.3. 인터럽트 관련 함수
- EQEP_enableInterrupt(base, intFlags): 인터럽트 활성화(예: 위치 오버플로우, 단위 타이머).
- EQEP_setInterruptSource(base, intSource): 인터럽트 발생 조건 설정.
- EQEP_clearInterruptStatus(base, intFlags): 인터럽트 플래그 지우기.
- Interrupt_register(intNumber, handler): 인터럽트 서비스 루틴(ISR) 등록.
2.4. 인덱스 및 스트로브 관련 함수
- EQEP_enableIndexEvent(base, enable): 인덱스 이벤트 활성화/비활성화.
- EQEP_setStrobeSource(base, source): 스트로브 입력 소스 설정.
3. eQEP 설정 및 동작 원리
- 시스템 초기화: 시스템 클럭, GPIO, 인터럽트 모듈 초기화(Device_init(), Device_initGPIO()).
- eQEP 모듈 설정: 클럭 활성화, 디코더 설정, 위치 카운터, 단위 타이머 구성.
- 인터럽트 설정(선택): 위치 카운터 오버플로우 또는 단위 타이머 인터럽트 활성화.
- 인덱스 및 캡처 설정(선택): 인덱스 펄스 또는 펄스 캡처 설정.
- eQEP 활성화: eQEP 모듈을 활성화하여 인코더 신호 처리 시작.
4. eQEP 예제 코드
아래는 C2000Ware의 DriverLib를 기반으로 작성된 eQEP 예제 코드입니다. 각 설정값은 계산식을 통해 도출되며, 상세한 주석을 포함하여 코드 가독성을 높였습니다. GPIO 설정은 별도의 initGPIO() 함수로 분리되어 있으며, 모든 코드는 Code Composer Studio(CCS)에서 실행 가능합니다.
4.1. 예제 1: 기본 위치 측정
eQEP1을 사용하여 쿼드러처 인코더의 위치를 측정합니다.
#include "driverlib.h"
#include "device.h"
// 디버깅용 상태 변수
volatile uint32_t eqepStatus = 0; // 0: 초기화 완료, 1: eQEP 동작 중, 0xFFFF: 오류
volatile int32_t position = 0; // 현재 위치 카운터 값 (32비트)
// 시스템 클럭 주파수 정의
#define SYSTEM_CLOCK_HZ 200000000 // 200MHz 시스템 클럭
// GPIO 초기화 함수
void initGPIO(void)
{
// GPIO0을 eQEP1A로 설정 (쿼드러처 A 입력)
GPIO_setPinConfig(GPIO_0_EQEP1A); // eQEP1A 핀 매핑
GPIO_setDirectionMode(0, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(0, GPIO_PULL_UP); // 풀업 저항 활성화 (외부 회로 안정화)
// GPIO1을 eQEP1B로 설정 (쿼드러처 B 입력)
GPIO_setPinConfig(GPIO_1_EQEP1B); // eQEP1B 핀 매핑
GPIO_setDirectionMode(1, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(1, GPIO_PULL_UP); // 풀업 저항 활성화
// 디버깅용 LED 설정 (GPIO31, LAUNCHXL-F28379D 기준)
GPIO_setPinConfig(GPIO_31_GPIO31); // 일반 GPIO로 설정
GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT); // 출력 모드
GPIO_setPadConfig(31, GPIO_PULL_UP); // 풀업 저항 활성화
GPIO_writePin(31, 0); // 초기 LED OFF
}
// eQEP1 초기화 함수
void initEQEP(void)
{
// eQEP1 클럭 활성화
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EQEP1); // eQEP1 모듈에 클럭 공급
// 쿼드러처 디코더 설정
// 4x 디코딩: A, B 신호의 모든 에지에서 카운트 (최대 해상도)
// 스왑 없음: A, B 신호 순서 변경 없이 표준 연결
EQEP_setDecoderConfig(EQEP1_BASE, EQEP_CONFIG_4X | EQEP_CONFIG_NO_SWAP);
// 위치 카운터 설정
// 리셋 모드: 리셋 없음 (연속 카운트)
// 최대 카운트: 0xFFFFFFFF (32비트 최대값)
EQEP_setPositionCounterConfig(EQEP1_BASE, EQEP_POSITION_RESET_NONE, 0xFFFFFFFF);
// eQEP 모듈 활성화
EQEP_enableModule(EQEP1_BASE);
// 상태 업데이트: eQEP 동작 시작
eqepStatus = 1;
}
void main(void)
{
// 시스템 클럭 및 주변 장치 초기화
// PLL, Watchdog, 주변 장치 클럭 설정
Device_init();
// GPIO 기본 초기화
Device_initGPIO();
// eQEP 관련 GPIO 설정
initGPIO();
// 인터럽트 모듈 초기화 (확장성을 위해 포함, 본 예제에서는 사용 안 함)
Interrupt_initModule();
Interrupt_initVectorTable();
// 시스템 클럭 확인 (디버깅용)
uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
if (sysClockHz != SYSTEM_CLOCK_HZ)
{
eqepStatus = 0xFFFF; // 오류 상태
GPIO_writePin(31, 0); // LED OFF로 오류 표시
ESTOP0; // 디버깅용 정지 (CCS에서 브레이크포인트 확인 가능)
}
// eQEP1 초기화
initEQEP();
// 초기화 오류 확인
if (eqepStatus != 1)
{
eqepStatus = 0xFFFF; // 초기화 실패
GPIO_writePin(31, 0); // LED OFF로 오류 표시
ESTOP0; // 디버깅용 정지
}
// 글로벌 인터럽트 활성화 (확장성을 위해 포함)
EINT;
// 저전력 모드 방지: Watchdog 활성화
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
SysCtl_serviceWatchdog();
// 무한 루프: 위치 데이터를 주기적으로 읽음
for(;;)
{
// 현재 위치 카운터 값 읽기
position = EQEP_getPosition(EQEP1_BASE);
// 디버깅용: 상태 표시 (정상 동작 시 LED ON)
GPIO_writePin(31, (eqepStatus == 1) ? 1 : 0);
// 1초 대기 (디버깅 및 CPU 부하 감소)
DEVICE_DELAY_US(1000000); // 1ms * 1000 = 1초
}
}
설명:
- 기능: eQEP1 모듈을 사용하여 쿼드러처 인코더의 위치를 실시간으로 측정.
- 설정:
- 디코더: 4x 모드로 설정하여 A, B 신호의 모든 에지에서 카운트 (최대 해상도).
- 위치 카운터: 리셋 없이 연속 카운트, 최대값 0xFFFFFFFF.
- GPIO:
- GPIO0: eQEP1A (A 신호 입력).
- GPIO1: eQEP1B (B 신호 입력).
- GPIO31: 디버깅용 LED.
- 출력: 위치 값은 position 변수에 저장, 정상 동작 시 LED ON.
- 용도: 모터 위치 추적, 로봇 위치 제어.
4.2. 예제 2: 속도 계산
eQEP1의 단위 타이머를 사용하여 인코더의 회전 속도를 계산합니다.
#include "driverlib.h"
#include "device.h"
// 디버깅용 상태 변수
volatile uint32_t eqepStatus = 0; // 0: 초기화 완료, 1: eQEP 동작 중, 0xFFFF: 오류
volatile int32_t position = 0; // 현재 위치 카운터 값
volatile uint32_t velocity = 0; // 속도 (펄스/단위 시간)
// 시스템 클럭 및 타이머 주기 정의
#define SYSTEM_CLOCK_HZ 200000000 // 200MHz 시스템 클럭
#define UNIT_TIMER_PERIOD (SYSTEM_CLOCK_HZ / 1000) // 1ms 주기 = 200MHz / 1000 = 200000 클럭
// GPIO 초기화 함수
void initGPIO(void)
{
// GPIO0을 eQEP1A로 설정
GPIO_setPinConfig(GPIO_0_EQEP1A); // eQEP1A 핀 매핑
GPIO_setDirectionMode(0, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(0, GPIO_PULL_UP); // 풀업 저항 활성화
// GPIO1을 eQEP1B로 설정
GPIO_setPinConfig(GPIO_1_EQEP1B); // eQEP1B 핀 매핑
GPIO_setDirectionMode(1, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(1, GPIO_PULL_UP); // 풀업 저항 활성화
// 디버깅용 LED 설정 (GPIO31)
GPIO_setPinConfig(GPIO_31_GPIO31); // 일반 GPIO로 설정
GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT); // 출력 모드
GPIO_setPadConfig(31, GPIO_PULL_UP); // 풀업 저항 활성화
GPIO_writePin(31, 0); // 초기 LED OFF
}
// 인터럽트 서비스 루틴 (단위 타이머)
__interrupt void eqep1ISR(void)
{
// 속도 계산: 단위 시간(1ms) 동안의 위치 변화
velocity = EQEP_getPositionLatch(EQEP1_BASE); // 위치 래치 값 읽기
EQEP_clearPositionLatch(EQEP1_BASE); // 래치 리셋
// 인터럽트 플래그 지우기
EQEP_clearInterruptStatus(EQEP1_BASE, EQEP_INT_UNIT_TIME_OUT);
// PIE 인터럽트 ACK
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP5);
// 상태 업데이트
eqepStatus = 1;
}
void initEQEP(void)
{
// eQEP1 클럭 활성화
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EQEP1); // eQEP1 모듈에 클럭 공급
// 쿼드러처 디코더 설정: 4x 모드, 스왑 없음
EQEP_setDecoderConfig(EQEP1_BASE, EQEP_CONFIG_4X | EQEP_CONFIG_NO_SWAP);
// 위치 카운터 설정: 리셋 없음, 최대 카운트 0xFFFFFFFF
EQEP_setPositionCounterConfig(EQEP1_BASE, EQEP_POSITION_RESET_NONE, 0xFFFFFFFF);
// 단위 타이머 설정
// 주기 = SYSTEM_CLOCK_HZ / 1000 = 200000 (1ms @ 200MHz)
EQEP_enableUnitTimer(EQEP1_BASE, UNIT_TIMER_PERIOD);
// 인터럽트 설정: 단위 타이머 타임아웃 시 발생
EQEP_enableInterrupt(EQEP1_BASE, EQEP_INT_UNIT_TIME_OUT);
// eQEP 모듈 활성화
EQEP_enableModule(EQEP1_BASE);
}
void main(void)
{
// 시스템 클럭 및 주변 장치 초기화
Device_init();
// GPIO 기본 초기화
Device_initGPIO();
// eQEP 관련 GPIO 설정
initGPIO();
// 인터럽트 모듈 초기화
Interrupt_initModule();
Interrupt_initVectorTable();
// eQEP1 인터럽트 ISR 등록
Interrupt_register(INT_EQEP1, &eqep1ISR);
// 시스템 클럭 확인
uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
if (sysClockHz != SYSTEM_CLOCK_HZ)
{
eqepStatus = 0xFFFF; // 오류 상태
GPIO_writePin(31, 0); // LED OFF로 오류 표시
ESTOP0;
}
// eQEP1 초기화
initEQEP();
// 초기화 오류 확인
if (eqepStatus != 1)
{
eqepStatus = 0xFFFF; // 초기화 실패
GPIO_writePin(31, 0); // LED OFF로 오류 표시
ESTOP0;
}
// 글로벌 인터럽트 활성화
EINT;
// Watchdog 활성화
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
SysCtl_serviceWatchdog();
// 무한 루프
for(;;)
{
// 현재 위치 카운터 읽기
position = EQEP_getPosition(EQEP1_BASE);
// 디버깅용: 상태 표시
GPIO_writePin(31, (eqepStatus == 1) ? 1 : 0);
DEVICE_DELAY_US(1000000); // 1초 대기
}
}
설명:
- 기능: eQEP1의 단위 타이머를 사용하여 1ms마다 인코더의 속도를 계산.
- 설정:
- 디코더: 4x 모드로 최대 해상도 제공.
- 단위 타이머: 주기 = 200MHz / 1000 = 200000 클럭 (1ms).
- 인터럽트: 단위 타이머 타임아웃 시 속도 계산.
- GPIO: GPIO0(eQEP1A), GPIO1(eQEP1B), GPIO31(LED).
- 출력: 속도는 velocity 변수에 저장 (펄스/1ms), 정상 동작 시 LED ON.
- 용도: 모터 속도 제어, 속도 피드백 시스템.
4.3. 예제 3: 인덱스 이벤트를 사용한 위치 초기화
eQEP1의 인덱스 신호를 사용하여 위치 카운터를 초기화합니다.
#include "driverlib.h"
#include "device.h"
// 디버깅용 상태 변수
volatile uint32_t eqepStatus = 0; // 0: 초기화 완료, 1: eQEP 동작 중, 0xFFFF: 오류
volatile int32_t position = 0; // 현재 위치 카운터 값
// 시스템 클럭 정의
#define SYSTEM_CLOCK_HZ 200000000 // 200MHz 시스템 클럭
// GPIO 초기화 함수
void initGPIO(void)
{
// GPIO0을 eQEP1A로 설정
GPIO_setPinConfig(GPIO_0_EQEP1A); // eQEP1A 핀 매핑
GPIO_setDirectionMode(0, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(0, GPIO_PULL_UP); // 풀업 저항 활성화
// GPIO1을 eQEP1B로 설정
GPIO_setPinConfig(GPIO_1_EQEP1B); // eQEP1B 핀 매핑
GPIO_setDirectionMode(1, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(1, GPIO_PULL_UP); // 풀업 저항 활성화
// GPIO2를 eQEP1I로 설정 (인덱스 신호)
GPIO_setPinConfig(GPIO_2_EQEP1I); // eQEP1I 핀 매핑
GPIO_setDirectionMode(2, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(2, GPIO_PULL_UP); // 풀업 저항 활성화
// 디버깅용 LED 설정 (GPIO31)
GPIO_setPinConfig(GPIO_31_GPIO31); // 일반 GPIO로 설정
GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT); // 출력 모드
GPIO_setPadConfig(31, GPIO_PULL_UP); // 풀업 저항 활성화
GPIO_writePin(31, 0); // 초기 LED OFF
}
void initEQEP(void)
{
// eQEP1 클럭 활성화
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EQEP1); // eQEP1 모듈에 클럭 공급
// 쿼드러처 디코더 설정: 4x 모드, 스왑 없음
EQEP_setDecoderConfig(EQEP1_BASE, EQEP_CONFIG_4X | EQEP_CONFIG_NO_SWAP);
// 인덱스 이벤트 설정: 상승 에지에서 위치 카운터 초기화
EQEP_setPositionInitMode(EQEP1_BASE, EQEP_INIT_RISING_INDEX);
EQEP_enableIndexEvent(EQEP1_BASE, true);
// 위치 카운터 설정: 인덱스 펄스에서 리셋, 최대 카운트 0xFFFFFFFF
EQEP_setPositionCounterConfig(EQEP1_BASE, EQEP_POSITION_RESET_INDEX, 0xFFFFFFFF);
// eQEP 모듈 활성화
EQEP_enableModule(EQEP1_BASE);
// 상태 업데이트
eqepStatus = 1;
}
void main(void)
{
// 시스템 클럭 및 주변 장치 초기화
Device_init();
// GPIO 기본 초기화
Device_initGPIO();
// eQEP 관련 GPIO 설정
initGPIO();
// 인터럽트 모듈 초기화
Interrupt_initModule();
Interrupt_initVectorTable();
// 시스템 클럭 확인
uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
if (sysClockHz != SYSTEM_CLOCK_HZ)
{
eqepStatus = 0xFFFF; // 오류 상태
GPIO_writePin(31, 0); // LED OFF로 오류 표시
ESTOP0;
}
// eQEP1 초기화
initEQEP();
// 초기화 오류 확인
if (eqepStatus != 1)
{
eqepStatus = 0xFFFF; // 초기화 실패
GPIO_writePin(31, 0); // LED OFF로 오류 표시
ESTOP0;
}
// 글로벌 인터럽트 활성화
EINT;
// Watchdog 활성화
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
SysCtl_serviceWatchdog();
// 무한 루프
for(;;)
{
// 현재 위치 카운터 읽기
position = EQEP_getPosition(EQEP1_BASE);
// 디버깅용: 상태 표시
GPIO_writePin(31, (eqepStatus == 1) ? 1 : 0);
DEVICE_DELAY_US(1000000); // 1초 대기
}
}
설명:
- 기능: eQEP1의 인덱스 신호를 사용하여 위치 카운터를 0으로 초기화.
- 설정:
- 디코더: 4x 모드로 최대 해상도.
- 인덱스: 상승 에지에서 위치 카운터 리셋.
- 위치 카운터: 인덱스 펄스에서 리셋, 최대값 0xFFFFFFFF.
- GPIO:
- GPIO0: eQEP1A (A 신호).
- GPIO1: eQEP1B (B 신호).
- GPIO2: eQEP1I (인덱스 신호).
- GPIO31: LED.
- 출력: 인덱스 펄스 발생 시 position이 0으로 리셋, 정상 동작 시 LED ON.
- 용도: 절대 위치 동기화가 필요한 애플리케이션.
4.4. 예제 4: 캡처 유닛을 사용한 펄스 간 시간 측정
eQEP1의 캡처 유닛을 사용하여 쿼드러처 펄스 간 시간을 측정하여 속도를 계산합니다.
#include "driverlib.h"
#include "device.h"
// 디버깅용 상태 변수
volatile uint32_t eqepStatus = 0; // 0: 초기화 완료, 1: eQEP 동작 중, 0xFFFF: 오류
volatile uint32_t capturePeriod = 0; // 펄스 간 시간 (클럭 수)
// 시스템 클럭 및 캡처 설정 정의
#define SYSTEM_CLOCK_HZ 200000000 // 200MHz 시스템 클럭
#define CAPTURE_PRESCALE 1 // 캡처 클럭 프리스케일러: 1 (직접 시스템 클럭 사용)
#define EVENT_PRESCALE 1 // 이벤트 프리스케일러: 1 (모든 펄스 캡처)
// GPIO 초기화 함수
void initGPIO(void)
{
// GPIO0을 eQEP1A로 설정
GPIO_setPinConfig(GPIO_0_EQEP1A); // eQEP1A 핀 매핑
GPIO_setDirectionMode(0, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(0, GPIO_PULL_UP); // 풀업 저항 활성화
// GPIO1을 eQEP1B로 설정
GPIO_setPinConfig(GPIO_1_EQEP1B); // eQEP1B 핀 매핑
GPIO_setDirectionMode(1, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(1, GPIO_PULL_UP); // 풀업 저항 활성화
// 디버깅용 LED 설정 (GPIO31)
GPIO_setPinConfig(GPIO_31_GPIO31); // 일반 GPIO로 설정
GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT); // 출력 모드
GPIO_setPadConfig(31, GPIO_PULL_UP); // 풀업 저항 활성화
GPIO_writePin(31, 0); // 초기 LED OFF
}
// 인터럽트 서비스 루틴 (캡처 이벤트)
__interrupt void eqep1ISR(void)
{
// 캡처된 펄스 간 시간 읽기
capturePeriod = EQEP_getCapturePeriod(EQEP1_BASE); // 펄스 간 클럭 수
// 인터럽트 플래그 지우기
EQEP_clearInterruptStatus(EQEP1_BASE, EQEP_INT_CAPT);
// PIE 인터럽트 ACK
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP5);
// 상태 업데이트
eqepStatus = 1;
}
void initEQEP(void)
{
// eQEP1 클럭 활성화
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EQEP1); // eQEP1 모듈에 클럭 공급
// 쿼드러처 디코더 설정: 4x 모드, 스왑 없음
EQEP_setDecoderConfig(EQEP1_BASE, EQEP_CONFIG_4X | EQEP_CONFIG_NO_SWAP);
// 캡처 유닛 설정
// 프리스케일러 = 1 (직접 시스템 클럭 사용)
// 이벤트 프리스케일러 = 1 (모든 펄스 캡처)
EQEP_setCaptureConfig(EQEP1_BASE, CAPTURE_PRESCALE, EVENT_PRESCALE);
// 캡처 유닛 활성화
EQEP_enableCapture(EQEP1_BASE);
// 인터럽트 설정: 캡처 이벤트 발생 시
EQEP_enableInterrupt(EQEP1_BASE, EQEP_INT_CAPT);
// eQEP 모듈 활성화
EQEP_enableModule(EQEP1_BASE);
// 상태 업데이트
eqepStatus = 1;
}
void main(void)
{
// 시스템 클럭 및 주변 장치 초기화
Device_init();
// GPIO 기본 초기화
Device_initGPIO();
// eQEP 관련 GPIO 설정
initGPIO();
// 인터럽트 모듈 초기화
Interrupt_initModule();
Interrupt_initVectorTable();
// eQEP1 인터럽트 ISR 등록
Interrupt_register(INT_EQEP1, &eqep1ISR);
// 시스템 클럭 확인
uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
if (sysClockHz != SYSTEM_CLOCK_HZ)
{
eqepStatus = 0xFFFF; // 오류 상태
GPIO_writePin(31, 0); // LED OFF로 오류 표시
ESTOP0;
}
// eQEP1 초기화
initEQEP();
// 초기화 오류 확인
if (eqepStatus != 1)
{
eqepStatus = 0xFFFF; // 초기화 실패
GPIO_writePin(31, 0); // LED OFF로 오류 표시
ESTOP0;
}
// 글로벌 인터럽트 활성화
EINT;
// Watchdog 활성화
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
SysCtl_serviceWatchdog();
// 무한 루프
for(;;)
{
// 디버깅용: 상태 표시
GPIO_writePin(31, (eqepStatus == 1) ? 1 : 0);
DEVICE_DELAY_US(1000000); // 1초 대기
}
}
설명:
- 기능: eQEP1의 캡처 유닛을 사용하여 쿼드러처 펄스 간 시간을 측정, 속도 계산에 활용.
- 설정:
- 디코더: 4x 모드로 최대 해상도.
- 캡처 유닛: 프리스케일러 = 1, 이벤트 프리스케일러 = 1 (모든 펄스 캡처).
- 인터럽트: 캡처 이벤트 발생 시 펄스 간 시간 업데이트.
- GPIO: GPIO0(eQEP1A), GPIO1(eQEP1B), GPIO31(LED).
- 출력: 펄스 간 시간은 capturePeriod 변수에 저장 (클럭 수), 정상 동작 시 LED ON.
- 용도: 저속 모터 또는 고정밀 속도 측정.
4.5. 예제 5: 위치 비교 이벤트
eQEP1의 위치 비교 기능을 사용하여 특정 위치에서 이벤트를 발생시킵니다.
#include "driverlib.h"
#include "device.h"
// 디버깅용 상태 변수
volatile uint32_t eqepStatus = 0; // 0: 초기화 완료, 1: eQEP 동작 중, 0xFFFF: 오류
volatile int32_t position = 0; // 현재 위치 카운터 값
volatile bool compareEvent = false; // 위치 비교 이벤트 플래그
// 시스템 클럭 및 비교 위치 정의
#define SYSTEM_CLOCK_HZ 200000000 // 200MHz 시스템 클럭
#define COMPARE_POSITION 1000 // 비교 위치: 1000 펄스
// GPIO 초기화 함수
void initGPIO(void)
{
// GPIO0을 eQEP1A로 설정
GPIO_setPinConfig(GPIO_0_EQEP1A); // eQEP1A 핀 매핑
GPIO_setDirectionMode(0, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(0, GPIO_PULL_UP); // 풀업 저항 활성화
// GPIO1을 eQEP1B로 설정
GPIO_setPinConfig(GPIO_1_EQEP1B); // eQEP1B 핀 매핑
GPIO_setDirectionMode(1, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(1, GPIO_PULL_UP); // 풀업 저항 활성화
// 디버깅용 LED 설정 (GPIO31)
GPIO_setPinConfig(GPIO_31_GPIO31); // 일반 GPIO로 설정
GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT); // 출력 모드
GPIO_setPadConfig(31, GPIO_PULL_UP); // 풀업 저항 활성화
GPIO_writePin(31, 0); // 초기 LED OFF
}
// 인터럽트 서비스 루틴 (위치 비교 이벤트)
__interrupt void eqep1ISR(void)
{
// 위치 비교 이벤트 발생
compareEvent = true;
// 인터럽트 플래그 지우기
EQEP_clearInterruptStatus(EQEP1_BASE, EQEP_INT_POS_COMP_READY);
// PIE 인터럽트 ACK
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP5);
// 상태 업데이트
eqepStatus = 1;
}
void initEQEP(void)
{
// eQEP1 클럭 활성화
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EQEP1); // eQEP1 모듈에 클럭 공급
// 쿼드러처 디코더 설정: 4x 모드, 스왑 없음
EQEP_setDecoderConfig(EQEP1_BASE, EQEP_CONFIG_4X | EQEP_CONFIG_NO_SWAP);
// 위치 카운터 설정: 리셋 없음, 최대 카운트 0xFFFFFFFF
EQEP_setPositionCounterConfig(EQEP1_BASE, EQEP_POSITION_RESET_NONE, 0xFFFFFFFF);
// 위치 비교 설정: COMPARE_POSITION (1000 펄스)에서 이벤트 발생
EQEP_enableCompare(EQEP1_BASE, COMPARE_POSITION);
// 인터럽트 설정: 위치 비교 이벤트 발생 시
EQEP_enableInterrupt(EQEP1_BASE, EQEP_INT_POS_COMP_READY);
// eQEP 모듈 활성화
EQEP_enableModule(EQEP1_BASE);
// 상태 업데이트
eqepStatus = 1;
}
void main(void)
{
// 시스템 클럭 및 주변 장치 초기화
Device_init();
// GPIO 기본 초기화
Device_initGPIO();
// eQEP 관련 GPIO 설정
initGPIO();
// 인터럽트 모듈 초기화
Interrupt_initModule();
Interrupt_initVectorTable();
// eQEP1 인터럽트 ISR 등록
Interrupt_register(INT_EQEP1, &eqep1ISR);
// 시스템 클럭 확인
uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
if (sysClockHz != SYSTEM_CLOCK_HZ)
{
eqepStatus = 0xFFFF; // 오류 상태
GPIO_writePin(31, 0); // LED OFF로 오류 표시
ESTOP0;
}
// eQEP1 초기화
initEQEP();
// 초기화 오류 확인
if (eqepStatus != 1)
{
eqepStatus = 0xFFFF; // 초기화 실패
GPIO_writePin(31, 0); // LED OFF로 오류 표시
ESTOP0;
}
// 글로벌 인터럽트 활성화
EINT;
// Watchdog 활성화
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
SysCtl_serviceWatchdog();
// 무한 루프
for(;;)
{
// 현재 위치 카운터 읽기
position = EQEP_getPosition(EQEP1_BASE);
// 디버깅용: 상태 표시 (이벤트 발생 시 LED 깜빡임)
GPIO_writePin(31, (compareEvent && eqepStatus == 1) ? 1 : 0);
if (compareEvent)
{
compareEvent = false; // 이벤트 플래그 리셋
DEVICE_DELAY_US(500000); // 0.5초 ON
GPIO_writePin(31, 0);
}
DEVICE_DELAY_US(1000000); // 1초 대기
}
}
설명:
- 기능: eQEP1의 위치 비교 기능을 사용하여 특정 위치(1000 펄스)에서 이벤트를 발생.
- 설정:
- 디코더: 4x 모드로 최대 해상도.
- 위치 비교: 1000 펄스에서 인터럽트 발생.
- GPIO: GPIO0(eQEP1A), GPIO1(eQEP1B), GPIO31(LED).
- 출력: 위치가 1000 펄스에 도달 시 compareEvent 플래그 설정, LED 0.5초 깜빡임.
- 용도: 특정 위치에서의 동작 트리거(예: 로봇 암 정지).
4.6. 예제 6: 스트로브 신호를 사용한 이벤트 감지
eQEP1의 스트로브 신호를 사용하여 특정 이벤트를 감지합니다.
#include "driverlib.h"
#include "device.h"
// 디버깅용 상태 변수
volatile uint32_t eqepStatus = 0; // 0: 초기화 완료, 1: eQEP 동작 중, 0xFFFF: 오류
volatile bool strobeEvent = false; // 스트로브 이벤트 플래그
// 시스템 클럭 정의
#define SYSTEM_CLOCK_HZ 200000000 // 200MHz 시스템 클럭
// GPIO 초기화 함수
void initGPIO(void)
{
// GPIO0을 eQEP1A로 설정
GPIO_setPinConfig(GPIO_0_EQEP1A); // eQEP1A 핀 매핑
GPIO_setDirectionMode(0, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(0, GPIO_PULL_UP); // 풀업 저항 활성화
// GPIO1을 eQEP1B로 설정
GPIO_setPinConfig(GPIO_1_EQEP1B); // eQEP1B 핀 매핑
GPIO_setDirectionMode(1, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(1, GPIO_PULL_UP); // 풀업 저항 활성화
// GPIO3을 eQEP1S로 설정 (스트로브 신호)
GPIO_setPinConfig(GPIO_3_EQEP1S); // eQEP1S 핀 매핑
GPIO_setDirectionMode(3, GPIO_DIR_MODE_IN); // 입력 모드
GPIO_setPadConfig(3, GPIO_PULL_UP); // 풀업 저항 활성화
// 디버깅용 LED 설정 (GPIO31)
GPIO_setPinConfig(GPIO_31_GPIO31); // 일반 GPIO로 설정
GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT); // 출력 모드
GPIO_setPadConfig(31, GPIO_PULL_UP); // 풀업 저항 활성화
GPIO_writePin(31, 0); // 초기 LED OFF
}
// 인터럽트 서비스 루틴 (스트로브 이벤트)
__interrupt void eqep1ISR(void)
{
// 스트로브 이벤트 발생
strobeEvent = true;
// 인터럽트 플래그 지우기
EQEP_clearInterruptStatus(EQEP1_BASE, EQEP_INT_STROBE_EVENT);
// PIE 인터럽트 ACK
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP5);
// 상태 업데이트
eqepStatus = 1;
}
void initEQEP(void)
{
// eQEP1 클럭 활성화
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EQEP1); // eQEP1 모듈에 클럭 공급
// 쿼드러처 디코더 설정: 4x 모드, 스왑 없음
EQEP_setDecoderConfig(EQEP1_BASE, EQEP_CONFIG_4X | EQEP_CONFIG_NO_SWAP);
// 스트로브 신호 설정: 상승 에지에서 이벤트 발생
EQEP_setStrobeSource(EQEP1_BASE, EQEP_STROBE_RISING_EDGE);
// 인터럽트 설정: 스트로브 이벤트 발생 시
EQEP_enableInterrupt(EQEP1_BASE, EQEP_INT_STROBE_EVENT);
// eQEP 모듈 활성화
EQEP_enableModule(EQEP1_BASE);
// 상태 업데이트
eqepStatus = 1;
}
void main(void)
{
// 시스템 클럭 및 주변 장치 초기화
Device_init();
// GPIO 기본 초기화
Device_initGPIO();
// eQEP 관련 GPIO 설정
initGPIO();
// 인터럽트 모듈 초기화
Interrupt_initModule();
Interrupt_initVectorTable();
// eQEP1 인터럽트 ISR 등록
Interrupt_register(INT_EQEP1, &eqep1ISR);
// 시스템 클럭 확인
uint32_t sysClockHz = SysCtl_getClock(DEVICE_OSCSRC_FREQ);
if (sysClockHz != SYSTEM_CLOCK_HZ)
{
eqepStatus = 0xFFFF; // 오류 상태
GPIO_writePin(31, 0); // LED OFF로 오류 표시
ESTOP0;
}
// eQEP1 초기화
initEQEP();
// 초기화 오류 확인
if (eqepStatus != 1)
{
eqepStatus = 0xFFFF; // 초기화 실패
GPIO_writePin(31, 0); // LED OFF로 오류 표시
ESTOP0;
}
// 글로벌 인터럽트 활성화
EINT;
// Watchdog 활성화
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_WD);
SysCtl_serviceWatchdog();
// 무한 루프
for(;;)
{
// 디버깅용: 상태 표시 (스트로브 이벤트 시 LED 깜빡임)
GPIO_writePin(31, (strobeEvent && eqepStatus == 1) ? 1 : 0);
if (strobeEvent)
{
strobeEvent = false; // 이벤트 플래그 리셋
DEVICE_DELAY_US(500000); // 0.5초 ON
GPIO_writePin(31, 0);
}
DEVICE_DELAY_US(1000000); // 1초 대기
}
}
설명:
- 기능: eQEP1의 스트로브 신호를 사용하여 특정 이벤트 감지.
- 설정:
- 디코더: 4x 모드로 최대 해상도.
- 스트로브: 상승 에지에서 인터럽트 발생.
- GPIO: GPIO0(eQEP1A), GPIO1(eQEP1B), GPIO3(eQEP1S), GPIO31(LED).
- 출력: 스트로브 신호 발생 시 strobeEvent 플래그 설정, LED 0.5초 깜빡임.
- 용도: 인코더의 특정 위치 이벤트 감지(예: 기계적 정지 신호).
5. 추가 고려 사항
- 펄스 해상도: 인코더의 PPR(Pulses Per Revolution)에 따라 최대 카운트를 계산. 예: PPR=1000, 4x 디코딩 → 최대 펄스 = 1000 * 4 = 4000.
- 속도 계산: 단위 타이머 주기는 속도 범위에 따라 조정. 예: 고속 모터는 0.1ms, 저속은 10ms.
- GPIO 설정: eQEP 핀은 풀업 저항 활성화로 신호 안정성 확보.
- C2000Ware: 코드는 C2000Ware의 DriverLib 기반 (C:\ti\c2000).
- 디버깅: Code Composer Studio의 .syscfg 툴로 eQEP 및 GPIO 설정 시각화.
키워드: TMS320F28388D, eQEP, DriverLib, C2000, 쿼드러처 인코더, 위치 측정, 속도 계산, 인덱스 이벤트, 캡처 유닛, 위치 비교, 스트로브, Code Composer Studio
'MCU > C2000' 카테고리의 다른 글
[TMS320F28388D] SDFM 사용법: DriverLib API로 SDFM 설정 및 코드 (0) | 2025.08.17 |
---|---|
[TMS320F28388D] CLB 사용법: DriverLib API로 CLB 설정 및 코드 (0) | 2025.08.17 |
[TMS320F28388D] CLA 사용법: DriverLib API로 CLA 설정 및 코드 (0) | 2025.08.17 |
[TMS320F28388D] EMIF 사용법: DriverLib API로 EMIF 설정 및 코드 (0) | 2025.08.17 |
[TMS320F28388D] eCAP 사용법: DriverLib API로 eCAP 설정 및 코드 (1) | 2025.08.17 |
[TMS320F28388D] ePWM 사용법: DriverLib API로 ePWM 설정 및 코드 (0) | 2025.08.16 |
[TMS320F28335] 기반 PSFB 컨버터 설계 및 위상 천이 PWM 제어 코드 (PSFB Converter Design and TMS320F28335-Based Phase-Shift PWM Control Code) (0) | 2025.08.10 |
[TMS320F28335] LLC 공진 컨버터 설계 및 제어 코드 가이드 (0) | 2025.08.09 |