10 Ocak 2016 Pazar

16F877 toplama devresi

PIC ödevleri-1

Üç adet 7 parçalı gösterge, 3 adet buton ve 1 adet PIC16F877'den oluşan, iki sayının toplamını hesaplayacak bir devre tasarlanması istenmişti.
Birinci buton birinci göstergeyi, ikinci buton ikinci göstergeyi 1 artıracak, üçüncü butona basıldığında ise birinci ve ikinci göstergedeki rakamların toplamı üçüncü göstergede gösterilecektir.
Birinci göstergedeki rakam birinci butona her basıldığında bir artacak, 9'a geldiğinde butona basılırsa 0 olacaktır.
İkinci göstergedeki rakam ikinci butona her basıldığında bir artacak, 6'ya geldiğinde butona basılırsa 0 olacaktır.
Üçüncü butona basıldığında ilk iki sayının toplamı üçüncü göstergeye yazılacaktır. Eğer sonuç 9'dan  büyük çıkarsa, onaltılı sistemdeki gibi A=10, B=11.... F=15 olarak gösterecektir.

Devreye enerji verildiğinde iki saniye kadar tüm göstergeler yanacak, sonra A,B ve A+B değerleri görüntülenecektir.
Ayrıca A ve B sayıları butonlar ile değiştirildiğinde sonuç hemen görünmeyecek, üçüncü "eşittir" düğmesine basıldığında sonuç güncellenecektir.

Yazılımsal olarak istenen özellikler bunlardı. Donanımsal olarak ise:
Devrenin 9 volt ile çalışması gerektiği,
Üç adet yedi parçalı gösterge, üç adet buton ve PIC16F877 mikrokontrolcü içermesi
şartları verilmişti.

PIC16F877'nin giriş - çıkış uç sayısı ve ihtiyaçlar göz önüne alındığında, göstergeler devreye tek tek bağlanabilirdi. Ancak çoğullama mantığını göstermek için, göstergeler çoğullamalı olarak bağlandı.
Sonuçta ortaya şöyle bir devre çıktı:






PIC'e yazacağımız program için, PICBASIC dilini kullanmayı seçtik. Çoğullamalı bir bağlantı kullandığımızdan,  yazacağımız kod da bir gerçek-zaman programlama örneği olacak.

Bunun için her çağırılışında bir göstergede değer gösteren "Display" adlı yordamımız var. Burası her çağrıldığında, bir sonraki göstergede gösterilecek değer belirlenip ilgili göstergeye bu değer gönderiliyor. Ta ki bir sonraki çağırışa kadar.

Bundan sonraki açıklamaları kod içinde yapalım ki, anlaşılır olsun. Açıklamaların başına rem işareti koyarak kodlarla karışmamasını hedefledik:

'En önce portların giriş mi çıkış mı olacağını belirtmemiz gerekiyor.
'Eğer bir port için ilgili TRIS biti 1 ise o uç giriş, 0 yapıldığında ise çıkış olur.
'C ve D portları çıkış olacağından bunlarla ilgili TRIS bitlerini 0 yapacağız. A ve B portlarını
'ise çıkış olarak kullanmayacağımız için giriş olarak ayarlayacağız:

trisa=255
trisb=255
trisc=0
trisd=0

'Bildiğiniz gibi bir girişe sıfır ya da bir değeri vermek gerekir. Boşta bırakılan bir girişin hangi
'değeri alacağını bilemeyiz. Girişe bir buton bağladığımızda, butonun diğer ucu şase olduğundan 'butona bastığımızda girişe "0" vermiş oluruz. Ancak butona basılmadığında uç boşta kalacağından 'alacağı değer belirsiz olur.
'Bu yüzden bu tür girişlere VCC'den bir direnç bağlanır. Eğer butona basılmazsa bu direnç üzerinden 'ilgili giriş beslemenin pozitif   ucuna bağlanmış olacağından "1" değerini almış olacaktır. Butona 'basıldığında ise, giriş doğrudan şaseye bağlanmış olacağından dirençten geçen tüm akım buton 'üzerinden şaseye akacağından PIC girişi de "0" değerine gelmiş olacaktır. Bu şekilde bağlanan
'dirençler "Pull-up" drenç olarak adlandırılır. Sıklıkla kullanılması gerektiğinden PIC işlemcilerinin 'neredeyse tümünde giriş olarak kullanılabilecek portlarından kimilerinde "weak pull up" adlı 'dirençler konmuştur. Bu dirençler PIC16F877'de "option_reg" adlı kaydedici ile devreye alınabiliyor. 'Weak pullup dirençlerini devreye almak için option_reg'i 0 yapıyoruz:

option_reg=000000

'Şimdi değişkenlerimizi belirleyelim.
'4 adet değişken kullanacağız. Bunlardan birincisi ekran belleği. "d" ile bunu tanımlıyoruz. d, 3 'elemanlı bir dizi ve her elemanındaki değer, ilgili 7 parçalı göstergede gösterilecek değeri ifade 'ediyor. Programın herhangi bir yerinde bu dizideki değeri değiştirdiğimizde, gösterge değişmiş 'oluyor.

d var byte [3]'Ekran belleği





'cs olarak tanımlayacağım değişken ise, karakter seti. Yani hangi rakamı göstermek istediğimizde 7 'parçalı göstergenin hangi parçalarını yakmamız gerektiğini buraya koyuyoruz. Burada 0-F arası 'göstermek istediğimize göre 16 elemanlı bir byte dizisi olacak bu. Her baytın içindeki her bit, 'göstergenin bir parçasına denk geliyor. En büyük bit kullanılmadığından daima sıfır. Diğerleri ise en 'küçük bit "a" parçası olmak üzere a,b,c,d,e,f,g parçalarını ifade ediyor. Örneğin "0" işareti için g 'hariç tüm parçalar yakılacağı için 00111111 değeri alıyor. Örneğin 1 için sadece b ve c parçaları 'yakılacağından 00000110 değeri alıyor.

cs var byte [16]'Karakter seti

'Çoğullamalı tarama yapacağımızı söylemiştik. Display adlı yordamı her çağırışımızda bir gösterge 'değer gösterecekti. Hangi göstergenin değer göstereceğini dc değişkeninde tutacağız. Bunu 1,2,3 'olarak her seferinde arttırıp 3'ü geçtiğinde tekrar sıfır yapacağız.

dc var byte'Ekran tarama sayıcısı

'Butonları düşen kenarda tetiklemek için eski durumlarını bilmemiz gerek. Bunun için butonların eski 'durumlarını tutacağımız bir değişkene ihtiyacımız var.  Bunu da p değişkende tutacağız.

p var byte'Butonların eski durumu

'Ödevde istenenlere göre, devreye enerji verildiğinde tüm ledlerin yanması gerekiyor. Yani 2 saniye boyunca ekranda 888 göstereceğiz. Bu yaklaşık 2 saniyeyi belirlemek için bir değişkene ihtiyacımız var:

i var byte 'Test sayıcısı

'Burada 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F karakterlerini görüntüleyecek değerleri tanımlıyoruz:
cs[0]=111111
cs[1]=000110
cs[2]=%01011011
cs[3]=%01001111
cs[4]=%01100110
cs[5]=%01101101
cs[6]=%01111101
cs[7]=000111
cs[8]=%01111111
cs[9]=%01101111
cs[10]=%01110111
cs[11]=%01111100
cs[12]=111001
cs[13]=%01011110
cs[14]=%01111001
cs[15]=%01110001

'Şimdi portlarımızın ilk değerlerini verelim:
portb=255
portc=254
portd=255

'İlk başlatıldığında 888 göstereceğimiz için, ekran belleğine 8 değerlerini koyalım.

d[0]=8
d[1]=8
d[2]=8

'Ekran tarama sayacını sıfırlayalım.
dc=0

'Butonların eski durumu olarak "basılı değil" olarak tanımlayalım.
p=255

'Yaklaşık 2 saniye için, "display" yordamını 150 defa çağırıyoruz.
for i=1 to 150
gosub display
next

'Artık ekranda üç değeri de "0" olarak gösterebiliriz.
d[0]=0
d[1]=0
d[2]=0


'Ana döngüde tuşlara bakıp eğer basılan varsa gereğini yapıp, "display" yordamını çağırmak dışında 'yapacağımız bir şey yok.

ana:

'Eğer birinci buton basılı ise daha önceden basılı olup olmadığına bakıyoruz. Eğer daha önce
'basılı değilse "düşen kenar" algılanmış olacağından birinci göstergedeki değer 1 arttırıyoruz. Değer '9'u aştı ise sıfırlıyoruz.

if portb.2=0 then
if p.2=1 then
d[0]=d[0]+1
if d[0]>9 then d[0]=0
endif
endif

'İkinci butonda da birincisi için yaptıklarımızın aynısını yapıyoruz. Sadece burada 9'a ulaştı ise 6'ya 'ulaştı ise sıfırlıyoruz

if (portb.1=0) then
if p.1=1 then
d[1]=d[1]+1
if d[1]>6 then d[1]=0
endif
endif

'Üçüncü butonda arttırdığımız bir değer yok. İki değeri toplayıp üçüncü değer olarak yerine 'koyuyoruz.
if (portb.0=0) then
if p.0=1 then
d[2]=d[0]+d[1]
endif
endif

'p değişkenine butonların şimdiki değerini koyuyoruz ki düşen kenar tetiklemesi çalışabilsin.
 p=portb


'"display" yordamımızı çağırıp en başa dönüyoruz.
gosub display
goto ana

'Burası programın "sihirli" bölümü. Karakter seti ve ekran belleğini kullanarak tek bir göstergede
'istenen değerin görünmesini sağlıyor.

display:
dc=dc+1
if dc>3 then dc=1
portd=cs[d[dc-1]]
if dc=3 then dc=4
portc=dc<<1
pause 2
return

Bu makale, kamu kullanımına sunulmakla birlikte başka bir mecrada iktibası yasaklanmıştır. Başka bir mecrada yayımlamak için en azından alıntının başında ve sonunda birer defa olmak üzere toplam en az iki defa bu sayfanın linki verilmelidir. Aksi halde kanuni haklarımız saklıdır. Başka mecralarda paylaşırken bu hususa dikkat etmenizi rica ediyorum.

Hiç yorum yok: