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"); }
Diff: PulseCounter.cpp
- Revision:
- 0:157c2fddaa68
- Child:
- 1:83149916f8a9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PulseCounter.cpp Sat Dec 15 14:26:47 2012 +0000 @@ -0,0 +1,123 @@ +#include "mbed.h" +#include "PulseCounter.h" + +PulseCounter *PulseCounter::instance; + +extern int CLOCK_FREQUENCY; + +void PulseCounter::init() +{ + instance = this; // pointer to instance + + // Power Control for Peripherals Register + LPC_SC->PCONP |= (1<<22); // Bit 22: 1 = Timer2 power on + + // Pin Function Select Register + LPC_PINCON->PINSEL0 |= (0x3<<8); // Bits 9/8: 1/1 = pin function CAP2.0 (p30) + LPC_PINCON->PINSEL0 |= (0x3<<10); // Bits 11/10: 1/1 = pin function CAP2.1 (p29) + + // Peripheral Clock Selection Register + LPC_SC->PCLKSEL1 |= (0x1<<12); // Bits 13/12: 0/1 = CCLK ( 96 MHz ) + // Prescale Register + LPC_TIM2->PR = 0x0; // 0 = no prescaling + + // Count Control Register + LPC_TIM2->CTCR = 0x7; // Bits 1/0: 1/1 = timer is incremented on rising & falling edges on clock sample capture pin + // Bits 3/2: 0/1 = clock sample capture pin: CAP2.1 (p29), (p29 signal is counter clock) + + // Capture Control Register + LPC_TIM2->CCR = 0x5; // Bits 2/1/0: 1/0/1 = capture on rising edge / generate interrupt on event + // Bits 5/4/3: 0/0/0 = don't capture - this is the clock sample capture pin + + // Set custom method to be called on Timer2 interrupt + NVIC_DisableIRQ(TIMER2_IRQn); + NVIC_SetVector(TIMER2_IRQn, (uint32_t)&_triggerInterrupt); + NVIC_EnableIRQ(TIMER2_IRQn); + // + + LPC_TIM2->TCR = 0x2; // Timer2 count reset + LPC_TIM2->TCR = 0x0; // Timer2 disabled + + _hasFinishedCounting = true; +} + +void PulseCounter::start() +{ + // reset array pointer to first array element + int arrayLength = sizeof(_pulseCountArray)/sizeof(uint32_t); + for(int i = 0; i < arrayLength; i++) { + _pulseCountArray[i] = 0; + } + _arrayPointer = &_pulseCountArray[0]; + _triggerCounter = 0; + // + + LPC_TIM2->TCR = 1; // Timer2 start + NVIC_EnableIRQ(TIMER2_IRQn); // enable capture interrupt + + _hasFinishedCounting = false; +} + +void PulseCounter::stop() +{ + LPC_TIM2->TCR = 0; // Timer2 stop + NVIC_DisableIRQ(TIMER2_IRQn); // disable capture interrupt + + _hasFinishedCounting = true; +} + +void PulseCounter::counterArray(int* counterArray, int counterArrayLength) +{ + int i = 1; + if(_hasFinishedCounting == true) { + while(i <= _pulseCountArrayLength) { + *counterArray = _pulseCountArray[i]; + counterArray++; + i++; + if (i > counterArrayLength) { + // parameter counterArray has less elements than pulseCountArray. Stop copying elements. + break; + } + } + } else { + // User didn't call stop() before reading pulseCountArray - prevent simultaneous read and write on array. Just return zero array. + while(i <= _pulseCountArrayLength) { + *counterArray = 0; + counterArray++; + i++; + if (i > counterArrayLength) { + // parameter counterArray has less elements than pulseCountArray. Stop copying elements. + break; + } + } + } + + // if parameter counterArray has more elements than pulseCountArray. Fill up with zeros. + if(counterArrayLength > _pulseCountArrayLength) { + while(i <= counterArrayLength) { + *counterArray = 0; + counterArray++; + i++; + } + } +} + +void PulseCounter::_triggerInterrupt() +{ + instance->_arrayPointer++; // increment array pointer + wait_us(1); // incrementing pointer needs a little time + *instance->_arrayPointer = LPC_TIM2->CR0; // store capture time in eventTimeCount-Array + + LPC_TIM2->TCR = 0x2; // Timer2 count reset + LPC_TIM2->TCR = 0x0; // Timer2 disabled + LPC_TIM2->TCR = 0x1; // Timer2 enabled + + instance->_triggerCounter++; + if (instance->_triggerCounter > _pulseCountArrayLength) { + instance->_arrayPointer = &instance->_pulseCountArray[0]; + instance->_triggerCounter = 0; + } + + LPC_TIM2->IR = 0x10; // clear interrupt +} +