1.4 Port Yazmacı (Port Register)


1.4 Port Yazmacı (Port Register)

Port yazmacı pin'lerden gelen Logic değerlerin yazıldığı veya çıkış olarak dışarıya aktarılması gereken değerleri yazdığımız yazmaçlardır. Bu yazmaçlar port'a göre isimlendirilir. Örneğin PortA, PortB, PortC, PortD, PortE. Yazmacın içeriğine bakarsak Tris yazmacından pek farklı olmadığını görürüz.

7
6
5
4
3
2
1
Bit 0
0
0
0
0
0
0
0
0
Pin 7
Pin 6
Pin 5
Pin 4
Pin 3
Pin 2
Pin 1
Pin 0

Yukarıdaki yazmacın PortB yazmacı olduğunu düşündüğümüzde eğer bütün uçlar çıkış konumuna alınmışsa bu durumda PortB'nin bütün çıkışları Logic 0 konumuna alınmış demektir. Yani uçların gerilim seviyesi 0 Volt seviyesindedir. Herhangi bir bit Logic olacak 1 yapılırsa bu durumda o uç gerilim seviyesi olarak Vcc’ye alınmış olacaktır. Yani besleme +5V ise ilgili uç +5V gerilim seviyesinde çıkış verecektir.

Eğer Tris yazmacını kullanılarak uçlardan biri giriş konumuna  alınmış ise o uca gerilim seviyesi olarak 0V geliyorsa ilgili bit 0 değerini eğer +5V geliyor ise ilgili bit 1 değerini alacaktır.

Şekil 6


Şekil 7

1.4 Port Yazmacı (devam 1) (Port Register)

Devre 1

Şekil 6’yı incelersek; 8 adet led 330R’lik dirençler üzerinden JP1 Jumper’ına bağlanmıştır. JP1 led'lerin katotlarına GND vermek için kullanılmaktadır. Jumper 2-3 konumuna takılırsa led’ler doğru polarlanmış olur. Devre 1 ise bu devrenin Proteus programında hazırlanmış şeklidir. Bu led'leri belirli kombinasyonlar ile yakmak için çeşitli örnek yazılımlar aşağıdadır.

Prg: 1

Device 16F877
XTAL 4

TRISB=0 ; Bütün PortB uçları çıkış konumuna alındı
PORTB=1 ; registere binary formatta 000001 yazıldı

End


PortB’nin 0 nolu ucuna bağlı led yanar. Çünkü ilgili uç gerilimsel olarak +5V seviyesine çıkartılmıştır.

Prg: 2


Device 16F877
XTAL 4

TRISB=0 ; Bütün PortB uçları çıkış konumuna alındı
PORTB=001111 ; PortB=15

End



Binary (ikilik sayı) formatta bir sayı değerini yazmak için sayının başına % sembolü konur. Bu ifade PortB yazmacının içeriğini aşağıdaki gibi değiştirecektir.

7
6
5
4
3
2
1
Bit 0
0
0
0
0
1
1
1
1
Pin 7
Pin 6
Pin 5
Pin 4
Pin 3
Pin 2
Pin 1
Pin 0


PortB = 001111 sayısının ondalık karşılığını hesaplarsak
PortB = 0x27 + 0x26 + 0x25 + 0x24 + 1x23 + 1x22 + 1x21 + 1x20
PortB = 0 + 0 + 0 + 0 + 8 + 4 + 2 + 1
             PortB = 15

Yukarıdaki programda PortB=001111 yerine PortB=15 yazmak aynı durumu ifade edecektir.

Bu program çalıştığında PortB.0, PortB.1, PortB.2, PortB.3 nolu uçlarına bağlı olan led’ler yanacak diğerleri sönük kalacaktır.

Prg: 3

Device 16F877
XTAL 4
    TRISB=0
    PORTB=000000
    DelayMS 1000
    PORTB=000001
    DelayMS 1000
    PORTB=000011
    DelayMS 1000
    PORTB=000111
    DelayMS 1000
    PORTB=001111
    DelayMS 1000
    PORTB=011111
    DelayMS 1000
    PORTB=111111
    DelayMS 1000
    PORTB=%01111111
    DelayMS 1000
    PORTB=%11111111
    DelayMS 1000
End

Yukarıdaki programda diğerlerinden farklı olarak yeni bir komut kullanıldı. DelayMS komutu milisaniye kadar bekleme işlevini yapar. Örneğin yukarıda DelayMS 1000 dendiğine göre her işlemden sonra 1000 Ms yani 1 Sn bekle demektir. Programı incelersek önce bütün ledler sönecektir. 1 Sn beklenecek arkasından PortB.0’a bağlı led yanacak 1 Sn beklenecek, arkasından PortB.1’e bağlı led yanacak ve bu PortB.7’e kadar sırası ile devam edecektir.


1.4 Port Yazmacı (devam 2) (Port Register)

Prg 4:

      Device 16F877
XTAL 4

    TRISB=0
    PORTB=1         ; 000001
    DelayMS 500
    PORTB=2         ; 000010
    DelayMS 500
    PORTB=4         ; 000100
    DelayMS 500
    PORTB=8         ; 001000
    DelayMS 500
    PORTB=16        ; 010000
    DelayMS 500
    PORTB=32        ; 100000
    DelayMS 500
    PORTB=64        ; %01000000
    DelayMS 500
    PORTB=128       ; %10000000
    DelayMS 500

End


Yukarıdaki örnekte PortB=1 demek ikilik sayı olarak 000001 demektir. Yani PortB.0 ucu Logic 1 olacak ve bağlı led yanacaktır. 500 Ms sonra PortB 000010 olacaktır. Bu durumda sadece PortB.1’re bağlı olan led yanacak diğerleri sönük kalacaktır. Bu şekilde birinci led’den itibaren bütün ledler 500ms aralıklarla sırası ile yanacaktır.

İlk bakışta 3. Program ile bu program aynı gibi gözükse de eylemler farklıdır. Birinci programda ledler sıra ile yanmaya başlayacak ve en son komutla bütün ledler yanık kalacak ve program sona erecektir. Fakat 4. Programda aynı anda sadece tek bir led yanık kalacaktır. Ledler sıra ile tek tek yanacak diğerleri ise sönük kalacaktır.

Prg 5:

      Device 16F877
XTAL 4
TRISB=0

Dongu:
    PORTB=1         ; 000001
    DelayMS 500
    PORTB=2         ; 000010
    DelayMS 500
    PORTB=4         ; 000100
    DelayMS 500
    PORTB=8         ; 001000
    DelayMS 500
    PORTB=16        ; 010000
    DelayMS 500
    PORTB=32        ; 100000
    DelayMS 500
    PORTB=64        ; %01000000
    DelayMS 500
    PORTB=128       ; %10000000
    DelayMS 500
GoTo Dongu

End

Yukarıdaki programda yeni bir yapı kullanıldı. Dongu: bir etikettir. Bu etiket program içinde belirli noktaları işaretlemek amacıyla kullanılır. Programın normal akışı içinde farklı noktalara gitmek istediğimizde bu etiketleri kullanırız. Bu etiketlere gidebilmek içinde GoTo komutu kullanılır. Goto git anlamına gelmektedir. Program çalışmaya başladığında GoTo Dongu komutunu gördüğünde program Dongu: ile işaretli yere geri döner. Böylece bu arada sonsuz bir döngü kurulmuş olur. Program sürekli olarak başa dönerek aynı işlemleri yapmaya devam eder.


1.4 Port Yazmacı (devam 4) (Port Register)

Prg: 8
     Device 16F877
XTAL 4
TRISB=0

Dim As Byte

Dongu:
   
    For I=0 To 255
        PORTB= I
        DelayMS 200
    Next

GoTo Dongu

End


Led’leri ikilik sayı sistemine uygun olarak yakan program. Burada da For Next komutu kullanılmıştır. Yukarıdaki örnekte For’dan sonra gelen değişkenin değeri 0’dan başlar ve 1 artarak 255’e kadar devam eder. I değişkeninin değeri 255 olduğunda döngünün dönüşü sona erer.
For I=0 to 255
....
....
Next
Yukarıdaki örnekte artış miktarı belirlenmiştir. I’nın değeri 0’dan başlar 2 artarak 0,2,4,6,8…254 şeklinde devam eder. Dikkat edilirse en son 254’te kalır çünkü döngü bir daha dönerse 256 değeri elde edilecektir. Döngü ile elde edilecek değer 255’ten büyük olamaz. En yakın değerde dönüş sonlandırılır. Aşağıdaki örnekte ise sayma işlemi geriye doğrudur. 255,253,251,1 şeklinde döngü devam eder. Geriye doğru sayma işlemi en son 1 değerini alınca durur. 
 
Devre 2

Prg: 9

Device 16F877
XTAL 4

TRISB=0
TRISD=000111

Dongu:
   
    If PORTD.0 = 1 Then
        PORTB.0=1
    Else
        PORTB.0=0
    EndIf  

GoTo Dongu

End


Yukarıdaki örnekte PortD’nin 0 nolu ucuna bağlı button’un durumuna göre PortB’nin 0’ıncı bacağındaki led yakılır yada söndürülür.

Programda If önermesi kullanılmıştır. Kullanımı aşağıdaki şekildedir.

IF <koşul> Then
…..
Else
…..
EndIf

Eğer <koşul> ise
…..
değilse
…..
Koşul Sonu

Eğer PortD’nin 0 nolu bacağının değeri 1 İse
          PortB’nin sıfır nolu bacağının çıkışı 1 yapılır
Değilse
          PortB’nin sıfır nolu bacağının çıkışı 0 yapılır
Koşul Sonu

1.4 Port Yazmacı (devam 5) (Port Register)

Prg: 10

            Device 16F877
XTAL 4

TRISB=0
TRISD=%00000111

Dongu:
    If PORTD.0 = 1 Then PORTB.0=1
    If PORTD.1 = 1 Then PORTB.0=0
GoTo Dongu

      End


If komutu bir koşul sağlanıyorsa gereğini yapmak için kullanılmaktadır. Bazı durumlarda Else kullanılmayabilir. Örneğin “IF PortD.0 = 1 Then PortB.0=1” şeklinde programa satır yazılırsa sadece şartın sağlanması kontrol edilmektedir. Ayrıca şart sağlandığında ise sadece bir işlem yapılmaktadır.

Prg: 11


Device 16F877
XTAL 4

TRISB=0
TRISD=%00000111

Dim Var1 As Word
Var1=0

Dongu:
    PORTB=Var1
    Var1=Var1 +1
   
    If Var1>=100 Then Var1=0
    DelayMS 200   

GoTo Dongu
     End


Yukarıdaki örnekte Var1 değişkeninin değeri programın her dönüşünde 1 artmaktadır. Eğer Var değişkeninin değeri 100’e eşit veya 100’den büyük olursa Var değişkeninin değeri tekrar 0’lanır.

Prg: 12

           Device 16F877
XTAL 4

TRISB=0
TRISD=%00000111

Dim Var1 As Word
Var1=0

Dongu:
    If PORTD.0=1 Then
        If Var1<100 Then Var1= Var1 + 1
    EndIf
    If PORTD.1=1 Then
        If Var1>1 Then Var1= Var1 - 1
    EndIf
    If PORTD.2=1 Then Var1=0   

GoTo Dongu

End


Eğer PortD.0 bacağı 1 ise (yani butona basıldı ise)
     Ve Var1 değişkeninin değeri 100’den küçükse Var1’in değerini 1 arttır

Eğer PortD.1 bacağı 1 ise
     Ve Var1 değişkeninin değeri 1’den büyükse Var1’in değerini 1 azalt

Eğer PortD.2 bacağı 1 ise Var1 değişkeninin değeri 0’lanır.

Yukarıdaki örnekten de anlaşılacağı gibi if önermeleri arka arkaya veya iç içe de kullanılabilir. Fakat burada önemli bir kural vardır o da önermelerin birbirini kesmemesidir. Soldaki önerme yapısı doğru sağdaki önerme yapısı ise yanlıştır.


Şekil 8

Yukarıdaki yapı önermelerin program içinde nasıl yerleştirileceğini göstermektedir. Soldaki çizimde if önermelerinin birbirini kesmeden nasıl iç içe yerleştirileceğini göstermektedir. Bu doğru bir program yazım akışıdır. Fakat sağdaki önerme grubuna bakarsanız içte birbirini kesen önermenin varlığını göreceksiniz. Bu yanlış bir yazılım dizilimidir. Bu yazılım dizimi aslında tüm program yazım yapıları için geçerlidir. For Next döngüsü, While Wend döngüsünde de döngülerinin birbirini kesmemesine dikkat etmek gerekmektedir.

1.4 Port Yazmacı (devam 6) (Port Register)

Prg: 13

           Device 16F877
XTAL 4

TRISB=0
TRISD=%00000111

Dongu:
    If PORTD.0=1 And PORTD.1=1 Then
        PORTB.0=1
    EndIf
    If PORTD.0=1 Or PORTD.2=1 Then
        PORTB.0=0
    EndIf

GoTo Dongu


Yukarıdaki örnekte ise aynı anda iki şart birden And, Or bağlaçları ile birbirine bağlanarak kontrol edilmiştir. Örneğin PortD.0 ve PortD.1’e bağlı butonlara aynı anda basılırsa PortB.0’ı Logic 1’e gider. Eğer PortD.0’a veya PortD.2’ye bağlı butonlara basılırsa PortB.0’a bağlı led söner.

Devre 3

Yukarıdaki devrede PortB çıkışlarına bir ortak katot Seven Segment Display bağlanmıştır. Seven Segment display’in içyapısında sekiz adet led bulunur. Bu led’ler belirli bir sıra ile yerleştirilmiştir.
Şekil 10

Şekil 11
Örneğin display ile 1 rakamı oluşturmak isteniyorsa B ve C ledlerinin yanması gerekmektedir. Yine aynı şekilde 3 rakamı için ise A,B,B,D,G ledleri yanmalıdır. Seven segmentler farklı büyüklüklerde tasarlanabilir. Segment’ler büyüdükçe içindeki led'lerinde sayıları artar. Her segmentte seri olarak bağlanmış 2,3 veya daha fazla led bulunabilir. Çalışma voltajları içindeki seri bağlı led'lerin sayılarına göre değiştiği için  led'lerin transistörler ile sürülmesi gerekebilir.

Prg:14

Device 16F877
XTAL 4

TRISB=0
TRISD=%00000111

Dim Sayac As Byte
Sayac=0
GoSub Display

Dongu:
    If PORTD.0=1 Then
        While PORTD.0=1 : Wend
        If Sayac<9 Then Sayac= Sayac +1
        GoSub Display
    EndIf
    If PORTD.1=1 Then
        While PORTD.1=1 : Wend
        If Sayac>0 Then Sayac= Sayac -1
        GoSub Display
    EndIf   
GoTo Dongu

Display:
    HSerOut [Dec Sayac]   
    If Sayac=0 Then PORTB=%00111111 ;0
    If Sayac=1 Then PORTB=%00000110 ;1   
    If Sayac=2 Then PORTB=%01011011 ;2
    If Sayac=3 Then PORTB=%01001111 ;3
    If Sayac=4 Then PORTB=%01100110 ;4
    If Sayac=5 Then PORTB=%01101101 ;5
    If Sayac=6 Then PORTB=%01111101 ;6
    If Sayac=7 Then PORTB=%00000111 ;7
    If Sayac=8 Then PORTB=%01111111 ;8
    If Sayac=9 Then PORTB=%01101111 ;9
Return

End 

Yukarıdaki örnekte yeni bir komut kullanılmıştır. Gosub komutu GoTo komutu gibi belirtilen etikete gitmeyi sağlar. Fakat bu komutun Goto komutundan farkı gidilen noktaya Return ile geri dönülmesidir. Goto kesin bir gidiştir. Gosub ise ana program döngüsü içinde gerektiği zaman geçici olarak gidilen gerekli kodlar çalıştıktan sonra tekrar geri dönülen noktalar için kullanılması uygundur.

Bu program parçalarına Alt program ( subrutine ) denir. Alt program parçaları program için birden fazla çalışması gereken fakat çalışacak kodların birbiri ile aynı olması durumlarında kullanılır. Programda tuşlara basıldığında Sayac değişkeninin değeri birer birer artmakta ve azalmaktadır. Her değer değişiminde de değer Seven Segment ile gösterilmektedir. Tuşlara basıldığında Seven Segment üzerinde gösterim yapacak olan kod parçacığı ortak olduğu için bu kod bir alt program şeklinde hazırlanmış ve gerektiği zaman bu koda gidilip programa geri dönülmüş ve kalınan yerden devam edilmiştir. Gosub ile gidilen yerden mutlaka Return komutu ile geri dönülmelidir.

Yine program içinde kullanılan yeni bir komutta While Wend komutudur. Bu komut şartlı döngü komutudur. Şart sağlandığı müddetçe döngünün dönüşü devam eder. Şart sağlanmadı noktada program Wend komutunun bir altındaki satırdan itibaren çalışmaya devam eder.

Döngü komutları üç grupta incelenir.
  1. Sonsuz döngü: Goto komutu ile sonsuz döngüler kurulur.
  2. Sayıya bağlı döngüler: For Next komutu istenilen sayıda döngü kurulmasını sağlarlar.
  3. Şartlı Döngüler: Bu tip döngülerde While Wend ve Repeat Until komutları kullanılır. Bu döngülerde şart doğru olduğu sürece  döngünün dönüşü devam eder.


Main:
     …..
     …..
     …..
     …..
     …..
Goto Main
Dim Sayac as byte
For Sayac=0 to 10
     …..
     …..
     …..
     …..
Next
Dim Sayac as byte
Sayac=0
While Sayac<10
     Sayac=Sayac+1
     …..
     …..
Wend
Programı satır satır incelemeye başlarsak;

Ekrana basılacak değerleri saklamak için öncelikle adı Sayac, tipi byte olan bir değişken tanımlanmış ve ilk değer olarak ta 0 yüklenmiştir. Bu değerin ilk kez seven segment’te gözükmesi için Gosub komutu ile alt rutine gidilmiştir. Alt rutinde if önermeleri ile Sayac değişkeninin değeri kontrol edilmiştir. Uygun olan değere göre gerekli olan segment ledleri yakılarak display'de sayı oluşturması sağlanmıştır. Sonra Return komutu ile  Gosub komutu ile gelinen yere geri dönülmüş ve bir alt satırdan itibaren program çalışmasına devam etmiştir.

Sonsuz döngünün içinde ilk önce tuşlara basılıp basılmama durumu kontrol edilmiştir. PortD.0’na bağlı tuşa basılırsa yani girişe Logic 1 verilirse şart sağlamış olur ve ilk önermenin içi çalışmaya başlar.

İlk önermenin hemen alt satırında While PORTD.0=1: Wend Komut satırı yer almaktadır. Burada ilk etapta incelenmesi gereken konu komutların arasına konmuş olan: sembolüdür. Bu sembol eğer bir satırda birden fazla komutu art arda yazmak gerekiyorsa komutları birbirinden ayırmak amacı ile kullanılır. Kısaca Wend komutu bir alt satıra yazılması gerekirken bu komutu üstteki satıra yazmak için: sembolü kullanılmıştır.

Gelelim bu satırı neden kullandık. Bildiğiniz gibi mikrodenetleyiciler bağlamış olduğunuz kristalin hızına göre farklı hızlarla çalışsa da yine elimizin butona basılması ve çekilmesi  işlemi sırasında program birçok kez aynı yerden geçecektir. Böyle bir çalışma bizim istediğimizin dışında sonuçlara neden olacaktır. Bu yüzden butona bastığımızda butondan elimizi çekinceye kadar programın o noktada takılı kalmasını sağlamak bu satırın görevidir. Bu satırda PortD.0 Logic 1 olduğu müddetçe bu satır While Wend arasında dönüp duracaktır. Elimizi butondan çektiğimizde ise Logic 0’a gidecek ve şart artık sağlanmayacağı için bir alt satıra gidilerek program kaldığımız yerden çalışmaya devam edecektir.

Bu satırda ise Sayac değişkeninin değeri 9'dan küçük ise değeri bir arttırılacak yeni sayaç değerine göre displaya yeniden değer basılacaktır. Diğer If önermesi ise Sayaç değişkeninin değerini azaltmak için kullanılmıştır.


1.4 Port Yazmacı (devam 7) (Port Register)


Devre 5’te Pic ile +12V’luk rölelerin kontrolüne dair bir uygulama devresi yer almaktadır. Bu yöntem ile daha yüksek Voltaj değerlerinin Pic ile kontrolü mümkün kılınmaktadır. Devrede kullanılan röleler 12V yerine 5V’ta seçilebilir. 5V’lik röleleri direk olarak Pic üzerinden de sürebilirsiniz. Fakat Pic üzerinden akan akımın sınırlandırılması ve pic’in daha az enerji kullanması için rölelerin transistörler üzerinden sürülmesi daha uygundur. Ayrıca oluşabilecek arızalarda ve rölelerin bobinlerinde oluşacak ters indüktif akımlarında rölelere girmesi bu şekilde engellenmiş olacaktır. Konu ile ilgili daha detaylı bilgileri çeşitli kaynaklarda bulabilirsiniz.

Prg: 15
            Device 16F877
XTAL 4

TRISB=0
TRISD=%00000111
PORTB=0

PORTB_PULLUPS false

Dongu:

    If PORTD.0=1 Then
        While PORTD.0=1 : Wend
        Toggle PORTB.0               
    EndIf
    If PORTD.1=1 Then
        While PORTD.1=1 : Wend
        Toggle PORTB.1       
    EndIf
    If PORTD.2=1 Then
        While PORTD.2=1 : Wend
        Toggle PORTB.2       
    EndIf
   
GoTo Dongu

End


Gönderen Ahmet Gürol KALAYCI

0 Yorum:

Yorum Gönder