Library to simplify using capture pins on hardware.
When I first started experimenting with the notion of capture pins, I had no idea where to begin. Rather than write to registers in every single program, I decided to create a class that'd handle that heavy lifting for me!
Import library
Public Member Functions |
|
TimerCapture (PinName pCapturePin) | |
Configures registers to use the given pin as a capture pin.
|
|
uint32_t | getTime () |
Get the time captured by the capture pin's register.
|
|
Static Public Member Functions |
|
static void | startTimer () |
Starts the TIMER2 timer, and configures it if it's not already configured.
|
|
static bool | isRunning () |
Checks if the TIMER2 timer is running.
|
|
static void | stopTimer () |
Stops the TIMER2 timer.
|
|
static void | resetTimer () |
Resets the TIMER2 timer.
|
This code uses TIMER2 on the LPC1768. I have no idea if it will work on other hardware, but I hope it helps someone else!
TimerCapture.cpp@0:94cfc6ceec2f, 2015-05-21 (annotated)
- Committer:
- dishbreak
- Date:
- Thu May 21 08:04:03 2015 +0000
- Revision:
- 0:94cfc6ceec2f
- Child:
- 2:7c4ca945bfe1
Initial commit of TimerCapture code.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dishbreak | 0:94cfc6ceec2f | 1 | #include "TimerCapture.h" |
dishbreak | 0:94cfc6ceec2f | 2 | |
dishbreak | 0:94cfc6ceec2f | 3 | bool TimerCapture::timerStarted = false; |
dishbreak | 0:94cfc6ceec2f | 4 | |
dishbreak | 0:94cfc6ceec2f | 5 | TimerCapture::TimerCapture(PinName pCapturePin) { |
dishbreak | 0:94cfc6ceec2f | 6 | uint8_t bitcount_pinselect = 0; |
dishbreak | 0:94cfc6ceec2f | 7 | uint8_t bitcount_capture_control = 0; |
dishbreak | 0:94cfc6ceec2f | 8 | |
dishbreak | 0:94cfc6ceec2f | 9 | #if DEBUG |
dishbreak | 0:94cfc6ceec2f | 10 | printf("Entering ctor\r\n"); |
dishbreak | 0:94cfc6ceec2f | 11 | #endif |
dishbreak | 0:94cfc6ceec2f | 12 | |
dishbreak | 0:94cfc6ceec2f | 13 | switch (pCapturePin) { |
dishbreak | 0:94cfc6ceec2f | 14 | case p30: |
dishbreak | 0:94cfc6ceec2f | 15 | bitcount_pinselect = 8; |
dishbreak | 0:94cfc6ceec2f | 16 | bitcount_capture_control = 0; |
dishbreak | 0:94cfc6ceec2f | 17 | break; |
dishbreak | 0:94cfc6ceec2f | 18 | case p29: |
dishbreak | 0:94cfc6ceec2f | 19 | bitcount_pinselect = 10; |
dishbreak | 0:94cfc6ceec2f | 20 | bitcount_capture_control = 3; |
dishbreak | 0:94cfc6ceec2f | 21 | break; |
dishbreak | 0:94cfc6ceec2f | 22 | default: |
dishbreak | 0:94cfc6ceec2f | 23 | error("TimerCapture: Invalid pin specified! Pick either p29 (P0.5) or p30 (p0.4)."); |
dishbreak | 0:94cfc6ceec2f | 24 | break; |
dishbreak | 0:94cfc6ceec2f | 25 | } |
dishbreak | 0:94cfc6ceec2f | 26 | |
dishbreak | 0:94cfc6ceec2f | 27 | #if DEBUG |
dishbreak | 0:94cfc6ceec2f | 28 | printf("Bitcounts selected: %d (pinselect) %d (capture control)\r\n", bitcount_pinselect, bitcount_capture_control); |
dishbreak | 0:94cfc6ceec2f | 29 | #endif |
dishbreak | 0:94cfc6ceec2f | 30 | |
dishbreak | 0:94cfc6ceec2f | 31 | uint32_t bitmask_pinselect = (0x3 << bitcount_pinselect); |
dishbreak | 0:94cfc6ceec2f | 32 | mCapturePin = pCapturePin; |
dishbreak | 0:94cfc6ceec2f | 33 | |
dishbreak | 0:94cfc6ceec2f | 34 | // error out if the pin is already configured. |
dishbreak | 0:94cfc6ceec2f | 35 | if (LPC_PINCON->PINSEL0 & bitmask_pinselect == bitmask_pinselect) { |
dishbreak | 0:94cfc6ceec2f | 36 | error("TimerCapture: Pin is already configured!"); |
dishbreak | 0:94cfc6ceec2f | 37 | } |
dishbreak | 0:94cfc6ceec2f | 38 | |
dishbreak | 0:94cfc6ceec2f | 39 | #if DEBUG |
dishbreak | 0:94cfc6ceec2f | 40 | printf("OK to configure registers\r\n"); |
dishbreak | 0:94cfc6ceec2f | 41 | #endif |
dishbreak | 0:94cfc6ceec2f | 42 | |
dishbreak | 0:94cfc6ceec2f | 43 | // configure the pin |
dishbreak | 0:94cfc6ceec2f | 44 | LPC_PINCON->PINSEL0 |= bitmask_pinselect; |
dishbreak | 0:94cfc6ceec2f | 45 | |
dishbreak | 0:94cfc6ceec2f | 46 | #if DEBUG |
dishbreak | 0:94cfc6ceec2f | 47 | printf("Configuring rising edge. Register is %08x\r\n", LPC_TIM2->CCR); |
dishbreak | 0:94cfc6ceec2f | 48 | #endif |
dishbreak | 0:94cfc6ceec2f | 49 | |
dishbreak | 0:94cfc6ceec2f | 50 | // store on rising edge of input |
dishbreak | 0:94cfc6ceec2f | 51 | LPC_TIM2->CCR |= (1 << bitcount_capture_control); |
dishbreak | 0:94cfc6ceec2f | 52 | |
dishbreak | 0:94cfc6ceec2f | 53 | #if DEBUG |
dishbreak | 0:94cfc6ceec2f | 54 | printf("Leaving ctor\r\n"); |
dishbreak | 0:94cfc6ceec2f | 55 | #endif |
dishbreak | 0:94cfc6ceec2f | 56 | } |
dishbreak | 0:94cfc6ceec2f | 57 | |
dishbreak | 0:94cfc6ceec2f | 58 | void TimerCapture::startTimer() { |
dishbreak | 0:94cfc6ceec2f | 59 | if (!timerStarted) { |
dishbreak | 0:94cfc6ceec2f | 60 | timerStarted = true; |
dishbreak | 0:94cfc6ceec2f | 61 | |
dishbreak | 0:94cfc6ceec2f | 62 | configureTimer(); |
dishbreak | 0:94cfc6ceec2f | 63 | |
dishbreak | 0:94cfc6ceec2f | 64 | //start timer |
dishbreak | 0:94cfc6ceec2f | 65 | LPC_TIM2->TCR = 1; |
dishbreak | 0:94cfc6ceec2f | 66 | } |
dishbreak | 0:94cfc6ceec2f | 67 | } |
dishbreak | 0:94cfc6ceec2f | 68 | |
dishbreak | 0:94cfc6ceec2f | 69 | void TimerCapture::stopTimer() { |
dishbreak | 0:94cfc6ceec2f | 70 | timerStarted = false; |
dishbreak | 0:94cfc6ceec2f | 71 | //stop timer |
dishbreak | 0:94cfc6ceec2f | 72 | LPC_TIM2->TCR = 0; |
dishbreak | 0:94cfc6ceec2f | 73 | } |
dishbreak | 0:94cfc6ceec2f | 74 | |
dishbreak | 0:94cfc6ceec2f | 75 | bool TimerCapture::isRunning() { |
dishbreak | 0:94cfc6ceec2f | 76 | return timerStarted; |
dishbreak | 0:94cfc6ceec2f | 77 | } |
dishbreak | 0:94cfc6ceec2f | 78 | |
dishbreak | 0:94cfc6ceec2f | 79 | void TimerCapture::resetTimer() { |
dishbreak | 0:94cfc6ceec2f | 80 | //reset timer |
dishbreak | 0:94cfc6ceec2f | 81 | LPC_TIM2->TCR = 2; |
dishbreak | 0:94cfc6ceec2f | 82 | LPC_TIM2->TCR = 0; |
dishbreak | 0:94cfc6ceec2f | 83 | LPC_TIM2->CR0 = 0; |
dishbreak | 0:94cfc6ceec2f | 84 | LPC_TIM2->CR1 = 0; |
dishbreak | 0:94cfc6ceec2f | 85 | } |
dishbreak | 0:94cfc6ceec2f | 86 | |
dishbreak | 0:94cfc6ceec2f | 87 | uint32_t TimerCapture::getTime() { |
dishbreak | 0:94cfc6ceec2f | 88 | uint32_t observedTime = 0; |
dishbreak | 0:94cfc6ceec2f | 89 | switch(mCapturePin) { |
dishbreak | 0:94cfc6ceec2f | 90 | case p30: |
dishbreak | 0:94cfc6ceec2f | 91 | observedTime = LPC_TIM2->CR0; |
dishbreak | 0:94cfc6ceec2f | 92 | break; |
dishbreak | 0:94cfc6ceec2f | 93 | case p29: |
dishbreak | 0:94cfc6ceec2f | 94 | observedTime = LPC_TIM2->CR1; |
dishbreak | 0:94cfc6ceec2f | 95 | break; |
dishbreak | 0:94cfc6ceec2f | 96 | default: |
dishbreak | 0:94cfc6ceec2f | 97 | observedTime = 0; |
dishbreak | 0:94cfc6ceec2f | 98 | break; |
dishbreak | 0:94cfc6ceec2f | 99 | } |
dishbreak | 0:94cfc6ceec2f | 100 | |
dishbreak | 0:94cfc6ceec2f | 101 | return observedTime; |
dishbreak | 0:94cfc6ceec2f | 102 | } |
dishbreak | 0:94cfc6ceec2f | 103 | |
dishbreak | 0:94cfc6ceec2f | 104 | void TimerCapture::configureTimer() { |
dishbreak | 0:94cfc6ceec2f | 105 | // Power on Peripheral TIMER2 |
dishbreak | 0:94cfc6ceec2f | 106 | LPC_SC->PCONP |= (1 << 22); |
dishbreak | 0:94cfc6ceec2f | 107 | |
dishbreak | 0:94cfc6ceec2f | 108 | // Set clock source for TIMER2 |
dishbreak | 0:94cfc6ceec2f | 109 | uint8_t clockSel = 0x01; |
dishbreak | 0:94cfc6ceec2f | 110 | LPC_SC->PCLKSEL1 |= (clockSel << 12); |
dishbreak | 0:94cfc6ceec2f | 111 | |
dishbreak | 0:94cfc6ceec2f | 112 | // Set prescaler counter |
dishbreak | 0:94cfc6ceec2f | 113 | LPC_TIM2->PR = 100000; //should increment once a milisecond. |
dishbreak | 0:94cfc6ceec2f | 114 | |
dishbreak | 0:94cfc6ceec2f | 115 | } |
dishbreak | 0:94cfc6ceec2f | 116 |