AMAÇ ve KAPSAM
En eğlenceli bulduğum projeler hareket eden şeyler yapmaya yönelik olanlar. İş hareket ve konumlandırma kontrolu olunca karşımıza motorlar ve encoderler çıkıyor.
Günün havalı terimi ile -robotik- için kullanılan servo ve step motorları sürmek için özelliklerine uygun darbe sinyallerini üretmemiz gerekiyor.
Bu yayının konusu darbe dizileri halindeki bu sinyallerin STM32 serisi mikradenetleyiciler ile üretilmesi.
Bunun için iki farklı yaklaşımdan söz etmek mümkün. Birincisi Timer interruptlarından (kesmelerden) yararlanmadan çalışmak, diğeri de kesmelerden yararlanarak.
KESME (UNTERRRUPT KULLANMADAN ÇALIŞMAK
Bunlardan birincisinde mikrodenetleyici ana süreçten hareket emrini alır, motoru hangi hızda hangi yönde ne kadar ilerleteceğini, buna bağlı olarak bobinlerine uygulanması gereken sinyalleri hesaplar, sonra birer darbe dizisi halinde olan bu sinyalleri çıkış ayaklarından motor sürücüye gönderir.
Burada ana süreç diye andığım şey, sistemin ana fonksiyonu. Ben bu alanda yaptığım neredeyse her çalışmayı masa üstü CNC sistemimde uygulamaya koyuyorum. Oradaki ana süreç, SD kart üzerinde verdiğim ya da PC den gönderdiğim CNC Gerber Kodlarını alıp onlara göre 3 adet eksen motorunu kontrol eden yazılımım.
Step motor bobin çiftlerinden her birinin ikişer ucuna gönderilen kontrol sinyalleri aşağıdaki gibi olacak. Üstteki iki sinyal A bobininin iki ucu, alttaki iki sinyal de B bobininin iki ucuna uygulanan kontrol gerilimleri. İki bobine uygulanan sinyaller arasında 90 derece faz farkı var. Bu bir bipolar motor, bobinlere iki yönde akımlar veriliyor.
Her 1 ms de bir adım ilerleyen bir adım motorunda verilen sinyaller bunlar. Yukarıdaki ekran görüntüsünde her milisaniyede bir bir değişim (inen ya da çıkan kenar) gözlenebiliyor.
ŞİMDİ GELELİM NEDEN KESMELERDEN YARARLANMAMIZ GEREKTİĞİNE
Bu sinyale biraz daha geri çekilip uzaktan bakalım :
Biraz gençlik enerjisi ve desteği fena olmaz. O ufaklık lojik analizör ile çalışmalarını sürdüre dursun, biz osiloskop ekranına bakalım.
Osiloskop ekranında motora 10 mm ileri gitmesi için gönderdiğim 500 adımlık darbeden oluşan sinyalleri görüyoruz. Her beşyüz adımdan sonra, bir sonraki komutu alıp işleyerek, ya da başka bişeyler yaparak geçirdiğimiz 60 milisaniyelik aralıklar var. Yani mikro denetleyicimiz motoru ilerletmekle meşgul iken başka iş yapamadığı için böyle bir zaman kaybı var. Ya motoru ilerletecek, ya da bu işleri yapacak, ikisi aynı anda olmuyor.
Ben bu 60 milisaniyede TFT ekrana bir şeyler yazdırıyorum, fazla bişey değil. Halbuki mikrodenetleyicinin motora yeni bir seri sinyal göndermeden önce yapması gereken çok daha önemli başka işler de var.
Kullanıcı herhangi bir düğmeye basmış mı diye bakacak, motorlar ısınmış mı, ana süreç motorun şimdi ne yapmasını istiyor diye bakacak, yeni komutu alıp analiz edecek …
Yani sistemimizde, örnekteki 60 milisaniyelik aralıklar rahatlıkla yüzlerce milisaniyeye ulaşabilecek. Bu da sistemimizin faydalı üretim hızını yavaşlatacak, verimini düşürecek.
Halbuki, motora adım sinyallerini göndermek gibi rutin tekrarlanan bir iş için mikro denetleyicinin CPU sunu meşgul etmeye gerek yok. STM32 nin bu işi kendi başına yapabilecek araçları (çevre birimleri = peripherals) var.
Bunun için STM32 nin kesme fonksiyonlarını ve zamanlayıcı (TIM = Timer) araçlarını kullanmamız gerekiyor. Bunu yaptığımızda motorun sürücü sinyalleri aşağıdaki gibi oluyor:
Osiloskop ekran görüntüsünde motorun kesintisiz olarak hareket ettiğini görebiliyoruz. Halbuki burada da sistemimiz bir önceki paragrafta anlattığım ile aynı işi yapıyor, yine ikide bir ekranda her biri yüzlerce milisaniye sürebilen mesajlar yazıyor, ama bunu yaparken motor da ilerlemeye devam ediyor.
İşte bunu mümkün kılan aşağıda anlattığım kesme -Interrupt- fonksiyonları.
Şimdi asıl konuya girebiliriz.
Genel : Kullandığım dil ve terimler hakkında
Öncelikle İngilizce teknik terimlerden dolayı kusura bakmayın. Bu yazıları hazırlayabilmek için çok zor zaman ayırabiliyorum. Kullandığım, başvurduğum bütün kaynaklar İngilizce. Yazıyı hazırlarken bunun Türkçe karşılığı ne olabilir diye durakladığımda iş daha da zorlaşıp yavaşlıyor. Genelde özen gösterdiğim “Türkçe yazıyorsam her şey Türkçe olmalı” kuralımı buradaki teknik yazılarda gözardı ediyorum. Teknik olmayan yayınlarda bunu fazlasıyla telafi etmeye söz veriyorum.
Ayrıca araya Ingilizce başlıklar da sıkıştırıyorum. Bunlar, yayınlarımın Google sorgulamalarında görünmesi amacına yönelik.
STM32 TIMER’ları ile darbe üretimi
GENERATING PULSES USING STM32 TIMERS
STM32 Serisi mikro denetleyicilerin zamanlayıcıları (ya da sayıcıları – Timers) ile istenen frekans ve genişliklerde tek ya da dizi halinde darbeler üretmek çok kolay oluyor.
Elbette, bu kolaylık STM32 TIM (Timer) larının yapısını ve kullanımını öğrenmek için biraz emek harcadıktan sonra sağlanıyor. Sadece zamanlayıcıları değil, biraz da “kesme” Interrupt (IT) kullanımını öğrenmek gerekiyor. Zamanlayıcıları kesme fonksiyonlarını kullanmadan da çalıştırmak mümkün, ama bu kullanım alan ve esnekliğini azaltmak oluyor.
Ben bu yayında STM32F103 denetleyicisinin TIM3 zamanlayıcısını ve Kesme fonksiyonlarını kullanarak, aynı anda 4 adede kadar çıkış ayağından 4 farklı genişlikte darbe üretimini sıfırdan başlayarak adım adım anlatmayı hedefliyorum.
Anlattıklarım her ne kadar STM32F103, TIM3, 1ms ve 0.5 ms ilk darbe üretimini ele alıyorsa da STM serisindeki başka mikro denetleyicilere ve başka zamanlayıcılara, farklı darbe frekans ve sürelerine kolayca uygulanabilir.
KULLANDIĞIM YAZILIM ve DONANIM
Geliştirme platformu : Atollic True Studio for STM
Diğer yazılım araçları : ST cube MX ve HAL Kütüphaneleri
Donanım : STM32F103C8 mini geliştirme kiti
Programlama ve debug aracı : ST-Link V2
İzleme/Ölçüm aracı : OWON 100Mhz, 2 kanal sayısal osiloskop
GEREKEN ÖN BİLGİLER
Burada verilen rehber okuyucunun aşağıdaki konularda bilgisi olduğu varsayımına dayanmaktadır:
- Gömülü (embedded) C Programlama,
- Atollic True Studio kullanımı,
- Mikroişlemciler, STM32 Ailesi hakkında bilgi
- ST Cube MX kullanımı
- ST HAL kütüphaneleri ile programlama
- ST-Link programlayıcı ve debugger kullanımı
- Osiloskop kullanımı
- Genel olarak Interruptlar ve STM32 Interruptları hakkında bilgi
ÇALIŞMA DÜZENİ
Bu konuda söylenecek fazla birşey yok. Geliştirme kitine ST_Link programlayıcı bağlanacak, osiloskop problarından birisi PA6, diğeri PA7 ayaklarına bağlanacak ve kite 5V beslemesi verilecek. Ben elimin altındaki bir STM32F103C8 kitini kullandım.
ST Cube MX İLE PROJENİN YARATILMASI
Adım 1 – Cube MX i çalıştırıp mikrodenetleyici seçimini yapmamız gerekiyor. Aşağıdaki resimde bazı ayaklara atamalar yapılmış olarak görünüyor, ama Cube MX ilk açıldığında yeni proje başlangıcında bunlar olmayacak. Burada anlattığım ayarlardan sonra belirecekler.
Adım 2 – Sistem saatlerinin ayarlanması
Bunun için önce mikroişlemcinin osilatörünün harici kristal ile mi yoksa dahili RCdevresi ile mi sürüleceği belirleniyor. İşlemcinin dahili RC osilatörü %5 den iyi bir kalibrasyona sahip olsa da benim kullandığım kitte bir 8 Mhz harici kristal varken kullanayım dedim ve seçimimi buna göre yaptım.
LSE (RTC Saat için) kullanmıyoruz, onun için kapalı bırakıyorum.
Sistem saati ayarlamasında ikinci adım şöyle :
Sistem saatini 72 MHz e ayarlayacağız. Bunun için aşağıdaki resimde görünen ayarları yapmak gerekiyor. Buradaki ayarlar ile daha düşük frekanslar da seçilebilir. Bu durumda benim burada vereceğim darbe period ve süreleri aynı oranda artacaktır.
Adım 3 – Projenin kaydedilmesi
Projeyi bu aşamada isimlendirip kaydetmekte yarar var. Project Manager sekmesi altındaki aşağıdaki bölüm görüldüğü gibi doldurulduktan sonra ekranın en üstündeki File sekmesinden “Save Project As” seçeceği ile istenen yere kaydedilir. Kaydedildikten sonra projenin isminin değiştirilemeyeceğini de belirteyim.
Adım 4 – Programlama ve debug arayüzü seçimi
ST-Link aracını tek telli modda (SW) kullanacak şekilde aşağıdaki resimde görünen ayarları yapıyoruz. Bu işlem PA13 ve PA14 ayaklarını programlama ve debug işlemlerine atıyor.
Adım 5 – Zamanlayıcı seçim ve ayarları
TIM3 zamanlayıcısını kullacağız. Mikro denetleyicinin desteklediği bir başka zamanlayıcı da benzeri ayarlarla kullanılabilir. TIM3 seçmenin özel bir nedeni yok, TIM1 ve TIM8 ve neredeyse tüm zamanlayıcılar rahatlıkla kullanılabilir, yeterki mikro denetleyicimizde bulunan bir Timer olsun.
Resimde sadece Channel 1 seçilmiş görünmekle birlikte istenen farklı sinyal çıkış sayısına göre 2, 3 ya da 4 kanal da aktif edilebilir. Örneğin 3 adet eksen motoru bulunan CNC için üç kanal kullanılabilir. Bütün zamanlayıcılarda 4 karşılaştırma çıkış kanalı bulunmuyor. O konuya da burada girmiyorum.
Sayıcımız dahili saat kaynağından sürüleceği için Internal Clock seçeceğini işaretliyoruz.
Ayrıca “kesme” kullanacağımızdan TIM3 Global Interrupt seçeneğini de işaretliyoruz.
TIM zamanlayıcılarının çıkış kanalları doğrudan denetleyici ayaklarına verilebiliyor, biz direkt vermeyeceğiz, Interrupt handler kodlarımızla gerekli işlemleri yaptıktan sonra istediğimiz ayaklara çıkış vereceğiz.
Ama, çıkışın bir ayağa nasıl yönlendirileceğini göstermek açısından aşağıdaki ekran görünümünü veriyorum. Bizim uygulamamızda böyle bir seçim yapılmıyor.
Not: Cube MX in bu penceresi biraz sorunlu, alt pencereler ekrana sığmıyor, kısmen görünüyor. Kaydırma çubukları da çok az ya da hiç görünmüyor. Bu nedenle, tam ekran modunda kullanmak gerekiyor, o da yetmiyor “Configuration” penceresini üst kenarından yukarı çekip büyütmek gerekiyor.
Çıkış pin seçimlerini yapabileceğiniz bölüm ancak o zaman ortaya çıkıyor.
Adım 6 – Burada ayrıca bir resim konulmuş olmasa da PA6 ve PA7 ayakları “GPIO Out PP” olarak ayarlanır. Bu işlem için sağ taraftaki işlemci resmi üzerinde ayakların üzeri tıklanarak drop down seçenek listelerine ulaşılır.
Adım 7 – Son olarak da “GENERATE CODE” tıklanarak proje dosyası üretilir.
Bu işlem tamamlandığında ya proje klasörünü açmak ya da projeyi doğrudan Atollic True Studio da açma seçenekleri sunulur. Ben Atollic’i açmayı tercih ediyorum.
Projenin Atollic True Studio’da devamı
Atollic True Studio ya geçişim – IDE Seçimi
Biraz daha önce kullandığım yazılım geliştirme araçları ile bugünlerde kullanmakta olduğum Atollic True Studio ya nasıl geldiğimden söz edeyim.
Gömülü (Embdedded) kod geliştirmede yararlanılacak olan geliştirme platformu önemli adımlardan birisi. Söz konusu yazılım geliştirme platformları oldukça kompleks – en azından benim gibi “alaylı” yazılımcılar için – araçlar. Her birisi ancak haftalarca çalışma ile öğrenilecek özellikler, menüler, fonksiyonlar içeren karmaşık yazılımlar. Karmaşık, öğrenmesi emek isteyen ama hakim olduktan sonra da hayatı kolaylaştıran vazgeçilmez araçlar.
Kullandığım gömülü yazılım geliştirme ortamı/aracı tanımına uygun ilk araç -2000 lerin başlarında- KEIL’in C51 8 bit işlemciler için geliştirdiği platform idi. Bunu kullanarak Atmel 89S53 mikro denetleyicili cihazlar geliştiriyordum. Bedava değildi ama boyut sınırlaması olan bedelsiz versiyonları işimi görüyordu.
Bundan sonra 16 bitlik denetleyicilere geçtiğimde kısa bir süre Motorola Code Warrior kullandım ama 16 bit denetleyicilerle çalışmam pek uzun sürmedi, 32 bit’e geçince bunu terkettim.
32 Bit denetleyicilerle birlikte yine KEIL’e, bu defa MDK4 ve MDK5 platformlarına geçtim. Bu arada emekli de olduğumdan KEIL bana hiç yüz vermiyor, sorularıma dahi yanıt vermiyordu. Bu toolların 32 Kbyte ile sınırlı ücretsiz sürümlerini kullandım. Ama bu sınırlama artık can sıkmaya başlamıştı. STM32 serisi 32 bit ARM işlemciler üzerinde geliştirdiğim yazılımlar 64 KB sınırını aşmaya başladı.
Ortalıkta ücretsiz geliştirme araçları vardı, ama onların kullanımını öğrenmek de gözümde büyüyordu.
Sonunda, ST Micro Electronics imdada yetişti. Kendi ürünleri olan STM32 serisi mikro denetleyicilerle kullanılmak üzere, hiçbir zaman ya da boyut sınırlaması olmasızın “Atollic True Studio for STM32” aracını müşterilerine sundu.
Böylece ben de şu anda kullanmakta olduğum Atollic platformuna geçmiş oldum. Bunu öğrenmek de epeyi bir çaba gerektiriyordu ama olsun, bundan kaçış yok. Hala öğrenme sürecindeyim. Tüm fonksiyonları ile öğrenmek hiçbir zaman mümkün olmayacak her halde.
Yakınlarda ST, bunun da yeni bir versiyonunu CubeIDE adı ile çıkardı. Cube MX ile Atollic’i birleştiren bir ürün. İndirip denedim ama henüz stabil olmadığını düşünüyorum – belki de benim hatalarım nedeniyle verimli kullanamadım.
Ben bir süre daha Cube MX ve Atollic’i ayrı ayrı kullanmaya devam edeceğim.
Edit 2020 Ocak :
ST bir mesaj göndererek bundan böyle Atollic True Studio ya destek vermeyeceğini, sadece CubeIDE ile yürüyeceğini haber verdi, kendinizi buna göre ayarlayın dedi. Mecburen CubeIDE ye geçtim, eski kodlarımı buna transfer etmeyi öğrendim. Artık CubeIDE ile çalışıyorum, memnunum.
Bu yayında anlattıklarım CubeIDE için de geçerlidir.
Projenin Atollic’de açılışı
Cube MX den sonra “Projeyi aç” seçeceği tıklandığında Atollic True Studio açılır. Sol taraftaki project explorer panelinde yeni projemizi görüyor olmamız gerek.
Cube MX projemizin dosya alt yapısını, temel bölümlerini hazırlayıp sunuyor. Ama bazı ayrıntıların tamamlanmasını gene de bize bırakıyor. İzleyen paragraflarda bunları anlatacağım.
Önce ana program içine eklenmesi gerekenler:
CubeMX seçmiş olduğumuz zamanlayıcılar için gereken kodların çoğunu hazırlamış durumda. Ama zamanlayıcıları kullanabilmek için önce onları başlatmak gerekiyor. Bunu da aşağıda 92. ve 93. satırlara koymuş olduğumuz komutlarla yapıyoruz. Bu örnekte ilk iki çıkış kanalını kullandığımdan sadece bunları “IT” yani kesmeleri de aktifleştirerek başlatıyorum.
Burada tekrar hatırlatayım: Zamanlayıcılar direkt olarak çıkış ayaklarına bağlanıp sinyallerini dışarı verebiliyorlar, ama ben çıkış sinyalleri üzerinde tam hakimiyet kurmak adına böyle yapmıyorum. Zamanlayıcılardan aldığım kesme sinyallerini kullanarak çıkış ayaklarına kendi istediğim sinyalleri vereceğim.
SİSTEM SAATLERİ AYAR RUTİNİ
Her ne kadar Cube MX gereken kodları hazırlamış olsa da, hazırlamış olduğu fonksiyonun nasıl bişey olduğunun görünmesi açısından buraya koymakta fayda var. Bu fonksiyon bu şekilde ise, yapmamız gereken başkaca bir değişiklik ya da eklenti yok. CPU saatimiz 72 MHz de çalışacak.
ATOLLIC İÇİNDE YAPILMASI GEREKEN EKLEME VE DÜZENLEMELER
GİRİŞ ÇIKIŞ (GPIO) AYARLARI
Yukarıdaki fonksiyon ile sadece 3 adet çıkış ayağını yapılandırıyoruz. Eğer 2 değil de daha fazla çıkış kanalı kullanılıp dışarıya sinyal verilecek ise, başka ayakların da benzeri şekilde eklenerek yapılandırılması gerekir.
TIMER AYARLARI
Cube MX in hazırladığı main programının 89. satırında çağrılan MX_TIM3_Init() fonksiyonu ile zamanlayıcı ayarları yapılıyor, ama buna bizim eklememiz/değiştirmemiz gereken şeyler var.
MX_TIM3_Init() fonksiyonu yine main.c dosyası içinde aşağıdaki gibi yer alıyor. Aşağıda görülen kod temel sayıcı kodlarını içeriyor. Burada 163 ve 165. satırlara bakacağız.
Bunlardan 163. satırda sistem saatinin kaça bölünerek zamanlayıcı sayacına verileceğini ayarlıyoruz. Cube MX de sistem saatini 72MHz e ayarlamıştık. Bunu 72 ye bölersek 1 MHz ilk bir saat ile zamanlayıcımızın sayıcısını sürmüş olacağız. Yani her 1 mikro saniyede bir adım ilerleyecek. O halde 163. satırdaki Prescaler parametresini 72 yapabiliriz. Daha yavaş çalışacak işler için bunu 0xFFFF e kadar arttırabiliriz. O zaman sayacımız aynı oranda yavaşlayacaktır.
Düzeltme : Aslında saat sinyalini 72 ye bölmek için prescaler değerini 72 değil, 71 yapmamız gerekiyor, zira TIM kütüphane fonksiyonları buna “1” ekliyor. “0” verildiğinde bu “1” e karşı düşsün, bölme yapılmasın amaçlanmış. Bu nedenle buradaki örneklerde bu hatayı bilerek ilerlemenizi rica ediyorum. Yayını revize edersem bunu da düzeltirim.
Peki sayıp sayıp nereye kadar gidecek ? İşte onu da 165. satırdaki Period parametresi ile ayarlıyoruz. Aşağıda 32 bit 0xFFFFFFFF göründüğüne bakmayın o yanlış, onu 16 bit yani 0xFFFF (65535) olarak düzeltiyoruz.
Böyle ayarlayınca sayaç her mikrosaniyede bir artarak 0 dan 65535 e kadar gidecek, sonra sıfıra dönerek yeniden başlayacak.
Bu şekilde 0 dan başlayıp 65535 e kadar sayıp sonra başa dönen sayıcıyı şöyle kullanacağız.
Zamanlayıcıların her bir çıkış kanalının kendisine ait birer karşılaştırma kayıtçısı (register) var. Bu kayıtçılara, her bir kanalda elde etmek istediğimiz darbe genişliğine karşı düşecek bir sayaç değeri yazıyoruz. Zamanlayıcının sayaç değeri bu karşılaştırma değerine eşitlenince çıkış kanalımız bir “kesme” üretiyor. Ta ki yeniden buna eşit bir sayaç değerine ulaşılana kadar.
Biz bu kesme işaretini alınca istediğimiz işlemi yapıyoruz. Örneğin bu uygulamada bir çıkış ayağının değerini tersine çeviriyoruz, “1” ise “0”, “0” ise “1” yapıyoruz.
Zamanlayıcının 4 çıkış kanalı olduğundan, bir birinden bağımsız 4 farklı periyottaki kesme sinyalini 4 farklı işlem yapmak için kullanabiliyoruz. Bu örnekteki uygulamamızda bu imkanı kanallardan ikisini kullanarak 2 farklı ayağa farklı genişlikte darbe sinyalleri vermek için kullanıyoruz.
Aşağıdaki ekran kopyasında 1. kanala 1000, ikinci kanala da 500 değerlerini koyuyoruz. Yani 1. kanal sayaç 1000 olduğunda, 2. kanal da 500 olduğunda kesme üretecek.
İyi ama, bu durumda sayaç 500 ya da 1000 olduktan sonra ta 65535 kadar gidecek, sonra 0 a dönüp tekrar 500 ve 1000 olana kadar başka kesme olmayacak. Bizim istediğimiz böyle 65 milisaniye genişlikte darbeler değil, 1000 ve 500 milisaniye genişliğinde tekrarlanan darbeler.
Bir başka deyişle 1 ms ve 0.5 ms genişlikte kare darbeler üretmek istiyoruz.
O halde 1. kanalın karşılaştırma değerini 1000, 2000, 3000… olarak, ikinci kanalınkini de 500, 1000, 1500 … olarak sürekli güncellemek gerekiyor. Bunu biraz sonra anlatacağımız kesme rutini (IRQ handler callback) içinde yapacağız.
KESME (INTERRUPT) KODLARI
Mikrodenetleyicide Timerlar bir kesme yarattığında “IRQ Handler” adı verilen kesme rutinleri devreye girer, her bir kesmeye karşı düşen işlemleri yaptıktan sonra akışı tekrar ana döngüye bırakır.
Bizim geliştirme ortamımızda da her türlü kesme için varsayılan kotarma (Handler) fonksiyonları var, kesme oluştuğunda her kesmenin kendi fonksiyonu çağrılır.
Kesme programının başlığı belirlenmiş olmakla birlikte içi boş olup, kulanıcı yani bizler tarafından ne isteniyorsa onu yapacak bir kod ile doldurulması gerekiyor.
Yukarıda sözünü ettiğimiz kesme rutin başlıkları startup.s dosyası içinde aşağıdaki gibi listeleniyor.
Bizim kullandığımız TIM3 ile ilgili olan handler fonksiyonunun 190. satırda TIM3_IRQHandler olduğunu görüyoruz. Bu fonksiyonun prototipi ise bir başka yerde stm32f1xx_it.c dosyasında TIM3_IRQHandler() olarak bulunuyor.
Bu da işi HAL_TIM_IRQhandler(&htim3) fonksiyonuna havale ediyor.
HAL_TIM_IRQhandler(..) fonksiyonu stm32f1xx_hal_tim.c dosyasında bulunuyor.
Böyle oradan oraya gidiyor olmak biraz yorucu oluyor olsa da sonunda ulaştığımız HAL_TIM_IRQhandler fonksiyonu bizi epeyi bir kod yazmaktan kurtarıyor.
Birincisi kesme sinyalinin hangi kanaldan geldiğine bakıp 2803. ve daha aşağıdaki başka satırlarda olduğu gibi tim->channel = … şeklinde kaydedip bize veriyor. Gereken kesme bayraklarını indirip kaldırıyor, bize sadece kesme oluştuğunda ne yapacağımızı kodlamak kalıyor. Bunun için de “HAL_TIM_OC_DelayElapsedCallback(htim)” fonksiyonlarına gönderme yapıyor. Bu fonksiyonu bu isim altında main.c dosyasında hazırlayacağız.
Her bir kesme geldiğinde istediğimiz genişlikte darbeyi üretecek HAL_TIM_OC_DelayElapsedCallBack fonksiyonu aşağıda görülüyor. Bu fonksiyon Main.c dosyası içinde. Bunu CubeMX hazırlamıyor, bizim hazırlayıp koymamız gerekiyor.
Call back fonksiyonunu hangi isim altında hazırlayacağımızı “stm32f1xx_hal_tim.c” içinde küçük bir araştırma yaparak bulabiliyoruz. Orada bu isim altında (ya da başka bir kesme işlemi ile ilgileniyorsan onun adı altında, her bir callback fonksiyonu için) ama “weak” ön eki ile bir şablon bulunuyor. Bu şablonu kopyalayarak main.c ye yapıştırıp içini istediğimiz gibi doldurabiliyoruz.
Bu örnekte bir hata olduğunu da belirtmekte yarar var. Bu call back fonksiyonunu User Code 4 bölümü içine koymak gerekirken, dışına koymuşum. Görseli değiştirmeye vaktim olmadı.
CallBack fonksiyonları bizi epey bir ayrıntıyı ezberlemekten ve yeniden kodlamaktan kurtarıyor. Sadece kesme geldiğinde yapmamız gereken işe odaklanabiliyoruz.
Burada görüldüğü gibi, her kesmede buna ilişkin çıkış ayağını tersine çeviriyoruz, sayıcının karşılaştırma değerini de darbe uzunluğu kadar öteye atıyoruz. Böylece istediğimiz sayıda sayaç adımı atıldığında yeni bir darbe kenarı üretiyoruz. Sonuçta kare dalgalardan oluşan bir çıkış sinyalimiz oluyor.
Her bir kanalda farklı darbe uzunlukları seçebiliyoruz. Bu örnekte iki kanal var, ama zamanlayıcmızın 4 kanalı olduğundan çıkış ayak ve sinyal sayısını 4 e kadar arttırabilir, sinyalleri istediğimiz mikroişlemci ayaklarına verebiliriz.
SONUÇ
Artık Atollic’in “build” butonlarına basıp programımızı derledikten sonra “debug” butonuna basarak kodumuzu mikro denetleyiciye aktarmak kalıyor.
Hazırlanan kodun ST-Link ile mikro denetleyiciye aktarılmasında bir sorun ile karşılaşılırsa, bir sefere mahsus olmak üzere ST-Link Utility Uygulaması ve “Connect Under Reset” seçeceği kullanılarak Atollic True Studio nun hazırladığı “.hex” ikili kod dosyasını doğrudan yüklemeniz gerekebilir. Atollic bu hex dosyasını varsayılan olarak üretmiyor, mikro denetleyiciye yüklenmek üzere sadece .elf dosyası üretiyor. Atollic’in bu hex dosyasını da üretmesi için “Tool Settings” menüsü altındaki bir ayarın yapılması gerekiyor.
Atollic’in ayarlarına burada girmeyeceğim.
Ve sonuç : A6 ve A7 ayaklarında 1ms ve 0.5ms genişliğinde darbeler. Arkadaki hayalet de benim.
Hocam öncelikle merhaba iyi günler, kusura bakmayın rahatsız ediyorum fakat sayfadaki görseller açılamadığından görememekteyim. Acaba pdf şeklinde veya başka bir formatta mevcutsa gönderme şansınız var mı? Emeğiniz ve öğretileriniz için çok teşekkür ederim.
Kontrol edeceğim Furkan bey. Sanırım web hosting tarafında bir aksaklık var.
Selamlar.
Furkan Bey merhaba,
Yayındaki sorunu gidermeye vakit ayıramayacağımı söylemiştim ama içim rahat etmedi. Görselleri bulup yeniden ekledim.
Selamlarımla,