srm32F407 DMA ve UART kullanarak veri alma sorunu

Başlatan ypr, 08 Aralık 2019, 19:48:03

ypr

Merhaba arkadaşlar öncelikle yapmak istediğim şeyi anlatayım;
  Telefondan oluşturduğum bir veriyi HC-05 ile stm32ye paket olarak almak istiyorum. aslında çok basit bir şey ama bir türlü yapamadım.
Mantık oturtma konusunda sıkıntılarım var. Öncelikle ilk sorunum.
aşağıdaki kodu uyarladığım yerde while(!dataArrived); döngüsü var yani veri aktarımı tamamlanana kadar aşağıya geçmeye izin vermiyor. Data alınınca  RxCpltCallback fonksiyonuna dallanıyor ve bunun içinde dataArrived 1'e setlenip döngüden çıkılıyor. Bir nevi kontrol amaçlı koyulmuş bir fonksiyon. Fakat bu döngü bana anlamsız geldi çünkü bu döngüyle beraber program aşağıya doğru inmiyor çalışmak için illa veri almayı bekliyor dolayısıyla program ana while döngüsü hiç ulaşmıyor.

Ben bu while(!dataArrived); döngüsünü programdan kaldırdım herhangi bir sıkıntı yaşamadım.

ikinci sorum ise benim asıl amacımda belirttiğim gibi ne zaman veri alacağım belli değil bu yüzden en başta uart interrupt şeklinde kullanmayı denedim fakat araştırmalarım sonucu uart interrupt yerine uart ile dma kullanımının daha sağlıklı olduğunu ve piyasada da böyle kullanıldığını öğrendim bu yüzden UART DMA aracılığıyla veriyi alıyorum fakat bu sefer de data dizisi ilk verileri aldıktan sonra başka veri yollamak istediğimde dizide bir değişiklik olmuyor.

Tahminimce bir yerlerde bayrak falan indirmem gerekiyor.   

Ekstra bir sorum daha var uint8_t data[1] şeklinde bir diziye sadece tek bir karakter yollayabiliyorum. bunun nedeni nedir? yani mantıken bu dizinin tek elemanına 255 sayısını yazdırabilmem lazım 8 bit olduğu için fakat maksimum 9 yazdırabiliyorum. Bu olması gereken bir durum mu? 
#include "main.h"

UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART1_UART_Init(void);

uint8_t dataArrived=0;
uint8_t i=0;
uint8_t data[10]={0};

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
 dataArrived=1;
}
int main(void)
{
  
  HAL_Init();

  SystemClock_Config();

  
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  

  HAL_UART_Receive_DMA(&huart1, data, 10);
  //while(!dataArrived);

  while (1)
  {
          i=data[2];
	  HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_12);
	  HAL_Delay(500);

  }
  
}


içimden bir ses bu işin doğrusu bu şekilde değil diyor. Kodun çalışmasından ziyade doğru kodun çalışmasını önemsiyorum bu yüzden sizlere sorma gereği hissettim. Teşekkür ederim şimdiden.

MrDarK

Selamlar,
Örnek bir kod üzerinden yürüyorsun anladığım kadarıyla, örnek koddaki mantığı arkadaşlar Interrupt + DMA ikilisi ile kurmuşlar. Veri akışı başladığında 10 byte oluncaya kadar "data" array'inin içine bu bilgiler dolduruluyor. HAL_UART_RxCpltCallback her uart interrupt'ı oluştuğunda eğer interrupt flaglerini temizlediysen çağrılır. Yani uart rx interrupt fonksiyonudur. İstersen DMA yerine uarttan veriyi o fonksiyon ile alabilirsin.

DMA yerine interrupt veya tam tersi metodu seçmek ise ne yapmak istediğinle alakalı. DMA'nın kullanım amaçlarını ve mantık yapısını araştırırsan interrupt mı DMA mı kullanmalısın onu anlayabilirsin. Çünkü tercihlere kalan bir durum o veya bu doğru diye birşey yok yani.

uint8_t data[1] -> 1 elemanlı 8 bitlik bir array demek, nesini anlamadığını anlamadım. Zaten tek karakterlik bir dizi açıp birde neden sadece tek karakter alabiliyorum tarzında bir soru sormuşsun. Bit, byte, ascii char terimlerini araştırmanı tavsiye ederim.

Benim içimden gelen bir ses de şöyle diyor,
"Kedi olmadan fare yakalamak istiyorsun gibi"
Picproje Eğitim Gönüllüleri ~ MrDarK

ypr

Merhaba, aslında Hal kütüphanesi kullanılarak oluşturulmuş örnek kodlar ile çalışma mantığını anlamaya çalışıyorum. Bu tarz örneklerde genelde 1 veya 0 göndererek led yakıp söndürüyorlar ben biraz daha büyük data alıp bir çok komutu yerine getirmek istiyorum.
HAL_UART_RxCpltCallback: bütün datayı aldıktan sonra bu fonksiyonun içine giriyor.
 Tekrar veri gönderdiğimde veriyi değiştiremememin nedeni dma mode'u normal mod seçmem imiş. Circular mod seçince o kısım düzeldi. Şuan için bir sıkıntı yok. (aslında bunu bu konu yayınlanmadan çözmüştüm fakat konuyu değiştiremedim maalesef)
 Tek karakterden kastettiğim şey ise bu fonksiyon ile alabildiğim veriler 1,2...9'a kadar olan tek karakterli sayılar, dizinin içine 12 sayısını alamıyorum maalesef bunun nedenini merak ettim ve bir kaç yerde de bu soru sorulmuş cevabı verilmemiş maalesef. Mantığını kuramadığım kısım bu ve while döngüsü olmuştu.

Yani şuan ben telefondan 254 sayısını yollamak için 3 elemanlı bir dizi oluşturmak zorundayım?

Genede zaman ayırıp cevap verdiğiniz için teşekkür ederim.


devrecii

Sen hex değil ascii veri yolluyorsun galiba , mesela 18 sayısı hex olrak  tek byte 12h iken ascii olrak iki byte 31h,32h olrak tanımlarır.

While dönhüsüne gerek yok zeten while döngüsünden kurtulmak için interrupt var.

ypr

Hocam ben veriyi telefondan androiddeki bir bluetooth terminali kullanarak yolluyordum. 123 yazıp yolladığımda veriler bana dediğiniz gibi ascii olarak geliyordu ve ben anlamıyordum. Sonra veriyi 1 bytelık sayı olarak yolladım ve 1bytle ile 255 sayısını alabildim sonunda. Yani anladığım kadarıyla bluetooth terminal yazılan şeyleri string tipinde yolladığı için ortalık karışmış.