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.

CCS/MSP430FR5994: Two modules need to us ADC, a conflict happens

Part Number: MSP430FR5994
Other Parts Discussed in Thread: BOOSTXL-AUDIO

Tool/software: Code Composer Studio

Hi,

I am using the MSP430FR5994 launch pad which needs to (1) detect the supply(the capacitor) voltage, and (2) sample audio signal through an audio sensor. Both of them need to use ADC12_B_BASE. I finished the code for them individually and they both work well but once combined together, the one that is executed later does not work well. 

I wrote the code for (1)detect the supply voltage based on the OutOfBox_MSP430FR5994, in which there is a FRAMLogMode.c file that has functions detecting and logging the battery voltage into FRAM. This is exactly what I need for (1). My system is powered by a capacitor and I need periodically check the capacitor voltage. 

I wrote the code for (2)sample the audio signal based on the BOOSTXL-AUDIO_RecordPlayback_MSP430FR5994. It has a file called audio_collect.c which uses DMA and ADC to sample the audio signal. The ADC is triggered by A0 internally.

In my final project, if I call(1) and then call (2), (1) works well but (2) does not work. (2) gets stuck in the LPM3. My understanding of how (2) works is like this: A0 triggers the ADC internally and ADC performs a sampling action after triggered. When ADC finishes one sampling, DMA directly read the data and save it into FRAM. I used a checkpoint in the DMA interrupt when debugging, the DMA interrupt is not called at all. So, I wonder if the ADC is not triggered by the timer properly.

If I call (2) and then call (1), (2) works well but (1) gets stuck in the LPM3 waiting for the ADC conversion to complete.

I wonder if there is some initialization needed before I call them each time because they both do some setting for ADC12_B_BASE and works well when executed first. The one executed later might be affected by the setting of the first one so it does not work well. But I checked the driverlib, there is no function which clear all the setting of ADC. Any suggestions?

Thanks,

Yubo

This is the initialization code of (1)

void framLog(){

    //Initialize the ADC12B Module
    /*
     * Base address of ADC12B Module
     * Use internal ADC12B bit as sample/hold signal to start conversion
     * USE MODOSC 5MHZ Digital Oscillator as clock source
     * Use default clock divider/pre-divider of 1
     * Use Temperature Sensor and Battery Monitor internal channels
     */
    ADC12_B_initParam initParam = {0};
    initParam.sampleHoldSignalSourceSelect = ADC12_B_SAMPLEHOLDSOURCE_SC;
    initParam.clockSourceSelect = ADC12_B_CLOCKSOURCE_ACLK;
    initParam.clockSourceDivider = ADC12_B_CLOCKDIVIDER_1;
    initParam.clockSourcePredivider = ADC12_B_CLOCKPREDIVIDER__1;
    initParam.internalChannelMap = ADC12_B_TEMPSENSEMAP | ADC12_B_BATTMAP;
    ADC12_B_init(ADC12_B_BASE, &initParam);

    //Enable the ADC12B module
    ADC12_B_enable(ADC12_B_BASE);

    // Sets up the sampling timer pulse mode
    ADC12_B_setupSamplingTimer(ADC12_B_BASE,
                               ADC12_B_CYCLEHOLD_128_CYCLES,
                               ADC12_B_CYCLEHOLD_128_CYCLES,
                               ADC12_B_MULTIPLESAMPLESENABLE);


    // Maps Battery Monitor input channel to Memory 0 and select voltage references
    /*
     * Base address of the ADC12B Module
     * Configure memory buffer 0
     * Map input A1 to memory buffer 0
     * Vref+ = IntBuffer
     * Vref- = AVss
     * Memory buffer 0 is not the end of a sequence
     */
    ADC12_B_configureMemoryParam configureMemoryParam = {0};
    configureMemoryParam.memoryBufferControlIndex = ADC12_B_MEMORY_1;
    configureMemoryParam.inputSourceSelect = ADC12_B_INPUT_BATMAP;
    configureMemoryParam.refVoltageSourceSelect =
        ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS;
    configureMemoryParam.endOfSequence = ADC12_B_ENDOFSEQUENCE;
    configureMemoryParam.windowComparatorSelect =
        ADC12_B_WINDOW_COMPARATOR_DISABLE;
    configureMemoryParam.differentialModeSelect =
        ADC12_B_DIFFERENTIAL_MODE_DISABLE;
    ADC12_B_configureMemory(ADC12_B_BASE, &configureMemoryParam);


    // Clear memory buffer 0 interrupt
    ADC12_B_clearInterrupt(ADC12_B_BASE,
                           0,
                           ADC12_B_IFG1
                           );

    // Enable memory buffer 0 interrupt
    ADC12_B_enableInterrupt(ADC12_B_BASE,
                            ADC12_B_IE1,
                            0,
                            0);

    // Configure internal reference
    while(Ref_A_isRefGenBusy(REF_A_BASE));              // If ref generator busy, WAIT
    Ref_A_enableTempSensor(REF_A_BASE);
    Ref_A_setReferenceVoltage(REF_A_BASE, REF_A_VREF2_0V);
    Ref_A_enableReferenceVoltage(REF_A_BASE);

    //Enable/Start sampling and conversion
    /*
     * Base address of ADC12B Module
     * Start the conversion into memory buffer 0
     * Use the single-channel, single-conversion mode
     */
    ADC12_B_startConversion(ADC12_B_BASE,
                            ADC12_B_MEMORY_0,
                            ADC12_B_SEQOFCHANNELS);

    __bis_SR_register(LPM3_bits | GIE);   // Wait for conversion to complete
    __bic_SR_register(GIE);

    ADC12_B_disable(ADC12_B_BASE);

    voltageData = ADC12MEM1;
}

This is the initialization code of (2):

void Audio_setupCollect(Audio_configParams * audioConfig)
{
    Timer_A_initUpModeParam upConfig =
    {
        TIMER_A_CLOCKSOURCE_ACLK,
        TIMER_A_CLOCKSOURCE_DIVIDER_1,
        7,// (__SYSTEM_FREQUENCY_MHZ__ / audioConfig->sampleRate) - 1,
        TIMER_A_TAIE_INTERRUPT_DISABLE,
        TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE,
        TIMER_A_DO_CLEAR,
        false
    };

    Timer_A_initCompareModeParam compareConfig =
    {
        TIMER_A_CAPTURECOMPARE_REGISTER_1,
        TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE,
        TIMER_A_OUTPUTMODE_TOGGLE_RESET,
        2,//((__SYSTEM_FREQUENCY_MHZ__ / audioConfig->sampleRate) / 2) - 1
    };

    // Turn on mic power full drive strength and enable mic input pin to ADC
    MIC_POWER_PORT_OUT |= MIC_POWER_PIN;
    MIC_POWER_PORT_DIR |= MIC_POWER_PIN;

    AUDIO_PORT_SEL0 |= MIC_INPUT_PIN;
    AUDIO_PORT_SEL1 |= MIC_INPUT_PIN;

    // For safety, protect RMW Cpu instructions
    DMA_disableTransferDuringReadModifyWrite();

    // Initialize the DMA. Using DMA channel 1.
    dma0Config.channelSelect = DMA_CHANNEL_1;
    dma0Config.transferModeSelect = DMA_TRANSFER_SINGLE;
    dma0Config.transferSize = SAMPLES_LENGTH;
    dma0Config.triggerSourceSelect = DMA_TRIGGERSOURCE_26;
    dma0Config.transferUnitSelect = DMA_SIZE_SRCWORD_DSTWORD;
    dma0Config.triggerTypeSelect = DMA_TRIGGER_RISINGEDGE;


    // Initialize the DMA. Using DMA channel 2.
    dma1Config.channelSelect = DMA_CHANNEL_2;
    dma1Config.transferModeSelect = DMA_TRANSFER_SINGLE;
    dma1Config.transferSize = SAMPLES_LENGTH;
    dma1Config.triggerSourceSelect = DMA_TRIGGERSOURCE_26;
    dma1Config.transferUnitSelect = DMA_SIZE_SRCWORD_DSTWORD;
    dma1Config.triggerTypeSelect = DMA_TRIGGER_RISINGEDGE;

	DMA_init(&dma0Config);
    DMA_init(&dma1Config);

    DMA_setSrcAddress(DMA_CHANNEL_1,
                      (uint32_t) &ADC12MEM0,
                      DMA_DIRECTION_UNCHANGED);

    DMA_setDstAddress(DMA_CHANNEL_1,
                      (uint32_t) (&dataRecorded1),
                      DMA_DIRECTION_INCREMENT);

    DMA_setSrcAddress(DMA_CHANNEL_2,
                      (uint32_t) &ADC12MEM0,
                      DMA_DIRECTION_UNCHANGED);

    DMA_setDstAddress(DMA_CHANNEL_2,
                      (uint32_t) (&dataRecorded2),
                      DMA_DIRECTION_INCREMENT);

    // Configure ADC
    ADC12CTL0 &= ~ADC12ENC;           // Disable conversions to configure ADC12
    // Turn on ADC, sample 32 clock cycles =~ 2us
    ADC12CTL0 = ADC12ON + ADC12SHT0_3;

    // Use sample timer, rpt single chan 0, use MODOSC, TA0 timer channel 1
    // ADC12SHP: SAMPCON signal is sourced from the sampling timer.
    // ADC12CONSEQ_2: Repeat-single-channel
    // ADC12SHS_1: see the device-specific data sheet for source
    //
    ADC12CTL1 = ADC12SHP + ADC12CONSEQ_2 + ADC12SHS_1;

    // Mic input to ADC, (AVCC/AVSS ref), sequence end bit set
    ADC12MCTL0 = MIC_INPUT_CHAN | ADC12EOS;

    // Initialize Timer_A channel 1 to be used as ADC12 trigger
    // Initialize TACCR0 (period register) 8MHz/20kHz = 400
    // Simple counter with no interrupt. 0...400 = 400 counts/sample
    Timer_A_initUpMode(TIMER_A0_BASE, &upConfig);

    // Initialize TA0CCR1 to generate trigger clock output, reset/set mode
    Timer_A_initCompareMode(TIMER_A0_BASE, &compareConfig);

    // Enable ADC to convert when a TA0 edge is generated
    ADC12CTL0 |= ADC12ENC;

    // Delay for the microphone to settle
    __delay_cycles(10000);
}

This is the DMA interrupt and ADC interrupt: 

//******************************************************************************
// DMA interrupt service routine
// every time when the ADC is ready, ADC will trigger the DMA which starts
// transferring data from ADC to memory
//******************************************************************************
#pragma vector=DMA_VECTOR
__interrupt void dmaIsrHandler(void)
{
    switch (__even_in_range(DMAIV, DMAIV_DMA2IFG))
    {
        case DMAIV_DMA0IFG: break;
        case DMAIV_DMA1IFG:
            // Disable the dma transfer
            DMA_disableTransfers(DMA_CHANNEL_1);
            // Disable DMA channel 1 interrupt
            DMA_disableInterrupt(DMA_CHANNEL_1);

            P1OUT &= ~BIT0;  // turn off LED

            //shutdown audio collect
            Audio_stopCollect();
            Audio_shutdownCollect();

            // Start Cpu on exit
            __bic_SR_register_on_exit(LPM3_bits);
            break;
        default: break;
   }
}



/* ADC12 Interrupt Service Routine*/
#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void)
{
  switch(__even_in_range(ADC12IV,76))
  {
    case  ADC12IV_NONE: break;                // Vector  0:  No interrupt
    case  ADC12IV_ADC12OVIFG: break;          // Vector  2:  ADC12MEMx Overflow
    case  ADC12IV_ADC12TOVIFG: break;         // Vector  4:  Conversion time overflow
    case  ADC12IV_ADC12HIIFG: break;          // Vector  6:  ADC12HI
    case  ADC12IV_ADC12LOIFG: break;          // Vector  8:  ADC12LO
    case ADC12IV_ADC12INIFG: break;           // Vector 10:  ADC12IN
    case ADC12IV_ADC12IFG0:  break;
    case ADC12IV_ADC12IFG1:                   // Vector 14:  ADC12MEM1
        ADC12IFGR0 &= ~ADC12IFG1;             // Clear interrupt flag
        __bic_SR_register_on_exit(LPM3_bits); // Exit active CPU
        break;
    case ADC12IV_ADC12IFG2: break;            // Vector 16:  ADC12MEM2
    case ADC12IV_ADC12IFG3: break;            // Vector 18:  ADC12MEM3
    case ADC12IV_ADC12IFG4: break;            // Vector 20:  ADC12MEM4
    case ADC12IV_ADC12IFG5: break;            // Vector 22:  ADC12MEM5
    case ADC12IV_ADC12IFG6: break;            // Vector 24:  ADC12MEM6
    case ADC12IV_ADC12IFG7: break;            // Vector 26:  ADC12MEM7
    case ADC12IV_ADC12IFG8: break;            // Vector 28:  ADC12MEM8
    case ADC12IV_ADC12IFG9: break;            // Vector 30:  ADC12MEM9
    case ADC12IV_ADC12IFG10: break;           // Vector 32:  ADC12MEM10
    case ADC12IV_ADC12IFG11: break;           // Vector 34:  ADC12MEM11
    case ADC12IV_ADC12IFG12: break;           // Vector 36:  ADC12MEM12
    case ADC12IV_ADC12IFG13: break;           // Vector 38:  ADC12MEM13
    case ADC12IV_ADC12IFG14: break;           // Vector 40:  ADC12MEM14
    case ADC12IV_ADC12IFG15: break;           // Vector 42:  ADC12MEM15
    case ADC12IV_ADC12IFG16: break;           // Vector 44:  ADC12MEM16
    case ADC12IV_ADC12IFG17: break;           // Vector 46:  ADC12MEM17
    case ADC12IV_ADC12IFG18: break;           // Vector 48:  ADC12MEM18
    case ADC12IV_ADC12IFG19: break;           // Vector 50:  ADC12MEM19
    case ADC12IV_ADC12IFG20: break;           // Vector 52:  ADC12MEM20
    case ADC12IV_ADC12IFG21: break;           // Vector 54:  ADC12MEM21
    case ADC12IV_ADC12IFG22: break;           // Vector 56:  ADC12MEM22
    case ADC12IV_ADC12IFG23: break;           // Vector 58:  ADC12MEM23
    case ADC12IV_ADC12IFG24: break;           // Vector 60:  ADC12MEM24
    case ADC12IV_ADC12IFG25: break;           // Vector 62:  ADC12MEM25
    case ADC12IV_ADC12IFG26: break;           // Vector 64:  ADC12MEM26
    case ADC12IV_ADC12IFG27: break;           // Vector 66:  ADC12MEM27
    case ADC12IV_ADC12IFG28: break;           // Vector 68:  ADC12MEM28
    case ADC12IV_ADC12IFG29: break;           // Vector 70:  ADC12MEM29
    case ADC12IV_ADC12IFG30: break;           // Vector 72:  ADC12MEM30
    case ADC12IV_ADC12IFG31: break;           // Vector 74:  ADC12MEM31
    case ADC12IV_ADC12RDYIFG: break;          // Vector 76:  ADC12RDY
    default: break;
  }
}

  • Oh, sorry. I copied the wrong code for This is the initialization code of (2). I copied it from the original example code. In my own project, I tailored it and only use one channel and one dataRecorded for DMA. But the ADC setting of my project is the same as the original example code. 

    Anyway, I put the right initialization code of (2) of my project here:

    void Audio_setupCollect(Audio_configParams * audioConfig)
    {
        Timer_A_initUpModeParam upConfig = {0};
            upConfig.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;
            upConfig.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_1;
            upConfig.timerPeriod = (__SYSTEM_FREQUENCY_MHZ__ / audioConfig->sampleRate) - 1;
            upConfig.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;
            upConfig.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE;
            upConfig.timerClear = TIMER_A_DO_CLEAR;
            upConfig.startTimer = false;
    
    
        Timer_A_initCompareModeParam compareConfig = {0};
            compareConfig.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1;
            compareConfig.compareInterruptEnable = TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE;
            compareConfig.compareOutputMode = TIMER_A_OUTPUTMODE_TOGGLE_RESET;
            compareConfig.compareValue = ((__SYSTEM_FREQUENCY_MHZ__ / audioConfig->sampleRate) / 2) - 1;
    
    
        // Initialize Timer_A channel 1 to be used as ADC12 trigger
        // Initialize TACCR0 (period register) __SYSTEM_FREQUENCY_MHZ__/sampleRate = NUM
        // Simple counter with no interrupt. 0...NUM = NUM counts/sample
        Timer_A_initUpMode(TIMER_A0_BASE, &upConfig);
    
        // Initialize TA0CCR1 to generate trigger clock output, reset/set mode
        Timer_A_initCompareMode(TIMER_A0_BASE, &compareConfig);
    
    
    
    
        // Turn on mic power full drive strength and enable mic input pin to ADC
        MIC_POWER_PORT_OUT |= MIC_POWER_PIN;
        MIC_POWER_PORT_DIR |= MIC_POWER_PIN;
    
        AUDIO_PORT_SEL0 |= MIC_INPUT_PIN;   // Enable A/D channel inputs
        AUDIO_PORT_SEL1 |= MIC_INPUT_PIN;
    
        // For safety, protect RMW Cpu instructions
        DMA_disableTransferDuringReadModifyWrite();
    
        // Initialize the DMA. Using DMA channel 1.
        dma0Config.channelSelect = DMA_CHANNEL_1;
        dma0Config.transferModeSelect = DMA_TRANSFER_SINGLE;
        dma0Config.transferSize = SAMPLES_LENGTH;
        dma0Config.triggerSourceSelect = DMA_TRIGGERSOURCE_26;
        dma0Config.transferUnitSelect = DMA_SIZE_SRCWORD_DSTWORD;
        dma0Config.triggerTypeSelect = DMA_TRIGGER_RISINGEDGE;
    
    
        DMA_init(&dma0Config);
    
        DMA_setSrcAddress(DMA_CHANNEL_1,
                          (uint32_t) &ADC12MEM0,
                          DMA_DIRECTION_UNCHANGED);
    
        DMA_setDstAddress(DMA_CHANNEL_1,
                          (uint32_t) (&dataRecorded),
                          DMA_DIRECTION_INCREMENT);
    
    
        // Configure ADC
        ADC12CTL0 &= ~ADC12ENC;           // Disable conversions to configure ADC12
        // Turn on ADC, sample 32 clock cycles =~ 2us
        ADC12CTL0 = ADC12ON + ADC12SHT0_3;
    
        // Use sample timer, rpt single chan 0, use MODOSC, TA0 timer channel 1
        ADC12CTL1 = ADC12SHP + ADC12CONSEQ_2 + ADC12SHS_1;
    
        // Mic input to ADC, (AVCC/AVSS ref), sequence end bit set
        ADC12MCTL0 = MIC_INPUT_CHAN | ADC12EOS;
    
    
    
        // Enable ADC to convert when a TA0 edge is generated
        ADC12CTL0 |= ADC12ENC;
    
        // Delay for the microphone to settle
        // ASMP401: the small red audio IC needs 0.2s init time before it starts sensing
        __delay_cycles(1600000); // 0.2s
    }

  • As I read this, you're (2) running a fixed-rate sampling sequence for the audio, and (1) every so often "sneaking in" to sample VCC. But to do (1) you re-initialize the ADC, losing all the configuration for (2) and then leaving the ADC disabled. There are ways of doing this better, but they're still complex and hazardous.

    I suggest that you're making this harder than it needs to be. Sampling VCC frequently won't hurt anything. Try sampling VCC as part of your audio sequence and save (DMA) the value away somewhere. Then every so often pick up the last sampled value.
  • Hi Bruce,

    I understand what you are suggesting. I wanted to do this too, sampling VCC along with the audio sensing. But the issue is that, from the original example code of (1), I mean in the function framLog(), I could not find where they set up the sampling port, e.g. the ADC is gonna sample from what port/pin. How should I set it up and combine it into the code of (2)?

    I will be very appreciated if you can guide me on how to sample VCC by combining it into (2).

    Thanks,
    Yubo
  • framLog is using ADC12_B_configureMemory to configure MCTL1 (to channel BATMAP). For this case, I suggest you stick with register access.

    The core change would be from
    > ADC12MCTL0 = MIC_INPUT_CHAN | ADC12EOS;
    to
    > ADC12MCTL0 = MIC_INPUT_CHAN;
    > ADC12MCTL1 = ADC12_B_INPUT_BATMAP | ADC12EOS; // Channel 31 for Vcc, last conversion in sequence

    and then change from CONSEQ=2 (repeat-single-channel) to CONSEQ=3 (repeat sequence-of-channels):
    > ADC12CTL1 = ADC12SHP + ADC12CONSEQ_3 + ADC12SHS_1;

    Since you're using MSC=0, each timer trigger will trigger only one conversion. (As a pleasant side-effect, you don't need to toggle ENC in between.) Thus you need to double the timer trigger rate:
    > upConfig.timerPeriod = (__SYSTEM_FREQUENCY_MHZ__ / audioConfig->sampleRate / 2) - 1;

    The VCC measurements will appear in the DMA (target) buffer, interleaved with the audio.

    I've probably forgotten something, but this should get you going.
  • Hi Bruce,

    Thanks, I am working on combining the two parts as you suggested.

    But I still do not see how the ADC is connected to the voltage. Actually, I do not know for both cases (1) FramLog.c and (2)audio_collect.c how the example codes connect the ADC to the target they want to sample. For (1)FramLog, it wants to sample the VCC voltage but which code line tells the system to sample from the VCC voltage; for (2)audio_collect.c, it wants to sample the audio signal and the external audio_IC's output is connected to P1.3. But I could not find which code line tells the system to sample data from P1.3. 

    I understand the command "ADC12SHS_x" connects the ADC with a certain timer internally (we need to see the device datasheet). So, I just wander if case (1) and (2) have some similar internal default settings for the relation between ADC and its sampling target too. 

    Actually this question (which line code tells the system to sample from where) confused me for a long time before. I just ended up using the same pin connection without understanding the code fully. Now that, it seems the time I have to. Could you give me some insights?

    Thanks,

    Yubo

  • Oh, actually " you're (2) running a fixed-rate sampling sequence for the audio, and (1) every so often "sneaking in" to sample VCC" is not exactly what I am doing. I only run (1) after (2) is finished. When (2) is called again, the function Audio_setupCollect( ) will be executed again. Thus, even (1) may have changed the configuration of ADC, when (2) is called again, (2) will setup the configuration again.

    Just to clarify my application.
  • I just realized "MIC_INPUT_CHAN" is connecting the ADC to the audio_IC's output and "ADC12_B_INPUT_BATMAP" is connecting the ADC to the VCC voltage. And by looking at the #define, MIC_INPUT_CHAN = ADC12INCH_3,  ADC12_B_INPUT_BATMAP = ADC12INCH_31.

    So, my last question can be converted into this:

    it seems the  ADC12INCH_3 means the P1.3(to which the audio_IC is connected), and ADC12INCH_31 means the VCC voltage. Where can I find the relations between all those ADC12INCH_x to a specific pin. For example, if I want to use another pin to connect the audio_IC's output, what ADC12INCH_x I should use?

    Another question is the use of "ADC12EOS":

    ADC12EOS: sequence end bit set. My current understanding is that if I use this command:

    ADC12MCTL0 = ADC12INCH_1 | ADC12INCH_2 | ADC12INCH_3 | ADC12INCH_4 | ADC12EOS;

    does it mean the ADC will sample from INCH1,2,3,4(in this 1,2,3,4 order) at each time when it is triggered by the internal timer? I can put several INCH_x before ADC12EOS.

    Thanks,

    Yubo

  • oh, to sample from more than one pin, the right command should be like this:

    ADC12MCTL0 = ADC12INCH_1;
    ADC12MCTL1 = ADC12INCH_2;
    ADC12MCTL2 = ADC12INCH_3 ;
    ADC12MCTL3 = ADC12INCH_4 | ADC12EOS;
    
    

    Each ADC12MCTLx is refered to one target pin you want to sample. Their ADC results will be saved into corresponding ADC12MEMx. So, I can use DMA to read only the ADC12MEMx I am interested. 

    It seems much clearer now. :)

  • Hi Bruce,

    I followed your advice and just use the (2) audio_collect.c to sample the voltage too, by change ADC12MCTL0=ADC12_B_INPUT_BATMAP. 

    The problem I have now is the sampled value. For the (1)FramLog.c, it gives me a direct sample value for the voltage, e.g. the sample value is 3400 for 3.3V, 2200 for 2.0V, etc. The value is not quite accurate but its variation is within my requirement. What setting I should do in (2) auido_collect.c in order to get a very direct sample value for the voltage?

    because in FramLog, there are:

        // Configure internal reference
        while(Ref_A_isRefGenBusy(REF_A_BASE));              // If ref generator busy, WAIT
        Ref_A_enableTempSensor(REF_A_BASE);
        Ref_A_setReferenceVoltage(REF_A_BASE, REF_A_VREF2_0V);
        Ref_A_enableReferenceVoltage(REF_A_BASE);

    I tried to set the ref in audio_collect.c using the following 

        // Configure internal reference
        while(REFCTL0 & REFGENBUSY);            // If ref generator busy, WAIT
        REFCTL0 |= REFVSEL_1 | REFON;           // Select internal ref = 2.0V
                                                // Internal Reference ON
        while(!(REFCTL0 & REFGENRDY));          // Wait for reference generator
                                                // to settle

    But it does not work. I get a sample value=710 for the 3.3V voltage. Actually, even I do not configure internal reference I still get a sample value=710 for the 3.3V voltage. 

    Thanks,

    Yubo

  • > initParam.internalChannelMap = ADC12_B_TEMPSENSEMAP | ADC12_B_BATTMAP;

    This connects the battery monitor to channel 31 (and the temperature sensor to ch 30). This is equivalent to

    > ADC12CTL3 = ADC12TCMAP | ADC12BATMAP; // Temp->CH30, Battery->CH31

    You don't really need TCMAP, but it won't hurt.
  • Also, I misread this the first time:

    > configureMemoryParam.refVoltageSourceSelect = ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS;

    I suspect this is expected for BATMAP; the equivalent is:

    > ADC12MCTL1 = ADC12_B_INPUT_BATMAP | ADC12VRSEL_1 | ADC12EOS; // Channel 31 for Vcc, ref=VREF, last conversion in sequence

    [Edit: Note: this is the second half of the post. The first half is "above the fold".]

  • Hi Bruce,

    Thank you very much for all your replies today. I tried to add "ADC12VRSEL_1 " when setting ADC12MCTLx, but it did not give me a value of 3400 for 3.3V voltage. However, it does give me varying values when I change the voltage values. So it solves my problem, as I only want to do some action when the voltage reaches up to 3.0V. If I do not add "ADC12VRSEL_1 " when setting ADC12MCTLx, the ADC just gives me the same value even given varying voltages.

    I kind of think all my problems are solved.

    Thanks,
    Yubo

**Attention** This is a public forum