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.
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(¶ms); //Hwi_create(INT_ADC14, ADC14_IRQHandler, ¶ms, 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
/* * 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(); /* Setting the DCO Frequency to a 8MHz */ MAP_CS_setDCOFrequency(8000000); /* * Setting up clocks * SMCLK = DCO/8 = 1MHz */ MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_8); /* Setting reference voltage to 2.5 and enabling reference */ MAP_REF_A_setReferenceVoltage(REF_A_VREF2_5V); MAP_REF_A_enableReferenceVoltage(); /* Initializing ADC (MCLK/1/1) */ MAP_ADC14_enableModule(); MAP_ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0); /* Configuring GPIOs for Analog In P4.5,4.6,4.7 */ MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7, GPIO_TERTIARY_MODULE_FUNCTION); /* Configuring P1.0 as output */ MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0); /* Configuring ADC Memory (ADC_MEM6 - ADC_MEM8 (A6 - A8) without repeat) * with internal 2.5v reference */ MAP_ADC14_configureMultiSequenceMode(ADC_MEM6, ADC_MEM8, false); MAP_ADC14_configureConversionMemory(ADC_MEM6, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A6, false); MAP_ADC14_configureConversionMemory(ADC_MEM7, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A7, false); MAP_ADC14_configureConversionMemory(ADC_MEM8, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A8, false); /* Configuring Timer_A in continuous mode and sourced from SMCLK */ MAP_Timer_A_configureUpMode(TIMER_A0_BASE, &upModeConfig); /* Configuring Timer_A0 in CCR1 to trigger at 0.5sec */ MAP_Timer_A_initCompare(TIMER_A0_BASE, &compareConfig); /* * Configuring the sample trigger to be sourced from Timer_A0 CCR1 * and setting it to automatic iteration after it is triggered */ MAP_ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false); /* * Setting up the sample timer to automatically step through the sequence * convert. */ MAP_ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION); /* * Enabling the interrupt when a conversion on channel 8 * and enabling conversions */ MAP_ADC14_enableInterrupt(ADC_INT8); MAP_ADC14_enableConversion(); /* * Clear IFGs before enabling interrupt */ MAP_ADC14_clearInterruptFlag(0xFFFFFFFFFFFFFFFF); MAP_Interrupt_enableInterrupt(INT_ADC14); MAP_Interrupt_enableMaster(); /* Starting the Timer */ MAP_Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UP_MODE); MAP_PCM_gotoLPM0(); __no_operation(); while(1); /* * Process three arrays */ } /* * This interrupt is fired whenever the sequence is completed * */ void ADC14_IRQHandler(void) { uint64_t status; // Turn on LED MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0); status = ADC14_getEnabledInterruptStatus(); MAP_ADC14_clearInterruptFlag(status); if(status & ADC_INT8) { MAP_ADC14_disableConversion(); prim_buffer0[measureIndex] = MAP_ADC14_getResult(ADC_MEM6); // Move A0 results, IFG is cleared prim_buffer1[measureIndex] = MAP_ADC14_getResult(ADC_MEM7); // Move A1 results, IFG is cleared prim_buffer2[measureIndex] = MAP_ADC14_getResult(ADC_MEM8); // Move A2 results, IFG is cleared // MAP_DMA_requestSoftwareTransfer(0); measureIndex++; __no_operation(); if(measureIndex == NUMBER_OF_SAMPLES) { /* * Stop Timer */ MAP_Timer_A_stopTimer(TIMER_A0_BASE); measureIndex = 0; //MAP_Interrupt_disableSleepOnIsrExit(); SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Pos; MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0); } else { MAP_ADC14_enableConversion(); } } }
**Attention** This is a public forum