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.

MSP430FR2355: reading multiple ADC channels

Part Number: MSP430FR2355


Hi im trying to debug my code to read 8 channels of ADC. seems i read the same channel every interrupt call...

attached is the code. can you help please?!

btw, im using the driverlib library.

#include <stdio.h>
#include "driverlib.h"
#include <board.h>
/**
 * hello.c
 */

#define TIMER_PERIOD 5      //  timer clock is 50kHz, 5 means 100uS clock cycle.
void Configure_Clocks(void);
void Configure_ADC(void);
void Configure_Timer(void);
void Configure_GPIOs(void);
uint32_t clockValue = 0;
unsigned int ADC_Result[8];                                    // 12-bit ADC conversion result array
unsigned char i = 7;
int main(void)
{

    WDT_A_hold(WDT_A_BASE);   // stop watchdog timer
    Configure_Clocks();
    Configure_ADC();
    Configure_Timer();
    Configure_GPIOs();
    //printf("Hello World!\n");
    //Disable the GPIO power-on default high-impedance mode to activate
    //previously configured port settings
    PMM_unlockLPM5();
    __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0, enable interrupts
    return 0;
}
void Configure_ADC(void)
{
    ADC_init(ADC_BASE, ADC_SAMPLEHOLDSOURCE_SC, ADC_CLOCKSOURCE_SMCLK,ADC_CLOCKDIVIDER_1);
    ADC_enable(ADC_BASE);
    ADC_setupSamplingTimer(ADC_BASE, ADC_CYCLEHOLD_16_CYCLES,ADC_MULTIPLESAMPLESENABLE);
    ADC_configureMemory(ADC_BASE, ADC_INPUT_A0, ADC_VREFPOS_INT,ADC_VREFNEG_AVSS);
    ADC_clearInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT);
    ADC_enableInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT);
    PMM_enableInternalReference();
    //while (PMM_REFGEN_NOTREADY == PMM_getVariableReferenceVoltageStatus());
}
void Configure_Clocks(void)
{
    CS_initClockSignal(CS_FLLREF,CS_REFOCLK_SELECT,CS_CLOCK_DIVIDER_1);     //  Set DCO FLL reference = REFO
    CS_initClockSignal(CS_MCLK,CS_DCOCLKDIV_SELECT,CS_CLOCK_DIVIDER_1);     //  Set MCLK sourced from DCOCLKDIV
    CS_initClockSignal(CS_SMCLK, CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_8);  //  Set SMCLK = MCLK/8
    CS_initClockSignal(CS_ACLK,CS_REFOCLK_SELECT,CS_CLOCK_DIVIDER_1);       //  Set ACLK = REFO ~= 32.85kHz
    CS_initFLLParam param = {0};                                            //  Create struct variable to store proper software trim values
    CS_initFLLCalculateTrim(16000,487,&param);                              //  Set Ratio/Desired MCLK Frequency, initialize DCO, save trim values
    CS_initFLLSettle(16000,487);                                            //  For demonstration purpose, change DCO clock freq to 16MHz
    CS_initFLLLoadTrim(16000,487,&param);                                   //  Reload DCO trim values that were calculated earlier
    clockValue = CS_getSMCLK();
    clockValue = CS_getMCLK();
    clockValue = CS_getACLK();
}
void Configure_Timer(void)
{
    //Start timer
    Timer_B_clearTimerInterrupt(TIMER_B0_BASE);
    Timer_B_initUpModeParam param = {0};
    param.clockSource = TIMER_B_CLOCKSOURCE_SMCLK;
    param.clockSourceDivider |= TIMER_B_CLOCKSOURCE_DIVIDER_40;
    param.timerPeriod = TIMER_PERIOD;
    param.timerInterruptEnable_TBIE |= TIMER_B_TBIE_INTERRUPT_DISABLE;
    param.captureCompareInterruptEnable_CCR0_CCIE |= TIMER_B_CAPTURECOMPARE_INTERRUPT_ENABLE;
    param.timerClear |= TIMER_B_DO_CLEAR;
    param.startTimer |= true;
    Timer_B_initUpMode(TIMER_B0_BASE, &param);
}

void Configure_GPIOs(void)
{
    GPIO_setAsInputPin(PS2_PG_PORT, PS2_PG_PIN);
    GPIO_setAsInputPin(PS3_PG_PORT, PS3_PG_PIN);
    GPIO_setAsInputPin(PS5_PG_PORT, PS5_PG_PIN);
    GPIO_setAsInputPin(PS7_PG_PORT, PS7_PG_PIN);
    GPIO_setAsInputPin(PS8_PG_PORT, PS8_PG_PIN);
    GPIO_setAsInputPin(PS9_PG_PORT, PS9_PG_PIN);
    GPIO_setAsInputPin(PS10_PG_PORT, PS10_PG_PIN);
    GPIO_setAsInputPin(PS11_PG_PORT, PS11_PG_PIN);
    GPIO_setAsInputPin(PS20_PG_PORT, PS20_PG_PIN);
    GPIO_setAsInputPin(PS21_PG_PORT, PS21_PG_PIN);
    GPIO_setAsInputPin(MNL_CONF_PORT, MNL_CONF_PIN);
    GPIO_setAsInputPin(SD_REQUEST_PORT, SD_REQUEST_PIN);
    GPIO_setAsInputPin(PLL_LOCKED_PORT, PLL_LOCKED_PIN);
    GPIO_setAsOutputPin(PS2_RUN_PORT, PS2_RUN_PIN);
    GPIO_setAsOutputPin(PS3_RUN_PORT, PS3_RUN_PIN);
    GPIO_setAsOutputPin(PS7_RUN_PORT, PS7_RUN_PIN);
    GPIO_setAsOutputPin(PS8_RUN_PORT, PS8_RUN_PIN);
    GPIO_setAsOutputPin(PS9_RUN_PORT, PS9_RUN_PIN);
    GPIO_setAsOutputPin(PS10_RUN_PORT, PS10_RUN_PIN);
    GPIO_setAsOutputPin(PS11_RUN_PORT, PS11_RUN_PIN);
    GPIO_setAsOutputPin(PS20_RUN_PORT, PS20_RUN_PIN);
    GPIO_setAsOutputPin(PS21_RUN_PORT, PS21_RUN_PIN);
    GPIO_setAsOutputPin(PLL_HW_SW_CTRL_PORT, PLL_HW_SW_CTRL_PIN);
    GPIO_setAsOutputPin(PS_PORB_PORT, PS_PORB_PIN);
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, MAIN_I2C_SDA_PIN + MAIN_I2C_SCL_PIN,GPIO_PRIMARY_MODULE_FUNCTION);
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, PLL_I2C_SDA_PIN + PLL_I2C_SCL_PIN, GPIO_PRIMARY_MODULE_FUNCTION);
    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC0, MSP_PIN_ADC0,GPIO_TERNARY_MODULE_FUNCTION);
    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC1, MSP_PIN_ADC1,GPIO_TERNARY_MODULE_FUNCTION);
    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC2, MSP_PIN_ADC2,GPIO_TERNARY_MODULE_FUNCTION);
    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC3, MSP_PIN_ADC3, GPIO_TERNARY_MODULE_FUNCTION);
    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC4, MSP_PIN_ADC4,GPIO_TERNARY_MODULE_FUNCTION);
    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC5, MSP_PIN_ADC5, GPIO_TERNARY_MODULE_FUNCTION);
    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC6, MSP_PIN_ADC6,GPIO_TERNARY_MODULE_FUNCTION);
    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC7, MSP_PIN_ADC7, GPIO_TERNARY_MODULE_FUNCTION);
}

//******************************************************************************
//
//This is the Timer B0 interrupt vector service routine.
//
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=TIMERB0_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(TIMERB0_VECTOR)))
#endif
void TIMERB0_ISR(void)
{
    ADC_startConversion(ADC_BASE,ADC_SEQOFCHANNELS);
}
//******************************************************************************
//
//ADC interrupt service routine
//
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(ADC_VECTOR)))
#endif
void ADC_ISR (void)
{
    switch (__even_in_range(ADCIV,12)){
        case  0: break; //No interrupt
        case  2: break; //conversion result overflow
        case  4: break; //conversion time overflow
        case  6: break; //ADCHI
        case  8: break; //ADCLO
        case 10: break; //ADCIN
        case 12:        //ADCIFG0
            //Automatically clears ADCIFG0 by reading memory buffer
            ADC_Result[i] = ADCMEM0;
            if(i == 0)  i = 7;
            else    i--;
            break;
        default: break;
    }
}

#include <stdio.h>#include "driverlib.h"#include <board.h>/** * hello.c */
#define TIMER_PERIOD 5      //  timer clock is 50kHz, 5 means 100uS clock cycle.void Configure_Clocks(void);void Configure_ADC(void);void Configure_Timer(void);void Configure_GPIOs(void);uint32_t clockValue = 0;unsigned int ADC_Result[8];                                    // 12-bit ADC conversion result arrayunsigned char i = 7;int main(void){
    WDT_A_hold(WDT_A_BASE);   // stop watchdog timer    Configure_Clocks();    Configure_ADC();    Configure_Timer();    Configure_GPIOs();    //printf("Hello World!\n");    //Disable the GPIO power-on default high-impedance mode to activate    //previously configured port settings    PMM_unlockLPM5();    __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0, enable interrupts    return 0;}void Configure_ADC(void){    ADC_init(ADC_BASE, ADC_SAMPLEHOLDSOURCE_SC, ADC_CLOCKSOURCE_SMCLK,ADC_CLOCKDIVIDER_1);    ADC_enable(ADC_BASE);    ADC_setupSamplingTimer(ADC_BASE, ADC_CYCLEHOLD_16_CYCLES,ADC_MULTIPLESAMPLESENABLE);    ADC_configureMemory(ADC_BASE, ADC_INPUT_A0, ADC_VREFPOS_INT,ADC_VREFNEG_AVSS);    ADC_clearInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT);    ADC_enableInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT);    PMM_enableInternalReference();    //while (PMM_REFGEN_NOTREADY == PMM_getVariableReferenceVoltageStatus());}void Configure_Clocks(void){    CS_initClockSignal(CS_FLLREF,CS_REFOCLK_SELECT,CS_CLOCK_DIVIDER_1);     //  Set DCO FLL reference = REFO    CS_initClockSignal(CS_MCLK,CS_DCOCLKDIV_SELECT,CS_CLOCK_DIVIDER_1);     //  Set MCLK sourced from DCOCLKDIV    CS_initClockSignal(CS_SMCLK, CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_8);  //  Set SMCLK = MCLK/8    CS_initClockSignal(CS_ACLK,CS_REFOCLK_SELECT,CS_CLOCK_DIVIDER_1);       //  Set ACLK = REFO ~= 32.85kHz    CS_initFLLParam param = {0};                                            //  Create struct variable to store proper software trim values    CS_initFLLCalculateTrim(16000,487,&param);                              //  Set Ratio/Desired MCLK Frequency, initialize DCO, save trim values    CS_initFLLSettle(16000,487);                                            //  For demonstration purpose, change DCO clock freq to 16MHz    CS_initFLLLoadTrim(16000,487,&param);                                   //  Reload DCO trim values that were calculated earlier    clockValue = CS_getSMCLK();    clockValue = CS_getMCLK();    clockValue = CS_getACLK();}void Configure_Timer(void){    //Start timer    Timer_B_clearTimerInterrupt(TIMER_B0_BASE);    Timer_B_initUpModeParam param = {0};    param.clockSource = TIMER_B_CLOCKSOURCE_SMCLK;    param.clockSourceDivider |= TIMER_B_CLOCKSOURCE_DIVIDER_40;    param.timerPeriod = TIMER_PERIOD;    param.timerInterruptEnable_TBIE |= TIMER_B_TBIE_INTERRUPT_DISABLE;    param.captureCompareInterruptEnable_CCR0_CCIE |= TIMER_B_CAPTURECOMPARE_INTERRUPT_ENABLE;    param.timerClear |= TIMER_B_DO_CLEAR;    param.startTimer |= true;    Timer_B_initUpMode(TIMER_B0_BASE, &param);}
void Configure_GPIOs(void){    GPIO_setAsInputPin(PS2_PG_PORT, PS2_PG_PIN);    GPIO_setAsInputPin(PS3_PG_PORT, PS3_PG_PIN);    GPIO_setAsInputPin(PS5_PG_PORT, PS5_PG_PIN);    GPIO_setAsInputPin(PS7_PG_PORT, PS7_PG_PIN);    GPIO_setAsInputPin(PS8_PG_PORT, PS8_PG_PIN);    GPIO_setAsInputPin(PS9_PG_PORT, PS9_PG_PIN);    GPIO_setAsInputPin(PS10_PG_PORT, PS10_PG_PIN);    GPIO_setAsInputPin(PS11_PG_PORT, PS11_PG_PIN);    GPIO_setAsInputPin(PS20_PG_PORT, PS20_PG_PIN);    GPIO_setAsInputPin(PS21_PG_PORT, PS21_PG_PIN);    GPIO_setAsInputPin(MNL_CONF_PORT, MNL_CONF_PIN);    GPIO_setAsInputPin(SD_REQUEST_PORT, SD_REQUEST_PIN);    GPIO_setAsInputPin(PLL_LOCKED_PORT, PLL_LOCKED_PIN);    GPIO_setAsOutputPin(PS2_RUN_PORT, PS2_RUN_PIN);    GPIO_setAsOutputPin(PS3_RUN_PORT, PS3_RUN_PIN);    GPIO_setAsOutputPin(PS7_RUN_PORT, PS7_RUN_PIN);    GPIO_setAsOutputPin(PS8_RUN_PORT, PS8_RUN_PIN);    GPIO_setAsOutputPin(PS9_RUN_PORT, PS9_RUN_PIN);    GPIO_setAsOutputPin(PS10_RUN_PORT, PS10_RUN_PIN);    GPIO_setAsOutputPin(PS11_RUN_PORT, PS11_RUN_PIN);    GPIO_setAsOutputPin(PS20_RUN_PORT, PS20_RUN_PIN);    GPIO_setAsOutputPin(PS21_RUN_PORT, PS21_RUN_PIN);    GPIO_setAsOutputPin(PLL_HW_SW_CTRL_PORT, PLL_HW_SW_CTRL_PIN);    GPIO_setAsOutputPin(PS_PORB_PORT, PS_PORB_PIN);    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, MAIN_I2C_SDA_PIN + MAIN_I2C_SCL_PIN,GPIO_PRIMARY_MODULE_FUNCTION);    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, PLL_I2C_SDA_PIN + PLL_I2C_SCL_PIN, GPIO_PRIMARY_MODULE_FUNCTION);    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC0, MSP_PIN_ADC0,GPIO_TERNARY_MODULE_FUNCTION);    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC1, MSP_PIN_ADC1,GPIO_TERNARY_MODULE_FUNCTION);    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC2, MSP_PIN_ADC2,GPIO_TERNARY_MODULE_FUNCTION);    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC3, MSP_PIN_ADC3, GPIO_TERNARY_MODULE_FUNCTION);    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC4, MSP_PIN_ADC4,GPIO_TERNARY_MODULE_FUNCTION);    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC5, MSP_PIN_ADC5, GPIO_TERNARY_MODULE_FUNCTION);    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC6, MSP_PIN_ADC6,GPIO_TERNARY_MODULE_FUNCTION);    GPIO_setAsPeripheralModuleFunctionInputPin(MSP_PORT_ADC7, MSP_PIN_ADC7, GPIO_TERNARY_MODULE_FUNCTION);}
//******************************************************************************////This is the Timer B0 interrupt vector service routine.////******************************************************************************#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)#pragma vector=TIMERB0_VECTOR__interrupt#elif defined(__GNUC__)__attribute__((interrupt(TIMERB0_VECTOR)))#endifvoid TIMERB0_ISR(void){    ADC_startConversion(ADC_BASE,ADC_SEQOFCHANNELS);}//******************************************************************************////ADC interrupt service routine////******************************************************************************#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)#pragma vector=ADC_VECTOR__interrupt#elif defined(__GNUC__)__attribute__((interrupt(ADC_VECTOR)))#endifvoid ADC_ISR (void){    switch (__even_in_range(ADCIV,12)){        case  0: break; //No interrupt        case  2: break; //conversion result overflow        case  4: break; //conversion time overflow        case  6: break; //ADCHI        case  8: break; //ADCLO        case 10: break; //ADCIN        case 12:        //ADCIFG0            //Automatically clears ADCIFG0 by reading memory buffer            ADC_Result[i] = ADCMEM0;            if(i == 0)  i = 7;            else    i--;            break;        default: break;    }}

  •     ADC_configureMemory(ADC_BASE, ADC_INPUT_A0, ADC_VREFPOS_INT,ADC_VREFNEG_AVSS);

    The FR2 series ADC counts down from ADCINCH to A0, so this counts from A0->A0, i.e. only one channel. Try:

    >    ADC_configureMemory(ADC_BASE, ADC_INPUT_A7, ADC_VREFPOS_INT,ADC_VREFNEG_AVSS);

    Unsolicited: Using CONSEQ=1 (sequence of channels) with a fast clock (SMCLK), you won't have time to fetch the result from one channel before the next conversion completes. You might succeed by using ADC_CLOCKSOURCE_ACLK instead.

**Attention** This is a public forum