cancel
Showing results for 
Search instead for 
Did you mean: 

Strange results, ADC by DMA (with scope shots)

mtb308
Associate II
Posted on November 19, 2013 at 23:26

 

 

The original post was too long to process during our migration. Please click on the attachment to read the original post.
8 REPLIES 8
mtb308
Associate II
Posted on November 20, 2013 at 03:38

Well, I figured out part of my problem, but not sure I understand why.  It seemed that the interrupt was firing twice as fast as it was supposed to.  With a cycle time of 239.5 (+12), and the ADC clocked at 48 MHz, it should complete a conversion at a rate of about 47.7 kHz.  I was getting ADC complete interrupts at a rate twice that. 

If I ignore every other interrupt, then I get the right ADC values, but still only half of them. 

It seems that there is an extra DMA transfer, corresponding with an extra ADC conversion (of what?), and so the Index gets incremented twice as much as it should.

Posted on November 20, 2013 at 04:02

I'm confused by the reason to enable a second ADC sample, and the temp/ref stuff?

ADC_TempSensorCmd(ENABLE);
/* Convert the ADC1 Vref with 5 Cycles as sampling time */
ADC_ChannelConfig(ADC1, ADC_Channel_Vrefint , ADC_SampleTime_239_5Cycles);
ADC_VrefintCmd(ENABLE);

Then again, I'm not spending any time with the F0 and ADC The use of DMA seems unnecessary if you're collecting/processing on EOC. I'd also wonder about if the DMA pointer is the slot the next sample goes too, not where the last one was stored.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
raptorhal2
Lead
Posted on November 20, 2013 at 04:19

.....and the F0 ADC clock is 14 MHz.

Cheers, Hal

mtb308
Associate II
Posted on November 20, 2013 at 04:23

EGADS!  Thank you and your eagle eyes. 

I removed that extra ADC_ChannelConfig, and now all is well!  That's what I get for a sloppy copy and paste job, now that seems obvious where the second ''mystery'' conversion was coming from.

Thanks again,

Marten

mtb308
Associate II
Posted on November 20, 2013 at 04:27

I thought that the maximum permitted ADC clock was 14 MHz, and the actual clock speed would depend on how it was configured.  With a 48 MHz system clock, and /4 for the ADC clock, it ends up at 12 MHz, unless the ADC clock is setup asynchronously from some other source, like a timer.

Is that not correct?

Marten

mtb308
Associate II
Posted on November 20, 2013 at 04:34

Regarding the DMA pointer, I think it is more convoluted then that.  The DMA_CNDTRx register counts down, indicating how many values are left to transfer, while the data in the circular buffer counts up (I think).  So the location of the last data is (Buf_Size - Index) (+/- 1), I'm not exactly sure.

mtb308
Associate II
Posted on November 20, 2013 at 22:09

FWIW, here are some photos of the filter working. This was done mainly for my education and familiarization with the STM32 F0 discovery board.

http://imgur.com/a/2egIS

I think that the code could be improved a lot, by either with some inline ASM, or at least unrolling the for loop. Code snippets:

//9 tap filter, 45% Available processing time
uint8_t Filter[NumTaps] = {5,12,31,50,58,50,31,12,5};
// Get index value NDT from DMA_CNDTR1 register
Index = DMA1_Channel1->CNDTR;
for(i = 0; i < 
NumTaps
; i++)
{
Acc += Filter[i]*InputData[(9-Index+i)%8];
//Divide by 256 to make gain unity in pass band
Acc >>= 8;
DAC_SetChannel1Data(DAC_Align_12b_R, Acc );

mtb308
Associate II
Posted on November 20, 2013 at 22:13

FWIW, here are some photos of the filter working. This was done mainly for my education and familiarization with the STM32 F0 discovery board.

http://imgur.com/a/2egIS

I think that the code could be improved a lot, by either with some inline ASM, or at least unrolling the for loop. Code snippets:

//9 tap filter, 45% Available processing time
uint8_t Filter[NumTaps] = {5,12,31,50,58,50,31,12,5};
// Get index value NDT from DMA_CNDTR1 register
Index = DMA1_Channel1->CNDTR;
for(i = 0; i < 
NumTaps
; i++)
{
Acc += Filter[i]*InputData[(9-Index+i)%8];
}
//Divide by 256 to make gain unity in pass band
Acc >>= 8;
DAC_SetChannel1Data(DAC_Align_12b_R, Acc );