PIC Programlama – 11 – USART

Merhabalar,

Önceki yazı ile birlikte, bir mikrokontrolöre nasıl SDK geliştirebileceğimizi ve PIC16F84A’nın tüm modüllerini detaylıca incelemiştik. Her iki başlık için de gerekli mesajların verildiği, gerekli bilgilerin aktarıldığı düşüncesi ile PIC yazılarının seyrini biraz daha değiştiriyorum.

PIC programlama yazı dizisinin bu bölümünde, şu zamana kadar incelemediğimiz, ancak gömülü sistemler dünyasının adeta kolonları/kirişleri olan temel modülleri inceleyeceğiz. Bunların başında da USART modülü geliyor. PIC16F84A’da ne yazık ki USART modülü bulunmuyor. Bu sebeple PIC16F877A üzerinden devam edeceğiz 🙂 Bu defa, PIC16F877A için de ayrıca bir kütüphane yazmak yerine, mecvut kütüphaneleri kullanarak uygulama yapacağız. Kütüphane geliştirme ile ilgili bilgileri önceki yazılarda yeterince işlemiş olduğumuzdan, bu yola girmekte artık bir sakınca görmüyorum. Dileyen azimli arkadaşlar, PIC16F877A için de kütüphane yazabilirler.

Şimdi gelelim her zamanki gibi USART’a bir girizgah yapmaya. Ancak öncesinde irdelememiz gereken bir başka önemli kavram var…

Haberleşme 

Bir bilgiyi, bir kaynaktan başka bir hedefe aktarmak o bilgili veriye dönüştürüp; veriyi kaynaktan hedefe aktaracak bir haberleşme hattı kurmakla mümkündür. Çok derinden girdiğimiz bu hususu bir örnekle irdeleyelim. Ali adlı arkadaşımız, o anki şaşkınlığını ifade eden ‘A’ sesini, Veli’ye duyurmak istediğinde haberleşme süreci nasıl oluşur?

Şaşkınlık bilgisi bu şemada ‘A’ sesi ile kodlanmıştır. Bu bilgi, havayı belli frekansta titreştiren ve Ali’nin ağzından gelen ‘A’ sesi vasıtası ile havada ilerler ve Veli’nin kulağında oluşan titreşimlerin algılanması ile Veli’ye bu veri aktarılır. Ardından Veli’nin beyni bu veriyi tekrardan bilgiye dönüştürerek ‘A’ sesini algılar ve Veli; Ali’nin şaşırdığını algılamış olur. Bu şemada kaynak Ali, hedef Veli, haberleşme kanalı hava, bilgi şaşkınlık, veri ise ‘A’ sesi olmaktadır. Haberleşme ses vasıtasyla da taşınsa, elektriksel olarak da taşınsa bu şema değişmez. Bilgi, veri ve haberleşme kaynaklarını açıkladığımız bu örnek çok saf ve naif görünse de, kompleksleşen haberleşme sistemlerinde temelleri hatırlamak ve bu gerçekliklerin farkında olmak hayat kurtarmaktadır.

Bilginin veriye dönüşümü, bu yazının odak noktası olmadığından; biz verinin aktarımı üzerine yoğunlaşacağız.Peki tek bir veriyi değil de, birden fazla veriyi göndermek istediğimizde ne yapacağız?

Paralel ve Seri Haberleşme

Yukarıdaki örnekte Ali’nin biraz daha konuşkan biri olduğunu düşünelim. Ali, Veli’ye “Selam Veli” dediğinde sesler ardışıl olarak; yani peşi sıra olarak Veli’ye gider. Yani Ali sırasıyla önce ‘S’,’e’,’l’,’a’,’m’ der biraz bekler, ardından sırasıyla ‘V’,’e’,’l’,’i’ harflerini peşisıra söyler. Veli de bu sesleri -kısa bir gecikmeden sonra- aynı sıra ile duyar. İşte bu şekilde ardı-sıra veri aktarımı olan haberleşme şemaları, seri haberleşme şemaları olarak adlandırılır. Özellikle, tek haberleşme kanalının bulunduğu durumlarda, bu haberleşme yöntemi kullanılır. Seri haberleşmede yalnızca tek kanal kullanılır, ancak tüm veri sırasıyla gönderildiğinden tüm verinin aktarımı zaman alır.

Paralel haberleşmede ise veri, -adı üzerinde- paralel olarak gönderilir. 8 hoparlörü olan bir cihaz, 8 mikrofonu olan bir cihaza ‘Selamlar’ mesajını paralel olarak iletmek isterse (her bir hoparlörü sadece 1 mikrofonun duyabildiğini varsayarsak) 1. hoparlör ‘S’ sesini, 2. hoparlör ‘e’ sesini, … , 8. hoparlör ‘r’ sesini aynı anda çıkartır. Karşı tarafta da bu sesler mikrofonlardan aynı karşılıkla aynı anda algılanırsa; tüm sesler paralel olarak gönderildiğinden bu haberleşme adı üzerinde “paralel haberleşme” olur. Paralel haberleşme, birden fazla haberleşme kanalı gerektirir ancak bilgi daha kısa sürede aktarılır.

Aynı konseptler elektriksel olarak da geçerlidir. Yani ses yerine bitleri inceleyecek olursak, aşağıdaki gibi bir gösterim yapmamız yanlış olmaz. [Resim Wikipedia sayfasından alınmıştır.]

Güzel.. Şimdi dönelim konumuza. USART dediğimiz nane, bir seri haberleşme algoritması olup; sıkça kullanılmaktadır. Özellikle “tracing”,”serial logging” gibi işler için; sıklıkla USART kullanılır. Ayrıca USART ile haberleşen çok sayıda sensör vb. elektronik ekipman bulunmaktadır.

PIC16F877A ve USART

Şimdi gelelim PIC16F877A ile USART haberleşmesi yapacak kodu yazmaya… Bunun için oldukça basit bir örnek yapacağız. İlk hedefimiz, USART üzerinden “Merhaba dünya!” yazısını gönderecek bir kod yazmak. Bunu, Microchip’in en yeni kütüphanesi olan; xc kütüphanesini kullanarak yapacağız. Unutmayınız ki, xc kütüphanesini kullanabilmek için XC8 derleyicisini yüklemeniz gerekmekte.

USART haberleşmesi seri bir haberleşme olduğundan, verilerin ardı sıra gönderilimindeki zamanlama çok önemlidir. Bu sebeple, kodumuza PIC16F877A’nın kristal osilatör fraksnsını aşağıdaki gibi giriyoruz.

Öncelikli olarak UART_Intialize fonksiyonunu incelemeye başlayalım. PIC16F877A’nın C portunun 6. pini USART_TX (transmit, veri gönderme), 7. pini ise USART_RX (receive, veri alma) pini olduğundan, 6. pini çıkış, 7. pini giriş olarak konfigure ediyoruz. Buna ilişkin kod aşağıda yer alıyor:

Ardından modülümüzü konfigüre edeceğiz. Buna göre datasheet’e baktığımızda konfigüre etmemiz gereken kütüklerin TXSTA, RCSTA, SPBRG kütükleri olduğunu görüyoruz. Veri göndermek için ise TXREG kütüğüne ihtiyaç duyacağız. Veri kağıdından sırası ile bu kütüklerle ilgli bilgilere bakıp, konfigürasyonumuzu yapalım 🙂

Buna göre SYNC=0 (Asenkron mod), BRGH = 1 (Yüksek hızlı mod), TXEN=1 (Veri gönderimi aktive edildi, izin verildi), TX9=0 (8 bit veri aktarımı modu) şeklinde konfigürasyon yaptığımız gözüküyor 🙂

Şimdi hemen diğer bir önemli kütüğümüz olan RCSTA’ya bakalım.

Buna göre RX9=0 (8 bit mod), ADDEN= 0 (9. bit parity biti olarak kullanılsın), CREN=1 (Sürekli veri alımı aktive edildi, izin verildi), SPEN=1 (Seri port aktive edildi) şeklinde konfigürasyon yaptığımız gözüküyor 🙂

Seri haberleşmemizi 9600 baudrate’te yapmak istiyoruz. Buna göre SPBRG kütüğüne yazmamız gereken değeri, PIC16F877A’nın datasheet dökümanından buluyoruz.  Buna göre, veri kağıdının aşağıdaki kısmından da görülebildiği üzere BRGH bitinin durumuna göre hesaplamalar değişiyor. Biz BRGH=1 olacak şekilde konfigüre etmiştik.

Bir diğer önemli tablo da, BRGH seçim tablosu. Veri kağıdından aldığım tablolar ise aşağıdaki gibi:

Yukarıdaki tablonun alt kısmını kullancağız, çünkü BRGH=1 olarak konfigüre etmiştik. Kullanacağımız osilatör frekansı 4MHz olduğunda ve istediğimiz Baudrate (veri aktarım hızı) 9600 baud = 9.6K baud olduğundan, SPBRG değerinizin 25 olması gerektiği tablodan görülebiliyor. Biz de bu sebeple aşağıdaki konfigürasyonu yaptık:

Artık USART modülümüzü konfigüre ettiğimizden, veri gönderme kısmına geçelim. Veri göndermek için yapmamız gereken şey, göndereceğimiz 8 bitlik değeri TXREG kütüğüne yazmak. Ancak hali hazırda gönderilmekte olan bir veri var ise öncelikle onun gönderilmesini beklememiz gerekiyor. TRMT biti 1 oldğunda veri gönderimi yok demektir. Buna göre TRMT kütüğü sıfır olduğu sürece bekliyoruz.

Yukarıdaki fonksiyon ile her seferinde 8 bitlik bir veri gönderebiliriz. Bu, her seferinde en fazla 1 ASCII karakteri gönderebileceğimiz anlamına geliyor. String, yani karakter dizisi göndermek için ise aşağıdaki fonksiyonu yazdık.

Buna göre uygulamamızın Proteus ISIS simülasyonundaki çıktısı aşağıdaki gibi oluyor [Benzetimden önce PIC16F877A’ya sağ tıklayarak Processor Clock Frequency parametresini 4MHz yapmanız gerekmekte] :

Şimdilik bu kadar 🙂 Bir sonraki yazımızda USART RX kesmesini ve USART aracılığı ile veri okumayı inceleyeceğiz.

 

Yazıları beğendiyseniz, faydalanabilecek tanıdıklarınızla paylaşmayı unutmayınız.

Önceki Sayfa   Sonraki Sayfa

PIC Programlama – 5 – Giriş Çıkış (I/O, Input/Output) İşlemleri -2

Önceki yazımızın başlığını giriş çıkış işlemleri olarak koymuştuk ama açıkça görülebildiği üzere, yalnızca çıkış işlemleri üzerinde durduk 🙂 Bu yazıda, vadedileni tamamlayarak PIC mikrokontrolörlerinde giriş işlemlerini nasıl yaparız ona değineceğiz.

PIC programlama yazı dizisinin asıl amaç seti, gömülü sistemlerin programlanması hususunda temel oluşturup, sürecin iç dinamiklerini de anlatmak olduğundan yine bir kütüphane kullanmadan devam edeceğiz. Giriş işlemleri üzerinden gidebilmemiz için, mikrokontrolörün pinlerine bağlayacağımız elemanların, pinde oluşturacağı gerilimsel seviyeyi okumamız gerekir. Buna göre buton ve switch uygulamaları, mevzuyu anlatmakta kullanılabilecek iki güzel ve basit eleman oluyor. Butona daha sonra da değineceğiz. Şimdi mevzuyu anlatmak için switch üzerinden gidelim. Butonun basit kullanımı switch’den çok farklı değil ama bouncing gibi problemlere de önlem alacağımız için butonu timer’dan sonra anlatacağız. Neyse 🙂

Öncelikle daha kolay olandan başlayalım. Switch yani anahtar elemanının kullanımına değinelim. Anahtar’ın adı üzerinde, elektriksel akımı açıp kapatabilen devre elemanı. Buna göre, iki durumlu bir anahtar için; anahtar bir konumdayken açık devre, diğer konumdayken kısa devre davranışı gösterecektir.

Wikipedia sayfasında daha fazla bilgi bulabilir, çeşitli switch’lerin fotoğraflarını da görebilirsiniz.

Şimdi gelelim bu anahtarın PIC16 ile kullanılmasına. Çok basit bir uygulama olacak olsa da, anahtar ile PIC’i aracı yaparak LED sürelim. LED’i normal şartlar altında PIC’siz de sürebiliriz ama mevzunun basit yoldan anlaşılması için böyle anlamsız bir uygulama üzerinden gitmek mantıklı olacak diye düşünüyorum. Bir sarı ve bir kırmızı olmak üzere iki LED, bir anahtar ve bir de PIC olan bir devre düşünelim (Direnc, kondansatör gibi elemanları saymıyorum). Birazcık da olsa farklılık yaratmak için anahtar bir konumda iken sarı LED’i yakıp kırmızı LED’i söndüreceğiz. Diğer durumda ise kırmızı ledi yakıp sarı ledi söndüreceğiz. Tabi bu basit işi yaparken bile, kodu ibretlik şekilde yazacağız. Haydi işe koyulalım 🙂

Kodu açıklamadan önce, bir define hinliği ile, daha şeker hale getirelim diyorum. Misal aşağıdaki gibi yapsak, kodun yaptığı iş daha iyi anlaşılacak sanki.

Tabi kodu yazdık öyle ama kısa bir açıklama da yapacağız. Ayrıca birinci kod ile ikincisi arasındaki farkları da ele almakta fayda var. Ancak bundan önce kodun Proteus ISIS ortamındaki çıktılarını bir paylaşalım.

switch1 switch2

 

Gördüğünüz gibi kodumuz çiçek gibi çalışıyor. Şimdi gelelim kod hakkında konuşma faslına. Malumunuz bu kod çok farklı şekillerde yazılabilirdi ama yine özgün bir iş yapalım istedik. Bu sebeple gittik her bir pini struct bitfield olarak tanımladık. Bu sayede port üzerindeki her pine tek tek, bir değişken üzerinden erişmek mümkün oldu. Tanımladığımız union ile, registerlara hem pin bazlı (tek tek) hem de port bazlı (topluca) erişim imkanı sağladık. Bu işin ekmeğini de kodu yazarken yedik; kodumuz hem çok anlaşılır hem de çok genişletilebilir oldu.

İkinci kodda yaptığımız trick ise, kodun okunurluğunu çok artırdı. Switch ve ledlerin hangi pinlere bağlı olduğunu define ile tanımlayarak, kodun okunurluğunu epeyce artırmış olduk. Bu sayede ikinci kodu okuyan birisi artık kodun fiziksel olarak ne iş yaptığını kolayca anlayabilir durumu geldi. Her kod bir hikaye anlatır malum. Birinci kod hikayeyi mikrokontrolörün perspektifinden anlatırken, ikinci kod hikayeyi insan gözü perspektifinden anlatmış oldu.

Bu yazı bu kadar olsun 🙂 Bir başka yazıda yine devam edeceğiz. Yazıları beğendiyseniz, faydalanabilecek tanıdıklarınızla paylaşmayı unutmayınız.

Önceki Sayfa   Sonraki Sayfa

Gömülü C – 4 : Sabitler ve Yorum Satırları

Önceki yazıda veri tipleri, değişkenler ve isimlendirmeden bahsetmiştim. Bu yazıda yorum satırlarından ve sabitlerden kısaca bahsedeceğim.

NŞA’da sabitler ve yorumlarla ilgili bahsedilebilecek şeyleri zaten okuduğunuzu / bildiğinizi varsayıyorum. Nitekim herhangi bir C kitabında ya da tutorial’inde mutlaka bir takım temel şeyler yer alıyor. Bu kısımda yine birazcık daha fazlasına değinmeye çalışacağım 🙂

YORUMLAR

C dilinde yorum satırları iki şekilde yazılır. Her iki duruma da örnek olarak aşağıdaki kod parçası örnek gösterilebilir:

Gördüğünüz gibi tek satırlık bir yorum yazmak için “//yorum”, çok satırlı yorum yazmak için ise “/* yorum */” kullanılır. Yıldızlı olan blok yorum esasen C++’da olan bir özellik olup sonradan faideleri görülüp C’ye de aktarılmıştır. Yorumun program için açıklayıcı olmasına dikkat edilmelidir.

SABİTLER

C dilinde yaratılan değişkenler, bellekte bir adreste saklanırlar. Bu değişkenlerin saklanış şekillerini bir önceki yazıda incelemiştik. Bu değişkenleri yaratırken, değişkenlerin bir işe yaramasını istiyorsak, değişkenlerin değer alması mecburi olacaktır. İşte bu değer atamasında, bir değişkeni başka bir değişkene atayabileceğimiz gibi, bir değişkene sabit bir değer de atayabiliriz. Misal,

Değişkene sabit değer ataması yapılırken, sabitin boyutunun değişkenin boyutu ile uyumlu olmasına dikkat etmek gerekir. Misal 8 bitlik bir değişkenin alabileceği azami değer 255 iken ona gidip 65372 gibi bir değeri atamaya çalışmamak gerekir. Ama oldu ki atadık, ne olacağını da bilmemiz gerekir. Bu durumda değişkene 65372’nin 255 modundaki değeri atanır. Bu da değerin bellekteki yerleşiminin düşük öncelikli byte’ı demektir. Tabi bu derleyiciden derleyiciye değişir.

AĞZIMDAKİ BAKLA

Şimdi gelelim asıl mevzuya… Esasen yorum satırları yazılım dünyasında büyük tartışmalara sebep olmuştur. Hatta benim de bir mensubu olduğum “birileri” yorum satırlarının mecburi durumlar dışında kullanılmaması gerektiği, gerektiği yerde de kullanılmamasının hata olduğu yönünde görüş bildirmiştir. Okulda ders aldığım hocamın da mensubu olduğu “birileri” ise, yorumsuz kodu koddan saymamış, reddetmiş, sıfır vermiş, onu hakir görmüştür.

Şimdi mevzu aslında yorum olup olmaması değil bence. Her ne kadar bu konuda bir taraf olsam da, görüşümü detaylıca açıklayacağım. Sonrasında yolunuzu seçmek üzere karar size ait 🙂 Ben derim ki, bir yazılım, baştan iyi tasarlanmış olmalıdır, iyi implemente edilmiş olmalıdır, iyi yazılmış olmalıdır. Yani kod öyle yazılmalıdır ki, ne iş yaptığını zaten anlatmalıdır. Bunu sadece ben de söylemiyorum “self-descriptive” yani kendini ifade eden kodlama, bir yazılım kalitesi unsuru olarak literatürde bakidir. Sonuçta C,C++,Java ne olursa olsun söz konusu araç bir dildir ve dilin kuralları herkes için ortaktır. int i=5 derken, dili bilen herkes i diye bir değişkenin, int cinsinden yaratıldığını ve ona 5 değerinin atandığını bilir. Sorun, bu 5 değerinin ne olduğudur ve i’ye niye atandığıdır. i’nin neden int olduğu ve neden 5’in ona atandığı da diğer sorular tabi ki. Şimdi kimisi der ki ben pis pis kodumu yazarım, üstünü de yorumla sıvarım. Nasıl mı? Misal:

Şimdi bu kodu yazan adamın arkasından nasıl konuşulur? Şöyle… Kardeş, kafan çok güzelmiş kodu da öyle yazmışsın, zahmet edip yorum da yapmışsın ama bu dizi kim? 255 dizinin neden son indeksi? Madem bu değişken bir dizinin son indeksi, değişkenin adını felancaDizininSonIndeksi filan diye koysan ne olurdu? Madem bu dizinin son indeksi 255, sen o bilgiyi başka bir yerde de kullanacaksın ve yine ne olduğunu kimse bilmeyecek. O bilgiyi etiketlesen canın mı çıkardı?

Ve nihayetinde o bildiğiniz acı son ile kodu yazan kişinin arkasından bir güzel dualar edilirdi.Bir de aşağıdaki satırı yazan kodcu var tabi…

Önce hiç bir şey denmez, çünkü herşeyi anlamış olmanın verdiği aydınlanma hissi bedeni kaplar. Yani neticede bir kodda bir sürü yerde 255 değerinde bir şeyler olabilir ama hangisinin ne anlama geldiğini anlatmak etiketler olmadan çok zordur. Etiket dediğim de #define ile yazdığım şey. Bu sayede kodda 25 geçtiği zaman o 25’in oda sıcaklığı mı yoksa, amerikanın bir eyaletindeki ehliyet alma yaşı mı olduğunu anlayabiliriz. Bu olaya “MAGIC NUMBER CODING” deniyor. Kodda nereden peydah olduğunu bilmediğimiz sabit değerler olmamalı 🙂 Yazılımda zaten mevzuyu anlamak zor, bir de yorumlarla sabitler doğru kullanılmadı mı olay epey işgenceye dönüyor doğrusu.

Şimdi bir diğer önemli konu da veri ve bilgi kavramlarının farklılığı.Programlamada birbirine en çok karıştırılan kavramlardan biri de bilgi ve veri kavramlarıdır. Eee haliyle çok sayıda yanlışlık da yapılıyor. Örneğin bir 3. sınıf öğrencisininn ‘A’ sınıfında olması bir bilgidir. O bilgi, sayısal karşılığı 0x41 yani 65 olan veri ile ifade edilebilir. Buradaki 65 sayısı, konu içeriği bilinmeyen bir veridir. Keza ülkemizde erkekler için emeklilik yaşı da 65’tir. Yani bu bilgi de ‘A’ ile aynı şekilde bellekte saklanmaktadır. Aaaaaa?

i=’A’, i=65, i=0x41;

Bunların hepsi aynı değerde olan atamalar. Demek ki biz söz konusu içeriği farklı şekilde sunsak, anlamlandırsak da (bilgi), bu anlamlandırmanın bellekteki yerleşimi aynı olabiliyormuş. Biz sadece okuyan adam daha iyi anlasın diye sınıfı gösteren değişkene ‘A’ verisini(değerini) atadık, emeklilik yaşına da 65’i atadık. Bu yaklaşımın değişkenin adını düzgün koymaktan bir adım öteye gittiğini lütfen kaçırmayalım. Sonuçta her iki durumda da derleyici bu ifadeleri 65 sayısına çevirecek ve bu veriyi bellek gözüne yazacak. Demek ki neymiş? Sabit’i atarken bile o bilgiyi ifade etme şeklimiz, iyi kod yazmak için, anlaşılabilir olmak için çok çok önemliymiş. Buradan çıkarılacak sayısız ibretler var. Parçaları birleştirecek olursak aslında ‘A’,65 gibi sayıları kodun çeşitli yerlerinde tekrar tekrar yazacağımıza, #define ile etiket oluşturup o etiketi kullanmakta büyük feyizler var.

Bu konunun bir örneği de printf ile verilebilir. Gömülü sistem yazılımcıları, çok pahalı bir fonksiyon olabildiği için printf’e karşı çok mesafeli olsa da, konsepti anlatabilmek adına örneğimizi onun üzerinden vermemiz mümkün.

Bu kodu çalıştırdığınızda her seferinde aynı veriyi yazdırmanıza rağmen, sırayla ‘A’, 65 ve 41 görürsünüz. Bu bellekteki verinin bilgiye dönüşümüdür. Üzerinde düşünüldüğünde burada da sayısız ibretler vardır.

Neticede ağzımdaki baklayı çıkardım. Yorum satırlarının kullanımı ile ilgili felsefemi aktardım. Karar sizin. Kararınıza sadık kalınız.Ardından sabitlerle ilgili çok önemli olduğunu düşündüğüm kavramları aktarmaya çalıştım. Umuyorum bir şeyler katmıştır, şimdi devam 🙂

Önceki Sayfa   Sonraki Sayfa