ONLINE PIC COMPILER NASIL KULLANILIR


Hoşgeldiniz. Online PIC compiler, PIC mikrodenetleyiciler için tarayıcı-tabanlı bir assembly derleyicisi ve simülatörüdür. Bu web sayfasında Assembly kodlarınızı derleyebilir, oluşturulan makina kodlarını indirebilir, hatalarınızı ayıklayabilir ve sonuçları online olarak simule edebilirsiniz.
Aşağıdaki figür anasayfanın bir ekran görüntüsüdür. 1) ÇALIŞMA ALANI:Assembly kodlarınızı buraya yazabilirsiniz.
2) DERLE BUTTONU: Kodlarınızı tek bir tıklamayla hatalar için test edebilir ve derleyebilirsiniz.
3) KONSOL:Hatalar ve Uyarılar burada belirmektedir.
4) HATA AYIKLAYICI VE SIMULASYON BUTONU: Programınızı derledikten sonra eğer hata yoksa programınızı hata ayıklayıcı/simulatör aracı ile test edebilirsiniz.
5) YAPILANDIRMA MENUSU:Kod koruma gibi yapılandırmaları bu menuden yapabilirsiniz.
6) MENU: 6 sayısı ile gösterilen menüden şu işlemleri yapabilirsiniz:
Her Hakkı Saklıdır.

HAKKINDA


GEMS
YAZILIM&ELEKTRONİK
Online PIC compiler GEMS Yazılım&Elektronik yazılımcıları ve mühendisleri tarafından geliştirilmiştir.
Geliştiriciler Ayrıca, geliştirme aşamasında bize yardımcı olan stajyerlerimize teşekkür ediyoruz: Hamidu Mbonde, Buğra Sertçelik, Yunus Emre Gazioğlu, Nurullah Mısır, Mehmet Ali İyikülah.

Sayı Düzenleri


Bir çok sayı düzeni (veya tabanı) bulunsa da, assembly programlamada bunlardan üçü oldukça önemlidir: ikilik, onluk ve onaltılık düzenler. Programlama yaparken, bu tabanlar arası dönüşümler için OnlinePicCompiler’ın Araçlar sekmesindeki Taban Dönüşüm Aracı’nı kullanabilirsiniz.

Aşağıdaki tablo, farklı tabanlarda kullanılan rakamları göstermektedir.

Taban Rakam
İkilik 0, 1
Onluk 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Onaltılık 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F

Genel olarak, N’lik sayı düzeni için 0’dan N-1’e kadar olan sayılar rakam olarak kullanılır. Onaltılık düzendeki A-F arası harfler, sırasıyla 10-15 arası sayıları göstermek için kullanılmaktadır.

Harf Sayı
A 10
B 11
C 12
D 13
E 14
F 15

Mikrodenetleyiciler, ikilik düzende yalnız 0 ve 1 kullanarak çalışan cihazlardır.

RAM

Tüm mantık ve aritmetik işlemler, ikilik düzende yapılır ve hafızadaki tüm veriler yine ikilik düzende 0 ve 1 kullanılarak saklanır. İkilik düzende yazılmış bir sayının her bir rakamı bir biti ifade eder.

Fakat tüm bu veri ve işlemleri ikilik tabanda düşünmek, bizim için zor bir iştir. Onaltılık düzen bu noktada devreye girer. Onaltılık düzen, ikilik düzene kıyasla çok daha derlitopludur (kompakt) ve kullanması kolaydır. Normal aritmetik işlemlerde onluk düzeni kullandığımız ve alışageldiğimiz düşünme yapımıza en fazla uyan taban, onluk olduğu halde; ikilik ve onaltılık düzenler arasındaki dönüşümler, ikilik ve onluk düzenler arasındaki dönüşümlere göre çok daha kolaydır. Bu nedenle assembly programlamada onaltılık düzen oldukça sık kullanılan bir düzendir.

Aşağıda, ikilik ve onaltılık düzenlerin birbirine dönüştürülmesi için kullanılan yöntemler anlatılmıştır.

İkilik tabanı onaltılık tabana dönüştürme

İkilik sistemde yazılmış bir sayıyı onaltılık düzene çevirmek oldukça kolaydır. Bu çevrimde ilk bilmemiz gereken şey, ikilik düzendeki dört rakamın onaltılık düzende bir rakama karşılık geldiğidir.

SayiDuzeniOrnek1

Bu nedenle, ilk olarak ikilik düzende yazılmış sayıyı 4’er bitlik gruplara ayırmalıyız.

SayiDuzeniOrnek2

Eğer, sayımızın içerisindeki toplam 0 ve 1 sayısı dördün tam katı değilse, gruplandırma işleminden önce sayının en soluna sıfırlar ekleyerek dördün tam katı bir sayıda rakam içermesini sağlamalıyız.

SayiDuzeniOrnek3

Bir sonraki adımda aşağıdaki tabloyu kullanarak her bir gruba karşılık gelen onaltılık düzendeki rakamı yazarız.

İkilik Onaltılık
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 A
1011 B
1100 C
1101 D
1110 E
1111 F

Son olarak, gruplara karşılık gelen onaltılık rakamları yanyana yazdığımızda sonucu elde etmiş oluruz.

Örnekler:

SayiDuzeniOrnek4

Onaltılık tabanı ikilik tabana dönüştürme

Onaltılık tabanı, ikilik tabana dönüştürmek için yukarıda uyguladığımız yöntemin tersini uygulayacağız.

Onaltılık düzendeki her bir rakamın ikilik düzendeki karşılıklarını bulup yanyana yazmamız bu dönüşüm için yeterli olacaktır. Eğer istenilirse, en soldaki sıfırlar sonuçtan çıkarılabilir.

Örnek:

SayiDuzeniOrnek5
Her Hakkı Saklıdır.

Online PIC Compiler'da Sayı Gösterimleri


OnlinePicCompiler'da beş çeşit sayı gösterimi bulunmaktadır. Bunlardan üçü onaltılık düzen, biri ikilik, sonuncusu ise onluk düzen için kullanılmaktadır.
ONLUK düzendeki bir sayı gösterimi D veya d ile başlar ve sayı tek tırnaklar arasına yazılır.
Örneğin, onluk düzendeki 23 sayısını ifade etmek için D'23' gösterimi kullanılır.
İKİLİK düzendeki bir sayı gösterimi B veya b ile başlar ve sayı tek tırnaklar arasına yazılır.
Örneğin, ikilik düzendeki 110 sayısını ifade etmek için B'110' gösterimi kullanılır.
Onaltılık sayılar için üç değişik gösterim bulunmaktadır:
Direk olarak yazılmış bir sayı her zaman onaltılık düzende algılanır.

Örnek:
Aşağıdaki tüm satırlar W'yu (ondalık düzende) 100 sayısına eşitlemektedir.
MOVLW D'100'
MOVLW 0x64
MOVLW H'64'
MOVLW 64
MOVLW B'01100100'


Her Hakkı Saklıdır.

Değişken/Adres Tanımlama


Assembly dilinde, değişken ve adres tanımlaması EQU komutu kullanılarak yapılmaktadır. Tanımlama için şu format kullanılır:
Isim EQU Deger
Isim tanımladığımız değişkene verilen isimdir. Isim için yalnızca iki sınırlama bulunmaktadır : bu kurallara uyan her isim Isim olabilir.
Deger ise, değişkene atanan değer ya da adrestir. Buraya yazılan değerin Sayı gösterim formatlarından birine uyması gerekmektedir.
Tanımlaması yapılmış bir değişken, bir sayı veya adres ifade etmek için kullanılabilir.

Örnek:
Diyelimki, RAM'in 0X15 adresinde, 0XFF sayısı yüklü olsun.
SAYAC EQU 0X15
tanımlamasından sonra
MOVLW SAYAC
komutu W'yu 0X15'e eşitler. Fakat,
MOVF SAYAC, 0
ise W'yu 0XFF'e eşitler.

İki farklı Ismi'ni aynı Deger'e eşitlemek mümkündür.
Örneğin,
SAYAC1 EQU 0X15
SAYAC2 EQU 0X15
komutları hem SAYAC1’, hem de SAYAC2’yi aynı değere eşitler. Aynı Isim iki farklı değere atanırsa, program ikinciyi doğru kabul eder.
Örneğin,
SAYAC1 EQU 0X15
SAYAC1 EQU 0X16
SAYAC1=0x16 olmasına neden olur.
Her Hakkı Saklıdır.

Etiketler


Etiketler, kullanıcı tarafından tanımlanmış ve program içerisinde istenilen satırları işaretlemek için kullanılan isimlerdir.

Örnek:
Örneğin,
MOVLW 0X05
MOVWF SAYAC
DONGU
MOVF PORTA, 0
MOVWF PORTB
DECFSZ SAYAC
GOTO DONGU
programında, DONGU satırı programcı tarafından tanımlanmış bir etikettir.

Bu sayfanın en altında belirtilen kurallara uymak şartıyla, kullanıcı istediği ismi etiket olarak kullanabilir.

Örnek:
Örneğin,
MOVLW 0X05
MOVWF SAYAC
BASLANGIC
MOVF PORTA, 0
MOVWF PORTB
DECFSZ SAYAC
GOTO BASLANGIC
programında DONGU yerine BASLANGIC etiketi kullanılmıştır.

Programlama açısından, yukarıdaki her iki örnek de tamamen birbirinin aynısıdır.

Bir etiket, program içerisinde tanımlandığı yerden sonraki ilk komutu temsil eder. İkinci örneğimizdeki BASLANGIC etiketi kendinden sonraki ilk komut olan MOVF PORTA, 0 satırına işaret etmektedir. Etiket ile komut arasına konulan boşluk satırlar ve yorumlar bu durumu değiştirmez.

Örnek:
Örneğin,
MOVLW 0X05
MOVWF SAYAC
BASLANGIC

;komutlar buradan başlıyor
MOVF PORTA, 0
MOVWF PORTB
DECFSZ SAYAC
GOTO BASLANGIC
programı da yukarıdakiler ile tamamiyle aynı şekilde çalışır.

Bir program içerisine, kullanılsın veya kullanılmasın, istenildiği kadar etiket yerleştirilebilir.

Örnek:
Örneğin
SATIR1
MOVLW 0X05
MOVWF SAYAC
BASLANGIC
MOVF PORTA, 0
ORTA
MOVWF PORTB
DECFSZ SAYAC
GOTO BASLANGIC
yukarıdaki programda MOVLW 0X05 komutu için SATIR1, MOVF PORTA, 0 komutu için BASLANGIC ve MOVWF PORTB komutu için ise ORTA etiketleri tanımlanmıştır.

Normal şartlar altında, kullanılmayan bir etiketin program içerisine yazılması tercih edilen bir durum değildir. Bu nedenle kullanılmayan etiketler için Online Pic Compiler uyarı mesajı verir. Etiketler programınız içerisinde kullanılmasa da dursun istiyorsanız, bu uyarıları gözardı edebilirsiniz.

Bu noktada aklınıza şöyle sorular gelebilir:

Etiket kullanmak ne anlama geliyor? Hangi durumlarda etiketleri kullanmış oluyoruz?

Etiketin program içerisindeki işlevi nedir?

Tüm bu soruların yanıtı, komut listemizde bulunan CALL ve GOTO komutlarıyla ilgilidir.

Öncelikle GOTO ile başlayalım.

Diyelim ki, PORTA’nın 0 numaralı pinine (RA0’a) bağlı bir LED’i sürekli olarak 1’er saniye aralıklarla yakıp söndürmek istiyoruz. LED’in bir kere yanıp sönmesi için aşağıdaki algoritmayı kullanabiliriz.

RA0’a 1 gönder
Yarım saniye bekle
RA0’a 0 gönder
Yarım saniye bekle

Bu algoritmayı koda dönüştürecek olursak, LED yarım saniye için yanar, söndükten sonra ise ikinci bir defa daha yanmaz. İkinci kez yanmasını istiyorsak aynı kodları ardarda yazabiliriz.

Örneğin,
RA0’a 1 gönder
Yarım saniye bekle
RA0’a 0 gönder
Yarım saniye bekle
RA0’a 1 gönder
Yarım saniye bekle
RA0’a 0 gönder
Yarım saniye bekle
algoritması LED’in iki kere yanmasını sağlar.

Bu işlemi 1000 defa gerçekleştirmek için aynı kodu 1000 defa ardarda yazmamız hem programlama açısından saçma olacak, hem de çipin program hafızası bu iş için yeterli olmayacaktır. İşlemci çalıştığı sürece bu işlemin sürekli olarak tekrarlanmasını istiyorsak, aynı kodları ardarda ne kadar yazarsak yazalım, istenilen sonuca ulaşamayız. Bu noktada çözüm, üst satırlara yazılan bir koda geri dönmekle mümkün olur. Kod dizisinde istenilen bir satıra atlama yapmak için GOTO komutu kullanılır. Örneğin, yukarıdaki yanıp sönme işlemini gerçekleştiren kod dizisinin başına bir etiket koyup (YAKSON olsun) en sonuna da GOTO YAKSON komutunu yazarsak, bu işlem sürekli olarak tekrarlanır.

YAKSON
RA0’a 1 gönder
Yarım saniye bekle
RA0’a 0 gönder
Yarım saniye bekle
GOTO YAKSON

Etiketin kullanıldığı ikinci komut ise CALL komutudur. Bu komut, programcı tarafından yazılan bir rutini çağırmak için kullanılır. Assembly dilindeki rutinler, daha üst seviye dillerdeki fonksiyonlara benzer. Bir rutin, CALL ile çağırıldığında, rutin içerisindeki komutlar işlenir ve rutin bittiğinde ise çağrıldığı satırın bir altındaki satırdan program çalışmaya devam eder.

Örneğin, yukarıdaki algoritmada RA0’da yaptığımız her bir değişiklikten sonra, yarım saniyelik gecikme kullanıyoruz. Programın bekleme kısmı için GECIKME adında bir rutinimiz olsun. Bir rutinin GECIKME ismine sahip olabilmesi için rutinin ilk satırına GECIKME etiketinin yazılmış olması gerekir.

Yukarıdaki örnek için bu rutini kullanacak olursak, program
YAKSON
RA0’a 1 gönder
CALL GECIKME
RA0’a 0 gönder
CALL GECIKME
GOTO YAKSON
haline dönüşür.

RA0’a 1 veya 0 göndermek için gerekli kodları da eklersek programımız,
YAKSON
BSF PORTA, 0
CALL GECIKME
BCF PORTA, 0
CALL GECIKME
GOTO YAKSON
haline dönüşür.

GECIKME rutini için ise Gecikme Kodu Üreteci aracını kullanabiliriz. 4 Mhz kristal kullanılıyorsa,

GECIKME
MOVLW 0X54
MOVWF DSAYAC1
MOVLW 0X8a
MOVWF DSAYAC2
MOVLW 0X03
MOVWF DSAYAC3
DONGU
DECFSZ DSAYAC1, 1
GOTO DONGU
DECFSZ DSAYAC2, 1
GOTO DONGU
DECFSZ DSAYAC3, 1
GOTO DONGU
NOP
RETURN

programı istenilen gecikmeyi sağlayacaktır. Görüldüğü gibi rutinin ilk satırında, bu gecikmeye ismini veren GECIKME etiketi bulunmaktadır.

Etiketleme Kuralları


Her Hakkı Saklıdır.

Bank'lar


16F ailesine üye PIC mikrodenetleyicilerin hafızası bank yapısına sahiptir.

16F84A için geçici hafıza (RAM) iki bank’tan oluşur.

Bankyapisi

Yukarıdaki resimde, her bir sütun bir bankı temsil etmektedir. Soldaki bank BANK 0, sağdaki ise BANK 1 olarak adlandırılır.

Bazı bellek alanları (STATUS gibi) her iki bankta da görünmektedir. Mikrodenetleyici hangi bankta olursa olsun, program bu tarz bellek alanlarına erişebilir. Sadece bir bankta rastlanan bir bellek alanı ile işlem (okuma, yazma veya değiştirme) yapabilmek için, programın o anda bu bellek alanının bulunduğu bankta olması gerekir.

Eğer mikrodenetleyicinin o an olmadığı banktaki bir bellek alanını kullanmaya çalışırsanız hata oluşur.

Bank seçmenin iki yolu vardır.

Bank değişimi ve kullanımını bir örnekle anlatalım.

Mikrodenetleyici, çalışmaya başladığında, tüm PORT’lar otomatik olarak giriş (input) olur. Eğer, PORTB’ye LED’ler bağlayacak ve bu LED’leri program akışında yakıp söndürecek bir program yazmak istiyorsak, PORTB’yi çıkış (output) moduna geçirmemiz gerekir. PORTB pinlerini çıkış yapabilmek için TRISB'yi sıfıra eşitlememiz gerekir, fakat yukarıdaki hafıza şemasına bakacak olursak TRISB yalnızca BANK 1’de bulunur. Bu nedenle, TRISB ile ilgili bir işlem yapmadan önce mikrodenetleyiciyi BANK 1'e geçirmeliyiz. Yukarıda anlatılan birinci yöntemi kullanarak, bu işlemi
BSF STATUS, 5
CLRF TRISB
komutları ile yapabiliriz.
İkinci yöntemi kullanmak istiyorsak
BANKSEL TRISB
CLRF TRISB
komutları da aynı işlevi gerçekleştirecektir.
Bu aşamadan sonra, eğer PORTB gibi sadece BANK 0’da bulunan bir register ile işlem yapacaksak, BANK 0’a geri dönmemiz gerekmektedir. Bunun için ise, Birinci yöntemi kullanarak,
BCF STATUS, 5
komutunu veya ikinci yöntem ile
BANKSEL PORTB
komutunu yazarak BANK 0’a geçiş yapabiliriz.


Her Hakkı Saklıdır.

Hedef


Hedef, işlem sonucunun nereye kaydedilmesi gerektiğini belirten komut parametresidir. ADDWF, ANDWF, COMF, DECF, DECFSZ, INCF, INCFSZ, IORWF, MOVF, RLF, RRF, SUBWF, SWAPF, XORWF komutlarında ikinci parametre olarak kullanılır.
Örneğin,
RLF SAYI, 0
komutundaki hedef, virgülden sonraki parametre olan 0’dır.
Hedef parametresi için iki seçenek bulunmaktadır: 0 ve 1. Hedefin 0 seçilmesi, sonucun W’ya, 1 seçilmesi ise kullanılan bellek alanı (register) üzerine yazılması gerektiğini gösterir.

Hedef1

Örneğin,
ADDWF SAYAC, 1
komutu W ile SAYAC bellek alanının içeriğini toplar ve SAYAC içerisine yazar. Bu durumda W’nun içeriği değişmez.

Hedef2

ADDWF SAYAC, 0
ise W ile SAYAC içeriklerini toplayıp W içerisine yazar. Bu durumda, SAYAC’ın içeriği değişmez.

Online Pic Compiler'da 0 yerine W veya w; 1 yerine ise F veya f kullanılabilir.

Örneğin,
ADDWF SAYAC, 1
ADDWF SAYAC, F ve
ADDWF SAYAC, f
komutarı aynı işlevi yerine getirir.

Örnek:
Diyelimki, W=15 ve SAYAC=63, olsun.
ADDWF SAYAC, F
SAYAC=78 olmasına neden olur. İşlem sonucunda W=15 olarak kalır. Bu örnekte, hedef F yerine W (veya 0 veya w) olsaydı, W=78 olurdu ve SAYAC=63 olarak kalırdı.


Her Hakkı Saklıdır.

Döngü Nasıl Oluşturulur?


Assembly programlamada döngüleri üç gruba ayırabiliriz. Bunlar: sonsuz döngüler, sonlu döngüler ve şartlı döngülerdir.

Sonsuz Döngüler

Sonsuz döngü, bir defa girildiği zaman içerisinden çıkılamayan döngüdür. Assembly dilinde yazılmış tüm programlarda, bir şekilde, (doğrudan veya dolaylı olarak) bir sonsuz döngüye ihtiyaç duyarız. Daha üst düzey programlama dillerinde ise, kullanıcı tarafından yazılmamışsa dahi, arka planda programa otomatik olarak sonsuz bir döngü eklenir.

Program sayacı, programda o an işlenecek satır numarasını gösteren bir değişkendir. Sonsuz döngü zorunluluğu, program sayacını belli sınırlar arasında tutma ihtiyacından doğar. Diğer programlama dilleri gibi assembly dilinde de komutlar yukarıdan aşağı doğru satır satır işlenir. Her bir satır işlendikten sonra, eğer program GOTO veya CALL komutlarıyla dallanmıyorsa, program sayacı otomatik olarak bir artar ve böylece bir sonraki işlenecek satırı işaret etmeye başlar. Eğer programın son satırına erişebiliyorsak ve bu satır gövdedeki bir satıra dallanmıyorsa, program sayacı, bu satır işlendikten sonra otomatik olarak bir artacağından, yazdığınız programın dışındaki bir noktaya gelir ve program hafızasının sonuna gelene kadar devam eder ve sonra tekrar programınızın ilk satırından devam eder. Bu da mikrodenetleyiciye reset atmaya benzer bir etki yaratır. Bu tarz problemlerle karşılaşmamak için program sayacını, bir şekilde, kendi programımız sınırları içerisinde tutmamız gerekir. Tek defa çalışacak bir algoritma yazmış olsak dahi, programın sonuna, program sayacının bu noktada takılıp kalmasını sağlayacak bir sonsuz döngü eklememiz gerekmektedir.

Örneğin,
SONSUZ
GOTO SONSUZ
bahsedilen işlevi yerine getirir. Program sayacı GOTO SONSUZ satırına ulaştığında, her zaman aynı satırda kalır. Çünkü bu satır, programın kendine dallanmasını sağlamaktadır.

Her zaman, programın sonuna yukarıdaki gibi bir sonsuz döngü koymak zorunda kalmayabiliriz. Örneğin, aşağıdaki kod parçası PORTA’yı sürekli kopyalayıp PORTB’ye yazar.

DONGU
MOVF PORTA, W
MOVWF PORTB
GOTO DONGU

Her yazımdan sonra, GOTO DONGU komutuyla beraber, tekrar başa dönüp işlemi tekrarlar. Bu örnek, ilkinden farklı olarak, aynı satırda sürekli kalmak yerine, bir kaç satır arasında sürekli gezinmektedir.

Aşağıdaki kod parçası da sonsuz dongu olarak sayılabilir.
DONGU1
GOTO DONGU3
DONGU2
GOTO DONGU1
DONGU3
GOTO DONGU2

Sonlu Döngüler

Program içerisinde aynı işlemin belirli bir sayıda tekrarlanmasını isteyebiliriz. Bu tarz döngüler, sonlu döngü kategorisindedir. Örneğin, RA0’a bağlı butona basınca RB0’a bağlı LED’i 10 kere yakıp söndüren bir program için, bir sonlu döngüye ihtiyaç duyarız. İçerisinde yaptığı işlemi 10 kere tekrar eden bir döngü oluşturabilmenin kolay yollarından birisi, ilk değeri 10 olan bir sayaç kullanmaktır. Bu sayacı her bir döngü tamamlandığında bir azaltıp, sıfır değerine ulaştığında programı döngüden çıkarmamız gerekecektir. Öncelikle, hafızada sayaç için EQU komutuyla bir yer ayırmalıyız.

SAYAC EQU 0x0C

İlk değerin 10 olması için ise
MOVLW 0x0A
MOVWF SAYAC
komutlarını kullanmalıyız. İlk değeri döngü dışarısında atamalıyız. Eğer döngünün içerisinde atarsak, her işlem tamamlandığında ilk değer tekrar tekrar atanacak ve böylece sayaç sıfır sayısına hiç bir zaman ulaşamayacaktır. Bu durumda istemeden sonsuz bir döngü oluşturmuş oluruz.

İlk değer atandıktan sonra SAYAC, döngü sonunda bir azaltılıp sıfıra ulaşıp ulaşmadığı kontrol edilmelidir.

Örneğin, aşağıdaki kodlar SAYAC sayısınca tekrarlanan bir sonlu döngü oluşturur. (....) ile gösterilen kısma, bu döngü içerisinde yapılması gereken işlemleri yazabiliriz.

DONGU
.....
DECFSZ SAYAC, F
GOTO DONGU

DECFSZ SAYAC, F satırı SAYAC’ı bir azaltıp kendi üzerine yazar (SAYAC=SAYAC-1). Eğer, yeni değeri sıfırsa, bir sonraki satır (GOTO DONGU) işlenmeden atlanır. Böylece, döngüden çıkılmış olunur. Yalnız sıfıra ulaşmadan önceki tüm değerler için, GOTO DONGU satırını atlamayacağından, döngünün ilk satırına geri dönüş yapar.

Tüm kodları bir araya getirecek olursak, aşağıdaki gibi bir tabloyla karşılaşırız.

SAYAC EQU 0X0C
.....
MOVLW 0X0A
MOVWF SAYAC
.....
DONGU
.....
DECFSZ SAYAC, 1
GOTO DONGU

Şartlı Döngüler

Belli bir duruma ulaşılana kadar devam eden döngülere, şartlı döngüler diyoruz. Örneğin, bir su ısıtıcısının 50C’ye kadar suyu ısıtıp, daha sonra durduğunu ve kontrol devresinde PIC kullandığımızı düşünelim. Bir sıcaklık sensörüyle (LM35 vb.), suyun sicaklığını santigrat derece cinsinden ölçüp, SENSOR isminde bir bellek alanına (register) kaydediyor olalım. Programda, ilk olarak, ısıtıcının çalışması sağlanmalı; daha sonra ise sicaklık 50C’yi dereceye ulaşana kadar bir döngü içerisinde sürekli olarak SENSOR değeri kontrol edilmelidir. Bu değere ulaştığında veya onu aştığında ise, döngüden çıkıp ısıtıcıyı kapatılmalıdır. Bu örnekte döngüden çıkma şartı SENSOR değerinin 50’ye erişmesidir.

Caydanlik

Aşağıdaki kodlarda, son dört satır bu işlemi gerçekleştirmektedir. (...) ile gösterilen yerde sicaklık değerinin ölçülüp SENSOR bellek alanı içerisine kaydedildiğini düşünelim.

DONGU
.....
MOVLW D’50’
SUBWF SENSOR, W; W=SENSOR-50
BTFSC STATUS, C
GOTO DONGU

İlk satırla, W içerisine 50 sayını yüklüyoruz. İkinci satırda ise, SENSOR’den 50 çıkarıp W içerisine yazıyoruz. Çıkarma işleminin sonucu sıfır veya daha büyük bir sayı ise (SENSOR 50 veya daha büyükse) Carry Flag=0 olacaktır. Bu durumda GOTO DONGU satırı atlanacağından program döngüden çıkar. Diğer durumda ise, GOTO DONGU satırı işleneceğinden, ölçümün tekrarlanması için program sayacı döngünün başına gider.


Her Hakkı Saklıdır.

Şartlı/Koşullu İfadeler


Giriş

Bu yazıya direk olarak, bir örnekle başlayalım. Butona bastığımızda bir DC motoru saat yönünde, butondan elimizi çektiğimizde ise bu motoru saat yönünün tersine döndüren basit bir sistem düşünelim.

Butonludevre

Mikrodenetleyici uygulamalarında bir sonuca erişebilmek için birden fazla çözüm yöntemi bulunabilir. Benzer şekilde buton algılamanın da bir çok yolu bulunmaktadır. Burada basit bir çözüm üzerinde duracağız. Butondan gelen sinyali sürekli olarak kontrol edecek ve programı eğer basıldığını tespit edersek, motorun saat yönünde dönmesini sağlayan, diğer durumda ise saat yönünün tersinde dönmesini sağlayan kodlara yönlendireceğiz.

Bu örnek için iki farklı durum

ve iki farklı tepki bulunmaktadır. Bu tepkiler kodlama seviyesinde gerçekleştirildiğinden, programda her bir tepki için ayrı bir kod sekmesi bulunmalıdır. Bu kod sekmelerine geçiş ise, bütona basılıp basılmadığını kontrol eden bir şartlı ifade ile gerçekleşmektedir.

Bit Kontrol Eden Şartlı İfadeler

Program içerisinde bir bitlik verinin, o an için, 0 mı yoksa 1 mi olduğunu kontrol etmek için oluşturulan kod parçası, bit kontrol eden şartlı bir ifadedir.

Bir bütona basılıp basılmadığını anlamak için aşağıdaki gibi bir devre kurup, bütonun bağlı olduğu pinin mantık-1 mi yoksa mantık-0 mı olduğunu test etmemiz gerekir.

Buton

Yukarıdaki devreyi takip edecek olursak, bütona basıldığı zaman, bağlı bulunduğu porta gelen voltajın 5V (mantık seviyesinin 1) olduğunu ve basılmadığı zaman ise voltaj değerinin 0V (mantık seviyesinin 0) olduğunu görebiliriz. Bu nedenle, bütonun o an için basılı olup olmadığını, bağlı olduğu port olan RA0’ın mantık seviyesine bakarak test edebiliriz. İki farklı durum için de, farklı bir sinyal göndereceğimizden, farklı bir kod sekmesine geçiş yapmamız gerekecektir. Bu geçişleri GOTO komutuyla gerçekleştirebiliriz. Karşılaştırma kısmı için ise, BTFSS veya BTFSC komutlarını kullanabiliriz.

Diyelim ki, motorun saat yönünde çalışmasını sağlayan kod parçası için SAAT, diğer yönün kod parçası için de TERSSAAT etiketi kullanılmış olsun. Bu durumda

BTFSC PORTA, 0
GOTO SAAT
GOTO TERSSAAT

komutları, RA0’ın karşılaştırmasını gerçekleştirecektir.

BTFSC komutu iki parametre alır. Bunlardan ilki, komutun hemen yanında belirtilen bellek alanı ismidir. İkincisi ise, virgülden sonra yazılan bit numarasıdır. BTFSC bellek alanının belirtilen bit numarasındaki mantık seviyesini kontrol eder. Eğer, bu mantık seviyesi 0 ise, bir sonra yazılan satırı (GOTO SAAT) atlar ve kendisinden sonraki ikinci satıra (GOTO TERSSAAT) geçer. Eğer mantık seviyesi 1 ise, atlama işlemini gerçekleştirmez ve kendisinden bir sonraki satıra (GOTO SAAT) gider. Böylece, eğer butona basılmışsa SAAT, basılmamışsa TERSSAAT ile etiketlenmiş kod parçasına geçilir. Buradaki koşullu ifade BTFSC komutuyla gerçekleştirilmektedir.

BTFSS komutu ise, BTFSC’nin tersini yapar. Yani, eğer kontrol edilen bitin mantık değeri 0 ise bir sonraki satır işlenir, 1 ise bir sonraki satır atlanarak iki sonraki satır işlenir. Eğer yukarıdaki işlemi BTFSS komutuyla yapmak istiyorsak kodlamamız şu şekilde olmalıdır:

BTFSS PORTA, 0
GOTO TERSSAAT
GOTO SAAT

Bit kontrolü sadece Giriş-Çıkış PORT’ları için değil, hafızadaki herhangi bir bellek alanının (register) istenilen bir biti için de yapılabilir. Örneğin, yazdığımız programda yaptığımız aritmetik işlemin sonucunu SONUC isimli bir bellek alanı içerisine kaydetmiş olalım. Sonucumuz tek sayı ise RB0’a bağlı LED’i, çift sayı ise RB1’e bağlı LED’i yakmamız gerektiğini düşünelim.

Devre

Bu durumda kontrol etmemiz gereken şey, SONUC isimli bellek alanının son bitidir. Çift sayılar için son bit her zaman 0, tek sayılar için ise her zaman 1 olur (Örneğin, 7’nin ikilik düzende gösterimi 0000 0111, 6’nınki ise 0000 0110’dir). Son bite göre işlem yapmamız için, bir önceki örnekteki gibi, BTFSC veya BTFSS komutlarından birini kullanabiliriz. SONUC çift olduğunda RB0’daki LED’i yakmak için yazdığımız program CIFT, diğer durumdaysa TEK etiketi altında olsun. Bu durumda,

BTFSC SONUC, 0
GOTO TEK
GOTO CIFT

satırları beklediğimiz dallanmayı program içerisinde yapacaktır. Son bitimiz (0 lokasyonundaki) 1 ise (yani SONUC tek bir sayı ise) bir sonraki satır olan GOTO TEK işlenecektir. SONUC, çift sayı olduğunda ise BTFSC’den sonraki satır atlanarak GOTO CIFT satırına geçilecektir.

Byte Kontrol Eden Şartlı İfadeler

Assembly programlamada, bellek alanlarında tutulan sayıların sabit sayılarla veya birbirleriyle karşılaştırılması gereken durumlarla sıklıkla karşılaşılır.

Program akışına göre, bu karşılaştırmalar büyüklük, küçüklük veya eşitlik ölçütlerine göre yapılabilir.

Eşitlik Durumu

7 segmentte dijital bir saat uygulaması yaptığımızı düşünelim. Bu uygulamadaki saniye, dakika ve saat sayılarını RAM’deki bellek alanları içerisinde tutmalıyız. Saniye değerini, SANIYE adında bir bellek alanında tutuyor olalım.

DijitalSaat

Her bir saniye geçtikten sonra, SANIYE’de tutulan sayı bir artırılmalıdır. Fakat, SANIYE 60’a eriştiğinde, değeri 7 segmente göndermeden önce sıfırlamalı ve dakikayı temsil eden sayıyı bir artırmalıyız. Bu nedenle, program içerisinde SANIYE’yi 60 sayısı ile karşılaştıran bir şartlı ifadeye ihtiyaç duymaktayız.

Assembly dilinde, iki sayının eşit olup olmadığını anlamanın bir kaç yolu bulunmaktadır. Bu yolların tümünde eşit olma ve olmama durumları için sıfır bayrağının (zero flag) farklı değerler alıyor olması kullanılmaktadır. Örneğin, SANIYE’den 60 çıkardığımızda, SANIYE 60’a eşit olduğu durumda sonuç sıfır olacaktır. Başka bir ifadeyle, sıfır bayrağı (zero flag) yalnızca SANIYE=60 durumunda 1 olacaktır. Toparlayacak olursak, SANIYE’den 60 çıkarıp, sıfır bayrağını BTFSC veya BTFSS komutlarından biriyle kontrol ederek bu registerın 60’a ulaşıp ulaşmadığını kontrol edebiliriz. Diğer bir çözüm yolu da, SANIYE’yi 60 ile XOR işleminden geçirmektir. İki registerın XOR değeri yalnızca bu iki sayı birbirine eşit olduğunda sıfırdır.

SANIYE’nin 60’a eşit olmadığı durumda değerini bir artıran kod sekmesine ARTIR, değerini sıfırlayıp dakikayı bir artıran kısma ise SIFIRLA etiketini verelim.

MOVF SANIYE, W
SUBLW D’60’
BTFSC STATUS, Z
GOTO SIFIRLA
GOTO ARTIR

ve

MOVF SANIYE, W
XORLW D’60’
BTFSC STATUS, Z
GOTO SIFIRLA
GOTO ARTIR

kod dizilerinin her ikisi de beklenen karşılaştırmayı yapmakta ve eğer SANIYE=60 ise SIFIRLA etiketine, diğer durumda ise ARTIR etiketi ile belirtilmiş kod sekmesine geçiş yapmaktadır. Yukarıdaki kod dizilerinde ilk satır, SANIYE değerinin W'ya kopyalanmasını sağlamaktadır. İkinci satırda yapılan çıkarma veya XOR işlemlerinin sonucu STATUS içerisindeki sıfır bayrağınının durumunu değiştirmektedir. Sayılar eşitse (sonuç sıfırsa) sıfır bayrağı 1, diğer durumda ise 0 olmaktadır. BTFSC komutu ise bu bitin değerine göre atlama yaptığından program eşitliğin olup olmamasına göre farklı sekmelere geçiş yapmaktadır.

Büyük veya Küçük olma durumları

Şimdi şöyle bir senaryo düşünelim: Bir analog sicaklık sensöründen (LM35 gibi) gelen verilerin belli periyotlarla mikrodenetleyicinin ADC ünitesine alınıp sonuçların SENSOR isimli bir bellek alanına kaydedildiğini düşünelim. Gelen sensör değeri 120’den büyükse, fanı çalıştırmak için, FAN isminde bir kod sekmesi çağrılacak olsun. Yukarıdaki örnekte olduğu gibi, her defasında, SENSOR bellek alanının içerisindeki değerin 120’den büyük olup olmadığına bakılacak ve karşılaştırma sonucuna göre FAN etiketine atlanacak veya SENSOR kontrol edilmeye devam edilecek olsun.

Böyle bir karşılaştırmayı yapabilmek için, SENSOR içeriğinden 120 değerini çıkarıp, Carry Flag değerinin ne olacağına bakabiliriz.

KONTROL
MOVLW D’120’
SUBWF SENSOR, W
BTFSS STATUS, C
GOTO KONTROL
GOTO FAN

Yukarıdaki kodlamada ilk satır, sadece kod sekmemizi etiketlemek için kullanılmaktadır. İkinci satırda (MOVLW D’120’) ise W’ya 120 değerini kopyalıyoruz. Üçüncü satırda (SUBWF SENSOR, W) ise SENSOR’den W’yu, yani 120 sayısını, çıkarıp tekrar W içerisine yazıyoruz. Kodlama terimleriyle yaptığımız işlem W=SENSOR-W olur. SENSOR eğer 120’den büyükse veya bu değere eşitse çıkarma işleminin sonucu negatif olmayacağından Carry Flag=1 olur. Tersi durumda ise Carry Flag=0 olacaktır. Dördüncü ve ilerleyen satırlarda, daha önce yaptığımız karşılaştırmalara benzer bir yöntem izlemekteyiz.


Her Hakkı Saklıdır.

Bellek Alanı (Register)


Bellek alanı (register), RAM içerisindeki hafıza ünitelerine verilen isimdir. 8-bitlik mikrodenetleyiciler için (16F84A gibi), her bir bellek alanı 8-bit’ten veya 1 byte’tan oluşur. RAM içerisinde bellek alanları iki gruba arılabilir: Özel İşlevli Bellek Alanları (Special Function Register) ve Genel Amaçlı Bellek Alanları (General Purpose Register).

Hafizaalani

Özel İşlevli Bellek Alanları, mikrodenetleyicilerin donanım ünitelerini ve fonksiyonlarını yapılandırmak için kullanılır. Bu alanlardan her birinin RAM içerisinde belirli ve değişmez adresleri bulunmaktadır. Örneğin, 16F84A için, PORTB her zaman 0X06 adresindedir, yazılım ile bunu değiştiremeyiz. Portları giriş veya çıkış yapmak, karşılaştırıcı ünitelerini çalıştırmak, iç osilatörü çalıştırmak gibi fonksiyonlar Özel işlevli Bellek Alanlarının bazı bitlerini 1 veya 0 yapmakla gerçekleştirilir. Mikrodenetleyicilerin tüm ayarları ve yapılandırması bu bellek alanları ile yapılır.

16F84A içerisindeki Özel İşlevli Bellek Alanları TMR0, PCL, STATUS, FSR, PORTA, PORTB, EEDATA, EEADR, PCLATH, INTCON, OPTION_REG, TRISA, TRISB, EECON1 ve EECON2’dir

Özel İşlevli Bellek Alanlarının aksine, Genel Amaçlı Bellek Alanları program içerisinde serbest kullanım için tasarlanmıştır. Örneğin, yazdığımız program içerisinde bir sayaç tutmak istiyorsak, öncelikle RAM içerisinde Genel Amaçlı Bellek Alanları için ayrılmış bölgeden bir adres seçmemiz gerekir. Seçtiğimiz bu adrese isim ataması yapabilir, programın istediğimiz yerinde veri kaydedebilir, kaydettiğimiz veriyi değiştirebilir ve üzerine yazabiliriz. 16F84A için 0X0C ile 0X4F adresleri arasındaki bellek adresleri Genel Amaçlı Bellek Alanları için ayrılmıştır. Bu aralık dışında atadığınız hiç bir adres Genel Amaçlı Bellek Alanı olarak kullanılamaz.


Her Hakkı Saklıdır.

W Nedir? Nasıl Kullanılır?


W bellek alanı (Working Register) programınız çalışırken, geçici işlemleri yapan 8-bitlik bir donanım ünitesidir. W, RAM’deki Genel Amaçlı Bellek Alanları’nın birinden diğerine veri aktarımı için kullanılabilir.

Örneğin, NUM1 ve NUM2 isimlerinde iki bellek alanını RAM içerisindeki 0X20 ve 0X21 adreslerinde tanımlamış olalım.

NUM1 EQU 0X20
NUM2 EQU 0X21

NUM1’in içeriğini direk olarak NUM2’ye aktaramayız. Bunu gerçekleştirebilmek için önce NUM1’i W’ya daha sonra ise W’yu NUM2’ye aktarmamız gerekiyor. Aşağıdaki iki satır bu işlemleri gerçekleştirmektedir.

MOVF NUM1, 0; W=NUM1
MOVWF NUM2;NUM2=W

RAM içerisindeki Genel Amaçlı Bellek Alanları (GABA) arasındaki veri aktarımının dışında, bu alanlar ile aritmetik ve mantık işlemler yapabilmek için de W’yı kullanmamız gerekir. Örneğin, yukarıda tanımladığımız NUM1 ve NUM2’yi toplayıp sonucu NUM2’e yazmak için aşağıdaki satırları kullanabiliriz.

MOVF NUM1, 0; W=NUM1
ADDWF NUM2, 1; NUM2=W+NUM2

PIC16F ve PIC18F ailelerinde, işlemcide W’dan yalnız 1 adet bulunur. Daha gelişmiş çiplerde (PIC24 gibi) birden fazla W register bulunmaktadır.


Her Hakkı Saklıdır.

İLK UYGULAMA


PIC mikrodenetleyicileri ile geliştirme kartından bağımsız çalışan bir uygulama yapmak oldukça kolaydır ve genellikle ucuza mal olur. Bu yazıda, 16F84A ile devre tahtasında çalışan bir flaşör uygulaması yapacağız.

Picdevresi

GEREKLİ MALZEMELER

PIC programlayıcınız, bağlantı kablolarınız (jumper) ve devre tahtanızın (breadboard) olduğunu varsayarsak, yalnızca aşağıdaki malzemelere ihtiyacınız olacaktır.

Eğer devrenizde RESET butonu olmasını da istiyorsanız, aşağıdaki iki malzemeyi listenize ekleyebilirsiniz. Devrenizde RESET İSTEMİYORSANIZ, ki bu uygulama için zorunlu değil, MCLR pinini direk olarak 5V kaynağına bağlayabilirsiniz. Bu malzemeleri elektronik marketlerden veya internetten kolaylıkla temin edebilirsiniz.

PROGRAMLAMA VE DEVRE

Malzemeleri aldıktan sonra, aşağıdaki 6 adımı sırasıyla izlerseniz, PIC16F84A ile yanıp sönen bir flaşör devreniz olacaktır.

  1. Online PIC Compiler’ı (Link) açın.
  2. Örnekler menüsünden, LED Yakıp Söndürme örneğini seçin. Gerekli kodlar çalışma alanında belirecektir.
  3. Derle butonuna basın.
  4. Aç/Kaydet menüsünde boşluğa, bir dosya ismi yazıp (“uygulama1” gibi) Makina Kodunu Kaydet seçeneğine tıklayın. Bu işlem, oluşturulan .hex dosyasını bilgisayarınıza kaydedecektir.
  5. .hex dosyasını programlayıcı aracılığı ile 16F84A’ya yükleyip, çipi programlayıcıdan çıkarın.
  6. Son olarak, yukarıdaki devreyi kurun.

İlk uygulamanız hazır :)


Her Hakkı Saklıdır.

EEPROM


Çok Yakında Hazır Olacak...