Picproje Elektronik Sitesi

MİKRODENETLEYİCİLER => ARM => Konuyu başlatan: tekosis - 17 Kasım 2018, 20:44:49

Başlık: [ÇÖZÜLDÜ] DMA + USART ile 16bit data transferi nasıl yapılır?
Gönderen: tekosis - 17 Kasım 2018, 20:44:49
stm32f103C8 + keil + Cubemx(hal library) kullanıyorum. 16 bit veriyi hızlı bir şekilde usarttan yollamam lazım. bu 16 bit veriyi yazılımsal olarak 8 bitlik iki parçaya ayırıp dma ile yollayabilirim ancak bunu yapmadan doğrudan yine dma ile 16 bitlik veriyi gönderme şansım var mıdır? bazen 8000 değişkene kadar veri yolamam gerekecek ki yazılımda zaman kaybetmeden mümkün ise donanımsal olarak bu işlemi gerçekleştirmek istiyorum.
Başlık: Ynt: DMA + USART ile 16bit data transferi nasıl yapılır?
Gönderen: devrecii - 17 Kasım 2018, 22:11:45
Dma'nin hafıza girişini 16bit tanımlayıp çıkışı 8bit ayarlayabilirsin.   uart data registeri 8 bit.
Başlık: Ynt: DMA + USART ile 16bit data transferi nasıl yapılır?
Gönderen: tekosis - 17 Kasım 2018, 22:47:43
Yeni yeni öğrenmeye başlıyorum hal library ve cubemx ayarlarını. Kullandığım dma ayarı aşağıdaki şekilde. Sizin dediğinize uyuyor mu?

(https://thumb.ibb.co/k8fvKf/DMA2.png) (https://ibb.co/k8fvKf)
Başlık: Ynt: DMA + USART ile 16bit data transferi nasıl yapılır?
Gönderen: devrecii - 18 Kasım 2018, 01:48:35
Her iki tarafın da byte olması daha doğru olur çünkü tek clockta 2 tane ard arda byte göndermeye çalışabilir. uarttan dma ya gelen her clokta bir byte gitmesi gerekir.

Önemli olan dizinin adresidir 16bit hafızada olsa 32bit de olasa hafızada byte olarak saklanıyor ,  dma ya source olarak bu dizinin adresini vermelisin, dest adres olarak uart data registeri adresini vermelisin.

uartın dma için register ayarları da var, cubemx bunları hallediyormu bilmiyorum, yoksa çok iş var.
Başlık: Ynt: DMA + USART ile 16bit data transferi nasıl yapılır?
Gönderen: Elektroemre - 18 Kasım 2018, 14:41:16
Mesela:

uint16_t dizi[8192]; olsun

Siz DMA ayarında source(dizi) ve destination(usart)'ın data size'ını 8bit ayarlayıp, DMA ile gönderilecek veri size'ını 8192 * 2 = 16384 yapmanız yeterli.

Diğer türlü source(dizi) 16bit, destination(usart) 8bit ayarlarlayıp, veri size'ını 8192 yaparsanız büyük ihtimalle, düşük ya da yüksek değerlikli 8bit karşıya gönderilir.


Ekleme: Her şey düzgün çalıştığında da endian problemi olabilir, dikkat etmek lazım. (byte order)

Başlık: Ynt: DMA + USART ile 16bit data transferi nasıl yapılır?
Gönderen: tekosis - 18 Kasım 2018, 19:05:59
en altta kod parçam mevcut. derlediğim zaman "error:  #167: argument of type "uint16_t *" is incompatible with parameter of type "uint8_t *" hatasını alıyorum. benden uint8_t tipinde değişken vermemi istiyor. Bir de MX_DMA_Init() kısmında 8 bit yada 16 bit ile ilgili bir ayar yok. şimdi kütüphaneyi inceliyorum.

hocam ayarlarım şu şekide ;
uart ayarları :
static void MX_USART1_UART_Init(void)
{
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 460800;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
}

dma ayarları :

static void MX_DMA_Init(void)
{
  __HAL_RCC_DMA1_CLK_ENABLE();
  HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
}

aşağıda da kod parçam mevcut :

  uint16_t data16bit[5];
  data16bit[0]=0xabcd;
  data16bit[1]=0x1234;
  data16bit[2]=0x1010;
  data16bit[3]=0x78cb;
  data16bit[4]=0x1000;
      HAL_UART_Transmit_DMA(&huart1,data16bit,10);
while (1)
{ }

dma ayar penceresi :

(https://thumb.ibb.co/gxs3qL/dma3.png) (https://ibb.co/gxs3qL)
Başlık: Ynt: DMA + USART ile 16bit data transferi nasıl yapılır?
Gönderen: tekosis - 18 Kasım 2018, 19:23:02
çözüldü: 
uygulamamda stm32f1xx_hal_msp.c altında aşağdıdaki kodlar mevcut. burada data genişliği vs ayarları mevcut. cubemx üzerinden veya buradan düzeltmek mümkün. Aşağıdaki satırlarda data boyutu ayarlanabiliyor. Henüz yüksek sayıda değişken denemedim bir problem olursa buradan yazarım.

@Elektroemre @iboibo teşekkür ederim.

/* USART1 DMA Init */
    /* USART1_TX Init */
    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
 

aşağıdaki kod parçası ile yaptığım deneme olumlu sonuç verdi, istediğim sonucu altım.

  printf("\nbirazdan veri yolanacak : \n");
   HAL_Delay(1500);
   
    uint16_t data16bit[5];
   data16bit[0]=0x6261;
   data16bit[1]=0x6463;
   data16bit[2]=0x6665;
   data16bit[3]=0x6867;
   data16bit[4]=0x6a69;
   
    HAL_UART_Transmit_DMA(&huart1,(uint8_t *)data16bit,10);// burada casting işlemi yapınca sorun çözüldü.
   while(1)
   {
   HAL_Delay(10);
   }