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@4:3ae9f68bae6a, 2015-06-10 (annotated)
- Committer:
- dishbreak
- Date:
- Wed Jun 10 06:21:13 2015 +0000
- Revision:
- 4:3ae9f68bae6a
- Parent:
- 2:7c4ca945bfe1
Tuning tick counter to behave correctly.;
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 | 2:7c4ca945bfe1 | 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 | 2:7c4ca945bfe1 | 39 | |
dishbreak | 2:7c4ca945bfe1 | 40 | //check if peripheral has power, else this operation will hang! |
dishbreak | 2:7c4ca945bfe1 | 41 | if ((LPC_SC->PCONP & (1 << 22)) == 0) { |
dishbreak | 2:7c4ca945bfe1 | 42 | error("TimerCapture: Attempted to write to timer registers with power off!"); |
dishbreak | 2:7c4ca945bfe1 | 43 | } |
dishbreak | 2:7c4ca945bfe1 | 44 | |
dishbreak | 0:94cfc6ceec2f | 45 | #if DEBUG |
dishbreak | 0:94cfc6ceec2f | 46 | printf("OK to configure registers\r\n"); |
dishbreak | 0:94cfc6ceec2f | 47 | #endif |
dishbreak | 0:94cfc6ceec2f | 48 | |
dishbreak | 0:94cfc6ceec2f | 49 | // configure the pin |
dishbreak | 0:94cfc6ceec2f | 50 | LPC_PINCON->PINSEL0 |= bitmask_pinselect; |
dishbreak | 0:94cfc6ceec2f | 51 | |
dishbreak | 0:94cfc6ceec2f | 52 | #if DEBUG |
dishbreak | 0:94cfc6ceec2f | 53 | printf("Configuring rising edge. Register is %08x\r\n", LPC_TIM2->CCR); |
dishbreak | 0:94cfc6ceec2f | 54 | #endif |
dishbreak | 0:94cfc6ceec2f | 55 | |
dishbreak | 0:94cfc6ceec2f | 56 | // store on rising edge of input |
dishbreak | 0:94cfc6ceec2f | 57 | LPC_TIM2->CCR |= (1 << bitcount_capture_control); |
dishbreak | 0:94cfc6ceec2f | 58 | |
dishbreak | 0:94cfc6ceec2f | 59 | #if DEBUG |
dishbreak | 0:94cfc6ceec2f | 60 | printf("Leaving ctor\r\n"); |
dishbreak | 0:94cfc6ceec2f | 61 | #endif |
dishbreak | 0:94cfc6ceec2f | 62 | } |
dishbreak | 0:94cfc6ceec2f | 63 | |
dishbreak | 0:94cfc6ceec2f | 64 | void TimerCapture::startTimer() { |
dishbreak | 0:94cfc6ceec2f | 65 | if (!timerStarted) { |
dishbreak | 0:94cfc6ceec2f | 66 | timerStarted = true; |
dishbreak | 0:94cfc6ceec2f | 67 | |
dishbreak | 0:94cfc6ceec2f | 68 | configureTimer(); |
dishbreak | 0:94cfc6ceec2f | 69 | |
dishbreak | 0:94cfc6ceec2f | 70 | //start timer |
dishbreak | 0:94cfc6ceec2f | 71 | LPC_TIM2->TCR = 1; |
dishbreak | 0:94cfc6ceec2f | 72 | } |
dishbreak | 0:94cfc6ceec2f | 73 | } |
dishbreak | 0:94cfc6ceec2f | 74 | |
dishbreak | 0:94cfc6ceec2f | 75 | void TimerCapture::stopTimer() { |
dishbreak | 0:94cfc6ceec2f | 76 | timerStarted = false; |
dishbreak | 0:94cfc6ceec2f | 77 | //stop timer |
dishbreak | 0:94cfc6ceec2f | 78 | LPC_TIM2->TCR = 0; |
dishbreak | 0:94cfc6ceec2f | 79 | } |
dishbreak | 0:94cfc6ceec2f | 80 | |
dishbreak | 0:94cfc6ceec2f | 81 | bool TimerCapture::isRunning() { |
dishbreak | 0:94cfc6ceec2f | 82 | return timerStarted; |
dishbreak | 0:94cfc6ceec2f | 83 | } |
dishbreak | 0:94cfc6ceec2f | 84 | |
dishbreak | 0:94cfc6ceec2f | 85 | void TimerCapture::resetTimer() { |
dishbreak | 0:94cfc6ceec2f | 86 | //reset timer |
dishbreak | 0:94cfc6ceec2f | 87 | LPC_TIM2->TCR = 2; |
dishbreak | 0:94cfc6ceec2f | 88 | LPC_TIM2->TCR = 0; |
dishbreak | 0:94cfc6ceec2f | 89 | LPC_TIM2->CR0 = 0; |
dishbreak | 0:94cfc6ceec2f | 90 | LPC_TIM2->CR1 = 0; |
dishbreak | 0:94cfc6ceec2f | 91 | } |
dishbreak | 0:94cfc6ceec2f | 92 | |
dishbreak | 0:94cfc6ceec2f | 93 | uint32_t TimerCapture::getTime() { |
dishbreak | 0:94cfc6ceec2f | 94 | uint32_t observedTime = 0; |
dishbreak | 0:94cfc6ceec2f | 95 | switch(mCapturePin) { |
dishbreak | 0:94cfc6ceec2f | 96 | case p30: |
dishbreak | 0:94cfc6ceec2f | 97 | observedTime = LPC_TIM2->CR0; |
dishbreak | 0:94cfc6ceec2f | 98 | break; |
dishbreak | 0:94cfc6ceec2f | 99 | case p29: |
dishbreak | 0:94cfc6ceec2f | 100 | observedTime = LPC_TIM2->CR1; |
dishbreak | 0:94cfc6ceec2f | 101 | break; |
dishbreak | 0:94cfc6ceec2f | 102 | default: |
dishbreak | 0:94cfc6ceec2f | 103 | observedTime = 0; |
dishbreak | 0:94cfc6ceec2f | 104 | break; |
dishbreak | 0:94cfc6ceec2f | 105 | } |
dishbreak | 0:94cfc6ceec2f | 106 | |
dishbreak | 0:94cfc6ceec2f | 107 | return observedTime; |
dishbreak | 0:94cfc6ceec2f | 108 | } |
dishbreak | 0:94cfc6ceec2f | 109 | |
dishbreak | 0:94cfc6ceec2f | 110 | void TimerCapture::configureTimer() { |
dishbreak | 0:94cfc6ceec2f | 111 | // Power on Peripheral TIMER2 |
dishbreak | 0:94cfc6ceec2f | 112 | LPC_SC->PCONP |= (1 << 22); |
dishbreak | 0:94cfc6ceec2f | 113 | |
dishbreak | 0:94cfc6ceec2f | 114 | // Set clock source for TIMER2 |
dishbreak | 0:94cfc6ceec2f | 115 | uint8_t clockSel = 0x01; |
dishbreak | 0:94cfc6ceec2f | 116 | LPC_SC->PCLKSEL1 |= (clockSel << 12); |
dishbreak | 0:94cfc6ceec2f | 117 | |
dishbreak | 0:94cfc6ceec2f | 118 | // Set prescaler counter |
dishbreak | 4:3ae9f68bae6a | 119 | LPC_TIM2->PR = SystemCoreClock/1000; //should increment once a milisecond. |
dishbreak | 0:94cfc6ceec2f | 120 | |
dishbreak | 0:94cfc6ceec2f | 121 | } |
dishbreak | 0:94cfc6ceec2f | 122 |