DMA ADC çalışıyor, işlemci çalışmıyor

Başlatan papsukkal, 03 Mayıs 2024, 15:05:54

papsukkal

İşte yeni bir sıkıntımla karşınızdayım.

Çin'den sipariş verdiğim STM32G030F6 işlemcilerim geldi. 32F030F4 için yazdığım kodu hemen aktardım. bütün konfigürasyonları birebir uyguladım ve çalıştırdım. her şey normal ama...

ADC çevrimini DMA ile yapıyorum. aynı zamanda DMA üzerinde iki kanal da PWM var.. PWM de sıkıntı yok iken ADC yi CIRCULAR modda aktifleştirdiğim anda işlemci yaptığı bütün işleri askıya alıp ADC ye yöneliyor. Sadece ADC Circular devrede değilken ya da DMA ContinuousRequest Disable iken main fonksiyona giriyor.

F030 da sıkıntı yok iken G030 daki bu durum G serisine özel bir durum mu? yoksa Çin'den gelen işlemcilerde mi bir hata olabilir?

Bu durum G030 serisinin genel özelliği ise nasıl aşılır?

/* USER CODE BEGIN PV */

uint32_t adc_deger[2];

/* USER CODE END PV */

  /* USER CODE BEGIN 2 */
  HAL_ADC_Start_DMA(&hadc1, adc_deger, 2);

  /* USER CODE END 2 */

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
	  HAL_Delay(500);
  }

/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.LowPowerAutoPowerOff = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.NbrOfConversion = 2;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_79CYCLES_5;
  hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_79CYCLES_5;
  hadc1.Init.OversamplingMode = DISABLE;
  hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
 

static void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

}



RaMu

MX_DMA_Init();
MX_ADC1_Init():

Init sırasıyla önce DMA, sonra ADC olacak şekilde mi olduğuna dikkat edin.
Bazı cube versiyonlarında böyle bir sıkıntı yaşamıştım.

Bunun haricinde işlemci hızı yüksekse
hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_79CYCLES_5;
ADC sampling time ı yükseltmeyi deneyin.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

papsukkal

Alıntı yapılan: RaMu - 03 Mayıs 2024, 21:56:26
MX_DMA_Init();
MX_ADC1_Init():

Init sırasıyla önce DMA, sonra ADC olacak şekilde mi olduğuna dikkat edin.
Bazı cube versiyonlarında böyle bir sıkıntı yaşamıştım.

Bunun haricinde işlemci hızı yüksekse
hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_79CYCLES_5;
ADC sampling time ı yükseltmeyi deneyin.

Hocam init sıralaması dediğiniz gibi. Önce DMA, sonra ADC. Sample time değerini  160.5 yaptım problem devam ediyor.

RaMu

hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

Satırı aşağıdaki gibi olması gerekir sanırım.

hadc1.Init.EOCSelection = EOC_SEQ_CONV;.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

papsukkal

Alıntı yapılan: RaMu - 03 Mayıs 2024, 23:32:20
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

Satırı aşağıdaki gibi olması gerekir sanırım.

hadc1.Init.EOCSelection = EOC_SEQ_CONV;.

@RaMu hocam gene aynı. Analog dönüşüm yapıyor. Ancak kod yürütmüyor. Led yanıyor ama sönmüyor.

RaMu

Muhtemelen ADC çok hızlı oluyor ve main e vakit kalmıyor.
Çözüm olarak timer triggered ADC DMA kullanabilirsin.

hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
Adc yi yavaşlatmak için Div8 vs. deneyebilirsin.

Birde data width word seçtin mi?
uint32_t adc_deger[2];
kullanmışsın;



https://controllerstech.com/stm32-adc-multiple-channels/
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

papsukkal

#6
Data with word seçili. Direk div 32 yaptım Hocam. Çalıştı. Teşekkür ederim. DMA core dan bağımsız çalisiyor zannediyordum ben demek ki yanlış biliyormuşum.

papsukkal

#7
"Direct memory access (DMA) is a feature of computer systems that allows some hardware devices (either internal or external) to communicate directly with another computer system's RAM memory and transfer data from it without processing it using the CPU."

Google böyle diyor.

Buna göre işlemcinin div=2 iken çalışmamasını anlayamadım. DMA çalışma yapısını ya da neden çalışmadığını anlatabilir misiniz?

RaMu

Kısaca anlatabileceğim bir şey değil ama genel olarak:

Evet DMA CPU dan bağımsız çalışıyor ama ram e erişim esnasında sadece biri RAM e erişebiliyor, temel sıkıntı bu.
Ayrıca DMA kesme üretiyor bu kesmeninde işlemmesi lazım.
Senin ayarlarında ADC iki kanal ardışık birer defa ölçüldüğünde ADC DMA transferi gerçekleşiyor ve bir kesme üretiliyor.

DMA ve CPU ortak kullanılan BUS lara erişim yalnızca biri tarafından yapılabileceği için
DMA CPU bağımsız çalışır yaklaşımı tam doğru olmuyor.

STM32 DMA CPU collision gibi arama yapabilirsin.

Kısaca DMA CPU dan bağımsız çalışır ama CPU ya yük veya engel olduğu durumlar vardır.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

papsukkal