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-09
- Revision:
- 4:0eb01612bcb2
- Parent:
- 3:9e7474866e48
File content as of revision 4:0eb01612bcb2:
/* 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);
//
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
}