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.

MSP430FR5949: ADC/TA0 triggers /Repeat-Sequence-of-Channels Mod

Part Number: MSP430FR5949

hello,everyone:

I want to implement a function: timer triggers adc module to implement Repeat-Sequence-of-Channels Mode. However, the problem now is that the Sequence sampling interval is either the timer turnover cycle or adc sampling conversion interval.Below is my software configuration and function diagram

void ADC_init(void)
{
P1SEL1 |= (BIT2+BIT3);
P1SEL0 |= (BIT2+BIT3); //BIT1+

P3SEL1 |= (BIT0+BIT1+BIT2+BIT3);
P3SEL0 |= (BIT0+BIT1+BIT2+BIT3);

while(REFCTL0 & REFGENBUSY);
REFCTL0 |= REFVSEL_2 | REFON;
//while(REFCTL0 & REFGENRDY);//Reference voltage output is ready to be used

ADC12CTL0 &= ~ADC12ENC;
ADC12CTL0 |= ADC12ON|ADC12MSC;//

ADC12CTL1 = ADC12SHP| ADC12SHS_1 |ADC12CONSEQ_3; //
ADC12CTL2 |= ADC12PWRMD;//ADC12RES_2 |; // 12-bit conversion results

ADC12CTL3 &= ~ADC12TCMAP;
ADC12CTL0 |= ADC12SHT0_0;
ADC12MCTL0 = ADC12VRSEL_1+ADC12INCH_3;//电场
ADC12MCTL1 = ADC12VRSEL_1+ADC12INCH_13;//小通道电流
ADC12MCTL2 = ADC12VRSEL_1+ADC12INCH_14+ADC12EOS;//大通道电流
ADC12IER0 = 0x04; // Enable ADC12IFG.3
ADC12CTL0 |= ADC12ENC |ADC12SC;//; //启动采样和转换

// Configure Timer0_A3 to periodically trigger the ADC12
TA0CCR0 = TIME_1MS; // PWM Period
TA0CCTL1 = OUTMOD_3;//CCIE;// | // TACCR1 set/reset
TA0CCR1 = TIME_1MS; // TACCR1 PWM Duty Cycle
TA0CTL = TASSEL__ACLK | MC__UP;//|TAIE; // ACLK, up mode // ACLK, up mode

}

  • Use CONSEQ=1 and MSC=1.

    In the ISR, you'll need to toggle ENC (low, then high), or the ADC will stop. [Ref User Guide (SLAU367o) Fig 34-9.]

  • Thanks,I’ll try.if I want to use DMA,how to toggle enc by MCU?
  • You probably want to do that in the DMA completion ISR. (The timer ISR is too early, and the ADC ISR is assumed non-functional with DMA.)

    That means you can only do one ADC burst per DMA sequence, but I think you're stuck with that anyway since DMASA and DMADA are re-set together.

    [Edit: Fixed typos.]

  • hi,

    I have implemented the previous requirements without DMA.

    I have a try with DMA.TA0 CCR1 trigger ADC12,TA0 CCR0 trigger DMA0.I coudle control the interval betwen CCR1 and CCR0.in fact,it does't work my way.

    void ADC_init(void)
    {
    P1SEL1 |= (BIT2+BIT3); //参考电压和电池电压
    P1SEL0 |= (BIT2+BIT3); //

    P3SEL1 |= (BIT0+BIT1+BIT2+BIT3);//电流通道2 电流通道1 电场采样 温度采样
    P3SEL0 |= (BIT0+BIT1+BIT2+BIT3);

    while(REFCTL0 & REFGENBUSY);
    REFCTL0 |= REFVSEL_2 | REFON;//先开启基准电压
    //while(REFCTL0 & REFGENRDY);//Reference voltage output is ready to be used

    ADC12CTL0 &= ~ADC12ENC;
    ADC12CTL0 |= ADC12ON|ADC12MSC;//

    ADC12CTL1 = ADC12SHP|ADC12SHS_1 |ADC12CONSEQ_1; //
    ADC12CTL2 |= ADC12PWRMD;//ADC12RES_2 |; // 12-bit conversion results

    ADC12CTL0 |= ADC12SHT0_1;
    ADC12MCTL0 = ADC12VRSEL_1+ADC12INCH_3;//电场
    ADC12MCTL1 = ADC12VRSEL_1+ADC12INCH_13;//小通道电流
    ADC12MCTL2 = ADC12VRSEL_1+ADC12INCH_14+ADC12EOS;//大通道电流
    //ADC12IER0 = 0x04;
    //ADC_all();//ADC_ui();//
    ADC12CTL0 |= ADC12ENC;// |ADC12SC;//; //启动采样和转换
    //ADC_stop();
    DMAInit1();
    // Configure Timer0_A3 to periodically trigger the ADC12
    TA0CCR0 = TIME_1MS;//TIME_1MS; // PWM Period
    TA0CCR1 = TIME_1MS/2;//TIME_1MS; // TACCR1 PWM Duty Cycle
    TA0CCTL1 = OUTMOD_7;//CCIE;// | // TACCR1 set/reset
    TA0CTL = TASSEL__ACLK | MC__UP;//|TAIE; // ACLK, up mode // 
    }


    void DMAInit1()
    {
    //ADC12IER0=0;
    DMACTL0 = DMA0TSEL_1;//DMA0TSEL_2:TA0CCR2 CCIFG |DMA1TSEL_26:ADC12 end of conversion

    DMA0CTL = DMADT_1| DMADSTINCR_3 | DMASRCINCR_3; //目标地址增加 destination address incremented 来源地址不变
    DMA0SZ = 3;//LF_NUM;//(VRECORD1_FLASH_ADDR-RECORD1_FLASH_ADDR)*2 总长度
    __data16_write_addr((unsigned short) &DMA0SA,(unsigned long) &ADC12MEM0);//电流采样转换结果存储区
    __data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &results);//目标地址

    DMA0CTL |=DMAEN+DMAIE;;//
    }

    #pragma vector=DMA_VECTOR
    __interrupt void DMA_ISR(void)
    {
        LPM3_EXIT;
        ADC12CTL0 &=~ ADC12ENC;
        ADC12CTL0 |= ADC12ENC;
    }

  • In what way does it not work? It doesn't transfer the data? Or the program locks up?

    I'm pretty sure you need to clear DMAIFG in the ISR, either with "&=" or by reading DMAIV. The symptom here would be a program lockup.

    Ordinarily I would expect to see DMA0TSEL_24 for the ADC [Ref data sheet (SLAS590N) Table 6-10.]  I think DMA0TSEL_1  with OUTMOD=7 will trigger the DMA and the ADC at the same time so you might get half-done results.

  • My initial idea was that the timer would automatically trigger ADC to perform sequence sampling, ADC sampling would trigger DMA, and 20 sequence sampling would complete to produce DMA interrupts.At the moment, my idea of MCU is unrealisable, so I give up on practical DMA.

  • Yes, you can do all that except the 20 sequences -- you want the SA to start over for every sequence, but the DA not to, and (looking through all the charts) I don't see any mode that does that.

    I'm pretty sure that if you use DMADT=5 you can arrange to only set up once, and let the DMA repeat itself, but you still get one interrupt per sequence.

  • hi,bruce

    I have a question.

    "When CONSEQx = {1,3}, theADC12IFG flag for the last ADC12MEMx in the sequence can trigger a DMA transfer. Any ADC12IFG flag

    is automatically cleared when the DMA controller accesses the corresponding ADC12MEMx." [Ref User Guide (SLAU367o)  11.2.11.]

    In fact, instead of the last ADC12IFG triggering a DMA transfer, each ADC12IFGx in the sequence sampling triggers a DMA transfer.

    why?

  • My memory is a bit hazy. What exactly are you observing? Are you getting a full block (3 samples) for each of the 3 conversions in the sequence?

  • I have this idea for two reasons :

    (1)DMA0CTL = DMADT_4| DMADSTINCR_3 | DMASRCINCR_3;

    Repeated Single transfer.Although only one DMA interrupt is generated, the DMA is still triggered in three times, I think so

    (2)When using ADC with DMA , the power consumption is even greater than when using ADC without DMA.

  • I don't know the answer. Maybe it has something to do with the fact that, in the single-transfer case, the trigger (level) isn't changed (cleared) by the DMA transfer until you get to the end. But that's only half a theory, because of the level vs edge thing.

    The UG sentence does read a bit oddly, since it implies a different ADC12<->DMA verilog-level interconnect based on CONSEQ setting. There's a "Documentation Feedback" link at the bottom of the UG page if you want to suggest something to the authors.

  • Thank you!I'll try it again.

**Attention** This is a public forum