PIC Assembly - PIC C PIC10/12/16 Serisi Mikrodenetçilerde RAM Banklarının Kullanımı By Konuk Yazar Posted on 23 Nisan 2017 29 min read 0 0 3,073 Paylaş ! Facebook Paylaş ! Twitter Paylaş ! Google+ Paylaş ! Reddit Paylaş ! Pinterest Paylaş ! Linkedin Paylaş ! Tumblr PIC10/12/16 Serisi Mikrodenetçilerde RAM Banklarının Kullanımı Resim1 – RAM banklarının çalışma ilkesi PIC denetleyicilerde; her biri 8-bit genişliğinde olan, Special Function Registers/Özel İşlev Yazmaçları ve General Purpose Registers/Genel Amaçlı Yazmaçların bulunduğu veri bellekleri haritalandırılmış bir yapıya sahiptir. Bu bellek haritası modelden modele değiştiğinden dolayı burada yalnızca sık kullanılan modellerden biri olan PIC16F628A modelinin veri belleği yapısından, bu bellekte verinin nasıl işlenebileceği ve yönetilebileceğinden söz edeceğim. Ancak bellek veya bank yönetimi mantığı diğer 10, 12 ve 16 modellerinin hepsinde aynıdır. Bu model üzerinde anlatılacakları kavradığınızda bank yönetimi mantığını kavramış olur; Assembly dilinde, tüm PIC10, PIC12 ve PIC16 serisinin bank yönetimini yapabilirsiniz. Şunu da belirtmek gerekir ki; kimi PIC modelleri yalnızca tek banktan oluşan bir veri belleğine sahiptir. Bu PIC modelleri için bank yönetimi yapma gereği yoktur çünkü zaten tüm yazmaçlar tek bir bank içinde konumlandırılmıştır. Bu PIC’lere örnek olarak; PIC10 serisinin bir çok modeli, PIC12F508, PIC16F54 gibi modeller verilebilir. PIC16F628A Denetleyicisinin Veri Belleği Haritasının İncelenmesi Resim2 – PIC16F628A denetçisinin veri belleği haritası Neden harita diyoruz? Çünkü bellek gerçekten fiziksel olarak haritalandırılmıştır. Biraz daha açacak olursak: Resimde görülen kimi boş, kiminde yazı olan dikdörtgen kutuların her biri 8-bitten oluşan bir yazmacı temsil eder. Yazmaç; İngilizce “register” sözcüğünün Türkçe karşılığıdır. Kimi yerlerde yazmaç yerine; kaydedici, saklayıcı ya da yazaç olarak da duyabilirsiniz ancak ben burada yazmaç olarak kullanacağım. Bu kutulardan içinde isim olanlar; Özel İşlev Yazmaçlarıdır(SFR). Alttaki içlerinde: “General Purpose Register 80 Bytes” yazan daha geniş kutular Genel Amaçlı Yazmaçlardır(GPR). Gri renkli kutular da fiziksel olarak işlenmemiş alanları temsil eder ki bu alanlara denk gelen adresler okunursa 0 olarak okunur. Bu yazmaçların her biri tıpkı birkaç sokaktan oluşan küçük bir kasabanın sokak ve binalarının haritalandırıldığı gibi haritalandırılmıştır. Resimdeki kutular arasındaki boşlukları haritalardaki sokaklar, kutuları da binalar ve evler gibi düşünebilirsiniz. Bu harita içindeki her sokak ve binanın kendine has bir adı ve adresi olacaktır. Burada bu yazmaçlardan herhangi biri ile işlem yapılacağında; bu yazmacın adres bilgisi İşlem birimine(CPU) sağlanmalıdır. Bunu uzakta bulunan bir eve bir posta göndermeye benzetebiliriz. Burada posta kaydedilecek veriyi, adres de verinin teslim edileceği adresi temsil eder. Postayı gönderebilmemiz için; posta merkezine gidecek adresi sağlamamız gerekir ve böylece verilen adres sayesinde posta biriminde çalışan bir postacı, o postayı yüzlerce ev ve binanın içinden yalnızca adresi verilen doğru yere bırakır. Bu yazmaçlarla çalışırken de aslında işlem birimi bir postahane gibi davranır ve yaptığı da aynı şeydir. Yani veriyi(postayı), bellek içinde bulunan yüzlerce yazmaçtan programcının adresini belirteceği yazmaca götürüp teslim etmektir. Buraya kadar temel veri belleği haritasını, nasıl işlediğini ve bu haritayı neden bilmemiz gerektiğini anlamış olduk. Şimdi ise biraz daha ileri gideceğiz ve bu haritadaki her bir adrese, bankları yani posta örneğimizdeki sokakları kullanarak nasıl işlem yapabileceğimizi göreceğiz: Önce şunu bilmemiz gerekir ki: PIC denetleyiciler varsayılan olarak Bank0’dan işlem yapmaya başlar. Bank0’ı burada sokağımızın adı olarak düşünürsek; bu bankta/sokakta olmamız demek; bu sokağa kapısı bulunan bütün evlere erişebilmemiz demektir. Diğer bir deyişle elimizdeki posta(veri) bu sokaktaki adreslerden birine gönderilmişse ilgili postayı(veriyi) adresi verilmiş olan eve ya da binaya bırakabiliriz demektir. Ancak postalardan hiç biri bu sokaktaki adreslere ait değilse, diyelim ki Bank1 sokağında bulunan 9A numaralı binada olan EEDATA kişisine ait olsun. Bizim de Bank0 sokağından çıkıp postayı doğru adrese verebilmek için Bank1 sokağına girmemiz gerekir ki; 9A numaralı binaya erişebilelim. Bank1’e geçme işlemini BANKSEL direktifi ile yapabiliriz. Bunun için şu adımlar izlenmelidir: Bank1’de değilsek Bank1’e geçilir. İstenen veri hazırlanır. Son olarak veri EEDATA yazmacına teslim edilir. Bunu bir assembly kod örneğini kullanarak inceleyelim: BANKSEL EEDATA ;1.Adım: Bu direktifle assembler’a EEDATA’nın konumlandırılmış olduğu banka geçmesini söylüyoruz. MOVLW d’57’ ;2.Adım: Bu komut gönderilecek veriyi işlem birimine bildirir. Bu veri bizim postamızdır. MOVWF EEDATA ;3.Adım: Bu komut da postanın yani verinin gideceği adresi işlem birimine bildirir. Bilgi: Kod içinde kullanılan BANKSEL, bir derleyici komutudur Assembly komutu değil. Yukarıdaki kodlamada bir derleyici komutu olan BANKSEL kullanılmıştır. Bu programlama yaparken programcıya zaman kazandırır. Derleyici komutu olan BANKSEL kullanılmadan yapılmak istenirse Assembly kodu şu şekilde olur: BSF STATUS, RP0 ;1.Adım: STATUS yazmacının RP0 bitini 1 yapınca BANK1 sokağına geçiyoruz. MOVLW d’57’ ;2.Adım: Bu komut gönderilecek veriyi işlem birimine bildirir. MOVWF EEDATA ;3.Adım: Bu komut da verinin gideceği adresi işlem birimine bildirir. EEDATA veri belleğinde Bank1 sokağında, 9A adresinde konumlandırılmıştır. Ama burada işlem birimi otomatik olarak sokak/bank değiştirme ya da seçme yeteneğine sahip değildir. Bu yüzden programcının, 9A(EEDATA) adresinin tam olarak hangi sokakta olduğunu da işlem birimine bildirmesi gerekir. İşte bu işleme Assembly programlamada “Bank Seçme” işlemi denir. Nedir bu işlem?: İşlem birimine postayı hangi sokaktaki hangi adrese göndereceğini bildirme işlemidir. Şimdi biraz daha ileri gidiyoruz ve kasabalar arası nasıl posta göndereceğimizi betimliyoruz. Bunu bilmek size dolaylı(indirect) adresleme ile veri yazma işlemlerinde çok yarar sağlar: 8-bit mikrodenetleyicilerde; tek bir adres seçici yazmaçla yalnızca 256 adres konumu indekslenebilir. Yani heksadesimal olarak 00’dan FF ‘ye kadar indeksleme yapılabilir. Bu sınır veri belleğinde bir sayfayı oluşturur. Bu şu demektir: 00’dan FF’ye kadar olan bölge bir kasaba içinde, 100’dan 1FF’ye kadar olan bölge de başka bir kasaba içinde yer almaktadır. Bu 00 – FF aralığında adresli ilk kasabanın adı 1.SAYFA kasabası, 100 – 1FF adresli bögenin kasabasının adı da 2.SAYFA kasabasıdır. Şimdi verilen bellek haritası resmine bir bakınız. BANK0 sokağının ilk adresi 00’dan başlıyor, ve BANK1 sokağının son adresi FF adresinde bitiyor. Bu demek oluyor ki; BANK0 ve BANK1 sokaklarındaki adreslerde bulunanlar 1.SAYFA kasabasına aittir. Aynı şekilde BANK2 sokağının ilk adresi100’dan başlıyor, BANK3 sokağının son adresi 1FF numarasında bitiyor. Böylece BANK2 ve BANK3 sokaklarında bulunan adresler de 2.SAYFA kasabasında yer almış oluyor. Bu durumda bizim işlem birimine gönderdiğimiz verinin 1.SAYFA kasabasındaki adrese mi yoksa 2.SAYFA kasabasındaki adreslere mi gideceği bilgisini de vermemiz gerekiyor ki; işlem birimi postayı(veriyi) doğru kasabada konumlanmış olan adrese teslim etsin. PIC denetçileri varsayılan olarak 1.SAYFA’da çalışacak şekilde üretilmişlerdir. Bu durumu da bir Assembly kod örneğiyle inceleyelim: Diyelim ki BANK2’nin 120h numaralı adresinden itibaren başlayıp 14Fh adresine kadar sıralı 48 tane 8-bit veri yazdırma işlemini dolaylı adresleme kullanarak gerçekleştireceğiz. Bunun için şu adımları izleyeceğiz: Bilgi: Denetçi varsayılan olarak 1.SAYFA’da bulunur. Denetçi 1.SAYFA’da bulunduğu için önce 2.SAYFA’ya geçilir. Veri yazılmaya başlanacak ilk adres FSR (File Select Register/Dosya Seçme Yazmacı) yazmacına yüklenir. Burada ilk adresimiz 120h olacak nitekim bu adresi 0x20 olarak FSR yazmacına yükleyeceğiz. Ardından yazdırılacak veri bir gölge yazmaç olan INDF yazmacına alınır. FSR yazmacının değeri 1 artırılır. Değeri 1 artırdığımızda FSR = 0x21 olacak yani bir sonraki adreste bulunan dosyayı seçecek. İşlem 48 tane dosyaya veri yazıldı mı? Hayır ise 3. Adıma dallan Evet ise bitir. Şimdi bunu örnek bir assembly kodunu yazarak görelim. Buradaki kodlardan bir şey anlamasanız da dert etmeyin çünkü kodun içeriği dolaylı adresleme kullanarak veri yazdırma gibi başlıca bir konu olan ayrı bir konu da içeriyor. Burada odaklanmanız gereken sayfalar arası geçişin nasıl yapıldığı. MOVLW .48 ;Hazırlık: Bu yazma işleminin tekrar sayısıdır. MOVWF SAYAC ;Hazırlık: Tekrar sayısını bir SAYAC dosyasına yükledik. PAGESEL 0x120 ;1.Adım: PAGESEL direktifini kullanarak assembler’a 2.SAYFA kasabasına gitmesini söylüyoruz. Çünkü hiç bir işlem yapılmamışsa denetleyici varsayılan olarak 1.SAYFA’da bulunur. MOVLW 0X20 ;2.Adım: Gönderilecek ilk adres 120h. MOVWF FSR ;2. Adım: Gönderilecek ilk adresi FSR yazmacına yükle. BANK2_YAZ ;3.Adım: Yazma işlemi burada başlıyor. MOVLW YAZILACAK_VERI ;3.Adım: Gönderilecek veriyi(postayı) al. MOVWF INDF ;3.Adım: Ve veri(posta) istenen kasabadaki istenen adrese teslim edilmiş oluyor, bu kadar basit. INCF FSR, F ;4.Adım: FSR yazmacını sıradaki dosya için 1 artır. DECFSZ SAYAC, F ;5.Adım: 48 dosyaya veri yazıldı mı? GOTO BANK2_YAZ ;6.Adım: Hayır, öyleyse 3.Adıma dallan. GOTO BITIR ;7.Adım: Evet, öyleyse bitirme işlemlerine git Bilgi: Kod içinde kullanılan PAGESEL, bir derleyici komutudur Assembly komutu değil. Yukarıdaki kodlamada bir derleyici komutu olan PAGESEL kullanılmıştır. Bu programlama yaparken programcıya zaman kazandırır. Aynı derleyici komutu olan PAGESEL kullanılmadan yapılmak istenirse Assembly kodu şu şekilde olur: BSF STATUS, IRP ;Önce 2.sayfaya geçmek için IRP biti 1 yapılır. BSF STATUS, RP1 ;Burada RP1 biti 1 yapılır BCF STATUS, RP0 ;Burada da RP0 biti 0 yapılır böylece BANK2 ;sokağına geçilmiş olur. MOVLW d’100’ ;Veri işlem birimine bildirilir. MOVWF SAYAC ;İşlem birimi de veriyi belirtilen adrese ;postalar. Bilgi: Sayfa seçimi işlemi; STATUS yazmacı içindeki 7. bit olan IRP biti 1 yapılarak da gerçekleştirilebilir. (Ancak IRP bitiyle sayfa değiştirme işi daha çok dolaylı adresleme kullanarak sıralı yazma ve silme işlemleri yapılırken kullanılır.) Ayrıca programa ilk başlarken, programın doğru sayfada olduğundan emin olmak için de kullanılabilir. Aşağıda bunun kod örneği veriliyor: ORG 0x00 ;00h adresine köklen PAGESEL GIRIS ;GIRIS programının olduğu sayfayı seç GOTO GIRIS ;GIRIS programına git Bunlar dışında bank seçim işlemleri STATUS yazmacının RP0 ve RP1 bitlerini kullanarak yapılır. Aşağıda RP0 ve RP1 bitleri kullanılarak hangi bankların seçilebileceği gisterilmiştir. Aşağıda STATUS yazmacı görülüyor. Peki bank seçmenin STATUS yazmacının IRP, RP1 ve RP0 bitleriyle ne ilgisi var diye düşünenler olabilir. Şunu diyebilirim ki; doğrudan doğruya ilgisi var. Çünkü bankların denetim yolları bu bitler üzerinden geçiyor. Bu yollar demultiplexer’lere yani kodçözücü/seçici devrelerine bağlanır. Dijital/Sayısal Elektronik derslerine iyi çalışanlar bu devreleri iyi bilirler ;)) . İhtimal gömülü olarak 74LS155/156 gibi bir 2’den 4’e seçici devresi kullanılmıştır. 74LS155/156 tümdevresinin (entegre) iç yapısını merak ederseniz aşağıdaki bağlantıdan veribetini (datasheet) inceleyebilirsiniz (İngilizce). Bu tümdevrenin içinde 2 tane 2’den 4’e kod çözücü vardır. >>>74LS155/156 Veribeti<<< RP0 ve RP1 bitleri bu seçicinin girişlerine, banklar da bu seçicinin çıkışlarına bağlıdır. Bu yapıyı yukarıdaki kasaba-sokak-postacı örneğine pekiştirdiğimizde bu bitler o kasaba ve sokaklara geçişi denetleyen birer bariyer gibidir. Bu bariyerleri gerektiği gibi açıp kapatarak ancak üzerinden istediğimiz sokağın ya da kasabanın yoluna girebiliriz. Bunu daha iyi anlayabilmek için aşağıdaki hazırlamış olduğum temsili blok diyagramı gif resmini izleyelim. Bu blok diyagramı tahmini olarak hazırladım, çipin içinde bağlantı ve yollar tam böyle olmayabilir ancak çalışma biçimi tam olarak böyle. Şimdi PIC16F628A tümdevresinin veribetinde(datasheet) verilmiş olan bank seçim tablosuna yeniden bakalım: Görüldüğü gibi tam olarak bank seçim tablosundaki değerlerle bire bir çalışıyor. Peki verileri yazarken doğru bankı seçmezsek ne olur? Bu durumda istenmeyen veri teslimi gerçekleşir ve veri umulmayan yerlere yazılır. Diğer bir deyişle: Posta birimine doğru adres verilmediği için postacı postayı, kuzeninize değil, kuzeninizin oturduğu yerin bir yan sokağında oturan bir kişiye teslim edecektir. Böylece kuzeniniz sizin gönderdiğiniz postayı alamayacaktır. Örneğin; Bank1 içinde bulunan A0h adresine atadığımız bir değişken olan TOPLAM değişkenine işlem sonuç verilerini yazdırmak istiyoruz ve o andaki konumumuz Bank0. Eğer veri yazma işleminden önce Bank1’e geçmezsek, işlem birimi bulunduğu banktaki(Bank0) karşılık gelen adrese veriyi yazacaktır. A0h adresinin Bank0 içindeki karşılık gelen adresi 20h’dir. Dolayısıyla veriler bu adrese yazılır. Sonra bu işlem sonucunu bu değişkenden okumak için Bank1’e geçip A0 adresini okuduğumuzda ise koca bir 0 değeri elde ederiz çünkü işlem sonucu Bank0’daki 20h adresine yazılmıştır. SFR(Özel İşlev Yazmaçları) yapılandırmalarını yaparken doğru banka geçmezsek ne olur? Bu program açısından daha ölümcül bir hata olacaktır çünkü denetleyici; işlev ayarları doğru denetim yazmaçları üzerinde yapılmadığı için, denetim yazmaçlarının reset sonrası durumlarını okuyacaktır. Bunu şöyle bir örnekle pekiştirebiliriz: Diyelim ki Port giriş – çıkışları yapılandırılıyor. Portb çıkış olarak ayarlanmak isteniyor. Bunun için Bank1’ e geçip TRISB yazmacına 0x00 değeri yüklememiz gerekir. Ancak Bank1’e geçilmeden TRISB yazmacına değer yüklenmeye kalkılırsa, Bank0’da olduğumuzu düşünürsek bu değer aslında PORTB’ye yüklenmiş olacak ve TRISB varsayılan olarak reset sonrası tüm port bacaklarını giriş olarak yapılandırdığından, PORTB hep giriş olarak kalacaktır. Dolayısıyla PORTB bacaklarına bağlı hiç bir şey denetlenemeyecektir. Örneğin PORTB’nin 3. bacağına bağlı bir led yakılıp söndürülemeyecektir. Sonuç olarak Assembly ile programlama yapılmak istenirse doğru bank seçimini yapmak çok önemlidir. Doğru bank seçimi yapılmadığı durumda yazılan program istendiği gibi işlemeyecek ve sürekli hatalı sonuçlar üretecektir. Bu yüzden doğru bankın seçildiğinden emin olmak programcının sorumluluğundadır.