Counts pulses on pin p29. Pulse frequency can be up to 48 MHz.
Example, counting 48MHz-pulses on pin p29 generated by pin p22 with PwmOscillator (https://mbed.org/users/geotec/code/PwmOscillator/). Pins p22 & p29 must be connected. Count is triggered when pin p30 = high (I connected oscillator with 9kHz that triggered periodically).
#include "mbed.h" #include "PwmOscillator.h" #include "PulseCounter.h" Serial usbPC(USBTX, USBRX); // sends log messages via USB to PC terminal PwmOscillator pulseGenerator; // generates pulses to be count (48 MHz) on pin p22. Connect this pin to p29 (counter input). PulseCounter pulseCounter; // counts the pulses on pin p29 between trigger events (= rising edges) on pin p30. int main() { usbPC.printf("---> start <---\n"); pulseGenerator.initWithFrequency(48000000); pulseCounter.init(); pulseGenerator.start(); pulseCounter.start(); wait(1); // waiting 1 second for trigger events (pin30: rising edge). Count pulses between trigger events. pulseCounter.stop(); pulseGenerator.stop(); // read & print pulseCounter results uint32_t pulseCounterResults[20]; pulseCounter.counterArray(&pulseCounterResults[0],sizeof pulseCounterResults / sizeof (uint32_t)); for(int i = 0; i < (sizeof pulseCounterResults / sizeof (uint32_t)); i++) { usbPC.printf("counter of trigger event %i = %u\n",i,pulseCounterResults[i]); } // usbPC.printf(" finished.\n"); }
PulseCounter.cpp@4:0eb01612bcb2, 2013-01-09 (annotated)
- Committer:
- geotec
- Date:
- Wed Jan 09 09:57:21 2013 +0000
- Revision:
- 4:0eb01612bcb2
- Parent:
- 3:9e7474866e48
bugfix: capture interrupt enabled before start()
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
geotec | 1:83149916f8a9 | 1 | /* Copyright (c) 2012 Christian Buntebarth, MIT License |
geotec | 1:83149916f8a9 | 2 | * |
geotec | 1:83149916f8a9 | 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software |
geotec | 1:83149916f8a9 | 4 | * and associated documentation files (the "Software"), to deal in the Software without restriction, |
geotec | 1:83149916f8a9 | 5 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, |
geotec | 1:83149916f8a9 | 6 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is |
geotec | 1:83149916f8a9 | 7 | * furnished to do so, subject to the following conditions: |
geotec | 1:83149916f8a9 | 8 | * |
geotec | 1:83149916f8a9 | 9 | * The above copyright notice and this permission notice shall be included in all copies or |
geotec | 1:83149916f8a9 | 10 | * substantial portions of the Software. |
geotec | 1:83149916f8a9 | 11 | * |
geotec | 1:83149916f8a9 | 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING |
geotec | 1:83149916f8a9 | 13 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
geotec | 1:83149916f8a9 | 14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
geotec | 1:83149916f8a9 | 15 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
geotec | 1:83149916f8a9 | 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
geotec | 1:83149916f8a9 | 17 | */ |
geotec | 1:83149916f8a9 | 18 | |
geotec | 0:157c2fddaa68 | 19 | #include "mbed.h" |
geotec | 0:157c2fddaa68 | 20 | #include "PulseCounter.h" |
geotec | 0:157c2fddaa68 | 21 | |
geotec | 0:157c2fddaa68 | 22 | PulseCounter *PulseCounter::instance; |
geotec | 0:157c2fddaa68 | 23 | |
geotec | 0:157c2fddaa68 | 24 | extern int CLOCK_FREQUENCY; |
geotec | 0:157c2fddaa68 | 25 | |
geotec | 0:157c2fddaa68 | 26 | void PulseCounter::init() |
geotec | 0:157c2fddaa68 | 27 | { |
geotec | 0:157c2fddaa68 | 28 | instance = this; // pointer to instance |
geotec | 0:157c2fddaa68 | 29 | |
geotec | 0:157c2fddaa68 | 30 | // Power Control for Peripherals Register |
geotec | 0:157c2fddaa68 | 31 | LPC_SC->PCONP |= (1<<22); // Bit 22: 1 = Timer2 power on |
geotec | 0:157c2fddaa68 | 32 | |
geotec | 0:157c2fddaa68 | 33 | // Pin Function Select Register |
geotec | 0:157c2fddaa68 | 34 | LPC_PINCON->PINSEL0 |= (0x3<<8); // Bits 9/8: 1/1 = pin function CAP2.0 (p30) |
geotec | 0:157c2fddaa68 | 35 | LPC_PINCON->PINSEL0 |= (0x3<<10); // Bits 11/10: 1/1 = pin function CAP2.1 (p29) |
geotec | 0:157c2fddaa68 | 36 | |
geotec | 0:157c2fddaa68 | 37 | // Peripheral Clock Selection Register |
geotec | 0:157c2fddaa68 | 38 | LPC_SC->PCLKSEL1 |= (0x1<<12); // Bits 13/12: 0/1 = CCLK ( 96 MHz ) |
geotec | 0:157c2fddaa68 | 39 | // Prescale Register |
geotec | 0:157c2fddaa68 | 40 | LPC_TIM2->PR = 0x0; // 0 = no prescaling |
geotec | 0:157c2fddaa68 | 41 | |
geotec | 0:157c2fddaa68 | 42 | // Count Control Register |
geotec | 2:8d50e024637b | 43 | LPC_TIM2->CTCR = 0x5; // Bits 1/0: 0/1 = timer is incremented on rising edge on clock sample capture pin |
geotec | 0:157c2fddaa68 | 44 | // Bits 3/2: 0/1 = clock sample capture pin: CAP2.1 (p29), (p29 signal is counter clock) |
geotec | 0:157c2fddaa68 | 45 | |
geotec | 0:157c2fddaa68 | 46 | // Capture Control Register |
geotec | 0:157c2fddaa68 | 47 | LPC_TIM2->CCR = 0x5; // Bits 2/1/0: 1/0/1 = capture on rising edge / generate interrupt on event |
geotec | 0:157c2fddaa68 | 48 | // Bits 5/4/3: 0/0/0 = don't capture - this is the clock sample capture pin |
geotec | 0:157c2fddaa68 | 49 | |
geotec | 0:157c2fddaa68 | 50 | // Set custom method to be called on Timer2 interrupt |
geotec | 0:157c2fddaa68 | 51 | NVIC_DisableIRQ(TIMER2_IRQn); |
geotec | 0:157c2fddaa68 | 52 | NVIC_SetVector(TIMER2_IRQn, (uint32_t)&_triggerInterrupt); |
geotec | 0:157c2fddaa68 | 53 | // |
geotec | 0:157c2fddaa68 | 54 | |
geotec | 0:157c2fddaa68 | 55 | LPC_TIM2->TCR = 0x2; // Timer2 count reset |
geotec | 0:157c2fddaa68 | 56 | LPC_TIM2->TCR = 0x0; // Timer2 disabled |
geotec | 0:157c2fddaa68 | 57 | |
geotec | 0:157c2fddaa68 | 58 | _hasFinishedCounting = true; |
geotec | 0:157c2fddaa68 | 59 | } |
geotec | 0:157c2fddaa68 | 60 | |
geotec | 0:157c2fddaa68 | 61 | void PulseCounter::start() |
geotec | 0:157c2fddaa68 | 62 | { |
geotec | 0:157c2fddaa68 | 63 | // reset array pointer to first array element |
geotec | 0:157c2fddaa68 | 64 | int arrayLength = sizeof(_pulseCountArray)/sizeof(uint32_t); |
geotec | 0:157c2fddaa68 | 65 | for(int i = 0; i < arrayLength; i++) { |
geotec | 0:157c2fddaa68 | 66 | _pulseCountArray[i] = 0; |
geotec | 0:157c2fddaa68 | 67 | } |
geotec | 0:157c2fddaa68 | 68 | _arrayPointer = &_pulseCountArray[0]; |
geotec | 0:157c2fddaa68 | 69 | _triggerCounter = 0; |
geotec | 0:157c2fddaa68 | 70 | // |
geotec | 0:157c2fddaa68 | 71 | |
geotec | 0:157c2fddaa68 | 72 | LPC_TIM2->TCR = 1; // Timer2 start |
geotec | 0:157c2fddaa68 | 73 | NVIC_EnableIRQ(TIMER2_IRQn); // enable capture interrupt |
geotec | 0:157c2fddaa68 | 74 | |
geotec | 0:157c2fddaa68 | 75 | _hasFinishedCounting = false; |
geotec | 0:157c2fddaa68 | 76 | } |
geotec | 0:157c2fddaa68 | 77 | |
geotec | 0:157c2fddaa68 | 78 | void PulseCounter::stop() |
geotec | 0:157c2fddaa68 | 79 | { |
geotec | 0:157c2fddaa68 | 80 | LPC_TIM2->TCR = 0; // Timer2 stop |
geotec | 0:157c2fddaa68 | 81 | NVIC_DisableIRQ(TIMER2_IRQn); // disable capture interrupt |
geotec | 0:157c2fddaa68 | 82 | |
geotec | 0:157c2fddaa68 | 83 | _hasFinishedCounting = true; |
geotec | 0:157c2fddaa68 | 84 | } |
geotec | 0:157c2fddaa68 | 85 | |
geotec | 3:9e7474866e48 | 86 | void PulseCounter::counterArray(uint32_t* counterArray, int counterArrayLength) |
geotec | 0:157c2fddaa68 | 87 | { |
geotec | 0:157c2fddaa68 | 88 | int i = 1; |
geotec | 0:157c2fddaa68 | 89 | if(_hasFinishedCounting == true) { |
geotec | 0:157c2fddaa68 | 90 | while(i <= _pulseCountArrayLength) { |
geotec | 0:157c2fddaa68 | 91 | *counterArray = _pulseCountArray[i]; |
geotec | 0:157c2fddaa68 | 92 | counterArray++; |
geotec | 0:157c2fddaa68 | 93 | i++; |
geotec | 0:157c2fddaa68 | 94 | if (i > counterArrayLength) { |
geotec | 0:157c2fddaa68 | 95 | // parameter counterArray has less elements than pulseCountArray. Stop copying elements. |
geotec | 0:157c2fddaa68 | 96 | break; |
geotec | 0:157c2fddaa68 | 97 | } |
geotec | 0:157c2fddaa68 | 98 | } |
geotec | 0:157c2fddaa68 | 99 | } else { |
geotec | 0:157c2fddaa68 | 100 | // User didn't call stop() before reading pulseCountArray - prevent simultaneous read and write on array. Just return zero array. |
geotec | 0:157c2fddaa68 | 101 | while(i <= _pulseCountArrayLength) { |
geotec | 0:157c2fddaa68 | 102 | *counterArray = 0; |
geotec | 0:157c2fddaa68 | 103 | counterArray++; |
geotec | 0:157c2fddaa68 | 104 | i++; |
geotec | 0:157c2fddaa68 | 105 | if (i > counterArrayLength) { |
geotec | 0:157c2fddaa68 | 106 | // parameter counterArray has less elements than pulseCountArray. Stop copying elements. |
geotec | 0:157c2fddaa68 | 107 | break; |
geotec | 0:157c2fddaa68 | 108 | } |
geotec | 0:157c2fddaa68 | 109 | } |
geotec | 0:157c2fddaa68 | 110 | } |
geotec | 0:157c2fddaa68 | 111 | |
geotec | 0:157c2fddaa68 | 112 | // if parameter counterArray has more elements than pulseCountArray. Fill up with zeros. |
geotec | 0:157c2fddaa68 | 113 | if(counterArrayLength > _pulseCountArrayLength) { |
geotec | 0:157c2fddaa68 | 114 | while(i <= counterArrayLength) { |
geotec | 0:157c2fddaa68 | 115 | *counterArray = 0; |
geotec | 0:157c2fddaa68 | 116 | counterArray++; |
geotec | 0:157c2fddaa68 | 117 | i++; |
geotec | 0:157c2fddaa68 | 118 | } |
geotec | 0:157c2fddaa68 | 119 | } |
geotec | 0:157c2fddaa68 | 120 | } |
geotec | 0:157c2fddaa68 | 121 | |
geotec | 0:157c2fddaa68 | 122 | void PulseCounter::_triggerInterrupt() |
geotec | 0:157c2fddaa68 | 123 | { |
geotec | 0:157c2fddaa68 | 124 | instance->_arrayPointer++; // increment array pointer |
geotec | 0:157c2fddaa68 | 125 | wait_us(1); // incrementing pointer needs a little time |
geotec | 0:157c2fddaa68 | 126 | *instance->_arrayPointer = LPC_TIM2->CR0; // store capture time in eventTimeCount-Array |
geotec | 0:157c2fddaa68 | 127 | |
geotec | 0:157c2fddaa68 | 128 | LPC_TIM2->TCR = 0x2; // Timer2 count reset |
geotec | 0:157c2fddaa68 | 129 | LPC_TIM2->TCR = 0x0; // Timer2 disabled |
geotec | 0:157c2fddaa68 | 130 | LPC_TIM2->TCR = 0x1; // Timer2 enabled |
geotec | 0:157c2fddaa68 | 131 | |
geotec | 0:157c2fddaa68 | 132 | instance->_triggerCounter++; |
geotec | 0:157c2fddaa68 | 133 | if (instance->_triggerCounter > _pulseCountArrayLength) { |
geotec | 0:157c2fddaa68 | 134 | instance->_arrayPointer = &instance->_pulseCountArray[0]; |
geotec | 0:157c2fddaa68 | 135 | instance->_triggerCounter = 0; |
geotec | 0:157c2fddaa68 | 136 | } |
geotec | 0:157c2fddaa68 | 137 | |
geotec | 0:157c2fddaa68 | 138 | LPC_TIM2->IR = 0x10; // clear interrupt |
geotec | 0:157c2fddaa68 | 139 | } |
geotec | 0:157c2fddaa68 | 140 |