Jump to content
Sign in to follow this  
ahgan84

About DMA on ADC12.

Recommended Posts

Exactly. If each sample is taking 1ms, taking 64 samples of 15 channels, plus filtering to only use channel 15's data, is going to take some time. If you only need channel 15, use that example I posted but remove the 2nd and 3rd adc starts and change the adc channel to 15.

I'm planning to ON all channels from channel 0 to 15 for my ADC12 for a user to use. Just that I thought of maybe a user won't know the sequence which one is channel 0 or which one is channel 15. Then if he put his device on channel 15, then he'll have to wait a long time only can get a result. I mean like, can't I get the ADC conversion from channel 0 to channel 15 all at the same time? Is there a configuration for this?

 

Because of you add an extra step which is the DMA transfer in the code, I felt like the conversion time with using DMA is slower compare to without using DMA. Am I right, or I'm just imagining? If I am right, is there any way to reduce the conversion time?

Share this post


Link to post
Share on other sites

There is no way to sample each channel simultaneously.

 

The DMA is going to be faster for a sequence of all 15 channels.

 

Using the DMA controller can increase the throughput of peripheral modules. It can also reduce system

power consumption by allowing the CPU to remain in a low-power mode, without having to awaken to

move data to or from a peripheral.

DMA controller features include:

 

Share this post


Link to post
Share on other sites

Do you have the MSP-EXP430FR5739? Even though it has an ADC10, I think it has better DMA examples than the F5529. Download the examples if you don't have them, and look at the adc10 example #10. It shows you how to transfer 3 sequential channels via DMA. It would only need minor changes to scan all 15 channels.

Yup. I had downloaded it. I think that you just have change to ADC10MCTL0 = ADC10INCH_15 and then DMA0SZ = 0x0F to scan all 15 channels right?

But now I want to collect 256 conversion from each channel and I want to do all channels and it's roughly in total 256x14=3586 (14 channels for my F5325) conversion each time. Below is my code in main():

void main(void)
{
 unsigned int i;

 WDTCTL = WDTPW+WDTHOLD;                   // Hold WDT
 REFCTL0 &= ~REFMSTR;

 P1OUT &= ~BIT0;                           // P1.0 clear
 P1DIR |= BIT0;                            // P1.0 output
 P5SEL |= BIT7;                            // P5.7/TB1 option select
 P5DIR |= BIT7;                            // Output direction
 P6SEL |= 0xFF;                            
 P7SEL |= 0x0F;
 P5SEL |= 0x03;

 // Setup ADC12
 ADC12CTL0 &= ~ADC12ENC;
 ADC12CTL0 = ADC12SHT0_6+ADC12MSC+ADC12ON+ADC12REF2_5V+ADC12REFON;// Sampling time, MSC, ADC12 on
 ADC12CTL1 = ADC12SHP+ADC12CONSEQ_2;//ADC12SHS_3+ADC12CONSEQ_2;     // Use sampling timer; ADC12MEM0
                                           // Sample-and-hold source = CCI0B =
                                           // TBCCR1 output
                                           // Repeated-single-channel
 ADC12CTL2 = ADC12RES_2+ADC12REFOUT;

 // Setup DMA0
 DMACTL0 = DMA0TSEL_24;                    // ADC12IFGx triggered
 DMACTL4 = DMARMWDIS;                      // Read-modify-write disable
 DMA0CTL = DMADT_4+DMAEN+DMADSTINCR_3+DMAIE; // Rpt single tranfer, inc dst, Int
 DMA0SZ = 256;                               // DMA0 size 

 __data16_write_addr((unsigned short) &DMA0SA,(unsigned long) &ADC12MEM0);
                                           // Source block address
 __data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &DMA_DST[0]);
                                           // Destination single address    

__enable_interrupt();

  while (1)
  {
// Channel 0 /////////////////////////////////////////////////////////////////////////////       
     while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_0;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

     for(i=0;i<256;i++)
     {
     	RAWvalue += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult0[AVGpnt] = RAWvalue >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue = 0;
  	  if (AVGpnt == MOVWIN-1) OVSvalue0 -= OVSresult0[0];	// Moving average with MOVWIN window size
  	  else OVSvalue0 -= OVSresult0[AVGpnt+1];
  	  OVSvalue0 += OVSresult0[AVGpnt];
  	  Dampvalue0 = OVSvalue0 / MOVWIN;   		// Divide by MOVWIN to get the average 
  	  AVGpnt++;

/*   	  
// Channel 1 /////////////////////////////////////////////////////////////////////////////   	  
  	  while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_1;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

//      LPM0;      // sleep until conversions are transferred by dma

     for(i=0;i<256;i++)
     {
     	RAWvalue1 += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult1[AVGpnt1] = RAWvalue1 >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue1 = 0;
  	  if (AVGpnt1 == MOVWIN-1) OVSvalue1 -= OVSresult1[0];	// Moving average with MOVWIN window size
  	  else OVSvalue1 -= OVSresult1[AVGpnt1+1];
  	  OVSvalue1 += OVSresult1[AVGpnt1];
  	  Damp1value0 = OVSvalue1 / MOVWIN;   		// Divide by MOVWIN to get the average

// Channel 2 /////////////////////////////////////////////////////////////////////////////    	  
  	  while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_2;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

//      LPM0;      // sleep until conversions are transferred by dma

     for(i=0;i<256;i++)
     {
     	RAWvalue2 += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult2[AVGpnt2] = RAWvalue2 >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue2 = 0;
  	  if (AVGpnt2 == MOVWIN-1) OVSvalue2 -= OVSresult2[0];	// Moving average with MOVWIN window size
  	  else OVSvalue2 -= OVSresult2[AVGpnt2+1];
  	  OVSvalue2 += OVSresult2[AVGpnt2];
  	  Damp2value0 = OVSvalue2 / MOVWIN;   		// Divide by MOVWIN to get the average


// Channel 3 /////////////////////////////////////////////////////////////////////////////    	  
  	  while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_3;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

//      LPM0;      // sleep until conversions are transferred by dma

     for(i=0;i<256;i++)
     {
     	RAWvalue3 += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult3[AVGpnt3] = RAWvalue3 >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue3 = 0;
  	  if (AVGpnt3 == MOVWIN-1) OVSvalue3 -= OVSresult3[0];	// Moving average with MOVWIN window size
  	  else OVSvalue3 -= OVSresult3[AVGpnt3+1];
  	  OVSvalue3 += OVSresult3[AVGpnt3];
  	  Damp3value0 = OVSvalue3 / MOVWIN;   		// Divide by MOVWIN to get the average

// Channel 4 /////////////////////////////////////////////////////////////////////////////    	  
  	  while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_4;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

//      LPM0;      // sleep until conversions are transferred by dma

     for(i=0;i<256;i++)
     {
     	RAWvalue4 += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult4[AVGpnt4] = RAWvalue4 >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue4 = 0;
  	  if (AVGpnt4 == MOVWIN-1) OVSvalue4 -= OVSresult4[0];	// Moving average with MOVWIN window size
  	  else OVSvalue4 -= OVSresult4[AVGpnt4+1];
  	  OVSvalue4 += OVSresult4[AVGpnt4];
  	  Damp4value0 = OVSvalue4 / MOVWIN;   		// Divide by MOVWIN to get the average

// Channel 5 /////////////////////////////////////////////////////////////////////////////    	  
  	  while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_5;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

//      LPM0;      // sleep until conversions are transferred by dma

     for(i=0;i<256;i++)
     {
     	RAWvalue5 += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult5[AVGpnt5] = RAWvalue5 >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue5 = 0;
  	  if (AVGpnt5 == MOVWIN-1) OVSvalue5 -= OVSresult5[0];	// Moving average with MOVWIN window size
  	  else OVSvalue5 -= OVSresult5[AVGpnt5+1];
  	  OVSvalue5 += OVSresult5[AVGpnt5];
  	  Damp5value0 = OVSvalue5 / MOVWIN;   		// Divide by MOVWIN to get the average

// Channel 6 /////////////////////////////////////////////////////////////////////////////    	  
  	  while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_6;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

//      LPM0;      // sleep until conversions are transferred by dma

     for(i=0;i<256;i++)
     {
     	RAWvalue6 += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult6[AVGpnt6] = RAWvalue6 >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue6 = 0;
  	  if (AVGpnt6 == MOVWIN-1) OVSvalue6 -= OVSresult6[0];	// Moving average with MOVWIN window size
  	  else OVSvalue6 -= OVSresult6[AVGpnt6+1];
  	  OVSvalue6 += OVSresult6[AVGpnt6];
  	  Damp6value0 = OVSvalue6 / MOVWIN;   		// Divide by MOVWIN to get the average

// Channel 7 /////////////////////////////////////////////////////////////////////////////    	  
  	  while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_7;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

//      LPM0;      // sleep until conversions are transferred by dma

     for(i=0;i<256;i++)
     {
     	RAWvalue7 += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult7[AVGpnt7] = RAWvalue7 >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue7 = 0;
  	  if (AVGpnt7 == MOVWIN-1) OVSvalue7 -= OVSresult7[0];	// Moving average with MOVWIN window size
  	  else OVSvalue7 -= OVSresult7[AVGpnt7+1];
  	  OVSvalue7 += OVSresult7[AVGpnt7];
  	  Damp7value0 = OVSvalue7 / MOVWIN;   		// Divide by MOVWIN to get the average

/*
// Channel 8 /////////////////////////////////////////////////////////////////////////////    	  
  	  while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_8;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

//      LPM0;      // sleep until conversions are transferred by dma

     for(i=0;i<256;i++)
     {
     	RAWvalue8 += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult8[AVGpnt8] = RAWvalue8 >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue8 = 0;
  	  if (AVGpnt8 == MOVWIN-1) OVSvalue8 -= OVSresult8[0];	// Moving average with MOVWIN window size
  	  else OVSvalue8 -= OVSresult8[AVGpnt8+1];
  	  OVSvalue8 += OVSresult8[AVGpnt8];
  	  Damp8value0 = OVSvalue8 / MOVWIN;   		// Divide by MOVWIN to get the average


// Channel 9 /////////////////////////////////////////////////////////////////////////////    	  
  	  while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_9;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

//      LPM0;      // sleep until conversions are transferred by dma

     for(i=0;i<256;i++)
     {
     	RAWvalue9 += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult9[AVGpnt9] = RAWvalue9 >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue9 = 0;
  	  if (AVGpnt9 == MOVWIN-1) OVSvalue9 -= OVSresult9[0];	// Moving average with MOVWIN window size
  	  else OVSvalue9 -= OVSresult9[AVGpnt9+1];
  	  OVSvalue9 += OVSresult9[AVGpnt9];
  	  Damp9value0 = OVSvalue9 / MOVWIN;   		// Divide by MOVWIN to get the average

// Channel 12 /////////////////////////////////////////////////////////////////////////////    	  
  	  while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_12;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

//      LPM0;      // sleep until conversions are transferred by dma

     for(i=0;i<256;i++)
     {
     	RAWvalue12 += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult12[AVGpnt12] = RAWvalue12 >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue12 = 0;
  	  if (AVGpnt12 == MOVWIN-1) OVSvalue12 -= OVSresult12[0];	// Moving average with MOVWIN window size
  	  else OVSvalue12 -= OVSresult12[AVGpnt12+1];
  	  OVSvalue12 += OVSresult12[AVGpnt12];
  	  Damp12value0 = OVSvalue12 / MOVWIN;   		// Divide by MOVWIN to get the average

// Channel 13 /////////////////////////////////////////////////////////////////////////////    	  
  	  while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_13;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

//      LPM0;      // sleep until conversions are transferred by dma

     for(i=0;i<256;i++)
     {
     	RAWvalue13 += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult13[AVGpnt13] = RAWvalue13 >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue13 = 0;
  	  if (AVGpnt13 == MOVWIN-1) OVSvalue13 -= OVSresult13[0];	// Moving average with MOVWIN window size
  	  else OVSvalue13 -= OVSresult13[AVGpnt13+1];
  	  OVSvalue13 += OVSresult13[AVGpnt13];
  	  Damp13value0 = OVSvalue13 / MOVWIN;   		// Divide by MOVWIN to get the average

// Channel 14 /////////////////////////////////////////////////////////////////////////////    	  
  	  while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_14;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

//      LPM0;      // sleep until conversions are transferred by dma

     for(i=0;i<256;i++)
     {
     	RAWvalue14 += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult14[AVGpnt14] = RAWvalue14 >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue14 = 0;
  	  if (AVGpnt14 == MOVWIN-1) OVSvalue14 -= OVSresult14[0];	// Moving average with MOVWIN window size
  	  else OVSvalue14 -= OVSresult14[AVGpnt14+1];
  	  OVSvalue14 += OVSresult14[AVGpnt14];
  	  Damp14value0 = OVSvalue14 / MOVWIN;   		// Divide by MOVWIN to get the average

// Channel 15 /////////////////////////////////////////////////////////////////////////////    	  
  	  while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_15;     // V+=AVcc V-=AVss, A0 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

//      LPM0;      // sleep until conversions are transferred by dma

     for(i=0;i<256;i++)
     {
     	RAWvalue15 += DMA_DST[i];     				// Summing up 256 raw values
     }

     OVSresult15[AVGpnt15] = RAWvalue15 >> 4;   	// Shift right 4 bits, oversampling.
  	  RAWvalue15 = 0;
  	  if (AVGpnt15 == MOVWIN-1) OVSvalue15 -= OVSresult15[0];	// Moving average with MOVWIN window size
  	  else OVSvalue15 -= OVSresult15[AVGpnt15+1];
  	  OVSvalue15 += OVSresult15[AVGpnt15];
  	  Damp15value0 = OVSvalue15 / MOVWIN;   		// Divide by MOVWIN to get the average  	  
}
}

 

To reduce the noise, I'm doing an oversampling and after that moving average for each channels of the results. My moving average is around 64 data each time. So, I need to collect 64 oversampled data first to get a stable result.

Because each channel need to collect 64 oversampled data and 1 oversampled data is equals to 256 conversion. So, total data is 256x64x15=245760 samples. From the spec, the ADC is 200000 sample per second. So, from theory, to collect all 15 channels I only need around 1 second. But I found out that my code really need over 10 seconds only can reach channel 15. Is there any problem with this code? Is there a way to speed up some more?

Is there any way or settings so that I can get the ADC to sample 200000 sample per second?

Can I omit this line "while (ADC12CTL1 & BUSY)" to make it faster?

And by he way, yes... I'm the same ahgan84 from the TI forum. Usually I ask my questions to this two forum.

Share this post


Link to post
Share on other sites

      for(i=0;i<256;i++)
     {
        RAWvalue += DMA_DST[i];                 // Summing up 256 raw values
     }

I found out that it is the above for loop which run 256 times to sum up the raw value for each channel that increase my time. Is there any other way that I can write to reduce the time?

Share this post


Link to post
Share on other sites

Hello ahgan84, I looked at the code you posted on E2E. For scanning all 15 channels, you're probably going about it the wrong way. You can use the multi-sample, repeat-sequence (CONSEQ_3) modes of the ADC instead of turning the ADC off and on to change channels. That method (in my example) was only implemented to eliminate scanning of all channels when only 12-14 were needed. The issue with repeat-sequence is that if you want to sample channels 3-5, you will be sampling 0-5 -you only pick the last channel of the sequence. If you change to that method, your loop becomes 1/14th of what it was. You will only need once "while(adcbusy)"

 

I found out that it is the above for loop which run 256 times to sum up the raw value for each channel that increase my time. Is there any other way that I can write to reduce the time?

Yes, sample less times. Less clock cycles per sample. Bitwise Division.

 

Use the repeat-sequence mode. You were right about the minor changes. You will also need to increase the size of the ADCdata storage array to the # of samples * # of channels. Then it's just about filtering each channels data.

For example:(I pulled this from some code where I sample 6 channels, repeat-sequence)

right_cal = 0;
for (r=ADCRIGHT; r < MAXADC; r+=6)
{
right_cal += ADCdata[r];
}
right_cal /= SAMPLES;

You'll notice that the incrementer is increased by 6 each time. So, this will filter the data for channel 5. The array is 48 bytes, which is 6 channels, 8 samples each.

 

And here is just a quick copy from some of adc10 code. It's a loop(repeats 50 times) that samples the 6 channels and averages each of the 2 channels needed.


void ADC10_init(void)
{
   ADC10CTL0 &= ~ENC;
   ADC10CTL0 = ADC10ON + MSC + ADC10SHT_2 + SREF_0;
   ADC10CTL1 = CONSEQ_3 + ADC10SSEL_1 + ADC10DIV_0 + SHS_0 + INCH_5;
   ADC10AE0 = 0x30;
   ADC10DTC0 = ADC10CT;
   ADC10DTC1 = 48;
   ADC10SA = (unsigned int)ADCdata;
   ADC10CTL0 |= ENC;
}

// collect 50 averaged samples for calibration of phototransistors
for (i = 0; i < 50; i++)
{	
	// sample ADC10 and use DTC
   	ADC10CTL0 &= ~ENC;
   	while (ADC10CTL1 & BUSY);               // Wait if ADC10 core is active
   	ADC10SA = (unsigned int)ADCdata;    	// Data buffer start
   	ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start

	for (c = 0; c < 3; c++)
	{
		shiftByte(color[c]);
		__delay_cycles(25000);
	}

   	// get float of left channel P1.4
   	left_cal = 0;
 		for (l=ADCLEFT; l < MAXADC; l+=6)
 		{
   		left_cal += ADCdata[l];
 		}
 		left_cal /= SAMPLES;

 		// get float of right channel P1.5
 		right_cal = 0;
 		for (r=ADCRIGHT; r < MAXADC; r+=6)
 		{
   		right_cal += ADCdata[r];
 		}
 		right_cal /= SAMPLES;
}
}

 

Also, for the oversampling, check out the recent post by dangerous prototypes. http://dangerousprototypes.com/2012/01/01/app-note-enhancing-adc-resolution-by-oversampling/

Share this post


Link to post
Share on other sites

From my method, each DMA_DST[0] to DMA_DST[255] is equals to a channel. But from your method, DMA_DST[0] is for channel 0, DMA_DST[1] is for channel 1, DMA_DST[2] is for channel 2, DMA_DST[3] is for channel 3, ....., DMA_DST[15] is for channel 15. Then DMA_DST[16] is for channel 0 again, DMA_DST[17] is for channel 1 again... and then repeat again. Am I right?

 

Then is it that my ADC12MCTL0 = ADC12SREF_1+ADC12INCH_15?

    right_cal = 0;
   for (r=ADCRIGHT; r < MAXADC; r+=6)
   {
   right_cal += ADCdata[r];
   }
   right_cal /= SAMPLES;

For your above for loop, what is ADCRIGHT? Is it I will need to increase ADCRIGHT too? Like for example if r=0, then right_cal = ADCdata[0] + ADCdata[6] + ADCdata[12] + ADCdata[18] + ADCdata[24].....If r=1, then right_cal = ADCdata[1] + ADCdata[7] + ADCdata[13] + ADCdata[19]+..... Am I right?

Then if 15 channel then my maximum r is also 15 right?

Seems like we are doing 15 times of your above for loop. Am I right? I haven't try this code yet but sounds the same with my method because you also use a for loop to sum up the ADC data... It really will speed up the conversion?

Share this post


Link to post
Share on other sites
From my method, each DMA_DST[0] to DMA_DST[255] is equals to a channel. But from your method, DMA_DST[0] is for channel 0, DMA_DST[1] is for channel 1, DMA_DST[2] is for channel 2, DMA_DST[3] is for channel 3, ....., DMA_DST[15] is for channel 15. Then DMA_DST[16] is for channel 0 again, DMA_DST[17] is for channel 1 again... and then repeat again. Am I right?

Exactly. Then you have all the samples for each channel in data array. It will be much faster as there is no starting, waiting and stopping between each channel.

 

For your above for loop, what is ADCRIGHT? Is it I will need to increase ADCRIGHT too? Like for example if r=0, then right_cal = ADCdata[0] + ADCdata[6] + ADCdata[12] + ADCdata[18] + ADCdata[24].....If r=1, then right_cal = ADCdata[1] + ADCdata[7] + ADCdata[13] + ADCdata[19]+..... Am I right?

Then if 15 channel then my maximum r is also 15 right?

ADCRIGHT is just a constant to do exactly what you've stated. If you're doing all 15 channels, you will have ADCdata[1] + ADCdata[16] + ADCdata[31] +...

15 would be the max, yes. But one thing you'll notice is that the position will be backwards. Channel 15 will be [0], channel 14 will be [1], 13 will be [2] and so on. This is from the ADC sequential mode starting at the highest channel and decreasing.

Share this post


Link to post
Share on other sites
The issue with repeat-sequence is that if you want to sample channels 3-5, you will be sampling 0-5 -you only pick the last channel of the sequence.

Is it that I only need to declare just one line of ADC12MCTL15 or I need to declare ADC12MCTL 0 to ADC12MCTL15 to sample channel 0 - 15? Then if it is just one line, is it I have to put ADC12MCTL0 = ADC12SREF_1+ADC12INCH_15 or ADC12MCTL15 = ADC12SREF_1+ADC12INCH_15? Here is my code for the initialization. I collect one sample from each ADC channel in sequence. But seems like it won't run. The program stuck at 'while (ADC12CTL1 & BUSY)'. Do you know what's wrong?

  ADC12CTL0 &= ~ADC12ENC;
 ADC12CTL0 = ADC12SHT0_6+ADC12SHT1_6+ADC12MSC+ADC12ON+ADC12REF2_5V+ADC12REFON;// Sampling time, MSC, ADC12 on
 ADC12CTL1 = ADC12SHP+ADC12CONSEQ_3;//ADC12SHS_3+ADC12CONSEQ_2;     // Use sampling timer; ADC12MEM0
                                           // Sample-and-hold source = CCI0B =
                                           // TBCCR1 output
                                           // Repeated-single-channel
 ADC12CTL2 = ADC12RES_2+ADC12REFOUT;
//  ADC12CTL0 |= ADC12ENC;

 // Setup DMA0
 DMACTL0 = DMA0TSEL_24;                    // ADC12IFGx triggered
 DMACTL4 = DMARMWDIS;                      // Read-modify-write disable
//  DMA0CTL &= ~DMAIFG; 
 DMA0CTL = DMADT_4+DMAEN+DMADSTINCR_3+DMAIE; // Rpt single tranfer, inc dst, Int
 DMA0SZ = 16;                               // DMA0 size = 1

 __data16_write_addr((unsigned short) &DMA0SA,(unsigned long) &ADC12MEM0);
                                           // Source block address
 __data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &DMA_DST[0]);

     while (ADC12CTL1 & BUSY);         // wait for adc10 to be ready
     ADC12MCTL0 = ADC12SREF_1+ADC12INCH_15;     // V+=AVcc V-=AVss, A0  - A15 channel
     ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

  j = 0;
     RAWvalue += DMA_DST[j++];     				
     RAWvalue1 += DMA_DST[j++];
     RAWvalue2 += DMA_DST[j++];
     RAWvalue3 += DMA_DST[j++];
     RAWvalue4 += DMA_DST[j++];
     RAWvalue5 += DMA_DST[j++];
     RAWvalue6 += DMA_DST[j++];
     RAWvalue7 += DMA_DST[j+2];
//      RAWvalue8 += DMA_DST[j++];
     RAWvalue9 += DMA_DST[j+3];
     RAWvalue12 += DMA_DST[j++];
     RAWvalue13 += DMA_DST[j++];
     RAWvalue14 += DMA_DST[j++];
     RAWvalue15 += DMA_DST[j++];
}

#pragma vector=DMA_VECTOR
__interrupt void DMA_ISR(void)
{	
 switch(__even_in_range(DMAIV,16))
 {
   case 0: break;
   case 2:                                 // DMA0IFG = DMA Channel 0
//      P1OUT ^= BIT0;                        // Toggle P1.0 - PLACE BREAKPOINT HERE AND CHECK DMA_DST VARIABLE
	ADC12CTL0 &= ~ADC12ENC;      		// disable adc10 to re-select channel after exit
//		LPM0_EXIT;
     break;
   case 4: break;                          // DMA1IFG = DMA Channel 1
   case 6: break;                          // DMA2IFG = DMA Channel 2
   case 8: break;                          // DMA3IFG = DMA Channel 3
   case 10: break;                         // DMA4IFG = DMA Channel 4
   case 12: break;                         // DMA5IFG = DMA Channel 5
   case 14: break;                         // DMA6IFG = DMA Channel 6
   case 16: break;                         // DMA7IFG = DMA Channel 7
   default: break;
 }
}

 

 

I found out another thing, we won't need to configure the PxSEL register for the ADC12 to work right? I've try putting PxSEL = 0 and I still can get the ADC value. Then how are we going to use those pin (A0 - A15) as I/O?

Share this post


Link to post
Share on other sites

void main(void)
{
 unsigned int i,j;

 WDTCTL = WDTPW+WDTHOLD;                   // Hold WDT
 REFCTL0 &= ~REFMSTR;

 P1OUT &= ~BIT0;                           // P1.0 clear
 P1DIR |= BIT0;                            // P1.0 output
 P5SEL |= BIT7;                            // P5.7/TB1 option select
 P5DIR |= BIT7;                            // Output direction
 P6SEL |= 0xFF;                            
 P7SEL |= 0x0F;
 P5SEL |= 0x03;

 // Setup ADC12
 ADC12CTL0 &= ~ADC12ENC;  	 
 ADC12CTL0 = ADC12SHT0_6+ADC12SHT1_6+ADC12MSC+ADC12ON+ADC12REF2_5V+ADC12REFON;
 ADC12CTL1 = ADC12SHP+ADC12CONSEQ_3;//ADC12SHS_3+ADC12CONSEQ_3;         
 ADC12CTL2 = ADC12RES_2;//+ADC12REFOUT; 
 ADC12MCTL0 = ADC12SREF_1+ADC12INCH_0;
 ADC12MCTL1 = ADC12SREF_1+ADC12INCH_1;
 ADC12MCTL2 = ADC12SREF_1+ADC12INCH_2;
 ADC12MCTL3 = ADC12SREF_1+ADC12INCH_3;
 ADC12MCTL4 = ADC12SREF_1+ADC12INCH_4;
 ADC12MCTL5 = ADC12SREF_1+ADC12INCH_5;
 ADC12MCTL6 = ADC12SREF_1+ADC12INCH_6;
 ADC12MCTL7 = ADC12SREF_1+ADC12INCH_7;
//  ADC12MCTL8 = ADC12SREF_1+ADC12INCH_8;
 ADC12MCTL9 = ADC12SREF_1+ADC12INCH_9;
 ADC12MCTL12 = ADC12SREF_1+ADC12INCH_12;
 ADC12MCTL13 = ADC12SREF_1+ADC12INCH_13;
 ADC12MCTL14 = ADC12SREF_1+ADC12INCH_14;
 ADC12MCTL15 = ADC12SREF_1+ADC12INCH_15+ADC12EOS; 

 // Setup DMA0
 DMACTL0 = DMA0TSEL_24;                    // ADC12IFGx triggered
 DMACTL4 = DMARMWDIS;                      // Read-modify-write disable
 DMA0CTL = DMADT_4+DMAEN+DMASRCINCR_3+DMADSTINCR_3+DMAIE; // Rpt single tranfer, inc dst, Int
 DMA0SZ = 32;                               // DMA0 size = 1

 __data16_write_addr((unsigned short) &DMA0SA,(unsigned long) &ADC12MEM0);
                                           // Source block address     
 __data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &DMA_DST[0]);  

ADC12CTL0 |= ADC12ENC + ADC12SC;   // start sampling and conversion

// __bis_SR_register(GIE);//(LPM0_bits + GIE);       // LPM0 w/ interrupts
//  __no_operation();                         // used for debugging

__enable_interrupt();

  while (1)
  {
// Channel 0 /////////////////////////////////////////////////////////////////////////////       
  j = 0;
     RAWvalue += DMA_DST[j++];     				
     RAWvalue1 += DMA_DST[j++];
     RAWvalue2 += DMA_DST[j++];
     RAWvalue3 += DMA_DST[j++];
     RAWvalue4 += DMA_DST[j++];
     RAWvalue5 += DMA_DST[j++];
     RAWvalue6 += DMA_DST[j++];
     RAWvalue7 += DMA_DST[j+2];     
//      RAWvalue8 += DMA_DST[j++];
     RAWvalue9 += DMA_DST[j+3];
     RAWvalue12 += DMA_DST[j++];
     RAWvalue13 += DMA_DST[j++];
     RAWvalue14 += DMA_DST[j++];
     RAWvalue15 += DMA_DST[j++];
}

#pragma vector=DMA_VECTOR
__interrupt void DMA_ISR(void)
{	
 switch(__even_in_range(DMAIV,16))
 {
   case 0: break;
   case 2:                                 // DMA0IFG = DMA Channel 0   
     break;
   case 4: break;                          // DMA1IFG = DMA Channel 1
   case 6: break;                          // DMA2IFG = DMA Channel 2
   case 8: break;                          // DMA3IFG = DMA Channel 3
   case 10: break;                         // DMA4IFG = DMA Channel 4
   case 12: break;                         // DMA5IFG = DMA Channel 5
   case 14: break;                         // DMA6IFG = DMA Channel 6
   case 16: break;                         // DMA7IFG = DMA Channel 7
   default: break;
 }
}

I've modified my code to the above coding and it worked. I've list out all the ADC12MCTL0...ADC12MCTL15 and channel 15 is the last channel by putting ADC12EOS on it.

 

My problem is, do I need to set it to increment my DMA source address DMASRCINCR_3? I've tested it with DMASRCINCR_3 on and it can get ADC value from DMA_DST[0] to DMA_DST[15] accurately, but after that from DMA_DST[16], DMA_DST[17], DMA_DST[18].... it get wrong data. Seems like it did not repeat by putting channel 0 data to DMA_DST[16], channel 1 data to DMA_DST[17] and so on... How do we solve this? Is there anything I miss?

 

Your code just show me how you init your ADC10. How bout init DMA? How bout the ISR? Is it the same with single channel sampling?

 

We configure that the ADC stop converting in the repeat single channel setting in ISR for DMA. Then how bout for repeat sequence channel? DO we need to stop the ADC from converting too?

 

Channel 10 is for Temperature Diode and Channel 11 is for (AVCC

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...