I designed a PCB including a STM32F429, which is connected to an two channels (16Bit) simultaneous sampling ADC. The ADC has two inputs, which are sampled at the same time instance. The results are interleaved clocked out on the rising edge of an data clock source provided by the ADC. This clock source is attached to PA9, and used in combination with the timer TIM1_CH2 to trigger the DMA. The timer is configured as followed:
Code: Select all
// TIM1_CH2
palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(1));
rccEnableTIM1(FALSE);
rccResetTIM1();
// enable DMA2 clock
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
// 6 (TS): Trigger selection: Input 2 (TI2FP2)
// 4 (SMS): Reset Mode
TIM1->SMCR |= 0x0064;
// CC2 channel is configured as input, IC2 is mapped on TI2 -> input capture
TIM1->CCMR1 |= 0x0100;
// CC2 capture enabled
TIM1->CCER |= STM32_TIM_CCER_CC2E;
// CC2 DMA request enabled
TIM1->DIER |= STM32_TIM_DIER_CC2DE;
TIM1->CR2 |= STM32_TIM_CR2_CCDS;
// Enable Counter
TIM1->CR1 |= STM32_TIM_CR1_CEN;
// Polarity: falling edge (data is clocked out on the rising edge)
// -> sampling on the falling edge of the data clock source
// -> in the middle of the data state (HIGH or LOW)
TIM1->CCER |= STM32_TIM_CCER_CC2P;
TIM1->CCER &= ~STM32_TIM_CCER_CC2NP;
To test the system, two sinewaves with a phaseshift of 90° are used, which are provided by a two channel laboratory AWG. Here is the DMA configuration:
Code: Select all
static uint16_t ADC_buffer[60000] = {0}; // static global memory
static void ADCsampling(void) {
memset(ADC_buffer, 0, sizeof ADC_buffer); // ensures "empty" buffer, for multiple uses
uint16_t samples = 25000; // an abritrary sample number
// Allocate the stream
dmaStreamAllocate(STM32_DMA2_STREAM2, 0, NULL, NULL);
// Set the source Address
dmaStreamSetPeripheral(STM32_DMA2_STREAM2, &(GPIOD->IDR));
// config 16-bit HWORD transfers, peripheral to memory,
// fixed source address, inc dest address
dmaStreamSetMode( STM32_DMA2_STREAM2,
STM32_DMA_CR_PL(3) | STM32_DMA_CR_PSIZE_HWORD |
STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_P2M |
STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
STM32_DMA_CR_CHSEL(6));
// Set the destination address
dmaStreamSetMemory0(STM32_DMA2_STREAM2, ADC_buffer);
// set the size of the output buffer
dmaStreamSetTransactionSize(STM32_DMA2_STREAM2, samples);
chThdSleepMilliseconds(100);
dmaStreamSetFIFO(STM32_DMA2_STREAM2,0);
chThdSleepMilliseconds(100);
dmaStreamEnable(STM32_DMA2_STREAM2);
// waite until all samples are transmitted:
// NDT = 0 and sets TCIF2 HIGH
while ((DMA2->LISR & 0x00200000) == 0){
}
// check if a transfere error occured (TEIF2)
if ((DMA2->LISR & 0x00080000) == 1){
palTogglePad(GPIOB, 10); // LED is connected to this Pin
}
chThdSleepMilliseconds(100);
SEND DATA TO PC. // LWIP is used, for simplicity the corresponding code is removed
dmaStreamDisable(STM32_DMA2_STREAM2);
dmaStreamRelease(STM32_DMA2_STREAM2);
}
The results of the two simultanous ADC stages are interleaved outputed. At the PC i can easily split this data stream to represent each channel.
To come to the problem now. I receive two clear/good looking sine waves whit the correct amplitude. However, the phase gets corrupted. The ADC samples its inputs continously and clocks the data out, the whole time. If I perform a DMA instruction several times, somtimes I get the correct phase of 90°. But most times there is a phase shift, which corresponds to ONE sample instance. I plotted the two sinewaves in one graph. For the corruped phase, I observed (sometimes) a mutual sample value at the begin of the data stream. So it looks like one ADC result is shifted by one sample.
Have I configured the Timer or the DMA wrong? I cannot explain this strange behaviour, I'm operating the system at a fairly low data clock rate of ~1.5 MHz. For me it looks like, in the beginning went something wrong with the memory pointer, but I don't know how to check this.
Maybe someone has a clue, what I'm making wrong .
BR Skadi