태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

Capture?

Capture의 사전적 의미는 '포획하다'이다. 28xx DSP가 뭔가를 포획한다는 것인데 무엇을 포획하는 것일까? 그것은 바로 펄스의 시간정보이다. 외부에서 인가되는 펄스의 시간정보를 캡처해서 해당 펄스의 듀티나 주기에 관한 정보를 쉽게 알아 낼 수 있는 것이다.

 

 


어떻게 작동되나?

캡처기능은 외부에서 인가되는 펄스의 시간 정보를 알아낸다고 했다. 그렇다면 어떻게 시간정보를 알아낼까? 100미터 달리기를 할 때 우리는 스톱워치를 가지고 기록을 잰다. 즉 시간 정보를 알아내기 위해서는 시계가 필요하다. 281x DSP는 어떨까? 칩 내부에 CPU Timer 3, GP Timer 4, WD Timer 1개 총8개의 시계를 가지고 있다. 많기도 하다. 281x의 캡처 유닛은 이중에서 4개의 GP Timer를 선택해서 사용할 수 있다. 다음 [그림 1] 을 보자.

 

 

[그림 1] 캡처 유닛 블럭다이어 그램

 

위의 [그림 1] 281x 6개의 캡처 유닛 중 이벤트 매니저A 에 속한 3개의 캡처 유닛을 나타내고 있다. 캡처를 위한 시계는 같은 이벤트 매니저A에 속한 GP Timer 1, 2를 먹스를 통해 선택해서 사용할 수 있게 되어 있다.

 

[그림 1] 우측을 보면 CAP 1,2,3 이라는 표시가 있다. 이것이 외부에서 인가되는 펄스를 입력받는 핀이다. 이벤트 매니저A, B에 각각 3핀씩 총 6핀이 된다. 이 핀으로 펄스가 입력되면, 엣지(edge)가 발생한 순간을 "Edge detect"가 찾아내 GP Timer의 시간 정보를 "2-level FIFO stacks" 에 저장되게 한다. 타이머 값을 엣지 감지로부터 FIFO에 저장하는 순각까지 걸리는 시간은 2 CPU Clock에 불과하다. 인터럽트로는 이렇게 빠른 처리를 해낼 수가 없다. 캡처 기능을 별도로 구현한 이유다.

 

입력된 펄스의 상승과 하강 엣지 모두에서 시간 정보를 기록한다면, 펄스의 듀티 정보를 얻을 수 있다. 상승 엣지나 하강 엣지에서만 시간 정보를 기록한다면 주기를 알 수 있다. 캡처를 제어하는 레지스터에는 펄스의 어떤 엣지에 반응할 것인지 정하는 비트가 구현되어 있다.

 

여기서 2-레벨 FIFO는 엣지 발생으로부터 2 CPU Clock안에 타이머의 내용을 CPU가 메모리에 기록하기가 어렵기에 구현된 것이다. 하지만 이러한 FIFO의 크기가 2-레벨, 2word이기에 쉽게 넘칠 수 있다. FIFO 값을 읽을 때에는 반드시 FIFO의 상태를 점검하는 과정을 가져야 한다.

 

점검은 간단하다. FIFO의 상태를 알려주는 레지스터, CAPFIFOx를 점검하면 알 수 있다. 이 레지스터가 FIFO가 넘치고 있다는 것을 표시하고 있다면, 원하는 값은 이미 사라져 버린 것이다. 캡처 기능을 사용할 경우에는 FIFO를 후다닥 퍼내는 습관을 가져야 한다.

 

 

캡쳐 유닛의 동작

   

[그림 2] 캡처 유닛 FIFO 동작

 

[그림 2] 캡처 유닛 동작 시에 캡처 유닛의 2-level FIFO의 상태를 잘 나타내주고 있다. CAPxFIFO 2-level FIFO의 상위 레지스터, CAPxFBOT 2-level FIFO의 하위 레지스터, CAPFIFOx 2-level FIFO의 상태를 나타내는 레지스터다. 캡처 유닛의 2-level FIFO FIFO(First Input First Output)이라는 이름답게 먼저 들어간 값이 먼저 나오고 있다. 첫 번째 캡처 시, 타이머 값이 FIFO의 상위 레지스터에 저장된다. 이때 캡처 유닛 상태 레지스터 값은 01b 이 된다. 두 번째 캡처 시, 하위 레지스터에 저장된다. 이때 캡처 유닛 상태 레지스터 값은 10b 이 된다. 만약 캡처 유닛 FIFO의 레지스터에 저장된 값을 읽어 들이지 않은 상태에서 다시 세 번째 캡처를 한다면, 상위 레지스터에 저장된 처음 캡처 값인 value #1 이 사라지고 그 자리에 value #2 가 올라오고, 세 번째 캡처 값이 하위 레지스터에 저장되게 된다.

 

 

캡처 유닛 사용을 위한 코딩예

캡처 유닛은 GP 타이머와 연동해서 동작하기에 캡처 유닛을 초기화 하기에 앞서 GP 타이머에 관한 초기화 설정이 먼저 이루어져야 한다. 또한 인터럽트 방식으로 FIFO 레지스터에서 값을 읽어 들이므로 인터럽트에 관한 초기화도 이루어져야 한다.

 

코딩 예의 조건은 Capture Unit 1 를 사용하고, 캡처를 위한 카운터는 GP 타이머 2를 사용하는 것으로 한다. 펄스의 엣지 탐색은 Capture Unit 1은 상승 엣지를 탐색하는 것으로 한다. 그리고 캡처 인터럽트 서비스 루틴에서 FIFO에 저장된 타이머 값을 읽어 펄스의 주기를 계산하는 것으로 한다. 이때 타이머의 주기는 캡쳐할 펄스의 주기보다 커야한다. 적당히 타이머 주기값 혹은 클럭 속도를 조절해 주어야 한다.

 

DINT; // 전역 인터럽트 비활성화

InitSysCtrl(); // 시스템 초기화

/* Disable CPU interrupts */

InitPieCtrl(); // 인터럽트 초기화

IER = 0x0000; // 모든 코어 인터럽트 비활성화

IFR = 0x0000; // 모든 코어 인터럽트 플래그 리셋

InitPieVectTable(); // 모든 코어 인터럽트 플래그 리셋

/* 캡처를 인터럽트 서비스 루틴의 이름 재설정 */   

EALLOW; // 레지스터 보호 해제

PieVectTable.CAPINT1 = &Capture1_isr;

// 캡처1 인터럽트 서비스 루틴 이름을 Capture1_isr 로 재정의

EDIS; // 레지스터 보호 설정

/* 캡처 핀 사용 설정 */

EALLOW; // 레지스터 보호 해제

GpioMuxRegs.GPAMUX.bit.CAP1Q1_GPIOA8 = 1; // 캡처1 핀으로 선택

EDIS; // 레지스터 보호 설정

/* GP 타이머2 초기화 */

EvaRegs.GPTCONA.all = 0; // 타이머 리셋

EvaRegs.T2PR = 37500; // 타이머 주기값은 캡처할 펄스의 주기에 따라 적당히 설정

EvaRegs.T2CNT = 0x0000; // 타이머 카운터 초기화

EvaRegs.T2CON.all = 0x1240; // 타이머 설정 및 타이머 스타트

/* 캡처 1, 2 초기화 */

EvaRegs.CAPCONA.all = 0x0000; // 캡처 유닛 리셋

EvaRegs.CAPCONA.bit.CAP12EN = 1; // 캡처 1 활성화

EvaRegs.CAPCONA.bit.CAP12TSEL = 0; // 캡처 유닛에 사용되는 타이머를 GP 타이머 2로 선택

EvaRegs.CAPCONA.bit.CAP1EDGE = 1; // 캡처 1은 상승엣지 탐색

EvaRegs.CAPFIFOA.all = 0x0000; // FIFO A 상태 레지스터 클리어

EvaRegs.CAP1FBOT = 0x0000; // 캡처 1 FIFO 히위 레지스터 클리어

EvaRegs.CAP1FIFO = 0x0000; // 캡처 1 FIFO 상위 레지스터 클리어

/* 캡처 1, 2 인터럽트 활성화 */

EvaRegs.EVAIFRC.all = 0xFFFF;

// EVA 인터럽트 플래그 레지스터 리셋 - 캡처 1, 2 인터럽트가 여기에 속함

EvaRegs.EVAIMRC.bit.CAP1INT = 1;

// EVA 인터럽트 마스크 레지스터에서 캡처 1 인터럽트 활성화

 

PieCtrlRegs.PIEIER3.bit.INTx5 = 1;

// PIE 인터럽트 마스크 레지스터에서 캡처 1 인터럽트 활성화

IER |= M_INT3;

// 캡처 1 인터럽트가 속한 코어 인터럽트 3을 활성

EINT; // 전연 인터럽트 활성화


 

[코드 1] Capture 초기화 코드

 

 

 

interrupt void Capture1_isr(void)

{

 temp1_1 = EvaRegs.CAP1FIFO; // 캡처 1 FIFO 상위 레지스터 저장값 읽기

 temp1_2 = EvaRegs.CAP1FIFO; // 캡처 1 FIFO 상위 레지스터 저장값 읽기

 Pulse1_prd = temp1_1 - temp1_2 // 펄스 주기 계산

 EvaRegs.T2CNT = 0x0000; // 타이머 초기화 - 주기계산의 오류를 방지하기 위함

 EvaRegs.EVAIFRC.bit.CAP1INT = 1; // 개별 인터럽트 플래그 초기화

 PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; // PIE 인터럽트 플래그 초기화

}

 

[코드 2] Capture 초기화 코드


DSP에 대해 좀 더 알고 싶으세요? 싱크웍스 무료실습강좌를 신청하세요. ----------> 무료실습강좌 신청하기
본 내용이 유익하셨다면 싱크웍스 블로그 2.0을 구독하세요. -------------------------> 싱크웍스 RSS
 

Posted by syncworks

댓글을 달아 주세요

티스토리 툴바