16f84a pclath öğrenmek istiyorum

Başlatan mustafaaxu, 20 Nisan 2009, 18:34:23

mustafaaxu

selam değerli üstatlarım benim sorunum16F84A ile  tablodan 255 den sonra değer alamıyorum araştırdım  sarun pclath  kullanamadığımdan kaynaklanıyor  araştırdım ama  konuyu anlayamadım lütfen bana yardımcı olurmusunuz    şimdiden teşekkür ederim
örnek:
cound
incf birler
btfss portb.4
goto cound

birler dosyası 255 olunca tablodan değer almıyor
MOVFW   BİRLER
CALL    TABLO
MOVWF   PORTB

bigbey

ilgili komut PCL register'ine etki etmektedir. register 8 bit olması nedeniyle ondalık sayı olarak 255'e kadar adreslenebilir.
bunun çözümü için
ORG    0x00     başlangıc adresi

TABLO1    
;255'inci satıra kadar tablo oluşturabilirsin.

ORG       0x100
TABLO2
; 2'inci 255 satırlık alan kullanabilirsin.

ORG       0x200
TABLO3
; 3'üncü 255 satırlık alan kullanabilirsin.

ORG       0x300
TABLO4
; 4'üncü 255 satırlık alan kullanabilirsin.



Not TABLO1 programda hangi satırdan başlıyor ise 255 - (başlangıç satırı) = kadar veri yazabilirsin
TA6R

Tagli

Aslında tablo 256'lık alandan taşabilir, yani daha büyük olabilir. Yani tablonun kafa kısmı (ADDWF PCL,F ve öncesindeki komutlar) haricinde FF ile biten bir adresten 00 ile biten bir adrese taşmasında sıkıntı yoktur, ancak bu durumda fazladan birkaç satır kod yazmak gerekir. Öncelikle taşma olup olmadığı kontrol edilmelidir. ADDWF PCL,W denilerek toplama işlemi yapılır ancak PC güncellenmez (tabi öncelikle atlama değerinin bir yerde yedeği olduğunu varsayıyorum). Onun yerine STATUS,C'ye bakılarak taşma olup olmadığı kontrol edilir. Eğer taşma varsa önce PCLATH 1 arttırılır, sonra da normalde eklenmesi gereken değer ADDWF PCL,F ile PC'a eklenerek atlama yapılır.

Tabloyu 256'dan büyük yapmak için toplanacak değerin de iki register'da saklanması gerekir. Tablonun kafa kısmının PCLATH değeri ile PCL register'ları 2 byte'lık bir adres değeri gibi düşünülür ve uygun şekilde toplama işlemi yapılır, ancak PCL hemen güncellenmez. Öncelikle sonucun büyük byte'ı PCLATH'a yazılır, sonra PCL'ye sonucun küçük byte'ı yazılarak atlama yapılır.

Dönüşte PCLATH için bir ayara gerek yoktur ancak döndükten sonra PCLATH eski haline getirilmezse sonraki GOTO ve CALL komutlarında sorun çıkacaktır.
Gökçe Tağlıoğlu

mustafaaxu

sayın taglı ilginiz için teşekkür ederim pclath ile anlattığınız şekilde bazı yazılımlarda görmüştüm ama 255 üzerine çıkmadığım için konuyu öğrenemedim sayın hocam cok kısa olarak anlatıgınız konuyu asm olarak ekleyebilirmisiniz çok tesekkür ederim hoşçakalın

Tagli

Konuyu biraz daha açayım. İşin temelini anlatmak açısından 14 bitlik komutlara sahip 16 (10 ve 12 için de geçerli) serisi PIC'lere göre durumu anlatacağım. Zira 18 serisi (ve sonrası) PIC'lerde durum biraz daha farklı.

Bilindiği üzere PIC'in program hafızasında her alanın bir adres değeri vardır. Bu değer genelde 16'lık tabanda ifade edilir. 16 serisi PIC'lerde program akışı içinde, programın o anda nerde olduğunu tutan bir sayaç vardır ki buna Program Counter (PC) denir. PC 13 bitlik bir sayıdır, yani 8192 alanı adresleyebilir.

16 serisi PIC'lerin program alanları 14 bitliktir ve her komut 1 alan kaplar. GOTO ve CALL komutları başka bir program alanına atlamayı gerektirdiğinden içlerinde 13 bitlik adres değerini bulundurmaları gerekir. Ama sorun şudur ki zaten 14 bitlik olan kumutların içine, komutun ne olduğunu tanımlayacak birkaç bit gerektiğini de düşünürsek 13 bitlik bir adresi sığdırmak mümkün değildir. O yüzden komutlarda adresin sadece küçük 11 bitine yer verilir. GOTO ve CALL komutu çağrıldığında diğer 2 bit PCLATH register'ındaki değerlerden alınarak atlama yapılır.

PC'ın düşük 8 biti RAM alanında adreslenmiştir, yani kullanıcı tarafından doğrudan ulaşılabilir. Bu alanda değişiklik yapıldığında atlama adresinin geriye kalan 5 biti PCLATH'den gelir.

Önce bir RETLW tablosunun normal yapısını inceleyelim. "SIRA" değişkeni tabloda gitmek istediğimiz yerin indeksi olsun ve tablo çağrılmadan bu değişkenin (register'ın) doldurulduğunu varsayalım.
ORG 100 ;Örnek adres değeri
TABLO
MOVF SIRA,W ;SIRA'daki değer W'ye alındı
ADDWF PCL,F ;PC değiştirilerek atlama yapılıyor
RETLW .....
RETLW .....

Burda CALL TABLO ile tabloya gidilmeden önce genelde "pageselw TABLO" yazılarak assembler'ın PCLATH'ı TABLO'nun adresine göre ayarlaması sağlanır. Tablonun başlangıç adresi, bu iki satırlık kafa koduyla mümkün olan en geniş alana sahip olmak için genelde sonu 00 ile biten bir adrese alanır. Çünkü tablonun içinde adres değerlerinde mesela 2FF'den 300'e geçme varsa burda sorun çıkmaktadır. Bunun sebebi de bu geçiş sırasında PC'ın 8. bitinin değişmesidir, yani PCLATH'ın en küçük biti. ADDWF PCL,F PCLATH'a müdahele etmez.

Şimdi de böyle bir taşmaya karşı nasıl önlem alınacağını görelim. Burda tablo yine 256'dan büyük değil, ama hafızada bulunduğu bölgede mesela 00FF'den 0100'e taşma olmuş.
TABLO
MOVF SIRA,W ;SIRA'daki değer W'ye alındı
ADDWF PCL,W ;Test amaçlı toplama işlemi yapılıyor
BTFSC STATUS,C ;Taşma olmuş mu?
INCF PCLATH,F ;Taşma varsa PCLATH 1 arttırılacak
MOVF SIRA,W ;SIRA'daki değer tekrardan W'ye alındı
ADDWF PCL,F ;PC değiştirilerek atlama yapılıyor.
RETLW ....
RETLW ....


Bu arada, daha önce bahsetmeyi unutmuşum, derlediğin (daha doğrusu assemble ettiğin) kodun hafızada nereye düştüğünü MPLAB'de View -> Program Memory seçeneğine tıklayarak görebilirsin. Bunu yapmak için önce kodu derlemen gerekir.

Şimdi de tablonun 256'dan büyük olduğu durumu ele alalım. Burda 2 byte'a ihtiyacımız var. Küçük byte'ı SIRA0, büyük byte'ı SIRA1 ile ifade edelim.
TABLO
MOVF SIRA0,W ;Küçük byte W'ye alındı
ADDWF PCL,W ;Test amaçlı toplama işlemi yapılıyor
BTFSC STATUS,C ;Taşma olmuş mu?
INCF PCLATH,F ;Taşma varsa PCLATH 1 arttırılacak
MOVF SIRA1,W ;Büyük byte W'ye alındı
ADDWF PCLATH,F ;PCLATH büyük byte ile toplanarak güncellendi
MOVF SIRA0,W ;Küçük byte W'ye alındı
ADDWF PCL,F ;PC değiştirilerek atlama yapılıyor.
RETLW ....
RETLW ....


Daha önce de belirttiğim gibi, TABLO'ya CALL ile gidilmeden önce PCLATH'ın uygun şekilde ayarlanması ("pageselw TABLO" yazılırsa MPLAB bu işi yapar) ve kafa kısmı dediğim, yani RETLW'lerden önceki bölümün xxFF'den xx00'a taşan bir adreste bulunmaması gerekiyor. Ayrıca GOTO tabloları için yukarıda bahsettiğim yöntemler geçerli değil, çünkü GOTO'ların hedeflerinin GOTO ile aynı page'de (2048'lik hafıza alanı) olması gerekir. Bu şart sağlanırsa ancak yukarda bahsettiğim kodlar GOTO tabloları için kullanılabilir. Bu arada, pageselw'nin aslında bir MOVLW - MOVWF ikilisi olduğu kullanıldığında W'deki mevcut değeri bozacağı unutulmamalı.

Umarım yazdıklarım yeterince açıklayıcı olmuştur. Bir hata yaptıysam affola.
Gökçe Tağlıoğlu

mustafaaxu

sayın taglı hocam tekkür ederim yazdıklarını iyice anlayıp takıldığım yerleri tekrar soracağım ben yeni başladım yaş 50 biraz ağır oluyor kusura bakma tesekkürler.....73

mustafaaxu

sayın tagli hocam
burada yapmak istediğimi anlatayım sana kolaylık olsun
INCF  TEMP dasyasını bir artırıyoruz ve  kapasiteyi kontrol ediyoruz
doluysa temp in iceriğini W yüklüyoruz W yi tekrar HEXLSB yüklüyoruz
hexlsb dekadeye cevirip displeyde gösteriyoruz işlem şöyle

hexlsb 100 çikarıp kontrol ediyoruz 100 den fazla ise yüzlere 1 ekliyoruz
hexlsb dende  100 çikarıyoruz kalanı tekrar kontrol ediyoruz
onlara gecip aynı işlemleri tekrar ediyoruz işlem bitince
yüzler .. onlar.. ve birler  içindeki değerleri displeye gönderiyoruz
hocam mümkünse
aşağıda asm ye  pclath eklesen sevinirim teşekkür ederim
;--- deneme 255 sonra 256 gelmiyor---------
COUNT
	INCF	TEMP, F        ;TEMPA SAYACINI 1 ARTTIR
	BTFSS	PORTA, 4       ;KONDANSATÖR DOLDU MU?
	GOTO	COUNT
;---------------------------------------------------------
	MOVF 	TEMP,W		;dolduysa  temp W yükle 
	MOVWF	HEXLSB		;W yi hexlsb yükle
;---------------------------------------------------------

YÜZLER_KONT
	MOVLW	0X64			;W = 0X64 (100)
	SUBWF	HEXLSB, W		;HEXLSB'DEN 100 ÇIKART.
	BTFSS	STATUS, C		;SONUÇ >= 100 DEN BÜYÜKMÜ
	GOTO	ONLAR_KONT		;HAYIR İSE ONLAR KONTROL ET.
	INCF	YÜZLER, F		;EVET İSE YÜZLER BİR ARTIR.
	MOVLW	0X64			;W = 0X64 (100)
	SUBWF	HEXLSB, F		;HEXLSB'DEN 100 ÇIKART.
	GOTO	YÜZLER_KONT		;ONLAR'I YENİDEN KONTROL ET.

ONLAR_KONT
	MOVLW	0X0A			;W = 0X0A (10)
	SUBWF	HEXLSB, W		;HEXLSB'DEN 10 ÇIKART.
	BTFSS	STATUS, C		;SONUÇ >= 10 MU?
	GOTO	BİRLER_KONT		;HAYIR İSE BİRLERİ KONTROL ET.
	INCF	ONLAR, F		;EVET İSE ONLARI BİR ARTIR.
	MOVLW	0X0A			;W = 0X0A (10)
	SUBWF	HEXLSB, F		;HEXLSB'DEN 10 ÇIKART.
	GOTO	YÜZLER_KONT		;ONLAR'I YENİDEN KONTROL ET.
BİRLER_KONT
	MOVF	HEXLSB, W		;W = HEXLSB
	MOVWF	BİRLER			;BİRLER = W, 
					
;---burada display secimi yapıyoruz--------------------
;---ve displeye yazdırmak için tobloya gidiyoruz
;----TABLO--------------------------------------

TABLO
	ADDWF	PCL,F
	RETLW b'11000000' ; 0
	RETLW b'11111001' ; 1
	RETLW b'10100100' ; 2
	RETLW b'10110000' ; 3
	RETLW b'10011001' ; 4
	RETLW b'10010010' ; 5
	RETLW b'10000010' ; 6
	RETLW b'11111000' ; 7
	RETLW b'10000000' ; 8
	RETLW b'10010000' ; 9
	
;-----------------------------------

Tagli

16F84'ün hafızası zaten 1024 word olduğundan GOTO ve CALL'larla ilgili bir sorun olmayacaktır. Sanırım şu şekilde yazman yeterli olur:
TABLO
pageselw $ ;PCLATH bulunulan yere göre ayarlanıyor
ADDWF PCL,F 
RETLW...
RETLW...


Tablo zaten küçük. Bunun için FF'ten  00'a taşma kontrolü yapmaktansa tabloyu uygun şekilde yerleştirmek çok daha kolay olacaktır. Programının hafızaya nasıl yerleştiğini bilemem. Bunu anlamak için daha önce de bahsettiğim üzere MPLAB'den Program Memory bölümüne bakmalısın. O zaman bir taşma olup olmadığını görebilirsin. Bu taşmalar kabaca 256 satırda bir olur (aslında tam olarak 256 komutta bir olur). Yani bu tabloyu alıp programın başlarında bir yere koyarsan muhtemelen pageselw $ yazmana bile gerek kalmaz.
Gökçe Tağlıoğlu

mustafaaxu

sayın taglı hocam tekkür ederim yazdıklarını toparlamaya çalışıyorum
bildiginiz gibi proğramı yazmak ayrı bir sorun protoboart a  devreyi kurup çalıştırma ayrı bir dert tekrar yardımını isteyeceğim cok sağol
bu arada sayın bigbey selam vereyim

mustafaaxu

sayın bigbey
ilginiz için çok teşekkür ederim anladıgım kadarı ile
tablo 1  İLE    0.....255 kadar saydır
tablo 2  İLE   255.....512
tablo 3  İLE   512 .....768 kadar saydır diyorsun
olayı tam kavrayamadım sayıları örneklersem
;--------------------------------------
COUNT
	INCF	TEMP, F        ;TEMPA SAYACINI 1 ARTTIR
	BTFSS	PORTA, 4        ;KONDANSATÖR DOLDU MU? DOLDUYSA EĞER
	GOTO	COUNT
;---------------------------------------
MOVF	TEMP, W
CALL	TABLO1
MOVWF	PORTB
;---------------------------------------
TABLO1
	ADDWF	PCL,F
	RETLW b'11000000' ; 0
	RETLW b'11111001' ; 1
	RETLW b'10100100' ; 2
	RETLW b'10110000' ; 3
	RETLW b'10011001' ; 4
	RETLW b'10010010' ; 5
	RETLW b'10000010' ; 6
	RETLW b'11111000' ; 7
	RETLW b'10000000' ; 8
	RETLW b'10010000' ; 9

;-----------------------------------------
TABLO2
                ADDWF	PCL,F

devamını gene retlw 1,2,3,,,0 diyemi yazacağız

bende 255 kadar sayıyor 256 gecin ce 000...001...002 diye devam ediyor
burayı biraz açarmısın teşekkürler
TA5EK...73...

Tagli

Tablo boyutu zaten 10 değil mi? Yani 10 rakam için 7 segmentli göstergede kullanılacak değerleri döndürecek, doğru mu anlamışım? Tablonun sonunda neden tekrardan 0 olduğunu anlamadım. Ayrıca neden birden fazla tablo gerektiğini de anlamadım.
Gökçe Tağlıoğlu

bigbey

Selam,
Alıntı yapılan: "mustafaaxu"benim sorunum16F84A ile  tablodan 255 den sonra değer alamıyorum araştırdım  sarun pclath  kullanamadığımdan kaynaklanıyor
Sorudan anladığım 255 ten daha fazla tablo değerini nasıl kullanabileceğimiz diye anladım va buna göre bir örnek verdim. soruyu doğrumu anladım?
Burada sonradan gördüğüm kadarıyle 0 - 9 arası 7segment değerlerini oluşturmak olarak görünüyor.
Benim sorudan anladığım sanırım farklı oldu.
TA6R

Tagli

Alıntı yapılan: "bigbey"Sorudan anladığım 255 ten daha fazla tablo değerini nasıl kullanabileceğimiz diye anladım va buna göre bir örnek verdim. soruyu doğrumu anladım?
Ben de öyle anlamıştım. Ama şimdi kafam karışmış durumda.

@mustafaaxu, konuya açıklık getirirsen sevinirim.
Gökçe Tağlıoğlu

mustafaaxu

sayın bigbey ve tagli
özür dilerim galiba hata benden kaynaklanıyor konuyu tam anlatamadım eğer incelemek isterseniz tam asm kodu ekliyebilirim
konuyu sizlerin yardımıile öğrenmek istiyorum
tablo da haklısınız acele ile tabloyu yapıştırırken fazladan almışım sıfır yok kod üzerinde düzeltim
tekrarlarsam şöyle toparlıyayım bir dosyanın içindeki bir sayıyı arttırıyorum kapasitemiz dolana kadar saydırıyoruz sonra bu dosyayı içeriğinden  yüz çıkarıyoruz 100 den fazlamı  kontrol ediyoruz fazla ise yüzleri 1 artiriyoruz
yüzden kücük se  onlara aynı işlemi yapıyoruz kalanıda birlere ekliyoruz
displeye yüzler ..onlar...ve birleri yazdırınca sonucu görüyoruz
sorunbenim yaptığım bu kondansatörü şarz eden ayarlı direnci 255 sayısını gösterecek sekilde ayarlıyorum  sonra  trimpotu degerini değiştirerek 256 göstermesini istediğimde 000..001 gösteriyor
burada 255 den sonra 256 gelmesi için ne yapmalıyız
teşekkür ederim

bigbey

siz analog bir değer okuyorsunuz öylemi
yazdığınız kodları bi koyun buraya olayı daha hızlı kavrar çözeriz
TA6R