This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Starterware/MSP432P401M: Looking For Sample Code For Frequency Counter

Part Number: MSP432P401M

Tool/software: Starterware

Customer looking sample code to measure frequency, idea is have external clock to be measured fed into internal timer against and compare against timer with known clock source to calculate frequency.

  • Hi Lawerence,

    Do you know what will be the max frequency that your customer is trying to measure??

    Thanks,

    David
  • David,

    They will utilize external programmable dividers to lower the frequency to be within acceptable range of the MSP432 (and other circuitry to square the signal). They want to measure anywhere between 1Hz - 100MHz. Obviously they will know what divider mode the external dividers are in.
  • Lawrence,
    I am working on getting you an example. I should be able to provide by Friday.

    Thanks,
    Chris
  • /* --COPYRIGHT--,BSD
     * Copyright (c) 2017, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    /*******************************************************************************
    * MSP432 Timer_A - Frequency counter
    *
    * Description: Capture a number of periods of P2.5 and store them in
    * an array. When the set number of periods is captured the program computes the
    * average.
    * ACLK = REFO = 32kHz (typ.), MCLK = 48Mhz, SMCLK = 24Mhz
    *
    *                MSP432P401
    *             ------------------
    *         /|\|                  |
    *          | |                  |
    *          --|RST         P1.0  |---> P1.0 LED
    *            |                  |
    *            |            P2.5  |--- TA0.2
    *            |                  |
    *******************************************************************************/
    /* DriverLib Includes */
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    
    /* Standard Includes */
    #include <stdint.h>
    #define NUMBER_TIMER_CAPTURES       128
    
    /* Timer_A Continuous Mode Configuration Parameter */
    const Timer_A_ContinuousModeConfig continuousModeConfig =
    {
            TIMER_A_CLOCKSOURCE_SMCLK,           // SMCLK Clock Source
            TIMER_A_CLOCKSOURCE_DIVIDER_1,       // SMCLK/1 = 24MHz
            TIMER_A_TAIE_INTERRUPT_DISABLE,      // Disable Timer ISR
            TIMER_A_SKIP_CLEAR                   // Skup Clear Counter
    };
    
    /* Timer_A Capture Mode Configuration Parameter */
    const Timer_A_CaptureModeConfig captureModeConfig =
    {
            TIMER_A_CAPTURECOMPARE_REGISTER_2,        // CC Register 2
    //        TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,          // Rising Edge
            TIMER_A_CAPTUREMODE_RISING_EDGE,          // Rising Edge
            TIMER_A_CAPTURE_INPUTSELECT_CCIxA,        // CCIxA Input Select
            TIMER_A_CAPTURE_SYNCHRONOUS,              // Synchronized Capture
            TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,  // Disable interrupt
            TIMER_A_OUTPUTMODE_TOGGLE_RESET            // Output bit value
    };
    
    /* DMA Control Table */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN(MSP_EXP432P401RLP_DMAControlTable, 1024)
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment=1024
    #elif defined(__GNUC__)
    __attribute__ ((aligned (1024)))
    #elif defined(__CC_ARM)
    __align(1024)
    #endif
    static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[16];
    
    uint16_t averagePeriod;
    uint16_t period[NUMBER_TIMER_CAPTURES/2];
    uint16_t timerAcaptureValuesPrimary[NUMBER_TIMER_CAPTURES];
    uint16_t timerAcaptureValuesAlternate[NUMBER_TIMER_CAPTURES];
    uint16_t* arrayPtr;
    uint8_t complete;
    
    int main(void)
    {
        uint16_t ii;
        /* Stop watchdog timer */
        MAP_WDT_A_holdTimer();
        MAP_Interrupt_disableSleepOnIsrExit();
    
        /* Configuring P1.0 as output */
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
    
        MAP_GPIO_setAsInputPin(GPIO_PORT_P2, GPIO_PIN5);
        /* Configuring P2.5 as peripheral input for capture*/
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN5,
                GPIO_PRIMARY_MODULE_FUNCTION);
    
        /*
         * Revision C silicon supports wait states of 1 at 48Mhz
         */
        MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
        MAP_FlashCtl_setWaitState(FLASH_BANK0, 1);
        MAP_FlashCtl_setWaitState(FLASH_BANK1, 1);
    
        /*
         * Setting up clocks
         * MCLK = MCLK = 48MHz
         * SMCLK = MCLK/2 = 24Mhz
         * ACLK = REFO = 32Khz
         */
        MAP_CS_setDCOFrequency(48000000);
        MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
        MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_2);
        MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    
        /* Configuring Capture Mode */
        MAP_Timer_A_initCapture(TIMER_A0_BASE, &captureModeConfig);
    
        /* Configuring Continuous Mode */
        MAP_Timer_A_configureContinuousMode(TIMER_A0_BASE, &continuousModeConfig);
    
        complete = 0;
        /* Enabling Interrupts */
        MAP_Interrupt_enableInterrupt(INT_TA0_N);
        MAP_Interrupt_enableMaster();
    
        /* Starting the Timer_A0 in continuous mode */
        MAP_Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_CONTINUOUS_MODE);
    
        while(1)
        {
            MAP_PCM_gotoLPM0();
            __no_operation();
            /*
             * Calculate frequency
             */
            if(complete == NUMBER_TIMER_CAPTURES)
            {
                MAP_Interrupt_disableMaster();
                BITBAND_PERI(P1->OUT, 0) = 1;
                for(ii=0;ii<NUMBER_TIMER_CAPTURES/2;ii++)
                {
                    period[ii] = timerAcaptureValuesPrimary[2*ii+1] - timerAcaptureValuesPrimary[2*ii];
                    averagePeriod += period[ii];
                }
                averagePeriod = averagePeriod/(NUMBER_TIMER_CAPTURES/2);
                __no_operation(); // output to ide - breakpoint properties, update view
                complete = 0;
                BITBAND_PERI(P1->OUT, 0) = 0;
                MAP_Interrupt_enableMaster();
            }
        }
    }
    
    //******************************************************************************
    //
    //This is the TIMERA interrupt vector service routine.
    //
    //******************************************************************************
    void TA0_N_IRQHandler(void)
    {
        if(TIMER_A0->IV == 0x0004)
        {
           timerAcaptureValuesPrimary[complete] = TIMER_A0->CCR[2];
           complete++;
        }
    }
    

    /* --COPYRIGHT--,BSD
     * Copyright (c) 2017, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    /*******************************************************************************
    * MSP432 Timer_A - Frequency counter
    *
    * Description: Capture a number of periods of P2.5 and store them in
    * an array. When the set number of periods is captured the program computes the
    * average.
    * ACLK = REFO = 32kHz (typ.), MCLK = 48Mhz, SMCLK = 24Mhz
    *
    *                MSP432P401
    *             ------------------
    *         /|\|                  |
    *          | |                  |
    *          --|RST         P1.0  |---> P1.0 LED
    *            |                  |
    *            |            P2.5  |--- TA0.2
    *            |                  |
    *******************************************************************************/
    /* DriverLib Includes */
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    
    /* Standard Includes */
    #include <stdint.h>
    #define NUMBER_TIMER_CAPTURES       128
    
    /* Timer_A Continuous Mode Configuration Parameter */
    const Timer_A_ContinuousModeConfig continuousModeConfig =
    {
            TIMER_A_CLOCKSOURCE_SMCLK,           // SMCLK Clock Source
            TIMER_A_CLOCKSOURCE_DIVIDER_1,       // SMCLK/1 = 24MHz
            TIMER_A_TAIE_INTERRUPT_DISABLE,      // Disable Timer ISR
            TIMER_A_SKIP_CLEAR                   // Skup Clear Counter
    };
    
    /* Timer_A Capture Mode Configuration Parameter */
    const Timer_A_CaptureModeConfig captureModeConfig =
    {
            TIMER_A_CAPTURECOMPARE_REGISTER_2,        // CC Register 2
    //        TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,          // Rising Edge
            TIMER_A_CAPTUREMODE_RISING_EDGE,          // Rising Edge
            TIMER_A_CAPTURE_INPUTSELECT_CCIxA,        // CCIxA Input Select
            TIMER_A_CAPTURE_SYNCHRONOUS,              // Synchronized Capture
            TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,  // Disable interrupt
            TIMER_A_OUTPUTMODE_TOGGLE_RESET            // Output bit value
    };
    
    /* DMA Control Table */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN(MSP_EXP432P401RLP_DMAControlTable, 1024)
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment=1024
    #elif defined(__GNUC__)
    __attribute__ ((aligned (1024)))
    #elif defined(__CC_ARM)
    __align(1024)
    #endif
    static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[16];
    
    uint16_t averagePeriod;
    uint16_t period[NUMBER_TIMER_CAPTURES/2];
    uint16_t timerAcaptureValuesPrimary[NUMBER_TIMER_CAPTURES];
    uint16_t timerAcaptureValuesAlternate[NUMBER_TIMER_CAPTURES];
    bool complete;
    
    int main(void)
    {
        uint16_t ii;
        /* Stop watchdog timer */
        MAP_WDT_A_holdTimer();
        MAP_Interrupt_disableSleepOnIsrExit();
    
        /* Configuring P1.0 as output */
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
    
        MAP_GPIO_setAsInputPin(GPIO_PORT_P2, GPIO_PIN5);
        /* Configuring P2.5 as peripheral input for capture*/
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN5,
                GPIO_PRIMARY_MODULE_FUNCTION);
    
        /*
         * Revision C silicon supports wait states of 1 at 48Mhz
         */
        MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
        MAP_FlashCtl_setWaitState(FLASH_BANK0, 1);
        MAP_FlashCtl_setWaitState(FLASH_BANK1, 1);
    
        /*
         * Setting up clocks
         * MCLK = MCLK = 48MHz
         * SMCLK = MCLK/2 = 24Mhz
         * ACLK = REFO = 32Khz
         */
        MAP_CS_setDCOFrequency(48000000);
        MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
        MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_2);
        MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    
        /* Configuring Capture Mode */
        MAP_Timer_A_initCapture(TIMER_A0_BASE, &captureModeConfig);
    
        /* Configuring Continuous Mode */
        MAP_Timer_A_configureContinuousMode(TIMER_A0_BASE, &continuousModeConfig);
    
        /* Configuring DMA module */
        MAP_DMA_enableModule();
        MAP_DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable);
    
        /*
         * Setup the DMA + ADC14 interface
         */
        MAP_DMA_disableChannelAttribute(DMA_CH1_RESERVED0,
                                     UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
                                     UDMA_ATTR_HIGH_PRIORITY |
                                     UDMA_ATTR_REQMASK);
        /*
         * Setting Control Indexes. In this case we will set the source of the
         * DMA transfer to ADC14 Memory 0 and the destination to the destination
         * data array.
         */
        MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH1_RESERVED0,
                UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
        MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH1_RESERVED0,
                UDMA_MODE_BASIC, (void*)&TIMER_A0->CCR[2],
                (void*)timerAcaptureValuesPrimary, NUMBER_TIMER_CAPTURES);
    
        /* Assigning/Enabling Interrupts */
        MAP_DMA_assignInterrupt(DMA_INT1, 1);
        MAP_DMA_assignChannel(DMA_CH1_RESERVED0);
        MAP_DMA_clearInterruptFlag(1);
        MAP_DMA_enableChannel(1);
    
        complete = false;
    
        /* Enabling Interrupts */
        MAP_Interrupt_enableInterrupt(INT_DMA_INT1);
        MAP_Interrupt_enableInterrupt(INT_TA0_N);
        MAP_Interrupt_enableMaster();
    
        /* Starting the Timer_A0 in continuous mode */
        MAP_Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_CONTINUOUS_MODE);
    
        while(1)
        {
            MAP_PCM_gotoLPM0();
            __no_operation();
            /*
             * Calculate frequency
             */
            if(complete)
            {
                MAP_Interrupt_disableMaster();
                for(ii=0;ii<NUMBER_TIMER_CAPTURES/2;ii++)
                {
                    period[ii] = timerAcaptureValuesPrimary[2*ii+1] - timerAcaptureValuesPrimary[2*ii];
                    averagePeriod += period[ii];
                }
                averagePeriod = averagePeriod/(NUMBER_TIMER_CAPTURES/2);
                __no_operation(); // output to ide - breakpoint properties, update view
    
                MAP_DMA_disableChannel(1);
                MSP_EXP432P401RLP_DMAControlTable[1].control =
                        (MSP_EXP432P401RLP_DMAControlTable[1].control & 0xff000000 ) |
                        (((NUMBER_TIMER_CAPTURES)-1)<<4) | UDMA_MODE_BASIC;
                MAP_DMA_enableChannel(1);
                complete = false;
                MAP_Interrupt_enableMaster();
            }
        }
    }
    
    //******************************************************************************
    //
    //This is the TIMERA interrupt vector service routine.
    //
    //******************************************************************************
    void TA0_N_IRQHandler(void)
    {
        if(TIMER_A0->IV == 0x0004)
        {
            //MAP_DMA_requestSoftwareTransfer(1);
            BITBAND_PERI(DMA_Channel->SW_CHTRIG, DMA_SW_CHTRIG_CH1_OFS) = 1;
        }
    
    }
    
    void DMA_INT1_IRQHandler(void)
    {
    
        BITBAND_PERI(P1->OUT, 0) = 1;
        complete = true;
        BITBAND_PERI(P1->OUT, 0) = 0;
    }
    

    Lawrence,

       Please find the attached examples.

    Chris

  • Thanks I will take a look at it.

    Regards,

    Lawrence

**Attention** This is a public forum