STM32F334 ADC donanımı.

Başlatan Logan, 16 Mart 2016, 15:58:43

Logan

Merhaba arkadaşlar.

Elimde STM32F334 MCU'nun Disco bordu var. Aktif olan bir projede bu malzemeyi kullanmayı düşünüyorum. Ancak aklıma takılan birkaç nokta var.

"A" ve "B" kanal olmak üzere 40 khz PWM sinyali üretip H-Bridge süreceğim ve geri besleme rutini için akım bilgisini referans sinyale eşitleyeceğim. Daha önce farklı MCU'lar ile yapılan uygulamalarda A kanalında bulunan PWM sinyalinin yükselen kenarında ADC çevrimini tetikleyip, çevrim bitiminde kesme programına dallanarak PID hesaplarını yapıyordum. MCU'nun FPU özelliği olması dolayısı ile noktalı sayıların çarpma ve bölme süreleri birkaç saykılda bitiyor ve yeni PWM tetiği gelmeden alt programdan çıkıyordum.

Aynı işlemleri yukarıda bahsi geçen MCU ile de yapmayı planlıyorum. ST'nin bu MCU için standart kütüphane desteği yok. Bu sebeple HAL kütüphanesi üzerinden MXCube ile ilerliyorum.

İlk olarak HRTIM kullanarak 2 kanal 40 khz pwm sinyalini oluşturdum. Daha sonra ADC kanalını ayarlayarak tetikleme sinyalini aktif ettim. PWM sinyalinin yükselen kenarında ADC tetikleniyor ve çevrim bittiği an alt programa dallanıp hesaplamaları yaparak çıkıyor. Buraya kadar sorun yok. Ancak ikinci ADC bloğunun kanallarını aktif ettiğim zaman işler karışıyor.

ADC1 ve AC2 modüllerinin kesmeleri aynı vektöre bağlı olduğu için ADC1 kanal çevrimleri kesmeleri aktif olsun, ADC2 kesme üretmesin gibi durum söz konusu değil. Kesmeyi aktif ettiğimiz zaman hangi kanaldan çevrim yaparsak yapalım kesme oluşuyor (ya da ben öyle anladım!). Bu durumda benim program içerisinde çok kritik olmayan (sıcaklık okuma, pot okuma, voltaj okuma vs. vs.) ADC ölçümleri de kesme rutinine dallanıyor. Her ne kadar olmasını istediğim bir durum olmasa da çevrim hızları yüksek olduğu için (200nS) çok da önemsenecek bir gecikme yaratmıyor (5 kanalın okunması toplam 2.1uS).

Ancak, donanım içerisinde ADC çevrim sonuçlarının yazıldığı değişken tek (DR registeri). Donanım, 5 çevrimi bitirip kesme alt programına geldiği zaman çevrim sonuçlarını aynı değişken üzerine yazdığı için ben sürekli bu değişkende son okunan kanalın değerini görüyorum. Her çevrimi farklı değişkenlere yazılması gerekir diye düşünüyorum ama teknik dökümanlarda böyle bir ibareye rastlamadım!

Ben, bir şekilde sadece 1. adc bloğunun kesmesini aktif edip diğer kanalları yazılımsal olarak okuyabilir miyim? Ya da hepsini "Scan conversation" ile okuyup bitiminde kesme alt programına geldiğinde farklı değişkenlerden okuma yapabilir miyim? Birinci problemim bu.

İkincisi, DMA modunu aktif ettiğimde ADC kanalları PWM ile tetiklendikten sonra çevrimlerini bitirip alt programa dallanıyor ve gayet hızlı bir şekilde pointer ile tanımladığımız değişkenlere sonuçları atıyor. Ancak kesme rutininin içerisinde DMA'ya ilişkin bir alt prosedür var ki işlem süresi yaklaşık 6uS. İçerisine baktığımızda ise 50 satıra yakın bir kod ve bir çoğu flag kontrolü. Hangisinin ne işe yaradığını anlamak güç. Üzerine kendi programınızı yazmaya kalktığınızda benim gibi 40 khz ve üstü frekanslarda çalışıyorsanız sıkıntılar yaşamaya başlıyorsunuz. Nanosaniyeler bile önemli hale geliyor ki 6uS oldukça uzun bir zaman.

Bu MCU'nun donanım olarak çok güçlü olduğunu düşünüyorum. Yüksek çözünürlüklü PWM modu, 4.6GHz PWM sinyali üretiyor (bizzat denedim.) ADC kanallarını birbirine bağlayarak 18 Msps (55nS çevrim süresi) hızlara ulaşabiliyorsunuz. Ayrıca trip zone özellikleri de oldukça esnek. Böyle güçlü bir donanımın, ADC kanallarının bu denli kilitleyici olması bana çok saçma geliyor. Kaldı ki elimde PFC + Buck Converter bordu var. İkisinin bütün kontrolünü tek MCU ile hallediyor. Ben ise 40 khz'de 5 kanal ADC'yi istediğim hızlarda ve şartlarda okuyamıyorum.

Problem budur. Konu hakkında bilgisi olan arkadaşların yorumlarını bekliyorum.

İyi çalışmalar.
İmza.

Klein

DMA kullanırken kesmeleri kullanmak zorunda değilsiniz. Kullansanız bile kütüphane kullanmadan yapabilirsiniz. O kadar zaman harcamamalı.
Bahsettiğiniz çipi hiç incelemediğim için kesin bir şey söyleyemem ama
DMA bufferini circular ayarlayıp , ADC'yi de scan moda alırsanız, hiç kesme kullanmadan işinizi halledebilirsiniz sanırım. 

Logan

Klein,

DMA modu circular olarak ayarlı. ADC'ler de scan modda çalışıyor. Ancak bir önceki mesajımda da dediğim gibi Cubemx kullandığımız için DMA kesmesini aktif etmeme gibi bir şansımız kalmıyor. Standart kütüphane desteği olsa muhtemelen bu kadar uğraşıyor olmazdık.

Anladığım kadarıyla DMA olmadan bu donanımı istediğim gibi kullanamayacağım. Dün bu mesajı yazdıktan sonra HAL kütüphanesinin oluşturduğu DMA alt programına biraz göz gezdirdim. Tam olarak ne işe yaradığını anlamadığım bir sürü bayrağı kontrol edip farklı değişkenlerin yedeklerini alıyor. Teker teker kapatarak programdaki tepkilerine baktım (bu tasvip ettiğim bir yöntem değil ancak destek alamıyoruz). İşe yaramadığını düşündüğüm kısımları sildim ve prosedürü daha soft bir hale getirdim. Şu an aynı bloktan (ADC1) 5 kanal ADC okuyup DMA'dan değişkenlere atması ve bayrakları temizlemesi 1.78uS sürüyor. Bana bütün PID algoritmasını bitirmek için en az 8uS kalıyor ki içinde FPU olan bir MCU için bu oldukça uzun bir zaman.

Şimdilik bir sıkıntı yok gibi. Fakat yukarıda da dediğim gibi bu hiç tasvip etmediğim bir yöntem. ST'nin MXcube ve HAL kütüphaneleri ile yaptığı iş sanırım tam olarak şuna benziyor; Diyelim ki Lexmark marka X544 model bir yazıcıyı windowsa tanıtmaya çalışıyorsunuz ancak windows içerisinde binden fazla yazıcının sürücüsü var. Siz ise belki ömrü hayatınızda bir ya da iki yazıcı kullanacaksınız. HAL kütüphanelerindeki durum da budur. Gerekli gereksiz bir sürü kontrol ve tanımları global olarak prosedürlerin içine yerleştirmişler. Halbuki işinize yarayan kısımları belki birkaç satır.

Pek zannetmiyorum ancak umarım ilerleyen zamanlarda standart kütüphane desteği çıkar. Yoksa bu HAL kütüphanesi içinden çıkılacak gibi değil.

İyi çalışmalar.
İmza.

tmcone

@Logan,

Kesme oluşunca hangi ADC modülünden kaynaklandığını ADC handle dan anlayabilirsin.

Regular kanallar için sadece bir tane ADC sonuç registeri var her modülde. Dolayısıyla DMA kullanmadan regular kanallarda tarama yaparsan üzerine yazar (discontinuous mode aktif değilse) ve sadece son çevrimi görürsün. Injected kanallarda 4 tane sonuç registeri bulunmakta. Eğer her iki ADC modülünde kanal sayısı 5'er veya daha az ise Regular ve/veya Injected çevrim ile DMA kullanmadan eş zamanlı tarama yaptırabilirsin.

STM32 lerin ADC peripheralı oldukça esnek ve gelişmiş özelliklere sahip. Reference manualde bunlar kapsamlı bir şekilde anlatılmış.

HAL kütüphanesi ve CubeMX hızlıca uygulama geliştirmeye olanak sağlıyor. Kullanımı da basit. Zor olan alışkanlıkları değiştirmek sanırım.


z

Bu bahsettiğin işlerin daha fazlasını 40Khz pwm ile (5 adet H bridge ile sürülen 2 adet step motor ve 1 solenoid) STM32F103C8 ile yapıyorum.

Seçtiğin işlemci ile hayli hayli yaparsın.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Logan

tmcone,

Şu Injected konusunu tam olarak anlamadım. Yaşadığım sıkıntı, farklı adc bloklarındaki adc kanallarının her birinin kesme üretmesi ve benim kesme alt programında bunları ayırt edememem. Bu durum normal. Senin de dediğin gibi çevrim sonuç registeri tek olduğu için hep son çevrilen değeri görüyorum. Her çevrim sonrası kesme alt programına gelse ve bu esnada handle ile hangi kanalı çevirdiğine baksam sorun olmaz. Ama ben kesme alt programına her seferinde değil bütün çevrimleri bitirdiğinde gelmesini istiyorum. Burada DMA'yı da kullanmadığımız zaman yukarıda da dediğim gibi değişkenler karışıyor.

Yanlış anlamadıysam Injected mod ile bu problemin aşılabileceğinden bahsetmişsin. Biraz daha detay verebilir misin?
İmza.