STM32 UART değişken uzunlukta veri Alımı

AMA NASIL…

Merhabalar arkadaşlar..

Uzunca bir süre projelerdeki yoğunluklar nedeniyle paylaşım yapamamaktaydım. Şimdi bu sessizliği sona erdirip sizlerle yeni bir projede buluşma kararı aldım.

Bu projeyi sizlerle paylaşmama ilham olan sebebe gelirsek geçenlerde Nextion ekran kullanmam gerekiyordu nextion ekranların bildiğiniz üzere Uart üzerinden haberleşiyor stm32 den nextion ekrana veri aktarmak istediğim de sorun yoktu. Aslında bu işin kolay kısmı kaç hane yollarsanız yollayın nextion verinin uzunluğunu kendi içerisinde hallediyor ve veriyi işliyordu FAKAT!!

Nextion ekrandan Uart üzerinden veri aktarmak istediğim de işler tamamen değişmişti çünkü nextion değişken uzunlukta veriler veriyordu eee iş böyle olunca HAL_UART_RECEIVE fonksiyonuna atadığım uzunluktan kısa veri geldiğinde hanede kaymalar oluyor uzun olunca ise bu seferde taşmalar oluyordu…

Şimdi bu insanı şişiren hatayı nasıl çözerim diye kara kara düşünürken verileri bayt bayt alıp işlemek geldi aklıma durum böyle olunca başladım yazmaya.

Uarttan her baytı tek tek aldım ve aldığım her baytı bir diziye aktardım sonrada veriyi istediğim gibi işledim uart 2. defa veri aldığında ise diziyi boşaltıp tekrar doldurduk bu şekilde işi basitçe çözdüm Haydi şimdi bakalım bu işi nasıl yapmışız.

CubeMX

Ben programlamada CubeMX ve keil ikilisini kullanıyorum derleyici olarak cubeide gibi ücretsiz bir seçenek olmasına rağmen cubeide debugta yaşattığı sorunlar gönül yorgunluğu yarattığından inatla ücretli olan keil devam ediyorum. Ancak siz dilediğiniz ide ile programlamanızı yaparbilirsiniz.

CubeMX Uart Ayarları
CubeMX Uart Ayarları

Uart ayarlarımızda ben 9600 baudrate tercih ettim ancak siz dilediğiniz hızı kullanmakta özgürsünüz kodlama aşamasında sizlere hiç bir fark yaratmıycak.

Yukarıdaki ayarlarımızı yaptıktan sonra şimdi DMA ile uart üzerinden veriyi işlemcimizin yoğunluğuna takılmadan güzelce almak için DMA modunu aktifleştiriyoruz ve ayarlarımızı aşağıdaki gibi yapalım.

CubeMX UART RX DMA ayaları
CubeMX UART RX DMA ayaları

Uartta dma ya transmit kısmında ihtiyaç duymuyorum çünkü çokta bir espirisi olmuyor. Şimdi NVIC sekmesinden uart kesmesiniaçalım bunu açma sebebim ise veri alım sonrasında hiç veri kaçırmadan sağlıklı bir şekilde alınmış veriyi sağlıklı şekilde işlemek istiyorum.

CubeMX Uart Kesmesi ayarı
CubeMX Uart Kesmesi ayarı

Şimdi CubeMX ayarlarımızın Uart kısmına dair tüm ayarlarını gerçekleştirdik programı generate edebiliriz. diğer ayarları göstermedim o kısımları yapabildiğinizi var sayıyorum zaten yapamasanız bu konuda olmazdınız bence 🙂

Şimdi Kodlama Kısmına geçelim.

KODLAMA

Şimdi kodlama kısmında dikkat etmenizi istediğim kısım uart haberleşme çatısını nasıl kurduğumuzu anlamanız kısa bir akış açıklaması vermek gerekirse yazılımımız da şöyle bir döngü geçekleştireceğiz;

  • Uart DMA haberleşme birimini 1 bayt alacak şekilde biçimlendiriyoruz. Bu aşamada sistem veri almaya açık olacak ancak alacağımız veri ELEKTRONİK ATOLYEM olduğunu var sayarsak veriler parça parça halde gelecek 1.E 2.L 3.E 4.K 5.T… şeklinde… Sonraki adıma devam edelim.
  • Şimdi kurduğumuz UART haberleşme birimi ve alımı gerçekleştikten sonra CubeMX üzerinde aktif ettiğimiz UART kesmesini tetikleyecek hale getireceğiz çünkü veriler anlık olarak akacağından veri kaçırmak istemiyoruz! Aldığımız verileri kesme servisi altında dizimize kayıt edeceğiz..
  • 3. adımda ise kesme servisinin içerine veri geldiği anda veriyi işliyoruz normal döngü altında kullanılmaya hazır oluyor.

Servisin kurulumu hakkında genel bir yapı bilgisi edindiğimize göre artık kodlamaya devam edebiliriz.

STM32 UART DMA Aktivasyonu
STM32 UART DMA Aktivasyonu

Stm32 Uart DMA servisimizi 1 bayt veri alacak şekilde Kurduk. Değişkenimizi aman unutmayalım 🙂

char rx_buff[10];
HAL_UART_Receive_DMA(&huart1,(uint8_t*)rx_buff,1);

Şimdi Uart üzerinden veri alımı tamamlandığında ne yapacağımızı belirtecek kilit nokta burası Ben burada nextiondan veri aldığım için verinin bir başlangıç ve 1 de bitiş baytı belirttim. bunlarda HEX 0x21 ve 0x3F bu iki değer arasında çok uzun yada çok kısa değerler alıyorum ve bu başlangıç bitiş baytını sonuç alırken kırpıyorum bu sayede değişken uzunlukta veriler alabiliyorum ancak siz dilerseniz başlangıç ve bitiş baytı olmaksızında veri alıp bunları ardıl olarak kayıt edebilirsiniz.

STM32 UART Kesme Servisi
STM32 UART Kesme Servisi
//Değişkenlerimizin yeri globaldir arkadaşlar sakın kesme servisine yazmayın :)
volatile uint8_t StartFlag = 0 ;
volatile uint8_t StopFlag = 0;
uint16_t i=0;
uint8_t array[2000];

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
 if (rx_buff[0] == 0x21){ //başlangıç baytı
    StartFlag = true; // başlangıç baytı alındı bilgisi
    i=0; } // sayaç değişkeni
  else{
      if (StartFlag){ // başlangıç biti alındı kısmı okeyse sıradaki bilgileri al 
          if (rx_buff[0] == 0x3F){ // bitiş baytı görene dek alacaktır.
                   sorgular();       // ben burada aldığım verileri işlediğim fonksiyonumu çalıştırdım. siz burada ne işlem yapmak isteseniz onu yapabilirsiniz.  
                   StopFlag = true;   // ve minik makromuzu tekrar başlangıç baytı alma konumuna soktuk.     
                   StartFlag = false;         
                   i = 0;  }      
           else         array[i++] = rx_buff[0];  // verileri başlangıç baytı gelmediyse sırasıyla array dizimize atıyoruz.          }     }   
 }

Şimdi size şöyle bir güzellikte yapayım ve başlangıç bitiş baytı olmadan alanı da yazayım..

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){

array[i++] = rx_buff[0];
}

veriyi okuduktan sonra basit bir for fonksiyonu ile dizimizi boşaltabiliriz.

for(i=0;i<2000;i++){
array[i]='\0';}

veri alma işlemimiz bu kadar aklınıza takılan birşey olursa lütfen yazmayı unutmayın. Sosyal medyadan bizi takip etmeyi de unutmayın.

You may also like...

4 Responses

  1. emre bozkurt dedi ki:

    Merhaba ben baslangıç degeri olmadan yapmak istiyorum veri alımının bittigini nasıl anlarım herhangi bayragı varmıdır.

  2. Bülent dedi ki:

    Bir timer içerisine sayaç değişkeni saydırıp her byte geldiğinde sıfırlanabilir. Sayaç değeri belirlenen degeri (Kullandığınız uartın hızına göre değişen ) aştıysa data alımı bitmiş kabul edilebilir.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir