Skip to main content
mtb308
Associate
November 19, 2013
Question

Strange results, ADC by DMA (with scope shots)

  • November 19, 2013
  • 8 replies
  • 1711 views
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.
    This topic has been closed for replies.

    8 replies

    mtb308
    mtb308Author
    Associate
    November 20, 2013
    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.

    Tesla DeLorean
    Guru
    November 20, 2013
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
    raptorhal2
    Lead
    November 20, 2013
    Posted on November 20, 2013 at 04:19

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

    Cheers, Hal

    mtb308
    mtb308Author
    Associate
    November 20, 2013
    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
    mtb308Author
    Associate
    November 20, 2013
    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
    mtb308Author
    Associate
    November 20, 2013
    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
    mtb308Author
    Associate
    November 20, 2013
    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
    mtb308Author
    Associate
    November 20, 2013
    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 );