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     
}