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.

MSP432P401R: ADC14 Multiple Conversion Triggered by Timer_A (Can't get the ISR to trigger....)

Part Number: MSP432P401R

Hi All,

I thought I had this working, but today, I can't get a multi channel conversion to actually interrupt, with TimerA.  What am I forgetting, or not understanding?

Thanks in advance for any ideas!

Rob

Here is the header file:

/*
 * adc14.h
 *
 *  Created on: May 2, 2017
 *      Author: frohro
 */

#ifndef ADC14_MULTI_H_
#define ADC14_MULTI_H_
//#include <ti/sysbios/family/arm/m3/Hwi.h>
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

/* Standard Includes */
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>

#define SMCLK_FREQUENCY     48000000

#define SAMPLE_FREQUENCY    8000
#define SAMPLE_LENGTH       128

//void ADC14_IRQHandler(void);
/* Timer_A Continuous Mode Configuration Parameter */
const Timer_A_UpModeConfig upModeConfig =
{
 TIMER_A_CLOCKSOURCE_SMCLK,           // SMCLK Clock Source
 TIMER_A_CLOCKSOURCE_DIVIDER_1,       // SMCLK/1 = 48MHz
 (SMCLK_FREQUENCY/SAMPLE_FREQUENCY)/4,  // Number of counts
 // (The /4 because SMCLK is divided by 4 in Energia setup needed for Serial class)
 TIMER_A_TAIE_INTERRUPT_DISABLE,      // Disable Timer ISR
 TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE, // Disable CCR0
 TIMER_A_DO_CLEAR                     // Clear Counter
};

/* Timer_A Compare Configuration Parameter */
const Timer_A_CompareModeConfig compareConfig =
{
 TIMER_A_CAPTURECOMPARE_REGISTER_1,          // Use CCR1
 TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE,   // Disable CCR interrupt
 TIMER_A_OUTPUTMODE_SET_RESET,               // Toggle output bit
 (SMCLK_FREQUENCY/SAMPLE_FREQUENCY)
};


static uint16_t resultsBuffer[8];
extern uint16_t refRe[SAMPLE_LENGTH];
extern uint16_t refIm[SAMPLE_LENGTH];
extern uint16_t measRe[SAMPLE_LENGTH];
extern uint16_t measIm[SAMPLE_LENGTH];


int adc14_main(void);
void startSampling(void);

#endif /* ADC14VNA_H_ */

and here is the main program:

/*
 * -------------------------------------------
 *    MSP432 DriverLib - v4_00_00_11
 * -------------------------------------------
 *
 * --COPYRIGHT--,BSD,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 ADC14 - Multiple Channel Sample without Repeat
 *
 * Description: In this code example, the feature of being able to scan multiple
 * ADC channels is demonstrated by the user a the DriverLib APIs.  Conversion
 * memory registers ADC_MEM0 - ADC_MEM3 are configured to read conversion
 * results from A6, A12, A10, A8 respectively. Conversion is enabled and then sampling is
 * toggled using a software toggle. Repeat mode is not enabled and sampling only
 * occurs once (and it is expected that the user pauses the debugger to observe
 * the results). Once the final sample has been taken, the interrupt for
 * ADC_MEM3 is triggered and the result is stored in the resultsBuffer buffer.
 *
 *                MSP432P401
 *             ------------------
 *         /|\|                  |
 *          | |                  |
 *          --|RST         P4.7  |<--- A6 (Analog Input, Measured, Real)
 *            |            P4.1  |<--- A12 (Analog Input, Measured, Imaginary)
 *            |            P4.3  |<--- A10 (Analog Input, Reference Real)
 *            |            P4.5  |<--- A8 (Analog Input, Reference Imaginary)
 *            |                  |
 *            |                  |
 *
 *            4.1, 4.3, 4.5, 4.7 are the eventual pins needed.
 *
 * Author: Timothy Logan
 * This was modified by Rob Frohne to do multiple ADC at 8 kHz sample rate.
 ******************************************************************************/
#include "adc14_multi.h"

uint16_t refRe[SAMPLE_LENGTH];
uint16_t refIm[SAMPLE_LENGTH];
uint16_t measRe[SAMPLE_LENGTH];
uint16_t measIm[SAMPLE_LENGTH];
extern bool doneADC;
bool sendMeasurement = false;
int numberFrequenciestoMeasure, frequencyIndex;
float  refSum, measSum;
bool doneADC = false;

int main(void)
{
    int i;
    // Halting WDT
    WDT_A_holdTimer();
    Interrupt_enableSleepOnIsrExit();
    //Hwi_Params params;

    // Register interrupt (sets up IRQ vectors)
    //Hwi_Params_init(&params);
    //Hwi_create(INT_ADC14, ADC14_IRQHandler, &params, 0);

    // Configuring debugging pins as output for debugging...
    //MAP_GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN1);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);


    // Set to Vcore1
    PCM_setCoreVoltageLevel(PCM_VCORE1);

    // Set to use DCDC
    PCM_setPowerState(PCM_AM_DCDC_VCORE1);

    // Initializes Clock System
    /*  These commented out because we need the Energia clock setup.  The
     *  data structures for the timer are adjusted accordingly.  The time
     *  between conversions may be four times as much as we had with these
     *  parameters below, but this seems like the easiest way to make everything
     *  play together for now. */
/*    CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48);
    CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );
    CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );
    CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );
    CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);*/



    //Zero-filling buffer
    memset(resultsBuffer, 0x00, 8);

    // Setting reference voltage to 2.5  and enabling reference
    REF_A_setReferenceVoltage(REF_A_VREF2_5V);
    REF_A_enableReferenceVoltage();

    //Initializing ADC (MCLK/1/1)
    ADC14_enableModule();
    ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0);

    //Configuring GPIOs for Analog In
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4,
        GPIO_PIN1 | GPIO_PIN3 | GPIO_PIN5 | GPIO_PIN7, GPIO_TERTIARY_MODULE_FUNCTION);


    // Configuring ADC Memory (ADC_MEM0 - ADC_MEM3 (A6, A12, A10, A8)  with no repeat)
    // with internal 2.5v reference
    ADC14_configureMultiSequenceMode(ADC_MEM0, ADC_MEM3, false); // No repeat mode.
    ADC14_configureConversionMemory(ADC_MEM0,
                                        ADC_VREFPOS_INTBUF_VREFNEG_VSS,
                                        ADC_INPUT_A6, ADC_NONDIFFERENTIAL_INPUTS);
    ADC14_configureConversionMemory(ADC_MEM1,
                                        ADC_VREFPOS_INTBUF_VREFNEG_VSS,
                                        ADC_INPUT_A12, ADC_NONDIFFERENTIAL_INPUTS);
    ADC14_configureConversionMemory(ADC_MEM2,
                                        ADC_VREFPOS_INTBUF_VREFNEG_VSS,
                                        ADC_INPUT_A10, ADC_NONDIFFERENTIAL_INPUTS);
    ADC14_configureConversionMemory(ADC_MEM3,
                                        ADC_VREFPOS_INTBUF_VREFNEG_VSS,
                                        ADC_INPUT_A8, ADC_NONDIFFERENTIAL_INPUTS);

    //  Enabling the interrupt when a conversion on channel 3 (end of sequence)
    //  is complete and enabling conversions (I assume this means memory not Analog channel.)
    ADC14_enableInterrupt(ADC_INT3);

    ADC14_setSampleHoldTime(ADC_PULSE_WIDTH_4, ADC_PULSE_WIDTH_4);

    // Configuring Timer_A in continuous mode as setup in upModeConfig above
    Timer_A_configureUpMode(TIMER_A0_BASE, &upModeConfig);

    // Configuring Timer_A0 in CCR1 to trigger as set in compareConfig above
    Timer_A_initCompare(TIMER_A0_BASE, &compareConfig);

    // Configuring the sample trigger to be sourced from Timer_A0  and setting it
    // to automatic iteration after it is triggered
    ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false);

    // Setting up the sample timer to automatically step through the sequence
    // convert.

    ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION);

    //MAP_ADC14_toggleConversionTrigger();

    // Enabling Interrupts
    Interrupt_enableInterrupt(INT_ADC14);
    Interrupt_enableMaster();

    // Starting the Timer
    Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UP_MODE);
    ADC14_enableConversion();

    for (i=0; i<SAMPLE_LENGTH; i++)
    {
        refRe[i] = 0;
        refIm[i] = 0;
        measRe[i] = 0;
        measIm[i] = 0;
    }
    doneADC = false;
    while(1)
    {
    }
    return 1;
}

/* This interrupt is fired whenever a conversion is completed and placed in
 * ADC_MEM3. This signals the end of conversion and the results array is
 * grabbed and placed in resultsBuffer */
void ADC14_IRQHandler(void)
{
    uint64_t status;
    static int i = 0;
    GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
    status = ADC14_getEnabledInterruptStatus();
    ADC14_clearInterruptFlag(status);

    if(status & ADC_INT3)
    {
        doneADC = false;
        ADC14_getMultiSequenceResult(resultsBuffer);
        measRe[i] = resultsBuffer[0];
        measIm[i] = resultsBuffer[1];
        refRe[i] = resultsBuffer[2];
        refIm[i] = resultsBuffer[3];
        //i=(i+1)%SAMPLE_LENGTH;
        ADC14_disableConversion();
        if (i!=SAMPLE_LENGTH)
        {
            i++;
            ADC14_enableConversion();
        }
        else
        {
            i=0;
            doneADC = true;
            ADC14_enableConversion();
        }
    }
}


  • Rob,

       I do not see anything obvious at first  glance, except both the Timer and the ADC are clocked above the maximum allowed frequency.  The ADC clock of MCLK is out of specification if the MCLK is greater than 25Mhz and the timer at 24Mhz.  I have attached an example that I will be using to compare with what you have done.

    Chris

    7776.adc14_multiple_channel_no_repeat_timera_source_01.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    /*
    * adc14_multiple_channel_no_repeat_timera_source_01.c
    *
    * Timer (2hz) Triggered sequence of conversions (ADC14 6,7,8),
    * where each conversion in the sequence is performed immediately
    * after the previous. After the last conversion in the sequence
    * the ADC14 waits for the timer trigger.
    * The ISR moves information from ADCMEM6-ADCMEME8 to three
    * seperate buffers buffer0[64], buffer1[64], buffer2[64]
    *
    */
    #include "driverlib.h"
    /* Standard Includes */
    #include <stdint.h>
    #include <string.h>
    #define NUMBER_OF_SAMPLES 64
    uint32_t prim_buffer0[NUMBER_OF_SAMPLES];
    uint32_t prim_buffer1[NUMBER_OF_SAMPLES];
    uint32_t prim_buffer2[NUMBER_OF_SAMPLES];
    /* Timer_A Continuous Mode Configuration Parameter */
    const Timer_A_UpModeConfig upModeConfig =
    {
    TIMER_A_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
    TIMER_A_CLOCKSOURCE_DIVIDER_8, // SMCLK/8 = 125khz
    62500, // 0.5 seconds -> 2Hz
    TIMER_A_TAIE_INTERRUPT_DISABLE, // Disable Timer ISR
    TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE, // Disable CCR0
    TIMER_A_DO_CLEAR // Clear Counter
    };
    /* Timer_A Compare Configuration Parameter */
    const Timer_A_CompareModeConfig compareConfig =
    {
    TIMER_A_CAPTURECOMPARE_REGISTER_1, // Use CCR1
    TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE, // Disable CCR interrupt
    TIMER_A_OUTPUTMODE_SET_RESET, // Toggle output but
    62500 //
    };
    uint16_t measureIndex;
    int main(void)
    {
    /* Halting WDT */
    MAP_WDT_A_holdTimer();
    MAP_Interrupt_disableMaster();
    // MAP_Interrupt_enableSleepOnIsrExit();
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Pos;
    /* Zero-filling buffer */
    memset(prim_buffer0,0x0000,NUMBER_OF_SAMPLES);
    memset(prim_buffer1,0x0000,NUMBER_OF_SAMPLES);
    memset(prim_buffer2,0x0000,NUMBER_OF_SAMPLES);
    measureIndex = 0;
    /*
    * Configure DCO for 8Mhz operation
    */
    /* Enabling FPU for DCO Frequency calculation */
    MAP_FPU_enableModule();
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Thanks Chris! You are correct. I am trying to use the Energia serial port stuff in a .ino file, while using this for the ADC14. Energia sets the clock up differently than I had the ADC14, and in changing that to be what I thought was compatible with Energia's Serial routines, I broke the ADC14 routine. I really want to change from one channel to the next in the minimum time if possible, so the measurements are as near to simultaneous as I can get. I need to research this more. Thanks for the pointer!

    Rob

**Attention** This is a public forum