Mikrodenetleyici Programlamaya Başlamak – 4

GPIO birimi ile çıkışları nasıl değiştireceğimizi diğer bir tabirle çıkışa, herhangi bir porta nasıl veri yazacağımızı, aslında bu işlemin temelinde mikrodenetleyicilerin tamamında olduğu gibi saklayıcılar arasında bir veri transferinden ibaret olduğunu incelemiştik. “Mikrodenetleyici Programlamaya Başlamak – 3” yazısında incelemiştik. Bu  bölümde giriş işlemleri ve bit tabanlı operatörleri inceleyeceğiz.

Bir port çıkışına veri yazdığımızda olduğu gibi, veri okumak istediğimizde de mikrodenetleyicinin çevre birimlerinde oluşturulan veriler ilgili saklayıcılara aktarılır. GPIO birimi için; pinlerde oluşan elektriksel bir değişikliği (Lojik 1 (5v) durumundan lojik 0(0v) durumuna geçmesi gibi) veri olarak okuyabilmek için ilgili portun saklayıcısındaki sayıyı/veriyi okuruz. Bunun için yazılmış hazır fonksiyonlar olsa da biz 3. bölümün sonunda yaptığımız gibi doğrudan saklayıcılar üzerinde işlemler yapalım.

Şekilde görüldüğü gibi B portuna 8 buton bağlanarak dışarıdan yapılacak fiziksel müdaheleler ile (butona basmak) mikrodenetleyiciye bilgi aktarmak ya da komut vermek mümkün kılınmış. Bu durumda mikrodenetleyiciden dışarıya bilgi aktarmak için konulmuş 8 ledi kontrol etmek için bu butonları kullanabiliriz.

Butonları nasıl okuyacağız?

Bir porttan veri okuyabilmemiz için  o portun TRIS saklayıcısının giriş olarak ayarlanmış olması gerekir.  Bunun için de 0x86 adresindeki TRISB saklayıcısına 0xFF (ya da 0b11111111) değerini atamamız gerekir. Giriş olarak ayarlanan B portunun pinlerinin durumunu (lojik durumunu) okumak için 0x06 adresindeki PORTB saklaycısının içerisindeki değeri bir değişkene atayarak yapabiliriz. Ardından bu okunan veri ile yapılacak işlemleri bu değişken üzerinden yapabiliriz.

Yukarıdaki kodda B portuna ait tüm pinlerin değeri bir saniyelik aralıkla okunur ve butonOku ismi verilen 8 bitlik değişkene kaydedilir. Yani B portundaki butonlar aracılığı ile kullanıcı tarafından mikrodenetleyiciye aktarılmış bilgiyi okumuş ve kaydetmiş oluruz.

Bit tabanlı operatörler

Bu bilgiyi kullanarak çıkış birimi olarak eklenen 8 led üzerinde yani D portu üzerinde işlemler yapalım; Giriş birimi olarak verilen 8 butondan birine basalım ve bu bastığımız butonun sırasına karşılık gelen sıradaki led hariç diğer tüm ledler yansın. Bunu nasıl yapabiliriz? Devam etmeden önce üzerinde biraz düşünmenizi tavsiye ederim.

Önce yukarıdaki devreyi inceleyelim; butona bastığımızda pinlerde nasıl bir değişiklik olacak. Butonlar pine pull-down direnci ile bağlanmışlar yani butona basılmadığı durumda pin üzerindeki elektriksel gerilim 0V iken butona basıldığında 5V olacaktır.(Pull-down ve pull-up bağlantı tipini araştırmanız daha iyi anlamanıza yardımcı olabilir)

Yani eğer butondan okuma işleminin yapıldığı anda butonlardan hangilerine basılı ise PORTB den okunan verilerde o butonlara karşılık gelen sıradaki bitler lojik 1 diğer bitler lojik 0 olacaktır. (Örneğin ilk ve son butona basıldıysa 0b10000001 değeri okunacaktır.) İstediğimiz işlemi gerçekleştirmek için bize bu sayının lojik olarak tam tersi lazım. Burada imdadımıza bit tabanlı operatörler yetişiyor;

İngilizce adıyla bit-wise operators verilen iki sayıyı bit-bit işleme sokan ve sonuç döndüren mantıksal operatörlerdir. Örneğin bizim problemimiz için butonlardan okuduğumuz sayının her bitini mantıksal değil (not) işlemine sokarsak yeni oluşan sayıyı doğrudan D portuna yazarak problemimizi çözebiliriz. Bunun için; “~” operatörünü kullanırız.

Az önce butonlardan okuduğumuzu varsaydığımız 0b10000001 sayısını örnek alırsak; tersButon=~0b10000001 veya doğrudan değişken üzerinden işlem yaparsak ; tersButon=~butonOku şeklinde okuduğumuz buton değerlerini tersButon adında bir değişkene kaydedebiliriz.

Not: Normalde herhangi bir butona basılmadığında 0x00 değeri okunacak ve terslenerek 0xFF olacaktı. Bu durumda butona basılmadıysa tüm ledler yanacaktı. Biz sadece butona basıldığında ledlerin yanmasını istediğimiz için 8. satırdaki koşulu koyduk. Böylelikle butondan okunan değer 0 dan büyük olduğu durumlarda PORTD değişecek.

Diğer bit tabanlı operatörler;

&    : AND işlemi (A&B )
∣      : OR işlemi (A|B)
^     : XOR işlemi (A^B)
~     : Tersleme (Complement) işlemi (~A)
<<   
: x bit sola kaydırma işlemi (A<<x)
>>   : x bit sağa kaydırma işlemi (A>>x)

Bu operatörler çoğunlukla maskeleme için kullanılırlar. Örneğin biz sadece B portuna bağladığımız butonlardan ikincisi ile ilgileniyoruz ve sadece onu okumak istiyoruz. Oradan okuduğumuz buton durumuna göre çeşitli işlemler yapacağız. Fakat bir porttan veri okuduğumuzda o porta ait tüm pinlerin değerini okumuş oluyoruz, bunlardan ilgilendiğimiz pinin lojik değerini nasıl çekeriz? Bunun için VE (AND) operatörünü kullanabiliriz. Örneğin 3. pinin değerini okumak istediğimizi varsayalım;

pin3= PORTB & 0b000000100 işlemini yaptığımızda 3. pin dışındaki tüm pinler 0 ile AND işlemine tabi tutulduğu için değerleri ne olursa olsun 0 değerini döndürürler. 3. pinde ise  ile AND işlemine tabitutulduğundan eğer değeri  1 ise 1 değerini, 0 ise 0 değerini döndürecektir. Böylelikle pin3 değişkenine 3. pinin değeri atanmış olacaktır.

Benzer şekilde porta değer yazma işlemlerinde eğer sadece bir (veya birkaç) pine diğer pinlerin değerini değiştirmeden veri yazmak istiyorsak yine AND ve OR operatörlerini kullanabiliriz. Sadece 3. ledin bağlı olduğu pine lojik 1 değerini yazmak istiyorsak;

PORTD= PORTD | 0b00000100 işlemi ile yapabiliriz. Burada 0 ile OR işlemine tabi tutulan diğer pinlerin değerleri değişmeyecek ve 1 ile OR işlemine tabi tutulacak 3. pin değeri ise 1 olacaktır. Benzer şekilde eğer bu pine 0 değerini yazmak istiyorsak ; PORTD= PORTD & 0b11111011 işlemi ile bunu gerçekleştirebiliriz.Bu işlemi daha da basitleştirmek için kaydırma operatörlerini kullanabiliriz. 

PORTD |= (1<<2); işlemini ele alalım; Burada eşitliğin sağ tarafında (1<<2) 1 sayısını 2 bit sola kaydırıyoruz. Böylelikle 0b00000100 sayısını elde ediyoruz ve bu sayıyı PORTD ile OR işlemine sokuyoruz böylelikle (PORTD= PORTD | 0b00000100) işlemini daha kısa ve daha basit bir şekilde gerçekleştirebiliriz. Hangi pini bir yapmak istiyorsanız  yerine o pinin değerini (pin numaraları 0 dan başlar) yazabiliriz.

Aslında doğrudan bir pinden değer okumak veya yazmak için mikrodenetleyici derleyicilerinde fonksiyonlar mevcut fakat mikrodenetleyicilerle yaptığınız işlemlerin karmaşıklığı arttıkça bit tabanlı operatörleri kullanma ihtiyacı duyacaksınız. Ayrıca bunları bilmek mikrodenetleyicilerin çalışma amntığını anlamak için de faydalı olacaktır.

Pin manipülasyon işlemleri için CCS C derleyicisinde tanımlı fonksiyonlar ve kullanım örnekleri aşağıdaki şekilde;