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
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 ...