Pic ASM uzun veya page aşan kod yazımı mini rehberi.

Başlatan RaMu, 09 Nisan 2015, 23:00:30

RaMu

   Öncelikle şunu söyleyelim
pic program hafızasına yazılmış olan program nasıl çalışır?
Program hafızası 0 1 2 ... şeklinde adreslere sahiptir
herbir asm komutu bir adresde bulunmaktadır,
picde Program Counter PC denen bir dahili sayıcı vardır
herbir komutu işleyince PC kendiliğinden bir artar,
bu sayede program hafızasındaki herbir komut sırayla işlenmiş olur.

Aslında sırayla işlenmemesi gereken birçok durum vardır,
bunun için goto ve call yardımcı olarakda return retlw ve retfie
komutları vardır.
Goto deyip karşısına bir adres gösterdiğimizde
PC o adresi gösterir ve program o satırdaki komuta zıplar.
Call deyip bir adres gösterdiğimizde
PC o adresi gösterir ve program o satırdaki komuta zıplar
goto dan farklı olarak call da
çağrıldığı adresi stack denen picde ilgili yazmaça kaydeder
ve
return veya retlw (ayrıca retfie) dediğimiz anda bu adresi PC ye yükler
ve çağrıldığı satırın hemen altındaki satıra döner.


Örnek:
Komut1
komut2
goto   adres1
.komut...
.komut  ..olabilir
.komut..
adres1
komut3
komut4
.
.
.


Burada komut2 den sonra adres1 e git dendiği için
komut3 işlenir arada komutlar varsa işlenmez.



Örnek:
Komut1
komut2
call   adres1
.komut...
.komut  ..olabilir
.komut..
SON GOTO SON


adres1
komut3
komut4
return
.
.
.


Burada komut2 den sonra adres1 çağrılıyor
bu esnada PC kaç ise stack a kaydedilir
PC ye adres1 in değeri yüklenir ve adres in olduğu satıra zıplanır,
komut3 komut4 işlenir ve return dendiği için
PC ye stack a kaydedilmiş olan değer yüklenir ve
tekrar call adres1 denilen satırın hemen altına dönülmüş olur,
komut ... işlenir
SON satırı kendini işaret ettiğinden program
enerji kesilenen kadar bu satırda takılı kalır.



Şimdi call ve goto nun sınırlarına değinelim:

Aşağıda datasheet ten alınan fotoda görüldüğü gibi
16f877 nin program hafızası 4 sayfadan oluşmakta
Page0 page1 page2 page3




CALL ve GOTO komutları sadece 11 bit edresleme yapabilmekte
11 bit en büyük sayı 0b 111 1111 1111 yani decimal 2047 dir
yani 0 dan 2047 ye toplam 2048 adres yani 2k (kilobayt)
adresi gösterebilir.

Bu nedenle picin 8k lık hafızası 2k lık 4 sayfaya bölünmüştür.

Peki bu sayfalara nasıl erişeceğiz?

Bunun için PCLATH denen bir register kullanılır,
fotodanda görüldüğü gibi



PC aslında PCL ve PCH olarak low ve high byte şeklinde iki kısımdır,
PC nin 11 biti (0 dan 10 a)direk goto veya call ile yazılırken
11 ve 12 bitleri (soldan sağa sayarsak 12. ve 13. bit)
ise PCLATH ın 4 ve 3 bitleri ile yazılır.

Misal PC = 0b 000 0000 0000 olsun
PCLATH,3 = 1
PCLATH,4 = 1 yapılırsa
      PC = 0b 110 0000 0000 olur.


PCLATH aslında PC nin üst 5 bitini tutmaktadır,
ama sadece PCLATH<3,4> kullanmak yeterli
çünkü gördüğümüz gibi goto ve call diğer 11 biti adresleyebiliyor.
(PCLATH ın tüm 5 bitini kullanmak gereken uygulamalarda bulunmaktadır
PC manipulasyonu gereken tablo uygulamaları vs.)


PCLATH registerına tüm banklardan erişilebilir



Şimdi bir kod yazalım ve
kodumuzun ana kısmı sayfa 0 da olsun
sayfa1 de bir alt programımız olsun
sayfa2 de başka bir alt programımız olsun.

Sayfa0 da iken bu alt programları çağırıp kullanalım.
Tırnak işaretleri satırları arasında kalanlar program örneğidir
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""Örnek başlangıcı
list	 p=16f877a
#include "p16f877a.inc"
_CONFIG	EQU  H'2007'

CBLOCK 20h
;değişkenler
ENDC


ORG 0
GOTO KURULUM



ORG	0x04
; Interrupt kesme rutini   ;sonraki örnekte değinilecek
retfie


KURULUM
banksel	TRISA
;port giriş çıkış atamaları
baksel  PORTA
;clrf PORTA vs. gibi başlangıç kurulumları
;analog digital comparator spi i2c vs. ayarları


BASLA   ;ana programımızın başlangıcı
.
.
.
.
..komutlar
.
.
.

PAGESEL sayfa1_prog      ;sayfa1_progun bulunduğu sayfayı seç (PCLATH ayarlanır)
CALL    sayfa1_prog
PAGESEL &                ;şuan bulunduğun sayfayı seç, normale dön
.
..komutlar
.

PAGESEL sayfa2_prog      ;sayfa2_progun bulunduğu sayfayı seç (PCLATH ayarlanır)
CALL    sayfa2_prog
PAGESEL &                ;şuan bulunduğun sayfayı seç, normale dön

.
..komutlar
.

goto BASLA



;***********************ALTPROGRAMLAR

;-------------------------------------
ORG 0x0800    ;sayfa1 başlangıc adresi
Sayfa1_prog
.
..komutlar
.
return
;-------------------------------------



;-------------------------------------
ORG 0x1000    ;sayfa2 başlangıc adresi
Sayfa2_prog
.
..komutlar
.
return
;-------------------------------------


END


""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""Örnek SONU



Evet aslında burada PCLATH kullanmamış gibi gözükebilir
ama kullandık,
pagesel bir derleyici komutudur asm de böyle bir komut yoktur,
aslında bizim yerimize
PCLATH<4,3> bitlerini ayarlar
meraklıları disassmbly listing den bakıp görebilirler.


Şimdi bu program eğer kesmede kullansaydı ne olurdu?
Kesmeye girildiğinde başka sayfada olunabilir
bu nedenle kesme rutininde PCLATH yedeklenmeli ve
kesmeden çıkarken tekrar yüklenmelidir.

Örnek bir kesme rutini şöyle olmalıdır,
(yedeklenmesi gereken her şeyin yedeklendiği tam kesme örneği)




ORG	0x04
Interrupt:
movwf w_temp	;W yi yedekle
		;önce W yedeklenmeliki sonraki aşamalarda W yi kullanabilelim
swapf STATUS,w 	;SWAP kullanılır çünkü MOVF gibi STATUS registerının değerlerini değiştirmez 
clrf STATUS	;bank0 ı işaret etmesini ve tüm bayraklarını sıfırlamasını sağladık
movwf status_temp;STATUS u yedekledik
movf PCLATH,w	;PClath ı yedekliyoruz
movwf pclath_temp
clrf PCLATH	;KESME rutinini 0. sayfaya yazdık PCLATH 0. sayfayı işaret ediyor oldu
;bcf status,irp	;CLRF STATUS satırı kullanılmazsa bu satır aktif edilmeli
movf FSR,w      ;FSR yi yedekliyoruz
movwf fsr_temp
;----------------------KESMEDE yapılması gereken işlemler burada yapılır-------------------

pagesel baska_sayfadaki_altprogram    ;eğer kesme başka sayfadaki altprogramı çağıracaksa
call	baska_sayfadaki_altprogram
pagesel $

KesmeDon:
;-----------------------KESMEDE yapılması gereken kullanıcı işleri bitti--------------------
movf fsr_temp,w      ;fsr yi geri yükle
movwf FSR
movf pclath_temp,w    ;pclath ı geri yükle
movwf PCLATH           
swapf status_temp,w   ;status u geri yükle
movwf STATUS 
swapf w_temp          ;W registerını geri yğkle
swapf w_temp,w
;********************

    RETFIE             ;kesmeden geri dön






Kafa karışıklığı olmasın diye bir açıklama yapayım
PCLATH ı değiştiriyorum ama o esnada program hemen
değiştirdiğim adrese zıplamaz mı
sonuçta PC nin üst 5 bitini değiştirmiş olmuyor muyum?
Diye bir soru sorulabilir,
tabiki PCLATH ı değiştirir değiştirmez
böyle birşey olacağını düşünmek normaldir ama böyle olmaz
çünkü PCLATH a yazılan bu değer yada değişim
ancak goto veya call kullanılması ile etkin olur.

09.04.2015
RaMu || uCanEL

Birde şu sayfada karşılaşılan problem ve çözümü var.
https://www.picproje.org/index.php/topic,58617.msg453033.html#msg453033
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html