STM32 ADC Fast Interleaved Mode hakkında soru

Başlatan strom, 10 Ocak 2015, 01:07:47

strom

Herkese iyi günler.
SMT32F429 referance manualinde anlatılanlardan pek birşey anlamadım. Tek anladığım daha hızlı çevrim yapılmasına imkan verdiği. Ancak ne nette ne de referance manualde tam olarak nasıl çalıştığını bulamadım.

Mesela normal mod kullandığımızda; varsayalım sampling time'ı 3cycle olarak ayarladık. 12bit çözünürlük için adc çevrimi 15cycle'da yapılıyor. Bu süreyi test etmek için  DMA'yı ayarlayıp, 1000 çevrim yaptırıp, bu çevriminde ne kadar sürede tamamlandığını görmek için timer kullandığımda gerçekten toplam geçen sürenin 15000 ADC cycle'ı olduğunu gördüm.
Benzer bir deneyi interleaved mod için uyguladım. Gerçektende 1000 çevrim, aynı ayarlarda (3cycle sample time ve 12bit çözünürlük) yaklaşık 3te1 hızda gerçekleşti. Ancak değişen bu hızı belirleyen faktörler neler onu anlamadım. Örnek kodu vermek gerekirse;

#include "adc_with_dma.h"

void ADC_Init()
{
  RCC_APB2PeriphClockCmd(RCC_APB2ENR_ADC1EN, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2ENR_ADC2EN, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1ENR_DMA2EN, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1ENR_GPIOAEN, ENABLE);
  
  ADC_CommonInitTypeDef adccom;
  ADC_InitTypeDef adc;
  DMA_InitTypeDef dma;
  GPIO_InitTypeDef  gpio;
  NVIC_InitTypeDef nvic;
  
  
  /*Configure ADC Pins*/
  gpio.GPIO_Mode = GPIO_Mode_AIN;
  gpio.GPIO_OType = GPIO_OType_PP;
  gpio.GPIO_PuPd = GPIO_PuPd_UP;
  gpio.GPIO_Speed = GPIO_Speed_50MHz;
  gpio.GPIO_Pin = GPIO_Pin_5;
  GPIO_Init(GPIOA, &gpio);
  
  /*Configure ADC's Common Settings*/
  adccom.ADC_DMAAccessMode      = ADC_DMAAccessMode_1;
  adccom.ADC_Mode               = ADC_DualMode_Interl;
  adccom.ADC_Prescaler          = ADC_Prescaler_Div4;
  adccom.ADC_TwoSamplingDelay   = ADC_TwoSamplingDelay_10Cycles;
  ADC_CommonInit(&adccom);
  
  /*Configure ADC1*/
  adc.ADC_ContinuousConvMode    = ENABLE;
  adc.ADC_DataAlign             = ADC_DataAlign_Right;
  adc.ADC_ExternalTrigConv      = ADC_ExternalTrigConvEdge_None;
  adc.ADC_ExternalTrigConvEdge  = ADC_ExternalTrigConvEdge_None;
  adc.ADC_NbrOfConversion       = 1;
  adc.ADC_Resolution            = ADC_Resolution_12b;
  adc.ADC_ScanConvMode          = DISABLE;
  ADC_Init(ADC1, &adc);
  ADC_Init(ADC2, &adc);
  
  /*Configure DMA*/
  dma.DMA_BufferSize          = 1000;
  dma.DMA_Channel             = DMA_Channel_0;
  dma.DMA_DIR                 = DMA_DIR_PeripheralToMemory;
  dma.DMA_Memory0BaseAddr     = (uint32_t) ADCBuffer;
  dma.DMA_MemoryBurst         = DMA_MemoryBurst_Single;
  dma.DMA_MemoryDataSize      = DMA_MemoryDataSize_HalfWord;
  dma.DMA_MemoryInc           = DMA_MemoryInc_Enable;
  dma.DMA_PeripheralBaseAddr  = (uint32_t) &ADC->CDR;
  dma.DMA_PeripheralBurst     = DMA_PeripheralBurst_Single;
  dma.DMA_PeripheralDataSize  = DMA_PeripheralDataSize_HalfWord;
  dma.DMA_PeripheralInc       = DMA_PeripheralInc_Disable;
  dma.DMA_Mode                = DMA_Mode_Circular;
  dma.DMA_FIFOMode            = DMA_FIFOMode_Disable;
  dma.DMA_FIFOThreshold       = DMA_FIFOThreshold_1QuarterFull;
  dma.DMA_Priority            = 0;  
  DMA_Init(DMA2_Stream4, &dma);
  
  ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_3Cycles);  
  ADC_RegularChannelConfig(ADC2, ADC_Channel_5, 1, ADC_SampleTime_3Cycles);
  
  /*Configure DMA's interrupt*/
  nvic.NVIC_IRQChannelCmd = ENABLE;
  nvic.NVIC_IRQChannelPreemptionPriority = 0;
  nvic.NVIC_IRQChannelSubPriority = 0;
  nvic.NVIC_IRQChannel = DMA2_Stream4_IRQn;
  NVIC_Init(&nvic);
  
  
  /*Other settings*/
  DMA_ITConfig(DMA2_Stream4, DMA_IT_TC, ENABLE);
  ADC_DMACmd(ADC1, ENABLE);
  ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
  DMA_Cmd(DMA2_Stream4, ENABLE);
  ADC_Cmd(ADC1, ENABLE);
  ADC_Cmd(ADC2, ENABLE);
  
}


Burda mesela   ADC_RegularChannelConfig fonksiyonu ile iki ADC içinde aynı kanaldan çevrim yapılacak şekilde ayarlıyoruz. Peki her bir adc için sampling time'ı değiştirsem, bu toplam çevrim süresini nasıl değiştirir?
Ayrıca ADC_TwoSamplingDelay_10Cycles bu değeri değiştirdiğimde de toplam çevrim süresi değişiyor. Ancak bununda nasıl bir katkısı olduğunu anlayamadım. Reference manual bana çok açıklayıcı gelmedi. Daha önce bu modu kullanan biri beni aydınlatırsa çok sevinirim.

strom

Detaylı araştırmalarım sonucu bazı bilgiler edindim. Sanırım şu şekilde işliyor olay;

Ölçümün süresi tamamen ADC_TwoSamplingDelay_10Cycles değeri ile belirleniyor. Datasheette bunu anlatmaya çalışmış. Diyorki; eğer fast interleaved kullanıyorsanız, ölçüm yapacağınız kanalın sampling time'ı maksimum 3cycle olmalı. Bu durumda toplam çevrim süresi TwoSamplingDelay + 2 cycle'da çevrim işlemi tamamlanır.
Ancak yaptığım bazı denemelerde bu durumun böyle olmadığını gördüm. Şöyleki; tek ADC ile 1000 tane ölçüm yaptığımda, bu ölçümün kaç cycle'da tamamlandığını görmek için kullandığımın timerın değeri 60000 oluyor (teorik hesaplamalarımda da böyle çıkıyor. Yani hesaplamalarımla birebir uyumlu). Daha sonra dual interleaved mod'u seçip, TwoSamplingDelay'ı 5cycle ayarladığımda datasheete göre yaklaşık 30000 filan görmem gerek (5cyle + 2cycle = 7cycle ediyor datasheete göre. Normal modda ise 15cycle'da tamamlanıyordu çevrim. Yani yaklaşık iki katı hızda. Bu durumda timer 30000 göstermesi gerekiyor). Ancak yaptığım denemelerde timer 20000 değerini gösterdi. Yani çevrim 5cyle'da bitmiş görünüyor. Datasheette belirtildiği gibi 7cycle'da değil. AdcTwoSamplin delay'ı 10cycle yaptığımda ise yine timer 20000'i gösteriyor. Bu işte bi gariplik var

Timer ölçümünü yaptığım kod ise bu;

  void DMA2_Stream4_IRQHandler()
  {  
    ADC->CCR &= ~(0xF);
    tim = TIM_GetCounter(TIM7);
    TIM_Cmd(TIM7, DISABLE);
    TIM_SetCounter(TIM7, 0);
    TIM_Cmd(TIM7, ENABLE);
    ADC->CCR |= (0xF);
    DMA_ClearFlag(DMA2_Stream4, DMA_IT_TCIF4 | DMA_IT_HTIF4);

  }

GreeN

STM32F4X   7.2 MSample/sec adc hızına çıkabiliyor. Triple Mode Interleaved , bu modda çalışırken 3 kanal adc birden çalışıyor.
adc1 örneklemeye başlıyor , 5 clock sonra adc2 ,adc2 den 5 clock sonrada adc3 örneklemeye başlıyor.

adc1'in ilk örneği 15 clock'ta hazır oluyor. Daha sonra her 5 clock'ta bir örnek elde edersin. Düz modda 15 clock olan süre triple modda 5 clock a düşer. 3 katı hız demek olur.
(stm32f407vg discovery board üzerinde triable modda sıkıntı var. adc girişşinde dc ofset oluşuyor. sendeki board ta sonucu paylaşır mısın?)
Terörü Lanetliyoruz.

z

ADC girişlerini opamp çıkışlarına bağlarsan ofset yok olur.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com