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
- Committer:
- geotec
- Date:
- 2013-01-08
- Revision:
- 3:9e7474866e48
- Parent:
- 2:8d50e024637b
- Child:
- 4:0eb01612bcb2
File content as of revision 3:9e7474866e48:
/* Copyright (c) 2012 Christian Buntebarth, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #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 = 0x5; // Bits 1/0: 0/1 = timer is incremented on rising edge 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(uint32_t* 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 }