STM32 etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
STM32 etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

10 Ocak 2024 Çarşamba

STM32F103 Mikrodenetleyici Çevre Birimlerinde Karşılaştığım Bir Problem #STM32Tips

Konunun hikayesinden başlamak gerekirse, STM32F0 ve STM32F1 serisi işlemcilerden oluşan ve CAN Bus üzerinden birbirleri ile haberleşen bir tasarım üzerine çalışıyordum. Her bir kart için CAN Bus bağlantısının yanında bilgisayar bağlantısını da kurmak için USB bağlantısını sisteme dahil etmiştim. Bu tasarım STM32F0 serisi işlemcide CAN Bus ve USB sorunsuz çalıştı.

STM32F1 serisi işlemciyi kullanırken aynı yazılıp mimarisi üzerinden devam ediyordum ancak bir sorun ile karşılaştım. Bir şekilde CAN Bus hattını kullanamıyordum. Problemi araştırmaya başladığımda USB ve CAN Bus'ın birlikte kullanımı ile ilgili başka problem yaşayanların da olduğunu gördüm. Sonrasında kullandığım işlemci olan STM32F103CB'nin datasheetini (Reference Manual RM0008 Rev 21) inceledim. CAN Bus kısmında aşağıdaki gibi bir not olduğunu gördüm.

"In low, medium-, high- and XL-density devices the USB and CAN share a dedicated 512-

byte SRAM memory for data transmission and reception, and so they cannot be used concurrently (the shared SRAM is accessed through CAN and USB exclusively). The USB and CAN can be used in the same application but not at the same time."

Buradan anladığımız CAN Bus ve USB işlemci üzerinde aynı SRAM alanlarını kullanıyor ve bu yüzden her iki çevre birimi birlikte kullanılamıyor. USB'yi kapatıp CAN Bus'ı çalıştırmak veya tam tersi mümkün ancak her ikisi aynı anda asla çalıştırılamıyor. Bu yüzden örnek vermek gerekirse CAN Bus üzerinden alınan bir veriyi USB üzerinden gerçek zamanlı alıp işlemek mümkün değil.

Ek olarak STM32F0 serisi ile bir çok uygulama yapmıştım ve bu yüzden USPDP, USPDM hatlarını direkt konnektöre bağlamıştım. STM32F103CB işlemci kullanırken USBDP hattına 3.3 V'a 1.5 kR pull-up resistor gerekiyormuş.

STM32 USB kullanılan uygulamalarda donanım tasarımı hakkında aşağıdaki doküman yayınlamış. Donanım tarafında yapılması gereken işler tek bir dokümanda bütün işlemci ailesi için verilmiş. Gelecek tasarımlar için işe yarar gibi görünüyor.


Link: https://www.st.com/resource/en/application_note/an4879-introduction-to-usb-hardware-and-pcb-guidelines-using-stm32-mcus-stmicroelectronics.pdf (10.01.2024)

23 Aralık 2023 Cumartesi

CAN Bus Temelleri ve Bir Mesajının Yapısı

CAN (Controller Area Network) Bus Robert Bosch GmbH tarafından oluşturulmuştur. 1986'da RB GmbH tarafından SAE'de yayınlanmıştır. Takip eden yıllarda CAN Bus'ın farklı versiyonları yayınlanmıştır ve ISO tarafından standardize edilmiştir. CAN Bus günümüzde içten yanmalı ve elektrikli bir çok araç tipinde aktif olarak kullanılan ve temel kontrol yetenekleri dolayısı ile sıklıkla tercih edilen bir haberleşme protokolüdür.

CAN Bus, mesaj tabanlı bir haberleşme protokolüdür. Hat üzerinde bulunan bütün noktalar hatta veri basabilir ve veriyi okuyabilir. Fiziksel olarak CANH, CANL şeklinde isimlendirilen iki fiziksel hat üzerinden iletilir. Fiziksel hat üzerinde bulunan voltaj farkı üzerinden çalışır.

CAN Bus ile haberleşen bir ağın fiziksel bağlantısı aşağıdaki gibidir. Bir hat boyunca bir çok sistem bağlanabilir. Her bir sistem ağa mesaj gönderebilir ve okuyabilir.

CAN Bus'a bağlantı için transreceiver yapılarına ihtiyaç duyulur. Mikrodenetleyiciler ile CANH, CANL hatları arasında aşağıdaki gibi transreceiver yapıları kullanılır. Mikrodenetleyiciler tarafında Rx, Tx hatları ile iletişim kurulur.

Aşağıda verilen görselde CANH, CANL hatlarındaki değişim ve bu değişimin CAN Rx ucundaki karşılığını gözlemleyebilirsiniz. CANH, CANL aynı seviyede iken CAN Rx 1'dir. Aksi durumda CAN Rx 0 olur. 0 değeri CAN Bus için baskın bit olarak ifade edilir.

Bir önceki görsel üzerinden CAN Bus mesajını inceleyecek olursak;

  • Start of frame: Bir CAN Bus mesajı 0 biti ile başlar.
  • ID-Arbitration: Takip eden bitler mesaj ID sini ifade eder. Mesaj ID'si aynı zamanda paketin önceliğini de ifade eder. Örneğin aynı anda iki sistem hatta veri basmak isterse CAN Bus'ın önceliklendirme yapısına göre değerlendirilir. Çok basitçe ifade etmek gerekirse Veri gönderimi başladığı anda bir mesajın ID'si ne kadar 0 ile başlarsa o kadar baskındır. Görseldeki sıraya göre "00001xx" ve "00100xx" başlayan iki mesaj paketi gelirken birinci paket önceliklendirilir ve ikinci paketi gönderen sistem gönderimi durdurur.
  • RTR: Remote transmission request olarak geçer. Bir mesaj paketini başka bir sistemden talep etmek için kullanılır.
  • Control: Bu kısımda mesaj ile ilgili ek bilgiler yer alır.
    • IDE: ID Extend olarak geçer. 1 olması durumunda 18 bitlik daha ID kısmı aktif olur. Mesaj paketi toplamda 29 bitle ifade edilir.
    • DLC: Data length code olarak geçer. Mesaj paketinin kaç byte olduğunu ifade eder.
  • Data: Veri aktarma kısmıdır. Kullanıcının iletmek istediği veri tam olarak buradadır.
  • CRC: Veri paketinin doğruluğunu teyit etmek için kullanılır.
  • ACK: Gönderilen paketin en azından bir sistem tarafından alındığını ifade eder. Bu kısım Herhangi bir alıcı sistem üzerinden sürülür. Eğer CAN Bus üzerinde başka bir sistem yoksa bu bit 0 olmaz ve gönderici mesajın iletilemediğini anlar.
  • End of frame: Mesaj paketi sonunda 7 bit 1 gönderilir.

12 Aralık 2023 Salı

STM32 Serisi İşlemcilerde Timer/Sayaç Modülünü Interrupt/Kesme Modunda Başlatma #STM32Tips

STM32F ve STM32G serisi mikrodenetleyicilerde Device Configurator Tool ve HAL kütüphanesi ile oluşturulan yazılımlarda timer modülleri için gereken ayarlar yapılır. Bu kapsamda timerların prescaler ve counter period gibi seçenekleri ayarlanır. Bunlarla beraber timer interruptları enable edilir.

Bu şekilde konfigürasyon yapıldıktan sonra kod oluşturulur.

Oluşturulan kodda timer başlatılmamış şekilde bir yapı kullanıcıya sunulur. İlgili timerları interrupt modunda başlatmak için aşağıdaki fonksiyon kullanılır. Bu fonksiyonda altı çizili htimX ilgili timerı ifade eder ve X yerine timer numarası yazılır.

HAL_TIM_Base_Start_IT ( &htimX );

Timerlar için yapılan konfigürasyona göre bu fonksiyonun çağrılma yapısı değişiklik gösterir. Auto-Reload edilmiş bir timer için bu fonksiyonu bir defa çalıştırmak yeterlidir.

Belli bir duruma göze özellikle tetiklenecek bir yapı var ise bu fonksiyon her tetiklemede tekrar çağrılır. Şart değil ancak bu modda genellikle auto-reload disable edilmiştir.



15 Temmuz 2022 Cuma

HAL Library Bir Milisaniyelik Sayaç #STM32Tips

STM32 HAL Library ile bir proje derlendiği zaman System tick timer üzerinden çalıştırılan, varsayılan olarak bir milisaniye çözünürlükte bir sayaç başlatır. Bu sayaç değerine HAL_GetTick fonksiyonu ile ulaşabiliriz. Bu fonksiyon 32 bit işaretsiz tamsayı (uint32_t) tipinde bir değer döndürür. Siz bu değeri yazdığınız programın herhangi bir yerinde zaman tutmak için kullanabilirsiniz.

Bu sayaç SysTick_Handler interruptı içerisinde HAL_IncTick fonksiyonu ile her bir interrupta girişte bir arttırılır. Sistem arka planda uwTick global değişkenini kullanır.

HAL_GetTick fonksiyonunun arka planda tuttuğu uwTick değişkeni 32 bitlik olduğu için 1 milisaniyede 1 artarak tam olarak 32 bitlik sayıyı doldurması 49,7 gün sürecektir. Bu süre, çok özel bir proje olmadığı sürece bir çok uygulama için zaman tutma, işlemleri sıralama, timeout tutma gibi işlemler için fazlası ile yeterlidir.

Örnek olarak ana döngü içerisinde bir veya bir kaç fonksiyonu periyodik olarak çalıştırmak istersek aşağıdaki gibi bir kod parçası işimizi görecektir. Aşağıda görünen kod parçası 1 saniyede 1 defa çalışır. 999 olan değer 99 olursa 100 milisaniyede bir çalışır.

if ( ( HAL_GetTick ( ) - timeStamp ) > 999 )
{
    timeStamp = HAL_GetTick ( );

    fnc1 ( );
    fnc2 ( );
}

Bu yapıda timeStamp = HAL_GetTick ( ); satırı if bloğunun başında olursa her 1 saniyede 1 defa bu koşul işletilir. Eğer bu ifade if bloğunun en sonuna konursa bu sefer fnc1 fonksiyonu 1 sn+fnc1+fnc2 kadar sürede bir tekrar çağrılır. Bu yaklaşım fonksiyon dallanmalarına göre değişkenlik göstereceği için tercih edilmez.

İkinci bir örnek olarak RTCsi olmayan bir işlemcide gerçek zaman bir haberleşme kanalı üzerinden alınır ve işlemci içerisindeki HAL_GetTick ( ); ile eşleştirilir. Böylece işlemci kapanıp açılana kadar işlemci kristali ile gerçek zamanı tutabilirsiniz.

Bu zaman referansı başka bir çok noktada işinize yarayabilir.



25 Haziran 2022 Cumartesi

STM32F Mikrodenetleyicilerinde İşlemci Benzersiz ID Değerini Okuma #STM32Tips

STM32F mikrodeneyleyicileri içerisinde 96 bit benzersiz bir ID vardır. Bu bilgi her bir işlemciye özeldir. Bu değer aşağıdaki üç fonksiyon ile okunur. Bu fonksiyonlar sırasıyla benzersiz ID'yi oluşturan 32 bitlik grupları bize verir.







24 Ocak 2022 Pazartesi

C dilinde, İyi Yazılmış, Taşınabilir Bir Sensör Sürücü Paketi İncelemesi

Bu yazıda gömülü sistemlere düşük seviyede sürücü geliştiren kişilere referans niteliğinde olan, BOSCH'un  sıcaklık, nem ve basınç sensörü BME280 için geliştirdiği, github üzerinden yayınladığı açık kaynak kütüphaneyi [1] inceleyeceğiz. Başlıkta da belirttiğim gibi kütüphane gerçekten çok modüler bir şekilde oluşturulmuş. Geliştirilen kütüphane platform-bağımsız olduğu için herhangi bir altyapıya adapte edilebilir. Bu yapıyı herhangi bir mikrodenetleyicide veya OS ile çalışan bir gömülü yapıya entegre edebilirsiniz.



Kütüphane geliştirilirken low-coupling, high-coherence kavramlarını başarılı bir şekilde uygulamış. Kütüphane içerisinde herhangi bir dış bağımlılık olmadığı gibi kendi içerisindeki fonksiyon ve veri setleri de tam olarak amaca yöneliktir.

Öncelikle kütüphanenin güzel bir README.md dosyası var. İçerisinde bu kütüphanenin nasıl kullanılabileceği detaylı bir şekilde anlatılmıştır.

Bu yazıda, ilgili kütüphaneyi SPI üzerinden nasıl kendi sisteminize entegre edeceğinizi yine README.md deki örnek üzerinden ele alacağız.

Kütüphane bme280_dev structure'ı üzerinden çalışıyor. Bu yapı aşağıda verilmiştir.

Bu yapıda öncelikle ilgili sensörün hangi arayüz ile hangi modda kullanılacağı çeşitli değişkenlerle seçilir. Bu seçimler değişken isimleri ve gerekli yorumlarla desteklenmiş ve açık bir şekilde belirtilmiştir.

Bunun haricinde taşınabilirlik açısında bizim en çok işimize yarayan kısım fonksiyon pointer yapılarıdır. SPI örneği üzerinden devam edecek olursak bme280_dev yapısı içerisinde okuma yazma fonksiyonları için dev.read ve dev.write fonksiyon pointerlarına ilgili platforma ait SPI yazma okuma fonksiyonları atanır. SPI okuma ve yazma fonksiyonları kendi içerisinde CS operasyonunu gerçekleştirmelidir. Fonksiyonel olarak yazılmış sensör sürücüsü soyutlanmış okuma, yazma fonksiyonları üzerinden çalışır. Bu iki fonksiyona ek olarak kütüphane içerisinde kullanmak üzere 1 ms çözünürlüklü bir delay fonksiyonunun da pointerı structure'a atanır.

Bu noktada önemli bir parantez olarak ilgili fonksiyon pointerları mevcut altyapınızla birebir uyumlu olmayabilir. Hatta muhtemelen farklıdır. Bu noktada sizin altyapınız ile kütüphane arasına bir adaptör katmanı yazmanız gerekebilir. Örnek olarak aşağıdaki fonksiyon incelenebilir. myusleep fonksiyonu platform tabanlı bir fonksiyondur. Örnek olarak ms gecikmesi için STM32 altyapısında HAL_Delay fonksiyonunu düşünebilirsiniz. Arduino altyapısında buna delay fonksiyonu karşılık gelir. Biz her iki platformda da mevcut fonksiyonun adresini aşağıdaki gibi bir adaptör vasıtasıyla bme280_dev yapısına atanır. Böylece kütüphane fonksiyonları platform bağımsız çalışır.

Bu kütüphane kullanılarak oluşturulmuş tam bir örneğe aşağıdaki linkten erişebilirsiniz. En başta da ifade ettiğim gibi gömülü sistemlerde sürücü seviyesinde yazılım geliştiriyorsanız bu kütüphaneleri hiç bir zaman başka bir platformda kullanmayacaksanız bile bu yaklaşımla geliştirmenizi öneririm. Kodun okunabilirliği, güncellenebilirliği ve bakım yapılabilirşliği açısından da oldukça faydalı olacaktır.

https://github.com/BoschSensortec/BME280_driver/blob/master/examples/bsd_userspace.c

Referanslar

[1] https://github.com/BoschSensortec/BME280_driver/

7 Nisan 2021 Çarşamba

ADC Nedir? Analog to Digital Çevrim İşleminde Karşılaşılan Hatalar Nelerdir?

 ADC (Analog-to-digital converter, Analogtan Dijitale Çevirici) analog verileri dijital verilere çeviren çevre birimleridir. ADC yapıları gerçek dünyadan dijital dünyaya veri almanın en bilinen yöntemidir. ADC yapıları sinyalleri tanımlanmış zaman aralıklarında alır ve ADC çözünürlüğü ölçüsünde quantize eder. Böylece ADC yapıları, dijital hesaplamalar için zamanda ve genlikte quantalanmış/ayrılmış veriler sağlar.



ADC işlemine örnek olarak ses verisinin dijitale çevrilmesi verilebilir. Ses sinyali ile mikrofon üzerindeki gerilim değişir. Bu gerilim değeri ADC tarafından okunarak ses sinyali dijitalleştirilmiş olur. İşlemciler üzerinde bu dijital veri işlenerek anlamlı bir bilgiye çevrilir.


ADC farklı tiplerde tasarlanabilir. Mikrodenetleyicilerde en yaygın kullanılan ADC tipleri SAR ve ΔΣ ADC tipleridir.

Farklı ADC çözünürlük ve ölçüm frekanslarına ait tablo aşağıdaki gibidir.ADC'nin çözünürlüğü Vcc/(2^bit) formülü ile bulunur. Örneğin 5 V ile çalışan 12 bitlik bir ADC'nin çözünürlüğü;

5 V/(2^12) = 5 V/4096 = 1,22 mV'dur.

Kısa bilgi olarak ADC'nin tersi yönde çalışan DAC yapıları da vardır. DAC yapıları işlemciler içerisindeki dijital verilerin analog verilere döndürülmesi için kullanılır. Bu iki yönlü dönüşüm aşağıdaki görselde verilmiştir.

ADC Hata Tipleri

ADC ölçümlerinde, ölçüm yapılan ADC yapısına göre çeşitli hata tipleri oluşabilir. Bu hatalar 3 ana başlıkta toplanabilir.

Doğrusallık Hatası

İdeal durumda ADC'nin normalde gerilime göre oransal bir çıkış vermesi gerekir. ADC'nin iç yapısına ve çevresel etkilere göre ADC üzerinde farklı aralıklarda farklı oranlar ortaya çıkabilir. Bu durumda doğrusallık hatası ortaya çıkar. Bu etkinin grafiksel gösterimi aşağıdaki gibidir.

Kazanç Hatası

ADC üzerinde kazanca bağlı değişen bir kazanç hatası ortaya çıkabilir. Bu ADC'nin o anki değerine göre oransal olarak artan bir hata tipidir. Bu durumda kazanç hatası ortaya çıkar. Bu etkinin grafiksel gösterimi aşağıdaki gibidir. Bunu kompanze etmek için ADC ölçümü bir katsayı ile çarpılabilir.

Dengeleme Hatası

ADC üzerinde belli bir dengeleme/ofset hatası ortaya çıkabilir. Bu ADC'nin herhangi bir andaki değerine göre sabit bir değer ekler. Bu durumda dengeleme hatası ortaya çıkar. Bu etkinin grafiksel gösterimi aşağıdaki gibidir. Bunu kompanze etmek için ADC değerine belli bir sabit değer eklenebilir.

Referanslar:

[1] https://en.wikipedia.org/wiki/Analog-to-digital_converter

6 Ocak 2021 Çarşamba

Lineer/Proportional/Oransal Çıkışlı Bir Analog Sensörün Okunması, Sensör Okuma ile ilgili Temel Mantıklar

 Sensör verilerinin okunması ve anlamlandırılması kontrol sistemleri için en temel girdiyi oluşturur. Sensör bilgileri, sensörün tipine, iç yapısına, ölçtüğü fiziksel niteliğin davranışına göre farklılık gösterebilir. Sensör çıkışları lineer veya bir polinoma bağlı olabilir.

Bu yazı kapsamında lineer çıkışlı sensörler hakkında detaylı bir açıklama yaptıktan sonra polinomsal çıkışlı bir sensör hakkında da kısa bir yorum yapıp bitireceğim.

Lineer çıkışlı analog bir sensöre örnek olarak SS495B ve LM35 üzerinden ilerleyeceğiz. Aşağıda gördüğünüz görselde SS495B'nin gauss/çıkış voltaj grafiği verilmiştir. Bu sensörün ölçüm yaptığı fiziksel nitelik ile çıkış voltajının lineer olduğu grafikten bellidir. Çıkış gerilimi gauss değerine göre lineer olarak artıp azalır.

SS495B Çıkış Karakteristiği
Bu şekilde çıkış veren sensörler çok basit bir matematiksel formülle tanımlanır. ADC değerini okuyup voltaja çevirdikten sonra, gerilim değerinden ilgili fiziksel değere geçilir. Bu örnekte o değer gauss'tur.

Grafikten görüldüğü gibi sensör 0.5V-4.5V arasıda tanımlıdır. Aralık dışıda bir değer okunması halinde uygulamanın çeşidine göre bir senaryo planlanır. Bu aralıkta da direkt bir eğik doğru formülü ile tanımlanır. Bu formül;

Gauss = ( Vout - 2.5 ) * ( 640 / 4.5 )

şeklindedir. Bu formüldeki ( 640 / 4.5 ) ifadesi grafiğin eğimidir. Bu değer sayısal olarak sadeleştirilip sadece bir çarpım ifadesi şeklinde de yazılabilir.

LM35 sensörü de sıcaklığa bağlı lineer çıkış veren bir sensördür. Bu sensörün datasheetinde çıkış aşağıdaki şekilde ifade edilmiştir. Sensör 2°C-150°C aralığında her bir derece için 10mV çıkış verir.
LM35 Çıkış Karakteristiği

Bu bilgilerden hareketle bu sensörün çıkışını santigrat derece şeklinde ifade etmek için aşağıdaki formül kullanılır.

Temperature = 2 + ( Vout / 0.01 ) = 2 + ( Vout * 100 )

İki ayrı sensör değerinin nasıl dijital veriye çevrildiğini bu iki örnekle özetlemiş olduk. Bir de polinomsal çıkış veren sensörler vardır. Bunlar için en yaygın örnekler NTC tipi sıcaklık sensörleri olabilir. Bu sensörlerin direnç değerleri sıcaklığa bağlı değişir ve en basit şekilde başka bir direnç ile seri bağlanarak orta noktanın gerilimi üzerinden bir dönüşüm yapılır. Burada ilk olarak basit gerilim bölücü mantığından sıcaklık sensörünün direnç değeri bulunur ve bu direnç değeri -nispeten- kopleks bir matematik denkleminden geçerek sıcaklık elde edilir. Bu denklem "Steinhart and Hart Equation" olarak adlandırılır. Burada yer alan A, B ve C sabitleri ilgili sensörün datasheetinde verilir. R değeri ise NTC'nin o anki direnç değeridir.


Bir NTC'nin direnç değerinin sıcaklığa bağlı değişimini gösteren grafikte aşağıdaki gibidir. Grafikte görünen PTC, NTC ile ters çalışan ama aynı amaçla kullanılan bir sensör türüdür.




Bu yazı kapsamında sensör okuma ve okunan değerleri fiziksel değere çevirme hakkında genel bilgiler vermeye çalıştım. Umarım faydalı olur. Çalışmalarınızda başarılar.



7 Aralık 2020 Pazartesi

Cooperative Multitasking

 Bu yazıda cooperative multitasking (CM olarak anılacak) kavramı üzerine bildiklerimi ve gömülü sistemler üzerinde bu yapıya benzer bir çalışma metodolojisi ile nasıl geliştirme yaptığımdan bahsedeceğim.

CM kavramı non-preemptive multitasking olarakta bilinir. Temel olarak görevi taskları sıralı bir şekilde işletmektir. Bilinen modern multitasking yapılarından farkı ise önceliğe göre aktif bir task switching yapmamasıdır. CM yapısında, işlemci aynı anda bir task ile ilgilenir ve o task tamamlanana kadar diğer taskların çalışmasına izin vermez. Bu yapı Windows 3.1x'te kullanılmıştır.[1]

CM yapısı ile çalışacak bir sistemde taskların zamanları önemlidir. Bu yüzden yazılacak taskların süreleri ve gereksinim durumu iyi analiz edilmelidir. Vakit alan bir task önemli bir taskı engellerse bu sistemi verimsiz/anlamsız/zararlı hale getirebilir.

CM kavramını görselleştirmek için aşağıdaki görseli kullanalım. Burada örnek olarak Task A 20ms de bir çalışır ve task aktif olduktan sonra 3 ms boyunca iş yapar. Diğer tasklarda da benzer şekilde çalışma periyotları ve çalışma süreleri tanımlanmıştır.

İlk ve en basit kural çalışma süresi, çalışma periyodundan büyük olmalıdır. Bu ikisi arasındaki fark ne kadar yüksek olursa ilgili taskın işlemciye yükü o kadar düşük olur.



Görselde CM metodu içe çalışan bir yapı verilmiş ve Task A, B, C tanımlanmıştır. Her bir taskın çalışma sürelerine göre işlemler grafikteki gibi verilir. Burada zamanları tek tek inceleyeceğiz.
  • @10. ms Task C çalışır ve 11. ms'de biter.
  • @15. ms Task B çalışır ve 17. ms'de biter.
  • @20. ms Task A çalışır ve 23. ms'de biter. Bu esnada Task A'nın da çalışma periyodu gelir ancak Task A bitmediği için sırasını bekler. Task A biter bitmez 23. ms'de Task C başlar. 24. ms'de biter. Bu kaymadan dolayı Task C'nin bir sonraki başlama zamanı kayar ve Task C 33. ms'de çalışır.
  • @30. ms Task B çalışır ve 32. ms'de biter.
  • @33. ms Task C çalışır ve 34. ms'de biter.
  • @40. ms Task A çalışır ve 43. ms'de biter.
  • @43. ms Task C çalışır ve 44. ms'de biter.
  • @45. ms Task B çalışır ve 47. ms'de biter.
Bu yapıda en önemli konu 20. ms'de yaşanan kaymaların olabileceğidir. Bu yüzden doğru bir düzen içerisinde tasarlanmalıdır. Çok daha uzun sürecek tasklar da olabilir. Bu durumda diğer taskların kritik görevlerinin olmaması önemlidir.

Bu yapıyı kurarken genelde tüm tasklar tek bir zaman sayacı üzerine kurulur ve ilgili zaman sayacını referans alark her bir task çalışma başlangıcını belirler.

Gömülü sistemlerde çalışırken, RTOS kullanmadan geliştirilecek uygulamlarda oldukça faydalı bir yöntemdir. RTOS'lara göre eksik kaldığı bir nokta normalde delay koyarak geliştirilebilecek basit akış diyagramlarını oluşturmak için switch case yapılarının gerekmesi olabilir ancak alışkanlık sağladığınızda fazlasıyla kolaylık sağlayacaktır.

Bu yazı kapsamında interruptsız bir program üzerine konuyu anlattım. Ek ve özet bilgi olarak bu yapılar çalışırken çalıştıracağınız interruptlar ile de tam gerçek zamanlı tasklar çalıştırabilirsiniz. Kurgulanacak bu yapıda yukarıda verilen tasklar interruptlar tarafından bölünür ve sizin hem interrupt yapınız hem de ana döngü yapınız sağlıklı bir şekilde çalışabilir.

Ana döngü içerisinde yavaş toplanacak veriler, haberleşme değerlendirme algoritmaları, dosya okuma/yazma yapıları vs. geliştirilebilir. Interruptlar içerisinde ise hızlı tepki verilmesi gereken giriş/çıkış yapıları, kontrol algoritmaları, periyoda bağımlı algoritmalar vs. çalıştırılabilir.

Umarım faydalı olur.

Referanslar

[1]. https://en.wikipedia.org/wiki/Cooperative_multitasking

31 Temmuz 2020 Cuma

STM32 HAL Kütüphanesi ile DMA Üzerinden ADC Okuma Hatası ve Çözümü

STM32CubeIDE ile oluşturduğum bir projede DMA üzerinden 3 kanal ADC okuması yapacaktım. Bu kapsamda ADC ve DMA birimlerini aşağıdaki şekilde düzenledim.



Aslında her şey doğru görünüyor. Bu şekilde projeyi oluşturdum ve aşağıdaki fonksiyon ile ölçümü başlattım ancak ölçüm sonunda sadece son tanımlanan ADC kanalının değerini buffer arrayin ilk elemanında görüyordum.

HAL_ADC_Start_DMA ( &hadc1, ( uint32_t * ) aADCxConvertedData, ADC_CONVERTED_DATA_BUFFER_SIZE );
Bunun problemini araştırırken code generator tarafına olan bir hatadan dolayı problem çıktığını tespit ettim. Code generator kodu aşağıdaki sırada oluşturuyor. Bu şekilde DMA ayarlarından önce ADC ayarları yapıldığı için DMA konfigürasyonu hatalı oluyor. ADC, DMA yapısı istediğimiz gibi çalışmıyor.




ADC ile DMA Init fonksiyonlarını yer değiştirdiğimizde problem ortadan kalkıyor ve ADC start fonksiyonu çağrıldıktan sonra tanımlanan buffera ADC değerleri sırasıyla yazılıyor.



Bu kısmı düzelttikten sonra ADC ölçümünü tetikleyebilir ve ölçüm verilerini ister bir periyodik interrupt içerisinde ister aşağıda verdiğim ölçüm tamamlandı interruptı içerisinde değerlendirebilirsiniz.

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *AdcHandle)
İyi çalışmalar.



CAN Bus Frame Tipleri

Yazıya başlamadan önce CAN Bus temelleri ve mesaj yapısının temellerini incelemek için bu linkte yer alan blog yazısını inceleyebilirisiniz ...