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.

MSP430FR5739: ADC10B: Repeat-sequence-of-channels conversion

Part Number: MSP430FR5739

Hello Team,

I have some confusion regarding Repeat-sequence-of-channels ADC10B. When we configured this mode of ADC, Are we getting ADC10IFG flag set on each channel conversion or complete sequence conversion? How to access results of all conversion as ADC10MEM0 is single word result resister? Please clarify the same..

My requirement is to sample ADC0 and ADC1 channels with repeat sequence mode. I have referred example where we are transferring 32 samples of same channel and modify it for my requirement as below: 

//******************************************************************************
#include <msp430.h>

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
// Configure SMCLK = 1MHz
CSCTL0_H = 0xA5;
CSCTL1 |= DCOFSEL0 + DCOFSEL1; // Set max. DCO setting
CSCTL2 = SELA_1 + SELS_3 + SELM_3; // set ACLK = VLO; MCLK = DCO
CSCTL3 = DIVA_0 + DIVS_3 + DIVM_3; // set all dividers

// Configure ADC10;
ADC10CTL0 = ADC10SHT_3 + ADC10MSC + ADC10ON;// 32ADCclks, ADC on
ADC10CTL1 = ADC10SHP + ADC10CONSEQ_3 + ADC10SSEL_3 + ADC10DIV_1; // SMCLK/2
// Sampling timer, rpt single ch
ADC10CTL2 = ADC10RES; // 10-bit resolution
ADC10MCTL0 = ADC10INCH_1 + ADC10SREF_1; // Vref+, A10

// Configure internal reference
while(REFCTL0 & REFGENBUSY); // If ref generator busy, WAIT
REFCTL0 |= REFVSEL_3+REFON; // Select internal ref = 2.5V
// Internal Reference ON
__delay_cycles(75); // Delay (~75us) for Ref to settle

// Configure DMA (ADC10IFG trigger)
DMACTL0 = DMA0TSEL__ADC10IFG; // ADC10IFG trigger
__data16_write_addr((unsigned short) &DMA0SA,(unsigned short) &ADC10MEM0);
// Source single address
__data16_write_addr((unsigned short) &DMA0DA,(unsigned short) 0xC800);
// Destination array address
DMA0SZ = 0x04; // 4 conversions
DMA0CTL = DMADT_5 + DMADSTINCR_3 + DMAEN + DMAIE + DMALEVEL;
// Rpt, inc dest, word access,
// enable int after 32 conversions

while(1)
{
while (ADC10CTL1 & BUSY); // Wait if ADC10 core is active
ADC10CTL0 |= ADC10ENC + ADC10SC; // Start sampling
__bis_SR_register(CPUOFF + GIE); // LPM0, ADC10_ISR will force exit
__no_operation(); // << SET BREAKPOINT HERE
__delay_cycles(5000); // Delay between conversions
}
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=DMA_VECTOR
__interrupt void DMA0_ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(DMA_VECTOR))) DMA0_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(DMAIV,16))
{
case 0: break; // No interrupt
case 2:
// 32 conversions complete
ADC10CTL0 &= ~ADC10ENC;
__bic_SR_register_on_exit(CPUOFF); // exit LPM
break; // DMA0IFG
case 4: break; // DMA1IFG
case 6: break; // DMA2IFG
case 8: break; // Reserved
case 10: break; // Reserved
case 12: break; // Reserved
case 14: break; // Reserved
case 16: break; // Reserved
default: break;
}
}

As per me, I should kept DMA0SZ as 0x2 as I need two ADC channel data but when I am keeping it , this program is giving me one channel duplicate results through DMA. When I keep it as 0x04, it is giving me Both the channel results as duplicate i.e. Channel 1 Result at 0xC800 , 0xC802 and Channel 0 result at 0xC804 , 0xC806

Please help me in correcting this example...

Regards,

Vikas Chola

  • Hello Vikas,

    ADC10IFG0 is set every time a conversion is completed and the result is stored into ADC10MEM0, since you are using repeated block transfer mode then a complete clock is transferred with one trigger. You will want to use a repeated single transfer (DMADT_4) instead so that each transfer requires a trigger. Please consult MSP430FR57xx_adc10_10.c and make sure to configure the ADC PxSEL registers. You should also just use sequence-of-channels mode (ADC10CONSEQ_1) if you plan on toggling the ADC10ENC bit.

    Regards,
    Ryan
  • Hello Ryan,

    Thanks for your response.. So that means if I don't use DMA then Each conversion of ADC0 and ADC1 will trigger ADC interrupt if enabled and I need to handle the ADC value by my software... Right?

    Also I wish to know why I am getting duplicate result through DMA transfer in my code... Please point out my mistake in the same, I have used DMADT_4 also but there is no difference in my outcome..

    Regards,

    Vikas Chola

  • Each conversion sets the ADC IFG regardless of DMA usage, please refer to Section 16.2.7 for more information. You should be able to use the DMA to transfer ADC values without the use of an ADC interrupt. I once again recommend that you validate MSP430FR57xx_adc10_10.c operation and then modify it for your own use.

    Regards,
    Ryan
  • Thanks Ryan,
    It works for my requirement. After going through it and comparing my existing program I found due to DMALEVEL bit my results were copied twice on destination memory.. I couldn't find reason for the same, Please explain why it should happen.. My customer issue gets solved with your guidance. Thanks for your support.

    Regards,
    Vikas Chola
  • Please read Section 7.2.3 of the User's Guide, level-sensitive triggers (DMALEVEL set) should only be used when the DMAE0 external trigger is selected. Otherwise, edge-sensitive triggers (DMALEVEL cleared) are used to initiate the transfer. You were getting two DMA transfers per conversion because the ADC10IFG had not yet reset by the time the DMA had finished the first transfer, hence beginning a second one since DMALEVEL was set.

    Regards,
    Ryan

**Attention** This is a public forum