Ders 2: Çalışma Mantığı ve Komutlar

Transkript

Ders 2: Çalışma Mantığı ve Komutlar
Hacettepe Robot Topluluğu
PIC Assembly Dersleri
2. Ders: Çalışma Mantığı ve
Komutlar
HUNRobotX - PIC Assembly Dersleri
2. Ders: Çalışma Mantığı ve
Komutlar
Yazan: Kutluhan Akman, Düzenleyen: Canol Gökel - 5 Haziran 2007
PIC'in Çalışma Mantığı Üzerine...
Geçen derste PIC'i çalıştırmak için gerekli olan minimum donanımdan bahsetmiştik. Beslemeleri
bağlamak (+5V, 0V), reset bacağını +5V'a bağlamak ve osilatör bacaklarının bağlantılarını
yapmak PIC'i çalıştırmak için yeterliydi. Şimdi biraz daha ayrıntılı inceleyeceğiz, PIC
komutlarına ve register (yazmaç) mantığına giriş yapacağız, PIC'in içinde neler olduğunu biraz
daha ayrıntılı olarak öğreneceğiz.
Eğer Microchip firmasının herhangi bir mikrodenetleyicisini kullanacaksınız data sheet'ler %90
ihtimalle sizin için yeterli olacaktır. Eğer Đngilizceniz varsa bir denetleyiciyi öğrenmek için tek
yapmanız gereken oturup data sheet'i okumak ve uygulamalar yapmaktır. Zaten yazacağınız
programı sınırlayan genelde denetleyicinin yetenekleri değil sizin yeteneklerinizdir. Bunu şöyle
açıklayayım: Đşlemcinin çarpma komutu olmayabilir, o zaman siz diğer komutların birleşimi
cinsinden çarpma fonksiyonunu yazmalısınız; işlemcinin analog/sayısal çeviricisi olmayabilir, siz
haricen kullanabilmelisiniz...
Đlk derste PIC'in içinde sabit disk yerine geçen, programın saklandığı bir program hafızası var
demiştik, şimdi onu inceleyelim.
2. Ders: Çalışma Mantığı ve Komutlar
Şekil 1
PIC ile çalışırken 2'lik 10'luk ve 16'lık sayı sistemlerini kullanacağız. 10'luk sistem zaten günlük
hayatta kullandığımız sistem ve "yeni başlayanlara temel dersler" diye verdiğimiz dökümanlarda
sayı sistemleri ayrıntılı olarak anlatıldı. 2'lik sistem de PIC'in kullandığı sistem, çünkü PIC'de
sadece 0 ve 1 var diye bahsetmiştik. Ben size sözlü olarak "00110101" sayısı ile "01101101"
sayısını toplayın desem bunları akılda tutmanız bile çok zor ama onun yerine bu sayıların 16'lık
karşılığı olan, "35" ile "6D" heksadesimal (16'lık sistemdeki sayılara böyle denir) sayılarını
toplayın desem cok daha rahat anlaşılır olur. Bir sayının sağ tarafına "h" harfi koymak ya da
sayının sol tarafına "0x" (sıfır ve x karakterleri) koymak o sayının heksadesimal olduğunu belirtir.
Bir diğer 16'lık sistem avantajı da 2'lik sistemden 16'lık sisteme çevirmenin kolay oluşudur. 2'lik
sayı sistemindeki sayıları sağ taraftan başlayıp 4'erli gruplarsınız ve her grubu ayrı ayrı 16'lık
sisteme çevirirsiniz böylece heksadesimal sayı kağıt kaleme ya da hesap makinasına ihtiyaç
kalmadan bulunabilir. Aynı işlemi tersten düşünüp 16'lık sistemi 2'li sisteme çevirirken de
kullanabiliriz. Daha ayrıntılı bilgi için sayı sistemleri notuna bakınız.
PIC'de genellikle adres isimleri heksadesimal olarak belirtilir (şekilde 1 numara ile gösterilmiştir).
Program hafızası yukarıdan aşağıya satırlar şeklinde oluşur (şekilde 4 numara ile gösterilmiştir) ve
her satırda 1 komut saklanır. Siz eğer 10 komut yazdıysanız, siz aksini belirtmediğiniz sürece
komutlarınız program hafızasında en üst satırdan (0000h) başlayarak ilk 10 satıra yazılır.
Eğer yazılmış örnek bir programa bakacak olursak komut satırlarının en başına ORG komutu
HUNRobotX - PIC Assembly Dersleri
konulduğunu görürüz. Bu komut programın program hafızasına yazılırken hangi program hafızası
satırından itibaren yazılmaya başlayacağını bildirir. Mesela biz ORG 0x000 komutu verince
komutlarımız program hafızasında heksadesimal 0. adresten başlayarak yazılır. Eğer biz ORG
0x004 yazarsak ORG komutundan sonraki yazdığımız satırlar program hafızasına heksadesimal 4.
adresten itibaren yazılmaya başlar. Şimdi bunun bize ne kazandırdığını açıklayacağız.
Bizim PIC'in bir reset bacağı var ve eğer bu bacak 1 seviyesinde (+5 Volt) olursa reset olmaz ama
eğer bu bacak 0 seviyesinde (0 Volt) olursa PIC reset olur demiştik. Şimdi gelelim reset'in
anlamına. Reset demek programınızın başa dönmesi demektir, başa dönmesi demek de programın
program hafızasında 0000h adresinden itibaren tekrar okunmaya başlaması demektir. Yani 0000h,
özellikli bir program satırıdır. Bir özellikli satırımız da 0004h satırıdır (şekilde 3 numara ile
gösterilmiştir). Bu satırın ismi "kesme adresi"dir. Đşlemciniz bir kesme durumunda bu adrese
gider. Peki kesme nedir? Normal program akışı içerisinde, isterseniz programınızın akışının
bozulmasına neden olabilecek öncelikler belirleyebilirsiniz, bu öncelikler oluşunca işlemci bütün
işlerini bırakır ve sizin 0004h adresine yazdığınız alt programı öncelikli olarak işler. Sonra kaldığı
yerden ana programı işlemeye devam eder. Burada program akışı kesildiği için (Mustafa'nın
deyimi ile reklam arasına girildiği için) bu olaya kesme denir. Kesme oluştuğunda programımız 4.
adrese yönelecek ve oradaki komutları işlemeye başlayacaktır. Yani ORG 0x004 komutundan
sonraki satırlar işlenecektir kesme oluştuğunda.
Şimdi diceksiniz ki daha program yazmayı anlatmadan programın nereye yüklendiğini
anlatıyosun, kesme diye bişi anlatıyosun. Siz de haklısınız ama bu bilgiler de dursun bir kenarda,
lazım olacak program yazarken. Gelelim program yazmak için gerekli diğer şeylere.
PIC ile bir program yazmak için komutları ve yazmaçları bilmek yeterlidir. 16F84 için sadece 35
adet komut ve 15 adet özel fonksiyon yazmacı (special function register, SFR) ile 1 adet
akümülatör (akü/working register/wreg/W) vardır. Bizim için en önemli olan, kaydedici komutları
incelerken de fark edeceğiniz gibi, W yani working register'dır. W, 8 bitlik bir yazmaçtır, yani
aynı anda sadece 8 bitlik veriyi saklayabilir ve Seyfullah'ın deyimi ile işlemci ile bellek arasında
elçilik görevi görür.
2. Ders: Çalışma Mantığı ve Komutlar
Şekil 2
Şekil-2'de genel kullanım amaçlı bellek adresleri ve SFR'ler gözüküyor, sanırım belleğin ne
olduğu gözünüzde accık canlandı. 0Ch adresinden 4Fh adresine kadar olan kısım genel amaçlı
bellek (general purpose register, GPR) olarak kullanılıyor. Bunu program memory ile
karıştırmayın, program memory PIC içindeki başka bir parça, bu başka bir parça. Bu kısım 2
bank'tan oluşuyor, bank 0 ve bank 1. Bank 0'da 00h'tan 0Bh adresine kadar SFR'ler, 0Ch'tan 4Fh
adresine kadar da GPR'ler tutulurken, bundan sonraki kısım ise kullanılmıyor. Bank 2'de ise
SFR'ler 80h'tan başlayıp 8B adresine kadar devam ederken buradan aşağısı kullanılmıyor, yani
16F84'te bank 1'de GPR bulunmuyor. Ama bank 1'deki GPR'a ulaşmak isterseniz bank 0'dakine
ulaşıyorsunuz. Yani bank 0'ın GPR kısmı bank 1'e yansıyor.
Bu GPR'ler nasıl kullanılıyor şimdi ona geleceğiz…
(Bi çay molası)
Geldik. Belleklerde de tıpkı program hafızasında olduğu gibi sol tarafta ve sağ tarafta yazan
HUNRobotX - PIC Assembly Dersleri
heksadesimal sayılar her satırın adresini gosteriyor. Program memory'deki her satır (adres) 14
bitten oluşur ama bellek adresleri 8 bitten oluşur (bu önemli bir ayrıntı). Yani genel amaçlı
kullandığınız adreslerin (satırların) her birisinde en fazla 8 bitlik bilgi saklayabilirsiniz. Mesela 4
sayı alıp karşılaştırıp en büyüğünü bulacaksınız. 8 bitlik 2'li sayı sisteminde yazılabilecek en
büyük sayı "11111111"dir. Bu sayının desimal (10'luk sistem) karşılığı 255'tir. Sizin 1. sayınız
255'ten büyükse o zaman sadece 1 adet bellek adresi kullanarak sayıyı saklayamazsınız. Her bir
satıra yazabileceğiniz en büyük sayı 255'tir. Programda kullanacağınız, geliştireceğiniz tekniklerle
satırları yan yana kullanabilirsiniz. Mesela 2 satırı yan yana kullanırsanız yazabileceğiniz en
büyük sayı "1111111111111111" olur. Bu sayının desimal karşılığı ise 65535'dir.
Bellekler ve SFR'ler 8 bitliktir dedik. SFR'yi tanımlamanın da zamanı geldi de geçiyor bile:
SFR'ler siz programınızda işlem yaparken bazı özel durumları kontrol etmeye ve/veya bazı
ayarları yapmaya yarayan bellek adresleridir. Nasıl ki program memory'de özel işlemi olan 2
adres vardı (0004h ve 0000h), bellek adreslerinde de bank 0 ve bank 1'de ilk 12 adres özel
fonksiyonlar için ayrılmıştır. Mesela aritmetiksel işlemlerden sonra sonucun – veya + olduğunu
kontrol etmek isteyebilirsiniz ya da PIC'in bir bacağı ile bir LED yakmak isterken başka bir
bacağına düğme bağlamanız gerekebilir. Başka örnekler de vermek gerekirse PIC'in içindeki
dahili sayıcı modülünü kullanmak istiyorsanız onun ayarlarını ilgili yazmaç vasıtası ile yaparsınız;
aynı şekilde kesmeleri de ilgili kesme yazmacı ile ayarlarsınız. Daha önce bahsettiğimiz PORTB
de aslında bir yazmaçtır. Bazen komutları işlerken bellek adreslerinden "file" diye de
bahsedeceğiz.
Bir de yukarıda bahsedilen working register'ımız (W) var. Mikrodenetleyici içindeki işlemci,
bellek ve program hafızası fiziksel olarak da ayrı şeylerdir. Bunlar arasındaki bağlantı da PIC
içindeki başka yardımcı donanımlar ile yapılır. Bu kısım ayrıntı olduğu için girmiyorum, bize de
bu ayrıntılar ileride zaten gerekli olmayacak. Đşlemci, bellek ile ilgili yapacağı birçok işlemi W
vasıtası ile yapar. Mesela bir file'ın (yazmacın, register'ın) içine direk bir bilgi yükleyemezsiniz.
Öncelikle W'ya atarsınız sonra da bunu W'dan file'a atarsınız. Diyelim ki PORTA'nın içindeki
sayısal bilgiyi 1 azaltıp PORTB'ye atmak istiyoruz. O zaman örnek komutlar şu şekilde olacaktır:
Not 1: Aşağıdaki komutlar ileride daha ayrıntılı olarak anlatılacaktır.
Not 2: ; (noktalı virgül) işaretinden sonra gelen yazılar derleyici tarafından dikkate alınmaz ve bu
yüzden programlarda yorum yazmak amacıyla kullanılır.
MOVFW PORTA
MOVWF REG1
DECF
REG1
MOVFW REG1
;
;
;
;
;
;
;
;
MOVe File to Working register. Burada file PORTA
oluyor. Yani PORTA, Working register'a taşınıyor
MOVe Working register to File. Burada file REG1 diye
tanımlanmış herhangi bir general purpose register
DECrement File. Register'ın içeriğini 1 azaltıyoruz,
Burada register dediğimiz REG1
MOVe File to Working register. REG1 ismini verdiğimiz
ve sadece PORTA'nın bilgisini taşıyıp 1 azaltmak için
2. Ders: Çalışma Mantığı ve Komutlar
MOVWF PORTB
; kullandığımız adresi şimdi geri W'ya taşıyacağız
; böylece W'dan PORTB'ye atayabileceğiz
; MOVe Working register to File. File burada PORTB oldu
Not: Program yazarken sonradan tanımlanan herşeyde (register, satır etiketi gibi) büyük/küçük
harf duyarlılığı vardır. Yani REG1 yazmacı ile reg1 yazmacı hatta Reg1 yazmacı birbirlerinden
hep farklı yazmaçlardır.
Komutları anlamaya başladıkça en son açıkladığım olayı daha net kavrayacaksınız.
PIC Assembly Komutları
Assembly dilinde her komut Đngilizce bir mananın kısaltılmışıdır ve bu komut aslında 2'lik
sistemde 6'bitlik bir sayıyı temsil eder. Eğer bu komutla birlikte bir sabit sayı falan da
kullanılacaksa (komut gerektiriyorsa) o zaman program memory'ye bu sabit ile yazılırlar.
(program memory'de her komut için 14 bit ayrıldığını söylemiştik)
Şekil 3
Öncelikle bit işlem komutlarından başlayalım anlatmaya. Bit işlem komutlarında her komut bir
yazmacın sadece 1 biti ile ilgili işlem yapar. Programda bir yazmacın bir bitini belirtmek için ilk
olarak yazmacın ismini yazarız sonra da virgül koyup kaçıncı bit ile ilgili işlem yapmak
istediğimizi yazarız. Mesela PORTA yazmacının 3. biti ile işlem yapacaksak PORTA, 3 yazarız.
Bir de komutlara gelmeden önce yazmaçlara ve bazı belirli bitlere isim vermeyi öğrenelim.
Yazmaçların içeriği ile çok oynayacağımızdan dolayı program sırasında yazmaçlara birçok defa
ulaşmamız gerekecektir. Her seferinde bir yazmaca adresi ile seslenmek zor olur çünkü adres
açıklayıcı olmadığından programın okunabilirliği azalır, programcı da hangi adresi ne için
kullandığını unutacaktır. Bu yüzden örneğin bir sayaç bilgisini tutacağımız bellek adresini
program içinde SAYAC diye çağırabilmemiz için EQU komutu yaratılmıştır. Bu komut ile
yaratacağımız isimlerin içeriği program boyunca tarafımızdan sürekli değiştirilebileceğinden
dolayı bunlara programlama dünyasında "değişken" ismi de verilir.
Bu komutun kullanımını bir örnekle görelim. Mesela 0x30 adresine SAYAC ismini vermek için
programa şöyle bir satır ilave ederiz:
HUNRobotX - PIC Assembly Dersleri
SAYAC
EQU
0x30
; Bildiğiniz gibi başına 0x eklenen sayılar
; heksadesimal oluyordu
Artık belleğimizdeki 0x30 adresini program içinde SAYAC yazarak da kullanabiliriz. Aynı
şekilde bitlere de istedigimiz ismi vermemiz mümkündür. Bunun için "#DEFINE" önişlemci
komutu kullanılır. PORTA'nın 0. bitine bir LED bağlamış olalım ve bit komutlarını kullanarak bu
LED'i söndürmek istiyoruz diyelim. Bu işlem için
BCF
PORTA, 0
demek yerine PORTA, 0'ı "LED" diye tanımlayıp ondan programın geri kalanında artık LED diye
bahsedebiliriz:
#DEFINE
LED
PORTA, 0
Birazdan bunların kullanımına da örnek vereceğiz. Şimdi esas komutlara gelirsek...
BCF (Bit Clear File)
Herhangi bir yazmacın istedigimiz bitini "0" yapar. O bitin önceki değeri önemli değildir.
BSF (Bit Set File)
Herhangi bir yazmacın istediğimiz bitini "1" yapar. O bitin önceki değeri önemli değildir.
Bu öğrendiğimiz ilk iki komutu bir örnekte kullanalım:
BCF
PORTA, 3
BSF
BSF
REG1, 0
HASAN, 7
;
;
;
;
;
;
PORTA'nın 3. bitinin 16F84'ün 2. bacağını temsil
ettiğini geçen ders öğrenmiştik. Burada da o bacağı 0
yapıyoruz
REG1 bizim sonradan tanımladığımız herhangi bir GPR.
HASAN da REG1 gibi bir GPR, adını REG1 değil de HASAN
koymuşuz.
BCF komutunu şu şekilde daha önceden tanımladığımız bir bit ile de kullanabiliriz:
BCF
LED
BTFSS (Bit Test File, Skip if Set)
Bu komutu istediğimiz bir biti test etmek için kullanıyoruz. Eğer bit 0 ise program akışımız hiç
birşey olmamış gibi bir alt satıra geçiyor. Eğer bitimiz set edilmiş ise (yani 1 ise, yani elektronik
için düşünürsek +5V seviyesinde ise), o zaman bir alt satırı atladıktan sonra programı işlemeye
devam ediyor.
Örnek: PORTB, 0'a bir düğme, PORTA, 0'a ise bir LED takılı olsun ve düğmenin takılı olduğu
bacağa düğme basılmadığı taktirde 0, basıldığı taktirde 1 geliyor olsun. Eğer 1 gelirse (düğmeye
basılırsa) LED yakılacak.
2. Ders: Çalışma Mantığı ve Komutlar
#DEFINE
#DEFINE
DUGME PORTB, 0
LED
PORTA, 0
BTFSS BUTON
GOTO $-1
BSF
LED
BTFSC (Bit Test File, Skip if Clear)
Bu komut ise aynı 1 satır atlama işlemini kontrol edilen bit 0 ise yapıyor.
GOTO (GO TO)
Programın bu komuta geldiğinde istediğimiz yere dallanmasını sağlar. Bu yer bir satır etiketi ile
belirtilebileceği gibi bu yerin kaç satır aşağısı ya da yukarısı olacağı da söylenebilir.
Örnek:
GOTO
BEKLE
; Başında "BEKLE" yazan satıra (yani BEKLE etiketine
; sahip satıra) dallanır ve program oradan devam eder
"$" karakteri PIC Assembly dilinde programın o an olduğu yeri belirtir. Yani
GOTO
$
şeklinde bir komut yazmakla
BEKLE
GOTO BEKLE
yazmak arasına fark yoktur. Programın 10 satır yukarıya (önceye) dallanmasını istersek $
işaretinin yanına "-0A" yazabiliriz. Yani $ (bulunduğu satır) - 0A (heksadesimal 10 sayısı)
Eger 10 satır aşağı gitmesini istersek + işaretini kullanırız:
GOTO $ + 0A
Sadece yorumlardan oluşan ya da boş satırlar bu sayıya dahil değildir. Eğer program yazarken
heksadesimal sayılar ile uğraşmak istemiyorsanız sayıyının sol tarafına "D" harfi koyarak sayının
desimal olduğunu "B" harfi koyaraksa binary (2'li sistemdeki sayılara verilen isim) bir sayı
olduğunu belirtebilirsiniz. Bu kullanımda sayıyı da ayrıca tek tırnak içinde yazmanız
gerekmektedir.
GOTO
GOTO
$ + D'15'
$ + B'00001111'
Bu 2 komut aynı işi yapıyor ama 1.'de desimal, 2.'de ise binary sayı kullanılıyor. Ama
heksadesimal bir sayı kullanacaksanız programda sayıların başına "H" yazmanıza gerek yok
HUNRobotX - PIC Assembly Dersleri
çünkü programda tüm sayılar varsayılan olarak heksadesimal'dir.
Şimdi sıra geldi byte oriented komutlara yani byte işlem komutlarına. 8 bitin toplamı 1 byte eder.
Dolayısı ile 16F84'ün her bellek adresi 1 byte'lıktır. Adından da anlaşılabileceği gibi byte oriented
komutlar da bütün byte'ı değiştirebilecek ya da etkileyebilecek komutlardır. Bundan önceki bit
oriented komutlarda sadece 1 biti değiştiriyor ya da kontrol ediyorduk, şimdi 1 byte'lık bellek
adresinin 1 satırındaki bitlerin alayını tek seferde değiştirebilecek ya da kontrol edebiliceğiz.
Şekil 4
Arkadaşlar yukarıdaki grafik ve şekillerin hepsi orijinal PIC16F84 data sheet'inde bulunmaktadır.
Ben de bütün bilgilerimi oradan öğrendim, yani ana kaynak orası. Dolayısı ile burada aklınıza
gelip de cevabını bulamadığınız herşeyi oradan bulabilirsiniz, orada da bulamazsanız
HUNRobotX birebir görüşmeler ile ya da forum üzerinden sizin sorularınızı itina ile
cevaplayacaktır. Neyse reklam arasından sonra devam edelim.
Önce yukarıdaki tabloyu okumayı öğrenelim. Aslında çok basit birazcık incelerseniz kendiniz de
çözebilirsiniz. En baştaki komuttan başlayalım.
ADDWF f, d (ADD Working register and File then write it into destination)
File ne demekti öğrenmiştik, register yani bellekteki adresler demekti. W ne demekti onu da
öğrenmiştik, working register. Yani bu komut W'nun içeriği ile istediğimiz herhangi bir yazmacın
içeriğini topluyor. Ama komutun kullanımında ADDWF f, d yazıyordu, hadi komutu anladık F ile
2. Ders: Çalışma Mantığı ve Komutlar
W toplanıyor peki topladıktan sonra bu toplamı nereye yazıyor? Burada "d" destination yani
toplamın yazılacağı hedef manasına geliyor, "d" yerine "f" ya da "w" yazabiliriz her komut için.
Eğer w yazarsak toplam W'ya eğer f yazarsak toplam f'ye yani mevzubahis hangi yazmaç ise ona
yazılır.
Örnek:
ADDWF REG1, f
ADDWF REG1, w
;
;
;
;
;
;
Burada W ile REG1 toplanır ve sonuc f'ye yani REG1'e
atılır. W'nun içeriği değişmez. REG1, EQU ile
tanımlanmış herhangi bir GPR adresidir
Burada W ile REG1 toplanır ve sonuc W'ya atılır
W'nun eski değeri silinir ve yerine yeni değer
yazılır. REG1'in içeriği ise değişmez
Bu komutu sadece komutları anlamaya örnek olarak verdim, şimdi komutları tek tek
inceleyeceğiz ama daha kolay anlaşılması bakımından yukarıdaki listedeki sıra ile gitmeyeceğiz.
MOVLW
k (MOVe Literal into Working register)
k, literal (sabit sayı) demektir D'3', D'5', D'34', D'155', H'3A', 0xFF, B'00110001' gibi... Bu komut
da vereceğiniz herhangi bir sabit sayıyı working register'a atmaya yarıyor.
MOVWF
f (MOVe Working register into File)
Bu komut W'nun içeriğini belirteceğiniz yazmaca atıyor.
Örnek: SAYAC adında bir yazmaç tanımlayalım sonra W içine atayacağımız bir sabit sayıyı bu
yazmacın içine yerleştirelim:
SAYAC
EQU
MOVLW D'10'
MOVWF SAYAC
MOVF
0x30
; SAYAC değişkenini tanımladık
; 10 sayısını W'nun içine attık
; W'nun içeriğini SAYAC yazmacına atadık
f, d (MOVe File)
Bu komutta dikkat edilmesi gereken bir şey d'yi kullanmanın anlamsız olacağıdır. "d" yerine f
yazarsanız yine kendi içine taşımaya calışacağı için bir anlamı olmayacaktır, yani "d" yerine w
yazılmak zorundadır.
Đpucu: MOVFW komutunu MOVF komutu yerine kullanın hatta MOVF komutunu hiç
öğrenmeyin. Đki komut da belirttiğiniz bir f'yi W'ya taşımaya yarar.
ADDLW
k (ADD Literal to Working register)
W ile bir sabit sayıyı toplar ve sonucu W'ya yazar.
Örnek: SAY1 ve SAY2 yazmaçlarındaki sayıları toplayıp SAY3 yazmacına yazalım ve üzerine de
HUNRobotX - PIC Assembly Dersleri
10 ekleyelim. SAY1, SAY2'nin daha önceden tanımlandığını ve içlerine sabit sayılar atandığını
varsayalım.
MOVFW
ADDWF
ADDLW
MOVWF
SAY1
SAY2, w
D'10'
SAY3
;
;
;
;
SAY1'i W'ya attık
W ile (W'nun içinde SAY1 vardı) SAY2'yi topladık
Sabit sayı olan 10 ile W'nun içeriğini topladık
Ve sonucu SAY3 yazmacı içine attık
CLRF f (CLeaR File)
Bahsi geçen yazmacın içeriğini 0x00 yapmak için yani temizlemek için kullanılır.
CLRW (CLeaR Working register)
Working register'ın içeriğini temizlemek için kullanılır.
NOP (No OPeration)
Bu komuta gelindiğinde 1 işlem süresince hiçbir işlem yapılmaz ve bir sonraki satıra geçilir.
INCF f (INCremet File)
Bahsi geçen yazmacın içeriğini 1 arttırmak için kullanılır. Eğer yazmacın içeriği 255 ise 1
arttırdığımız zaman sonucun 256 olması gerekir, fakat yazmaçlar 8 bitlik oldukları için 256
sayısını saklayacak yerleri yoktur (B'1 0000 0000' = D'256'). O zaman sonuç ne olacak sorusunun
cevabı 0, yani 256 sayısı ile 0 sayısının arasında bir fark yoktur yazmaç olarak. Dolayısı ile
mod(256)'da işlem yapmış oluyoruz.
DECF f (DECrement File)
Bahsi geçen yazmacın içeriğini 1 azaltır. Eğer yazmaç içeriği 0 ise, önceki komutta da 256 ile 0'ın
farkı yok demiştik. Bunun sonucu olarak içeriği 0 olan bir yazmacın içeriğini 1 azaltırsak yeni
değeri 255 olur.
DECFSZ
f (DECrement File Skip if Zero)
Bahsi geçen yazmacın içeriğini 1 azaltır ve yazmacın içeriğini kontrol eder. Eğer yazmacın yeni
içeriği 0 ise bir sonraki satırı atlar, işlemez.
INCFSZ
f (INCrement File Skip if Zero)
Bahsi geçen yazmacın içeriğini 1 arttırır ve bu arttırma sonucu yeni içerik değeri 0 olursa (yani
256 olursa) sonraki 1 satırı ihmal eder ve işlemez.
Örnek: Diyelim ki benim PIC'imin bir bacağına LED (PORTA, 3), bir başka bacağına da
(PORTB, 0) düğme bağlı, benim istediğim çalışma biçimi ise şöyle: Eğer düğmeye basmıyorsam
LED yanmasın, eğer düğmeye basıyorsam LED sürekli yanıp sönsün. Fakat biliyorum ki işlemci
1 komutu 1 mikrosaniyede işliyor ve bu kadar hızlı olduğundan dolayı sürekli BCF ve BSF
2. Ders: Çalışma Mantığı ve Komutlar
komutlarını arka arkaya kullanırsam gözüm yanıp sönmeleri algılayamaz.
#DEFINE
#DEFINE
DUGME PORTB, 0
LED
PORTA, 3
BASLA
BTFSS
GOTO
BSF
BCF
GOTO
DUGME
$ - 1
LED
LED
BASLA
Yukarıdaki program sanki çalışırmış gibi durmasına rağmen PIC'in bu işlemleri 5-6
mikrosaniyede bitirecek olmasından dolayı sonuç alamayız. Dolayısı ile yakma ve söndürme
satırları arasına bir bekleme zamanı koymalıyız, yani program LED'i yaktıktan sonra biraz
beklemeli ve öyle söndürmeli, söndürdükten sonra da biraz beklemeli ve öyle yakmalı.
Đşlemcinin her komutu 1 mikrosaniyede işlediğini geçen derste görmüştük. Yukarıda da NOP
komutunun hiçbir işlem yapmadan 1 mikrosaniye işlemciyi beklettiğini biliyoruz. Ama 1
mikrosaniyelik bekleme bizim işimize yaramaz, alt alta yüzlerce NOP yazmak da kullanışlı değil.
O yüzden bir sayaç oluşturmalı ve yazacağımız komutları tekrar ettirerek (işlemciye boş boş sayı
saydırarak) zaman harcatmalıyız.
Yukarıda DECFSZ komutunu görmüştük. Mesela şimdi yazacağımız programda SAYAC diye bir
yazmaç tanımlayalım ve onun vasıtası ile gecikme yapalım.
SAYAC
#DEFINE
#DEFINE
EQU
0x1A
DUGME PORTB, 0
LED
PORTA, 3
BASLA
BTFSS DUGME
;
GOTO $ - 1
;
BSF
LED
;
MOVLW D'200'
;
MOVWF SAYAC
;
NOP
; Đşlem yapma
NOP
; Đşlem yapma
DECFSZ
SAYAC ;
;
GOTO $ - 3
;
;
BCF
LED
; SAYAC
MOVLW D'200'
;
MOVWF SAYAC
NOP
NOP
DUGME'den gelen veri 1 ise 1 satır atla
Değilse geri dön
DUGME 1 ise LED'i yak
W'ya desimal 200 sayısını yükle
W'yu SAYAC'a at. SAYAC'ın yeni değeri 200 oldu
SAYAC'ı 1 azalt, 0 ise 1 satır atla değilse alttaki
satırı işle
Eğer sayac'ın 1 azaltılmış değeri 0 değilse 3 satır
yukarı geç
0 olunca LED'i söndür
Yukarıdaki gecikme satırlarının aynısı
HUNRobotX - PIC Assembly Dersleri
DECFSZ
SAYAC
GOTO $ - 3
GOTO BASLA ; SAYAC 0 olunca BASLA satırına dön ve tekrar DUGME'yi
; kontrol et.
Gelelim diğer bir aritmetik işlem komutumuz olan SUB'a.
SUBLW
k (SUBtract W from Literal), SUBWF
write the result into destination)
f, d (SUBtract W from File then
Çıkarma işlemi yapmak için SUBLW ve SUBWF olmak üzere 2 komutumuz bulunuyor. Bu
komutlarda çıkartılan taraf hep W. Nereden çıkartılacağının cevabı ise komutta. SUBLW
komutunda herhangi bir sabit sayıdan W çıkartılıyor, SUBWF komutunda ise herhangi bir
yazmacın içeriğinden W çıkartılıyor.
PIC'te mantık işlemleri yapmak için komutlar bulunmakta ve bu komutlar bizim işimizi birçok
konuda kolaylaştırmaktadır. Mantık kapılarından ve bunların yaptığı işlemlerden temel elektrik ve
elektronik dersinde gereken bilgiler verilecek. Şimdi gelelim bu komutlara ve ne iş için nasıl
kullanıldıklarına.
Not: Burada anlatılmayan RLF ve RRF komutları ders 3'te ayrıntılı olarak anlatılacaktır.
SWAPF
f, d (SWAP File then write the result into destination)
Bahsi geçen yazmacın ilk 4 biti ile son 4 bitinin yerlerini değiştirir.
Örnek:
SWAPF REG1, f
; REG1 diye tanımlanmış olan yazmacın ilk 4 biti ile son 4
bitini yer değiştir.
PIC'te mantık kapılarından 4 tanesi bulunmaktadır. NOT (DEĞĐL, tersleme), OR (VEYA,
toplama), AND (VE, çarpma) kapıları ile XOR (ÖZELVEYA) kapısı bulunur.
COMF
f, d (COMPlement File then write the result into destination)
Belirtilen yazmacın içeriğindeki 1'leri 0, 0'ları 1 yapar. Yani yazmaç içeriğinin tersini alır. Bir
nevi NOT işlevi görür. Her bit için NOT işlemini gerçekleştirir.
Đçeriği 10001110 olan DENEME isimli bir yazmacımız olsun.
COMF DENEME, f
komutunu kullanacak olursak DENEME yazmacının tersi alınacak ve destination olarak yine
yazmaç gösterildiğinden yeni içerik 01110001 olacaktır. Eğer
COMF DENEME, w
2. Ders: Çalışma Mantığı ve Komutlar
yazsaydık yani destination olarak W'yu gösterseydik o zaman deneme isimli yazmacın içeriği
değişmeyecekti çünkü tersi alınmış olan içerik W'ya yazılacaktı.
ANDWF f, d (AND Working register and File then write the result into destination)
Belirtilen yazmaç ile W'yu mantıksal VE işlemine tutar. Hatırlayacağınız gibi VE işlemine tabi
tutulan 2 bitten birisi bile 0 ise sonuç 0 olurken eğer ikisi de 1 ise sonuç 1 oluyordu.
ANDWF
DENEME, w
Đşlemini yapacak olursak (DENEME ve W için kafadan ilk değerler belirledim.)
01110001 → DENEME yazmacının ilk içeriği
10011100 → W'nun ilk içeriği
01110001 → DENEME'nin uyguladığımız işlemden sonraki içeriği
00010000 → W'nun uyguladığımız işlemden sonraki içeriği
Đşlem yapıldıktan sonra kayıt yeri olarak W gösterildiği için sonuç W'ya atıldı. Bu işlemin amacını
şu şekilde basitçe düşünebiliriz: Bir evimiz var ve evde 8 adet lamba yanıyor. Ben bunlardan
belirlediğim birkaç tanesini söndürmek istiyorum (o an yanıyor olması veya sönük olması ile
ilgilenmiyorum). Bu lambaların yanması da DENEME yazmacının içeriğine bağlı olsun. Yani
DENEME yazmacının 0. bitinde 1 varsa 0. lamba yanıyor, 0 varsa 0. lamba sönük, aynı şey diğer
bitler için de geçerli. Eğer 3., 5. ve 0. lambaların sönüklüğünden emin olmak istiyorsam W'nun
içine 11010110 yüklerim ve DENEME yazmacı ile VE işlemine tutarım.
ANDLW
k (AND a Literal and Working register then write the result into destination)
Bu komut VE işlemini bir sabit sayı ile W arasında yapar ve sonucu W'ya yazar.
IORWF f, d (Inclusive OR Working register and File then write the result into destination)
Bu komut ise mantık işlemlerinden VEYA'yı yerine getirir. Hatırlayacağınız gibi VEYA
işleminde işleme tutulan bitlerden herhangi birisi 1 ise sonuç 1, ancak her ikisi de 0 ise sonuç 0
oluyordu. Bu komutu da odadaki lambaları yakmak için kullandığımızı düşünebiliriz.
Lambalardan yakmak istedikerimize karşılık gelen bitlerin içeriğine 1 yükleriz ve geri kalanların
içeriğine de 0 yükleriz. 1 ile VEYA işlemine tutulanlar yanar, geri kalanların konumunda
değişiklik olmaz.
Örnek:
IORWF DENEME, f
; DENEME ile W'yu VEYA işlemine tutar sonucu yine DENEME'nin
; içine atar.
01110001 → DENEME'nin ilk içeriği
HUNRobotX - PIC Assembly Dersleri
10010011 → W'nun ilk içeriği
11110011 → DENEME'nin uyguladığımız işlemden sonraki içeriği
10010011 → W'nun uyguladığımız işlemden sonraki içeriği
IORLW
k (Inclusive OR a Literal and Working register)
VEYA işlemini sabit bir sayı ile W arasında yapar.
Örnek:
IORLW
D'23'
;
;
;
;
Desimal olarak belirtilen 23 sayısı ile W'nun içeriğini
VEYA işlemine tutuyoruz. Bu işlemi kolay anlamak için
öncelikle 23 desimal sayısını binary olarak yazalım:
D'23' = B'00100011'
00100011 → 23'ün binary karşılığı
10011100 → W'nun ilk içeriği
10111111 → W'nun uyguladığımız işlemden sonraki içeriği
XORWF
f, d (XOR Working register and File then write the result into destination)
Veee işte sıra geldiii son mantık işlemimizzzz ÖZELVEYA işlemineee. Bu işlem mantık işlemleri
içinde akılda tutulması en zorudur, niye bilmiyorum aslında çok kolaydır. Bu işlem farklılığı
seven bir işlemdir. Eğer girişler birbirinden farklı olursa (zaten ne kadar farklı olabilir, 1 ve 0'dan
başka bişi yok elimizde) sonuç 1 oluyor, eğer girişler aynı ise, yani iki sayı da 0 veya 1 ise sonuç
0 oluyor. Bu komut da W ve belirtilen yazmacın içeriğini alır, ÖZELVEYA işlemine tutar. "d"
yerine w yazılmışsa sonucu W'ya, f yazılmışsa sonucu bahsi geçen yazmaca atar.
XORLW
k ( XOR a Literal and Working register)
Bir sabit sayı ile W'yu ÖZELVEYA işlemine tutar, sonucu da W'ya atar.
Bu komut pratikte çok işimize yarıyor. Mesela bir yazmacın içinde 13 sayısı olup olmadığını
merak ediyoruz. O zaman önce o yazmacın içeriğini W'ya atıp sonra W'yu 13 sabit sayısı ile
XORLW işlemine tutarız ve sonucun 0 olup olmadığına bakarız. Eğer sonuç 0 ise sayımız 13
demektir.
Đpucu: Aynı işlemi W'ya 13 sayısını yükleyip XORWF işlemini uygulayarak da yapabiliriz.
Bu komutun başka bir kullanım alanı ise durumunu değiştirmek istediğimiz bitlerledir. Mesela
PORTA, 2'ye LED bağladık ve bu LED'i yanıyorsa söndürmek, sönükse yakmak istiyoruz. Bu
durumda bu biti 1 ile ÖZELVEYA işlemine tabi tutarız. PORTA, 2'de 1 varsa aynı olduklarından
sonuc "0" olur, eğer 0 varsa farklı olduklarından sonuç "1" olur.
2. Ders: Çalışma Mantığı ve Komutlar
Örnek: W'nun içine 36 yükleyip SAYI isimli yazmaçla W'yu XOR işlemine tutalım.
MOVLW
XORWF
D'36'
SAYI, w
; W'nun içine 36 yükledik
; SAYI isimli yazmaçla W'yu XOR yaptık
Şimdi bunun sonuçlarını inceleyelim. SAYI isimli yazmacın içinde önceden B'00011011'
sayısının olduğunu varsayalım.
00011011 → SAYI'nın ilk içeriği
00110100 → W'nun ilk içeriği
00011011 → SAYI'nın uyguladığımız işlemden sonraki içeriği
00101111 → W'nun uyguladığımız işlemden sonraki içeriği
Şimdi SAYI yazmacının içeriğinin de önceden 36 olduğunu varsayalım.
00110100 → SAYI'nın ilk içeriği
00110100 → W'nun ilk içeriği
00110100 → SAYI'nın uyguladığımız işlemden sonraki içeriği
00000000 → W'nun uyguladığımız işlemden sonraki içeriği
Gördüğünüz gibi SAYI yazmacı ile W'nun içeriği aynı olduğundan sonuç 0 oldu.
Yardımcı Komutlar
PIC'te sayfaya komutları yazmaya başlamadan önce bazı yardımcı komutları kullanmamız
gerekebilir. Bunların bazılarından yukarıda bahsettik (EQU, #DEFINE ve ORG gibi). Diğerleri
ise şunlar:
list: Kullandığınız PIC çeşidini belirtmeye yarar. Kullanımı şu şekildedir:
list
p=16F84A
__CONFIG (CONFIGuration): Bu komut ile işlemcinin bazı özelliklerini ayarlarsınız. Aşağıda
komutun tam yazım şekli ve komut hakkındaki açıklamalar belirtilmiştir.
__CONFIG
_CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
_CP_OFF (Code Protect OFF): Buraya OFF yerine ON da yazabilirsiniz. Bu komut ile
işlemcinize yazdığınız kodu başkalarının okuyabilip okuyamayacağını belirlersiniz.
_WDT_OFF (Watch Dog Timer OFF): Watch Dog Timer'ın açık mı kapalı mı olacağını
belirlemenize yarar, Watch Dog Timer'ın ne olduğunu ileride göreceksiniz.
_PWRTE_ON: Đşlemcinin açılışta kendisine reset atmasına yarar, OFF veya ON olabilir.
HUNRobotX - PIC Assembly Dersleri
_XT_OSC: Devrede kullandığınız osilatör tipini belirtmenize yarar. Diğerlerinden farklı olarak 4
farklı değer alabilir: RC, XT, LP, HS.
RC: Ösilatör olarak sadece 1 direnç 1 de kapasitörden oluşturduğumuz bir devre kullandığımızı
belirtir.
XT: Devrelerimizde hep bu değeri kullanacağız. Devreye kristal + 2 kapasitör bağladığımızı
belirtmeye yarar. Bu osilatör tipi en hassas osilatör tipidir.
Bağlantılar
http://robot.ee.hacettepe.edu.tr/
http://www.microchip.com/

Benzer belgeler

aile watchdog.us

aile watchdog.us Ben de bütün bilgilerimi oradan öğrendim, yani ana kaynak orası. Dolayısı ile burada aklınıza gelip de cevabını bulamadığınız herşeyi oradan bulabilirsiniz, orada da bulamazsanız HUNRobotX birebir ...

Detaylı