Örnek:STM32 ST_Lib ADC + DMA (Çok kanal)

Başlatan Klein, 18 Kasım 2012, 23:08:00

SpeedyX

Dual Simultaneous Sampling ile ilgilenen var mı?

Örneğin ADC1 ile 2 kanal, ADC3 ile 2 kanal (ve ADC2 ile 2 kanal) ölçümü DMA ve Dual modda mümkün olan en hızlı şekilde nasıl yapabiliriz?
ADC1 i dual mod kurup DMA ile okutup sonucu RAM e yazabiliriz, aynı şekilde başka DMA kanallarıyla da ADC3 (ve ADC2) yi okutabilir miyiz? Aynı DMA da bir de DAC işlemleri olsa DMA her işlemi sırayla mı yapar yoksa tüm kanallar paralel çalışabiliyor mu?


Yukarıdaki kodun, eksiklerinin tamamlanmış hali:
/**
  ******************************************************************************
  * @file    ADC/3ADCs_DMA/main.c 
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    08-April-2011
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"

/** @addtogroup STM32F10x_StdPeriph_Examples
  * @{
  */

/** @addtogroup ADC_3ADCs_DMA
  * @{
  */ 

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define ADC1_DR_Address    ((uint32_t)0x4001244C)
#define ADC3_DR_Address    ((uint32_t)0x40013C4C)

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
__IO uint16_t ADC1ConvertedValue = 0, ADC3ConvertedValue = 0, ADC2ConvertedValue = 0;

/* Private function prototypes -----------------------------------------------*/

/* Private functions ---------------------------------------------------------*/

void ADC1_2_IRQHandler(void)
{
  /* Get injected channel13 converted value */
  ADC2ConvertedValue = ADC_GetConversionValue(ADC2);
}

/**
  * @brief   Main program
  * @param  None
  * @retval None
  */
void ADC_DMA_INIT(void)
{
  ADC_InitTypeDef ADC_InitStructure;
  DMA_InitTypeDef DMA_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;

  /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
     */     
       
  /* System clocks configuration ---------------------------------------------*/
  /* ADCCLK = PCLK2/4 */
  RCC_ADCCLKConfig(RCC_PCLK2_Div4); 
  /* Enable peripheral clocks ------------------------------------------------*/
  /* Enable DMA1 and DMA2 clocks */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 | RCC_AHBPeriph_DMA2, ENABLE);

  /* Enable ADC1, ADC2, ADC3 and GPIOC clocks */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 |
                         RCC_APB2Periph_ADC3 | RCC_APB2Periph_GPIOC, ENABLE);


  /* NVIC configuration ------------------------------------------------------*/
  /* Configure and enable ADC interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);


  /* GPIO configuration ------------------------------------------------------*/
  /* Configure PC.02, PC.03 and PC.04 (ADC Channel12, ADC Channel13 and 
     ADC Channel14) as analog inputs */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
  
  
  /* DMA1 channel1 configuration ----------------------------------------------*/
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC1ConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 1;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);  
  /* Enable DMA1 channel1 */
  DMA_Cmd(DMA1_Channel1, ENABLE);

  /* DMA2 channel5 configuration ----------------------------------------------*/
  DMA_DeInit(DMA2_Channel5);
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC3_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC3ConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 1;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA2_Channel5, &DMA_InitStructure);  
  /* Enable DMA2 channel5 */
  DMA_Cmd(DMA2_Channel5, ENABLE);

  /* ADC1 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);
  /* ADC1 regular channels configuration */ 
  ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_28Cycles5);    
  /* Enable ADC1 DMA */
  ADC_DMACmd(ADC1, ENABLE);

  /* ADC2 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC2, &ADC_InitStructure);
  /* ADC2 regular channels configuration */ 
  ADC_RegularChannelConfig(ADC2, ADC_Channel_13, 1, ADC_SampleTime_28Cycles5);
  /* Enable ADC2 EOC interrupt */
  ADC_ITConfig(ADC2, ADC_IT_EOC, ENABLE);

  /* ADC3 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC3, &ADC_InitStructure);
  /* ADC3 regular channel14 configuration */ 
  ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 1, ADC_SampleTime_28Cycles5);
  /* Enable ADC3 DMA */
  ADC_DMACmd(ADC3, ENABLE);

  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);

  /* Enable ADC1 reset calibration register */   
  ADC_ResetCalibration(ADC1);
  /* Check the end of ADC1 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC1));

  /* Start ADC1 calibration */
  ADC_StartCalibration(ADC1);
  /* Check the end of ADC1 calibration */
  while(ADC_GetCalibrationStatus(ADC1));

  /* Enable ADC2 */
  ADC_Cmd(ADC2, ENABLE);

  /* Enable ADC2 reset calibration register */   
  ADC_ResetCalibration(ADC2);
  /* Check the end of ADC2 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC2));

  /* Start ADC2 calibration */
  ADC_StartCalibration(ADC2);
  /* Check the end of ADC2 calibration */
  while(ADC_GetCalibrationStatus(ADC2));

  /* Enable ADC3 */
  ADC_Cmd(ADC3, ENABLE);

  /* Enable ADC3 reset calibration register */   
  ADC_ResetCalibration(ADC3);
  /* Check the end of ADC3 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC3));

  /* Start ADC3 calibration */
  ADC_StartCalibration(ADC3);
  /* Check the end of ADC3 calibration */
  while(ADC_GetCalibrationStatus(ADC3));

  /* Start ADC1 Software Conversion */ 
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
  /* Start ADC2 Software Conversion */ 
  ADC_SoftwareStartConvCmd(ADC2, ENABLE);
  /* Start ADC3 Software Conversion */ 
  ADC_SoftwareStartConvCmd(ADC3, ENABLE);
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}

#endif

/**
  * @}
  */ 

/**
  * @}
  */ 

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

camby

#16
Alıntı yapılan: Klein - 18 Kasım 2012, 23:08:00
STM 32 içerisindeki ADC'lerde Regular kanalların tümü için sadece 1 adet sonuç registeri var.
Eğer ADC scan modda ise ve birden fazla kanal çevirime giriyorsa; ADC çevrimi tamamlayınca değer bu registere yazılıyor ve bir sonraki çevrime geiliyor. Bu çevrim de bittiğinde, sonuç yine aynı registere yazılıyor. 
Bir sonraki çevirim bitmeden ADC'yi okudunuz okudunuz. Okuyamazsanız o kanalın verisine elveda deyin.

ADC'yi  tek kanal çalıştırıp, Scan modu kapatıp, her çevirim bittiğinde değeri okumak ve birsonraki kanalı SQR registerine yazıp, çevirimi tekrar başlatmak bir çözüm.

Eğer ben her seferinde tüm kanalları taramayayım ADC kendisi SCAN etsin istiyorsanız, yukarıda bahsettiğim sebepten ötürü işler biraz karışıyor.   Eğer scan mode kullanılıyorsa, loop içinde bu çevirimlere yetişmek mümkün değil. İlla ki interrupt kullanmak gerekiyor. 
STM32F1'de  interrupt kullanmak ta çözüm değil.  Çünkü kesme  tüm kanalların çevirimi bittikten sonra geliyor.
STM32F4'te CR2 registerinde EOCS biti vardı. Bunu set ederek , her kanalın çevirimi bittiğinde kesme üret diyebiliyorduk. Ama STM32F1'de bu bit yok. (Belki benzer bir şey var ama ben bulamadım)

Bu durumda geriye tek seçenek  DMA kullanmak kalıyor. DMA kullandığınızda her kanalın çevrimi bittiğinde DMA bu değeri alıp, sırayla istediğiniz adreslere yazıyor. 

Önce donanımlara saat sinyali sağlayalım ve port ayarlarını yapalım.
void init_gpio(void){
GPIO_InitTypeDef  GPIO_InitStructure;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1 | GPIO_Pin_2 |GPIO_Pin_3 | \
		 	   GPIO_Pin_4 |GPIO_Pin_5 | GPIO_Pin_6 |GPIO_Pin_7 ;
GPIO_Init(GPIOA, &GPIO_InitStructure);

}

void init_rcc(void){
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1 | RCC_APB2Periph_AFIO,ENABLE);
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
}


uint16_t ADC_ValArray[8]; // ADC değerlerimiz bu diziye atılacak



ADC Ayarlarımızı yapalım.
void init_adc1(void)
{
ADC_InitTypeDef  ADC_InitStructure;

  RCC_ADCCLKConfig(RCC_PCLK2_Div2); 
  ADC_DeInit(ADC1);

  ADC_InitStructure.ADC_ScanConvMode = ENABLE; // tarama modu açık
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // sürekli çevirim yapacağız
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 8; // sekiz kanal tarayacağız.
  ADC_Init(ADC1, &ADC_InitStructure);

  ADC_Cmd(ADC1, ENABLE); 

  ADC_ResetCalibration(ADC1);
  while(ADC_GetResetCalibrationStatus(ADC1));

  ADC_StartCalibration(ADC1);
  while(ADC_GetCalibrationStatus(ADC1));
}


Hangi kanalların çevirime gireceğini ve hangi sırada çevirime gireceklerini ayarlayalım.
void adc_channel_config(void){
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_1, 2, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_2, 3, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_3, 4, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_4, 5, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_5, 6, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_6, 7, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_7, 8, ADC_SampleTime_239Cycles5);
}


ADC1 için DMA Ayarlarını yapalım.
void ADC1_DMAConfig(void){
DMA_InitTypeDef DMA_InitStructure;

  DMA_Cmd(DMA1_Channel1,DISABLE);
  DMA_DeInit ( DMA1_Channel1);

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0x4001244C; // ADC->DR Adresi
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) ADC_ValArray; // hedef adresimiz
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // ADC kaynak. Veri yönü ADC -> Hafıza 
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // ADC adresi sabit kalacak
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // Her değer alındığına memory adresi 1 artırılacak
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  // Kaynaktan alınacak veri 16 bit
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // Hedef büyüklüğü 16 bit
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 8 veri alındıktan sonra başa dönülecek.
  DMA_InitStructure.DMA_Priority = DMA_Priority_High ; // Kanal Önceliği yüksek. ( bu bize kalmış)
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // hafızadan hafızaya transfer kapalı. 
  DMA_InitStructure.DMA_BufferSize = 8; // Alacağımız verisayısı 8 ( 8 kanal adc okuyacağız) 
  
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  DMA_Cmd(DMA1_Channel1,ENABLE);

}
 

int main(void){
     init_rcc();
     init_gpio();
     adc_channel_config();
     init_adc1();
    ADC1_DMAConfig();
    ADC_DMACmd(ADC1,ENABLE);
    ADC_SoftwareStartConvCmd(ADC1,ENABLE); // çevirimi başlatıyoruz.
while(1)
{
}

}


8 kanalın değeri dizimizde hazır.

---------------------------

Hocam bu örnekler , hangi st lib versiyonu ile yazılmış ? Kullanmaya çalışıyorum direk ama dma.c ve dma.h dosyası içindeki neredeyse tüm tanımlamalar farklı. ADC ve diğer modüller için de bu geçerli. Acaba benim kullandığım mı eski sizinki mi ?


Benim kullandıklarım :

  * @file    stm32f4xx_dma.c
  * @author  MCD Application Team
  * @version V1.0.2
  * @date    05-March-2012


------------------

İşin garibi zipli bir şekilde indirdim driver dosyası içindeki kütüphane ve örnek kodlar arasında uyuşmazlık var.

İndirdiğim dosyanın adı : STM32F4xx_DSP_StdPeriph_Lib_V1.0.1

Dosya içindeki "STM32F4xx_StdPeriph_Driver" klasöründe bulunan library dosyalarının versiyonları hep V1.0.2

Aynı dosya içinde example bölümünde yazılmış olan kodlar da V1.0.1 için yazılmış.

.h header dosyalarında tanımlamalar v1.0.2'de farklı olduğu için çalışmıyor.

ST neden böyle bir şey yapıyor ? Ben bir birşeyleri karıştırıyorum acaba , kontrol edebilir misiniz ?

--------------------

Sitede şimdi de v.1.1.0 diye bir şey gördüm , onu indiriyorum...

Sürekli ST driverlarını değiştirecek , eski yazılmış programlar birbirine girecek.....


ADC_Init içinden , ADC_CommonInitStructure diye birşey türetmişler , bazı parametreleri oraya almışlar flan filan uzayıp gidiyor.....

/* ADC Common Init **********************************************************/
	ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
	ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
	ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
	ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
	ADC_CommonInit(&ADC_CommonInitStructure);

Klein


camby

#18
Alıntı yapılan: Klein - 09 Nisan 2013, 14:28:54
Örnek STM32F10x için.

Evet hocam ama V1.0.1 ile V1.0.2 arasında farklılıklar var. Yukarıdaki mesajımda sonradan yazdım , stm'den indirilen dosyadaki library ve örnek kodlar bile birbiri ile uyumsuz versiyonda gözüküyor. Neyse karıştırıp çözeceğim..



Klein

/**
  ******************************************************************************
  * @file    stm32f10x_dma.h
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    11-March-2011
  * @brief   This file contains all the functions prototypes for the DMA firmware
  *          library.
  ******************************************************************************

camby

tamam çalıştırdım..

V1.0.1 ile V1.0.2 gibi farklılar görünce stm32f4 library'de sıkıntı var diye düşündüm. Sıkıntı yok gibi.

Klein

DMA kanalları paralel çalışmıyor. Ancak Öncelik (veya önem) sırası ayarlanabiliyor.

Çok kanallı multiplex ADC'lerde kanalların birbirine sarkması gibi bir sorun var. Bu sadece STM32'nin ADC'si için geçerli değil. Tümünde böyle bir sorun var. Sorun ölçüm yönteminin doğasından kaynaklanıyor. Daha Önce de Z hocam bahsetmişti bir başlıkta.
Çok hızlı örnekleme ve kanal değişimi yaptığınızda , sample-hold kapasitesi tam boşalmadığı için diğer kanalın ölçüm sonucu değişiyor.
Eğer ADC girişini besleyen kaynağın empedansı yüksekse, bu daha da belirgin oluyor.
Eğer çok hızlı bir uygulama yapılacaksa , analog gerilim bir opamptan geçirilmeli. Ya da hız düşürülmeli.

SpeedyX

Hocam Dual Sampling de adc 2 kanalından aynı anda okuyor gibi bir durum olmalı. Örneğin DAC ı dual kullanarak 2 kanala ait 16 bit verileri 32 bitlik bir sayı olarak direkt update edebiliyorsunuz.

Örneğin DMA1 = DAC oldu, DMA3=ADC oldu. Bunlar paralel çalışır diye düşünüyorum. Fakat aynı DMA nın farklı kanalları seri çalışıyor.

Klein

Sözüm Aynı DMA'nın farklı kanalları içindi zaten.
Ancak
Farklı DMA kanalları bile olsa, ikisi de belleğe yazma ve bellekten okuma yaparken adres ve veri yolunu kullanacaklar. Biri belleğe yazarken diğeri bekleyecek.
Veri yolu ve adres yolununun nasıl paylaşıldığını bilmiyorum. 

SpeedyX

Muhtemelen priority mantığına göre yürüyordur.

ADC DAC mantığında işlemler paralel sayılabilir, çünkü ADC max 1us de sample alabiliyorsa, DAC da 0.25us de update edilsin, 36Mhz veri yolu hızı olduğuna göre... Zaten adc done bayrağı 1 Mhz hızla set oluyor.

mistek

Klein hocam ilk mesajınızda anlattığınız durumda DMA bizim ADC dizimizi her kanalın verisiyle doldurduktan sonra circular ayarladığımız için 2. turu atarken 1. turdaki verileri okuduk okuduk okuyamazsak onlarıda kaybedeceğiz değil mi?

Birde mesela 8 kanal ADC kullanıyorum ancak 1 ADC kanalının t=3 süresindeki değerini almak istiyorum. Bunu yapmak için ADC dizisinin ilgili elemanını t=3 anında okumam ile doğrudan o kanalı okumam arasında bir fark var mı?
boş işlerin adamı ---- OHM Kanunu: I = V/R ---- Güç Formülü: P = V*I = I^2*R = V^2/R

Klein

Evet veri kaybolur.  Eğer T=3 verisini okumak istiyorsanız , Buffer uzunluğunu 3 kat artırıp, DMA buffer uzunluğunu 3 kat verirseniz 3 tur sonunda başa döner. Bufferin 3. bölümünü işlersiniz.
Doğrudan o kanalı okumaktan kasıt nedir? DMA kullanmadan mı?

mistek

Alıntı yapılan: Klein - 05 Eylül 2013, 07:04:35
Evet veri kaybolur.  Eğer T=3 verisini okumak istiyorsanız , Buffer uzunluğunu 3 kat artırıp, DMA buffer uzunluğunu 3 kat verirseniz 3 tur sonunda başa döner. Bufferin 3. bölümünü işlersiniz.
Doğrudan o kanalı okumaktan kasıt nedir? DMA kullanmadan mı?

Evet hocam DMA kullanmadan.

7 kanal sürekli olarak okunması gerekiyor sadece 1 tanesinin t=3  t=8 t=n anındaki değeri lazım, sadece bu kanala ait t=1 ve t=2 değerleri kaybolabilir problem değil.
boş işlerin adamı ---- OHM Kanunu: I = V/R ---- Güç Formülü: P = V*I = I^2*R = V^2/R

Klein

Doğrudan okumanı önermem. Hatta 7 kanalı doğrudan okuman neredeyse imkansız. Eğer programda ADC okuma dışında pek bir şey yoksa, kesme ile belki. ADC hızını çok düşürmen gerekir.
Sebebini aynı başlıkta açıklamıştım.

mistek

DMA modülü ile 3 elemanlı adc dizisini dolduruyorum ancak sıralaması düşündüğüm gibi olmadı.
uint16_t adc[3] = {0};
Sıra olarak
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5); 
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_55Cycles5);

ayarladım.

Beklediğim sonuç ise
adc[0] = Kanal 10 verisi
adc[1] = kanal 11 verisi
adc[2] = kanal 12 verisi

şeklindeydi.

Ancak öyle olmadı ve sonuç şu şekilde.
adc[0] = Kanal 11 verisi
adc[1] = kanal 12 verisi
adc[2] = kanal 10 verisi

DMA neden benim dizimi son elemandan başlayıp başa dönerek dolduruyor ? Bu bilgi nerede yazar?
boş işlerin adamı ---- OHM Kanunu: I = V/R ---- Güç Formülü: P = V*I = I^2*R = V^2/R