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@0:157c2fddaa68, 2012-12-15 (annotated)
- Committer:
- geotec
- Date:
- Sat Dec 15 14:26:47 2012 +0000
- Revision:
- 0:157c2fddaa68
- Child:
- 1:83149916f8a9
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
geotec | 0:157c2fddaa68 | 1 | #include "mbed.h" |
geotec | 0:157c2fddaa68 | 2 | #include "PulseCounter.h" |
geotec | 0:157c2fddaa68 | 3 | |
geotec | 0:157c2fddaa68 | 4 | PulseCounter *PulseCounter::instance; |
geotec | 0:157c2fddaa68 | 5 | |
geotec | 0:157c2fddaa68 | 6 | extern int CLOCK_FREQUENCY; |
geotec | 0:157c2fddaa68 | 7 | |
geotec | 0:157c2fddaa68 | 8 | void PulseCounter::init() |
geotec | 0:157c2fddaa68 | 9 | { |
geotec | 0:157c2fddaa68 | 10 | instance = this; // pointer to instance |
geotec | 0:157c2fddaa68 | 11 | |
geotec | 0:157c2fddaa68 | 12 | // Power Control for Peripherals Register |
geotec | 0:157c2fddaa68 | 13 | LPC_SC->PCONP |= (1<<22); // Bit 22: 1 = Timer2 power on |
geotec | 0:157c2fddaa68 | 14 | |
geotec | 0:157c2fddaa68 | 15 | // Pin Function Select Register |
geotec | 0:157c2fddaa68 | 16 | LPC_PINCON->PINSEL0 |= (0x3<<8); // Bits 9/8: 1/1 = pin function CAP2.0 (p30) |
geotec | 0:157c2fddaa68 | 17 | LPC_PINCON->PINSEL0 |= (0x3<<10); // Bits 11/10: 1/1 = pin function CAP2.1 (p29) |
geotec | 0:157c2fddaa68 | 18 | |
geotec | 0:157c2fddaa68 | 19 | // Peripheral Clock Selection Register |
geotec | 0:157c2fddaa68 | 20 | LPC_SC->PCLKSEL1 |= (0x1<<12); // Bits 13/12: 0/1 = CCLK ( 96 MHz ) |
geotec | 0:157c2fddaa68 | 21 | // Prescale Register |
geotec | 0:157c2fddaa68 | 22 | LPC_TIM2->PR = 0x0; // 0 = no prescaling |
geotec | 0:157c2fddaa68 | 23 | |
geotec | 0:157c2fddaa68 | 24 | // Count Control Register |
geotec | 0:157c2fddaa68 | 25 | LPC_TIM2->CTCR = 0x7; // Bits 1/0: 1/1 = timer is incremented on rising & falling edges on clock sample capture pin |
geotec | 0:157c2fddaa68 | 26 | // Bits 3/2: 0/1 = clock sample capture pin: CAP2.1 (p29), (p29 signal is counter clock) |
geotec | 0:157c2fddaa68 | 27 | |
geotec | 0:157c2fddaa68 | 28 | // Capture Control Register |
geotec | 0:157c2fddaa68 | 29 | LPC_TIM2->CCR = 0x5; // Bits 2/1/0: 1/0/1 = capture on rising edge / generate interrupt on event |
geotec | 0:157c2fddaa68 | 30 | // Bits 5/4/3: 0/0/0 = don't capture - this is the clock sample capture pin |
geotec | 0:157c2fddaa68 | 31 | |
geotec | 0:157c2fddaa68 | 32 | // Set custom method to be called on Timer2 interrupt |
geotec | 0:157c2fddaa68 | 33 | NVIC_DisableIRQ(TIMER2_IRQn); |
geotec | 0:157c2fddaa68 | 34 | NVIC_SetVector(TIMER2_IRQn, (uint32_t)&_triggerInterrupt); |
geotec | 0:157c2fddaa68 | 35 | NVIC_EnableIRQ(TIMER2_IRQn); |
geotec | 0:157c2fddaa68 | 36 | // |
geotec | 0:157c2fddaa68 | 37 | |
geotec | 0:157c2fddaa68 | 38 | LPC_TIM2->TCR = 0x2; // Timer2 count reset |
geotec | 0:157c2fddaa68 | 39 | LPC_TIM2->TCR = 0x0; // Timer2 disabled |
geotec | 0:157c2fddaa68 | 40 | |
geotec | 0:157c2fddaa68 | 41 | _hasFinishedCounting = true; |
geotec | 0:157c2fddaa68 | 42 | } |
geotec | 0:157c2fddaa68 | 43 | |
geotec | 0:157c2fddaa68 | 44 | void PulseCounter::start() |
geotec | 0:157c2fddaa68 | 45 | { |
geotec | 0:157c2fddaa68 | 46 | // reset array pointer to first array element |
geotec | 0:157c2fddaa68 | 47 | int arrayLength = sizeof(_pulseCountArray)/sizeof(uint32_t); |
geotec | 0:157c2fddaa68 | 48 | for(int i = 0; i < arrayLength; i++) { |
geotec | 0:157c2fddaa68 | 49 | _pulseCountArray[i] = 0; |
geotec | 0:157c2fddaa68 | 50 | } |
geotec | 0:157c2fddaa68 | 51 | _arrayPointer = &_pulseCountArray[0]; |
geotec | 0:157c2fddaa68 | 52 | _triggerCounter = 0; |
geotec | 0:157c2fddaa68 | 53 | // |
geotec | 0:157c2fddaa68 | 54 | |
geotec | 0:157c2fddaa68 | 55 | LPC_TIM2->TCR = 1; // Timer2 start |
geotec | 0:157c2fddaa68 | 56 | NVIC_EnableIRQ(TIMER2_IRQn); // enable capture interrupt |
geotec | 0:157c2fddaa68 | 57 | |
geotec | 0:157c2fddaa68 | 58 | _hasFinishedCounting = false; |
geotec | 0:157c2fddaa68 | 59 | } |
geotec | 0:157c2fddaa68 | 60 | |
geotec | 0:157c2fddaa68 | 61 | void PulseCounter::stop() |
geotec | 0:157c2fddaa68 | 62 | { |
geotec | 0:157c2fddaa68 | 63 | LPC_TIM2->TCR = 0; // Timer2 stop |
geotec | 0:157c2fddaa68 | 64 | NVIC_DisableIRQ(TIMER2_IRQn); // disable capture interrupt |
geotec | 0:157c2fddaa68 | 65 | |
geotec | 0:157c2fddaa68 | 66 | _hasFinishedCounting = true; |
geotec | 0:157c2fddaa68 | 67 | } |
geotec | 0:157c2fddaa68 | 68 | |
geotec | 0:157c2fddaa68 | 69 | void PulseCounter::counterArray(int* counterArray, int counterArrayLength) |
geotec | 0:157c2fddaa68 | 70 | { |
geotec | 0:157c2fddaa68 | 71 | int i = 1; |
geotec | 0:157c2fddaa68 | 72 | if(_hasFinishedCounting == true) { |
geotec | 0:157c2fddaa68 | 73 | while(i <= _pulseCountArrayLength) { |
geotec | 0:157c2fddaa68 | 74 | *counterArray = _pulseCountArray[i]; |
geotec | 0:157c2fddaa68 | 75 | counterArray++; |
geotec | 0:157c2fddaa68 | 76 | i++; |
geotec | 0:157c2fddaa68 | 77 | if (i > counterArrayLength) { |
geotec | 0:157c2fddaa68 | 78 | // parameter counterArray has less elements than pulseCountArray. Stop copying elements. |
geotec | 0:157c2fddaa68 | 79 | break; |
geotec | 0:157c2fddaa68 | 80 | } |
geotec | 0:157c2fddaa68 | 81 | } |
geotec | 0:157c2fddaa68 | 82 | } else { |
geotec | 0:157c2fddaa68 | 83 | // User didn't call stop() before reading pulseCountArray - prevent simultaneous read and write on array. Just return zero array. |
geotec | 0:157c2fddaa68 | 84 | while(i <= _pulseCountArrayLength) { |
geotec | 0:157c2fddaa68 | 85 | *counterArray = 0; |
geotec | 0:157c2fddaa68 | 86 | counterArray++; |
geotec | 0:157c2fddaa68 | 87 | i++; |
geotec | 0:157c2fddaa68 | 88 | if (i > counterArrayLength) { |
geotec | 0:157c2fddaa68 | 89 | // parameter counterArray has less elements than pulseCountArray. Stop copying elements. |
geotec | 0:157c2fddaa68 | 90 | break; |
geotec | 0:157c2fddaa68 | 91 | } |
geotec | 0:157c2fddaa68 | 92 | } |
geotec | 0:157c2fddaa68 | 93 | } |
geotec | 0:157c2fddaa68 | 94 | |
geotec | 0:157c2fddaa68 | 95 | // if parameter counterArray has more elements than pulseCountArray. Fill up with zeros. |
geotec | 0:157c2fddaa68 | 96 | if(counterArrayLength > _pulseCountArrayLength) { |
geotec | 0:157c2fddaa68 | 97 | while(i <= counterArrayLength) { |
geotec | 0:157c2fddaa68 | 98 | *counterArray = 0; |
geotec | 0:157c2fddaa68 | 99 | counterArray++; |
geotec | 0:157c2fddaa68 | 100 | i++; |
geotec | 0:157c2fddaa68 | 101 | } |
geotec | 0:157c2fddaa68 | 102 | } |
geotec | 0:157c2fddaa68 | 103 | } |
geotec | 0:157c2fddaa68 | 104 | |
geotec | 0:157c2fddaa68 | 105 | void PulseCounter::_triggerInterrupt() |
geotec | 0:157c2fddaa68 | 106 | { |
geotec | 0:157c2fddaa68 | 107 | instance->_arrayPointer++; // increment array pointer |
geotec | 0:157c2fddaa68 | 108 | wait_us(1); // incrementing pointer needs a little time |
geotec | 0:157c2fddaa68 | 109 | *instance->_arrayPointer = LPC_TIM2->CR0; // store capture time in eventTimeCount-Array |
geotec | 0:157c2fddaa68 | 110 | |
geotec | 0:157c2fddaa68 | 111 | LPC_TIM2->TCR = 0x2; // Timer2 count reset |
geotec | 0:157c2fddaa68 | 112 | LPC_TIM2->TCR = 0x0; // Timer2 disabled |
geotec | 0:157c2fddaa68 | 113 | LPC_TIM2->TCR = 0x1; // Timer2 enabled |
geotec | 0:157c2fddaa68 | 114 | |
geotec | 0:157c2fddaa68 | 115 | instance->_triggerCounter++; |
geotec | 0:157c2fddaa68 | 116 | if (instance->_triggerCounter > _pulseCountArrayLength) { |
geotec | 0:157c2fddaa68 | 117 | instance->_arrayPointer = &instance->_pulseCountArray[0]; |
geotec | 0:157c2fddaa68 | 118 | instance->_triggerCounter = 0; |
geotec | 0:157c2fddaa68 | 119 | } |
geotec | 0:157c2fddaa68 | 120 | |
geotec | 0:157c2fddaa68 | 121 | LPC_TIM2->IR = 0x10; // clear interrupt |
geotec | 0:157c2fddaa68 | 122 | } |
geotec | 0:157c2fddaa68 | 123 |