Hello,
I just wanted to interleave 3 of my ADCs of my STM32F429ZIT6 and store the data via DMA in a buffer with a length of 3000. The PCLK2 is 45MHz so since each ADC takes 5 cycles to output a result I should be able to get from 4.5 to 1.125 Msps depending on the Prescaler value. I'm using the lowest prescale value at the moment so I should get
4.5 Msps.
At first, I started to write my own code but I realized that
some user has an example for this specific application, and I decided to use that. In the example the configuration is as follows:
- The buffer is uint32_t
- The three ADCs are configured for the same channel obviously
- ADC1 is set to:
DMAContinuousRequests = ENABLE,
ContinuousConvMode = ENABLE- ADC2&3 are set to:
DMAContinuousRequests = DISABLE,
ContinuousConvMode = ENABLE-
mode.Mode = ADC_DUALMODE_INTERL-
mode.DMAAccessMode = ADC_DMAACCESSMODE_2- So my first problem is that the weird thing about this example is it is configured in Dual Interleaved Mode. Is that a mistake? Should it be configured as ADC_TRIPLEMODE_INTERL instead?
Then I tried the code and to check whether the code works, I added a HAL_GPIO_TogglePin in both
HAL_ADC_ConvCpltCallback &
HAL_ADC_ConvHalfCpltCallback , and I also added a breakpoint in both the toggle lines for debugging. At first when I tried the
ADC_DUALMODE_INTERL and
ADC_DMAACCESSMODE_2 I got a period of 2 ms on the GPIO pin, which means that I was getting 3000/0.002=1.5Msps If I'm doing the math right. So I think DUALMODE should be changed into TRIPLEMODE, right?
So I changed it into
TRIPLEMODE and the
DMA Access Mode still set to
2 and the rest of the configs unchanged, and I got a period of 1.332 ms on the GPIO pin, which corresponds to 3000/0.001332=2.25 Msps which is half of the 4.5 Msps expected rate, Which is again weird.
And the next weird thing happened was when I ran the code in debug mode, although I put a breakpoint in the half and full conversion callbacks, the code would stop only when the full length of the buffer is filled.
- So my second problem is why it doesn't callback at the half-length of the buffer? i.e it breaks at the HAL_ADC_ConvHalfCpltCallback but when it does the buffer is already filled up.
That might also be the reason why I was reading half the expected sample rate. The buffer is actually filled at the twice speed I was reading.
- And my third problem is that in ADC_DMAACCESSMODE_2 according to the datasheet we have:
1st request: ADC_CDR[31:0] = ADC2_DR[15:0] | ADC1_DR[15:0]
2nd request: ADC_CDR[31:0] = ADC1_DR[15:0] | ADC3_DR[15:0]
3rd request: ADC_CDR[31:0] = ADC3_DR[15:0] | ADC2_DR[15:0]
4th request: ADC_CDR[31:0] = ADC2_DR[15:0] | ADC1_DR[15:0], ...
So in order to process the data stored in the buffer, later I would need to convert this 32-bit array into a 16-bit buffer of double the length, which would take some time and need some processing power. So now I thought if I could use the
ADC_DMAACCESSMODE_1 then I should be able to get the data in the required 16-bit format which would take double DMA requests but would, in turn, reduce the processing time. So I changed the
DMA access mode to
1, and did the same GPIO period measurement. The period is 500us which would give us 3000/0.0005 = 6 Msps! So what just happened here? How can I properly set it up in the Access Mode 1?
Thanks in advance