Input Capture는 원래 다른 input간의 시간을 측정하는데 쓰인다. 예를 들면 주파수와 펄스 측정에 쓰인다. 하지만 그냥 edge에서 인터럽트를 발생하는 외부 인터럽트와 같이 쓸 수도있다.
PIC32의 외부 인터럽트의 경우 외부 인터럽트는 edge-sensitive이기 때문에 모든 edge에서 인터럽트를 발생시킬 수 없다. NEC 방식을 사용하는 리모컨이나 incremental 인코더의 경우에는 모든 edge에서 인터럽트가 발생해야하기 때문에 Input Capture를 사용하면 쉽게 구현할 수 있다.
Input Capture Control Registers
ICxCON(x는 숫자)
bit31-16
Reserved
bit15
ON: Input Capture Module Enable bit
1: Input Capture 를 사용한다.
0: Input Capture 를 사용하지 않는다.
bit14
FRZ: Freeze in Debug Mode bit
1: 디버그 모드에서 멈춘다.
0: 디버그 모드에서 멈추지 않는다.
bit13
SIDL: Stop in Idle Mode bit
1: Idle 모드에서 멈춘다.
0: Idle 모드에서 멈추지 않는다.
bit12-10
Unimplemented
bit9
ICFEDGE: First Capture Edge Select bit (ICM<2:0> = 110 일때만)
1: Rising Edge를 먼저 Capture
0: Falling Edge를 먼저 Capture
bit8
ICC32: 32-bit Capture Select bit
1: 32-bit 타이머를 사용한다.
0: 16-bit 타이머를 사용한다.
bit7
ICTMR: Timer Select bit (ICxC32 (ICxCON<8>이 1일땐 영향을 주지 않는다. )
1: 타이머 2를 사용
0: 타이머 3을 사용
bit6-5
ICI: Interrupt Control bits
11: 4번째 이벤트에서 인터럽트
10: 3번째 이벤트에서 인터럽트
01: 2번째 이벤트에서 인터럽트
00: 1번째 이벤트에서 인터럽트
bit4
ICOV: Input Capture Overflow Status bit(읽기 전용)
1: 오버플로우가 생겼다.
0: 오버플로우가 생기지 않았다.
bit3
ICBNE: Input Capture Buffer Not Empty Status bit(읽기 전용)
1: 버퍼가 비지 않았다 - 최고 하나 이상의 capture value를 읽을 수 있다.
0: 버퍼가 비었다.
bit2-0
ICM: Input Capture Mode Select bit
111: 인터럽트만 한다. (Sleep이나 Idle 모드에서만 지원)
110: Simple Capture Mode - 모든 엣지에서, 특정 엣지에서 먼저 그리고나선 모든 엣지에서
101: 매 16번째 rising 엣지에서 이벤트
100: 매 4번째 rising 엣지에서 이벤트
011: 모든 rising edge에서 이벤트
010: 모든 falling edge에서 이벤트
001: Edge Detect mode - 모든 엣지
000: Captue 하지 않는다.
아래의 소스는 두 개의 모터의 인코더 A상 B상을 각각 icap1,2,3,4에 물렸다.
PORT D의 8,9,10,11번 포트에 각각 연결시키고,
인코더 값을 변화시키는 소스이다. incremental encoder를 사용하고, 정역 모두 잘 동작한다.
< pic32_icap.c >
#define RISING_EDGE 1 #define FALLING_EDGE 2 #define A_PULSE 1 #define B_PULSE 2 long long int right_motor_encoder = 0; long long int left_motor_encoder = 0; Uc Rencoder_change = A_PULSE, Lencoder_change = A_PULSE;; void Init_icap() { //Input capture 인터럽트 초기화 //OpenTimer3(T3_ON | T3_PS_1_256, 0xffff); //65535 * 256 = 16776960 OpenTimer3(T3_ON | T3_IDLE_CON | T3_PS_1_1, 25000); // Enable Input Capture Module 1 - RD8 // - Capture Every edge // - Enable capture interrupts // - Use Timer 3 source // - Capture rising edge first OpenCapture1( IC_EVERY_EDGE | IC_INT_1CAPTURE | IC_TIMER3_SRC | IC_FEDGE_RISE | IC_ON ); mIC1IntEnable(1); mIC1SetIntPriority(3); OpenCapture2( IC_EVERY_EDGE | IC_INT_1CAPTURE | IC_TIMER3_SRC | IC_FEDGE_RISE | IC_ON ); mIC2IntEnable(1); mIC2SetIntPriority(3); OpenCapture3( IC_EVERY_EDGE | IC_INT_1CAPTURE | IC_TIMER3_SRC | IC_FEDGE_RISE | IC_ON ); mIC3IntEnable(1); mIC3SetIntPriority(3); OpenCapture4( IC_EVERY_EDGE | IC_INT_1CAPTURE | IC_TIMER3_SRC | IC_FEDGE_RISE | IC_ON ); mIC4IntEnable(1); mIC4SetIntPriority(3); // OpenCapture5( IC_EVERY_EDGE | IC_INT_1CAPTURE | IC_TIMER3_SRC | IC_FEDGE_RISE | IC_ON ); // mIC5IntEnable(1); // mIC5SetIntPriority(3); mIC1ClearIntFlag(); mIC2ClearIntFlag(); mIC3ClearIntFlag(); mIC4ClearIntFlag(); // mIC5ClearIntFlag(); } void __ISR(_INPUT_CAPTURE_1_VECTOR,ipl3) _ic1(void) { mIC1ClearIntFlag(); // icap1cnt++; icap1 = PORTD & 0x100 ? RISING_EDGE : FALLING_EDGE; if(Rencoder_change == B_PULSE) { if(icap1 == RISING_EDGE) { if(icap2 == RISING_EDGE) { right_motor_encoder--; } else { right_motor_encoder++; } } else { if(icap2 == RISING_EDGE) { right_motor_encoder++; } else { right_motor_encoder--; } } } Rencoder_change = A_PULSE; } //Input Capture 인터럽트 2 void __ISR(_INPUT_CAPTURE_2_VECTOR,ipl3) _ic2(void) { mIC2ClearIntFlag(); // icap2cnt++; icap2 = PORTD & 0x200 ? RISING_EDGE : FALLING_EDGE; if(Rencoder_change == A_PULSE) { if(icap2 == RISING_EDGE) { if(icap1 == RISING_EDGE) { right_motor_encoder++; } else { right_motor_encoder--; } } else { if(icap1 == RISING_EDGE) { right_motor_encoder--; } else { right_motor_encoder++; } } } Rencoder_change = B_PULSE; } //Input Capture 인터럽트 3 void __ISR(_INPUT_CAPTURE_3_VECTOR,ipl3) _ic3(void) { mIC3ClearIntFlag(); // icap3cnt++; icap3 = PORTD & 0x400 ? RISING_EDGE : FALLING_EDGE; if(Lencoder_change == B_PULSE) { if(icap3 == RISING_EDGE) { if(icap4 == RISING_EDGE) { left_motor_encoder--; } else { left_motor_encoder++; } } else { if(icap4 == RISING_EDGE) { left_motor_encoder++; } else { left_motor_encoder--; } } } Lencoder_change = A_PULSE; } //Input Capture 인터럽트 4 void __ISR(_INPUT_CAPTURE_4_VECTOR,ipl3) _ic4(void) { mIC4ClearIntFlag(); // icap4cnt++; icap4 = PORTD & 0x800 ? RISING_EDGE : FALLING_EDGE; if(Lencoder_change == A_PULSE) { if(icap4 == RISING_EDGE) { if(icap3 == RISING_EDGE) { left_motor_encoder++; } else { left_motor_encoder--; } } else { if(icap3 == RISING_EDGE) { left_motor_encoder--; } else { left_motor_encoder++; } } } Lencoder_change = B_PULSE; }
'Enginius > Firmware' 카테고리의 다른 글
PIC32 - SPI (0) | 2010.04.13 |
---|---|
PIC32 - PWM (0) | 2010.02.19 |
PID 제어 (1) | 2010.02.18 |
PIC32 - I2C (0) | 2010.02.17 |
PIC32 - GPIO (0) | 2010.02.17 |