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");
}
Committer:
geotec
Date:
Tue Jan 08 14:25:02 2013 +0000
Revision:
3:9e7474866e48
Parent:
2:8d50e024637b
Child:
4:0eb01612bcb2
changed datatype of counterArray (int -> uint32_t)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
geotec 1:83149916f8a9 1 /* Copyright (c) 2012 Christian Buntebarth, MIT License
geotec 1:83149916f8a9 2 *
geotec 1:83149916f8a9 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
geotec 1:83149916f8a9 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
geotec 1:83149916f8a9 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
geotec 1:83149916f8a9 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
geotec 1:83149916f8a9 7 * furnished to do so, subject to the following conditions:
geotec 1:83149916f8a9 8 *
geotec 1:83149916f8a9 9 * The above copyright notice and this permission notice shall be included in all copies or
geotec 1:83149916f8a9 10 * substantial portions of the Software.
geotec 1:83149916f8a9 11 *
geotec 1:83149916f8a9 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
geotec 1:83149916f8a9 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
geotec 1:83149916f8a9 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
geotec 1:83149916f8a9 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
geotec 1:83149916f8a9 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
geotec 1:83149916f8a9 17 */
geotec 1:83149916f8a9 18
geotec 0:157c2fddaa68 19 #include "mbed.h"
geotec 0:157c2fddaa68 20 #include "PulseCounter.h"
geotec 0:157c2fddaa68 21
geotec 0:157c2fddaa68 22 PulseCounter *PulseCounter::instance;
geotec 0:157c2fddaa68 23
geotec 0:157c2fddaa68 24 extern int CLOCK_FREQUENCY;
geotec 0:157c2fddaa68 25
geotec 0:157c2fddaa68 26 void PulseCounter::init()
geotec 0:157c2fddaa68 27 {
geotec 0:157c2fddaa68 28 instance = this; // pointer to instance
geotec 0:157c2fddaa68 29
geotec 0:157c2fddaa68 30 // Power Control for Peripherals Register
geotec 0:157c2fddaa68 31 LPC_SC->PCONP |= (1<<22); // Bit 22: 1 = Timer2 power on
geotec 0:157c2fddaa68 32
geotec 0:157c2fddaa68 33 // Pin Function Select Register
geotec 0:157c2fddaa68 34 LPC_PINCON->PINSEL0 |= (0x3<<8); // Bits 9/8: 1/1 = pin function CAP2.0 (p30)
geotec 0:157c2fddaa68 35 LPC_PINCON->PINSEL0 |= (0x3<<10); // Bits 11/10: 1/1 = pin function CAP2.1 (p29)
geotec 0:157c2fddaa68 36
geotec 0:157c2fddaa68 37 // Peripheral Clock Selection Register
geotec 0:157c2fddaa68 38 LPC_SC->PCLKSEL1 |= (0x1<<12); // Bits 13/12: 0/1 = CCLK ( 96 MHz )
geotec 0:157c2fddaa68 39 // Prescale Register
geotec 0:157c2fddaa68 40 LPC_TIM2->PR = 0x0; // 0 = no prescaling
geotec 0:157c2fddaa68 41
geotec 0:157c2fddaa68 42 // Count Control Register
geotec 2:8d50e024637b 43 LPC_TIM2->CTCR = 0x5; // Bits 1/0: 0/1 = timer is incremented on rising edge on clock sample capture pin
geotec 0:157c2fddaa68 44 // Bits 3/2: 0/1 = clock sample capture pin: CAP2.1 (p29), (p29 signal is counter clock)
geotec 0:157c2fddaa68 45
geotec 0:157c2fddaa68 46 // Capture Control Register
geotec 0:157c2fddaa68 47 LPC_TIM2->CCR = 0x5; // Bits 2/1/0: 1/0/1 = capture on rising edge / generate interrupt on event
geotec 0:157c2fddaa68 48 // Bits 5/4/3: 0/0/0 = don't capture - this is the clock sample capture pin
geotec 0:157c2fddaa68 49
geotec 0:157c2fddaa68 50 // Set custom method to be called on Timer2 interrupt
geotec 0:157c2fddaa68 51 NVIC_DisableIRQ(TIMER2_IRQn);
geotec 0:157c2fddaa68 52 NVIC_SetVector(TIMER2_IRQn, (uint32_t)&_triggerInterrupt);
geotec 0:157c2fddaa68 53 NVIC_EnableIRQ(TIMER2_IRQn);
geotec 0:157c2fddaa68 54 //
geotec 0:157c2fddaa68 55
geotec 0:157c2fddaa68 56 LPC_TIM2->TCR = 0x2; // Timer2 count reset
geotec 0:157c2fddaa68 57 LPC_TIM2->TCR = 0x0; // Timer2 disabled
geotec 0:157c2fddaa68 58
geotec 0:157c2fddaa68 59 _hasFinishedCounting = true;
geotec 0:157c2fddaa68 60 }
geotec 0:157c2fddaa68 61
geotec 0:157c2fddaa68 62 void PulseCounter::start()
geotec 0:157c2fddaa68 63 {
geotec 0:157c2fddaa68 64 // reset array pointer to first array element
geotec 0:157c2fddaa68 65 int arrayLength = sizeof(_pulseCountArray)/sizeof(uint32_t);
geotec 0:157c2fddaa68 66 for(int i = 0; i < arrayLength; i++) {
geotec 0:157c2fddaa68 67 _pulseCountArray[i] = 0;
geotec 0:157c2fddaa68 68 }
geotec 0:157c2fddaa68 69 _arrayPointer = &_pulseCountArray[0];
geotec 0:157c2fddaa68 70 _triggerCounter = 0;
geotec 0:157c2fddaa68 71 //
geotec 0:157c2fddaa68 72
geotec 0:157c2fddaa68 73 LPC_TIM2->TCR = 1; // Timer2 start
geotec 0:157c2fddaa68 74 NVIC_EnableIRQ(TIMER2_IRQn); // enable capture interrupt
geotec 0:157c2fddaa68 75
geotec 0:157c2fddaa68 76 _hasFinishedCounting = false;
geotec 0:157c2fddaa68 77 }
geotec 0:157c2fddaa68 78
geotec 0:157c2fddaa68 79 void PulseCounter::stop()
geotec 0:157c2fddaa68 80 {
geotec 0:157c2fddaa68 81 LPC_TIM2->TCR = 0; // Timer2 stop
geotec 0:157c2fddaa68 82 NVIC_DisableIRQ(TIMER2_IRQn); // disable capture interrupt
geotec 0:157c2fddaa68 83
geotec 0:157c2fddaa68 84 _hasFinishedCounting = true;
geotec 0:157c2fddaa68 85 }
geotec 0:157c2fddaa68 86
geotec 3:9e7474866e48 87 void PulseCounter::counterArray(uint32_t* counterArray, int counterArrayLength)
geotec 0:157c2fddaa68 88 {
geotec 0:157c2fddaa68 89 int i = 1;
geotec 0:157c2fddaa68 90 if(_hasFinishedCounting == true) {
geotec 0:157c2fddaa68 91 while(i <= _pulseCountArrayLength) {
geotec 0:157c2fddaa68 92 *counterArray = _pulseCountArray[i];
geotec 0:157c2fddaa68 93 counterArray++;
geotec 0:157c2fddaa68 94 i++;
geotec 0:157c2fddaa68 95 if (i > counterArrayLength) {
geotec 0:157c2fddaa68 96 // parameter counterArray has less elements than pulseCountArray. Stop copying elements.
geotec 0:157c2fddaa68 97 break;
geotec 0:157c2fddaa68 98 }
geotec 0:157c2fddaa68 99 }
geotec 0:157c2fddaa68 100 } else {
geotec 0:157c2fddaa68 101 // User didn't call stop() before reading pulseCountArray - prevent simultaneous read and write on array. Just return zero array.
geotec 0:157c2fddaa68 102 while(i <= _pulseCountArrayLength) {
geotec 0:157c2fddaa68 103 *counterArray = 0;
geotec 0:157c2fddaa68 104 counterArray++;
geotec 0:157c2fddaa68 105 i++;
geotec 0:157c2fddaa68 106 if (i > counterArrayLength) {
geotec 0:157c2fddaa68 107 // parameter counterArray has less elements than pulseCountArray. Stop copying elements.
geotec 0:157c2fddaa68 108 break;
geotec 0:157c2fddaa68 109 }
geotec 0:157c2fddaa68 110 }
geotec 0:157c2fddaa68 111 }
geotec 0:157c2fddaa68 112
geotec 0:157c2fddaa68 113 // if parameter counterArray has more elements than pulseCountArray. Fill up with zeros.
geotec 0:157c2fddaa68 114 if(counterArrayLength > _pulseCountArrayLength) {
geotec 0:157c2fddaa68 115 while(i <= counterArrayLength) {
geotec 0:157c2fddaa68 116 *counterArray = 0;
geotec 0:157c2fddaa68 117 counterArray++;
geotec 0:157c2fddaa68 118 i++;
geotec 0:157c2fddaa68 119 }
geotec 0:157c2fddaa68 120 }
geotec 0:157c2fddaa68 121 }
geotec 0:157c2fddaa68 122
geotec 0:157c2fddaa68 123 void PulseCounter::_triggerInterrupt()
geotec 0:157c2fddaa68 124 {
geotec 0:157c2fddaa68 125 instance->_arrayPointer++; // increment array pointer
geotec 0:157c2fddaa68 126 wait_us(1); // incrementing pointer needs a little time
geotec 0:157c2fddaa68 127 *instance->_arrayPointer = LPC_TIM2->CR0; // store capture time in eventTimeCount-Array
geotec 0:157c2fddaa68 128
geotec 0:157c2fddaa68 129 LPC_TIM2->TCR = 0x2; // Timer2 count reset
geotec 0:157c2fddaa68 130 LPC_TIM2->TCR = 0x0; // Timer2 disabled
geotec 0:157c2fddaa68 131 LPC_TIM2->TCR = 0x1; // Timer2 enabled
geotec 0:157c2fddaa68 132
geotec 0:157c2fddaa68 133 instance->_triggerCounter++;
geotec 0:157c2fddaa68 134 if (instance->_triggerCounter > _pulseCountArrayLength) {
geotec 0:157c2fddaa68 135 instance->_arrayPointer = &instance->_pulseCountArray[0];
geotec 0:157c2fddaa68 136 instance->_triggerCounter = 0;
geotec 0:157c2fddaa68 137 }
geotec 0:157c2fddaa68 138
geotec 0:157c2fddaa68 139 LPC_TIM2->IR = 0x10; // clear interrupt
geotec 0:157c2fddaa68 140 }
geotec 0:157c2fddaa68 141