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:
Prg 5:
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 I 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
Prg: 11
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.
Ş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.
- Sonsuz döngü: Goto komutu ile sonsuz döngüler kurulur.
- Sayıya bağlı döngüler: For Next komutu istenilen sayıda döngü kurulmasını sağlarlar.
- Ş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 byteFor Sayac=0 to 10…..…..…..…..Next
Dim Sayac as byteSayac=0While Sayac<10Sayac=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.
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
|
0 Yorum:
Yorum Gönder