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");
}

Files at this revision

API Documentation at this revision

Comitter:
geotec
Date:
Sat Dec 15 14:26:47 2012 +0000
Child:
1:83149916f8a9
Commit message:
Initial commit

Changed in this revision

PulseCounter.cpp Show annotated file Show diff for this revision Revisions of this file
PulseCounter.h Show annotated file Show diff for this revision Revisions of this file
--- /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     
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PulseCounter.h	Sat Dec 15 14:26:47 2012 +0000
@@ -0,0 +1,77 @@
+#ifndef MBED_PULSECOUNTER_H
+#define MBED_PULSECOUNTER_H
+
+#include "mbed.h"
+
+const int _pulseCountArrayLength = 20;
+
+/** Counts pulses on pin29 coming in with a frequency up to 48 MHz. The counter is read (and reset to 0) by rising edge (trigger event) on pin30.
+ *  These events can be triggered at a rate up to 9kHz. The counter results are stored in a "circular array" of 20 elements.
+ *  ("circular array" = array pointer increments each time a new value is stored into the array; if pointer reaches last element, it is redirected to first element)
+ *   */
+class PulseCounter
+{
+    public:
+
+    /** Initializer for PulseCounter instance
+     */
+    void init();
+ 
+    /** Start counter
+     */
+    void start();
+
+    /** Stop counter
+     */
+    void stop();
+    
+    /** Read pulse count results into external array. Do not call this method before you called method stop() - otherwise it will return zeros.
+     * @param counterArray          = Pointer to array in which the pulse count results should be read into. 
+     * @param counterArrayLength    = Size of counterArray. Should be 20 or less. If more than 20, remaining elements will be filled with zeros. 
+     * @code    #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
+                    int pulseCounterResults[20];
+                    pulseCounter.counterArray(&pulseCounterResults[0],sizeof pulseCounterResults / sizeof (int));
+    
+                    for(int i = 0; i < (sizeof pulseCounterResults / sizeof (int)); i++) {
+                        usbPC.printf("counter of trigger event %i = %i\n",i,pulseCounterResults[i]);
+                    }
+                    //
+    
+                    usbPC.printf("   finished.\n");
+                }
+       * @endcode  */
+    void counterArray(int* counterArray, int counterArrayLength);
+            
+private:
+    
+    static void _triggerInterrupt();
+    static PulseCounter *instance;
+    bool _hasFinishedCounting;
+    
+    volatile int _triggerCounter;
+    volatile uint32_t *_arrayPointer;
+    volatile uint32_t _pulseCountArray[_pulseCountArrayLength + 1];
+};
+
+#endif