http://www.picproje.org/index.php/topic,13891.msg90713.html#msg90713
PIC de acemilerin düşdüğü tuzaklar:
--------------------------------------------------------------------------------
Saykıl tuzağı:
PIC ler çoğunlukla bir saykılda komut işler.
Ama bir saykıl tek tekikleme değil, 4 tetikleme demek.
Bir
NOP emiri 10MHZ de 100ns değil 400ns zaman harcıyor. Gecikme
fonksyonlarda bunu hesaba katın. Zamanlayıcılar (Timer) maksimum 1/4
İşlemci frekansında çalışabiliryor.
--------------------------------------------------------------------------------
Kesme tuzağı:
Bütün işlemciler kesme anında programsayacı ve statü hücreyi kurtarıyor. PIC de ama sadece programsayacı kurtarılıyor.
Kesme
işlemi yapan bölüm bu statü hücreyi bozuyor. Ana programa geri
dölüldüğü zaman program yanlış statü bilgilerle devam ediyor.
Onun
için kesme bölümde statü hücresini kayıt edin ve bitdiğinde geri yazın.
mov komutu bunun için kullanılmaz çünkü Z-bilgiyi değiştiriyor.
Microchip bunun için bir öneride bulunuyor:
16F84:
movwf w_temp
swapf STATUS,w
movwf status_temp
Kesme bitiş:
swapf status_temp,w
movwf STATUS
swapf w_temp,f
swapf w_temp,w
retfie
16F62x veya 12F6xx:
movwf w_temp
swapf STATUS,w
bcf STATUS, RP0 ; status_temp Bank 0
movwf status_temp
Kesme biitiş:
swapf status_temp,w
movwf STATUS
swapf w_temp,f
swapf w_temp,w
retfie
16F87x:
MOVWF W_TEMP
SWAPF STATUS,W
CLRF STATUS
MOVWF STATUS_TEMP
MOVF PCLATH, W
MOVWF PCLATH_TEMP
CLRF PCLATH
Kesme bitiş:
MOVF PCLATH_TEMP, W
MOVWF PCLATH
SWAPF STATUS_TEMP,W
MOVWF STATUS
SWAPF W_TEMP,F
SWAPF W_TEMP,W
retfie
'status-temp' Bank 0 tanımlanması gerek çnükü kesme anında hangi 'Bank'
bulunduğunuz bilemezsiniz.
--------------------------------------------------------------------------------
Kesme tuzağı 2:
Bir kesmede işlemci Interrupt-Flag denilen hücreye 1 verir.
Kesme sonunda bu hücreye 0 verilmesi gerek. Yoksa kesme işleminden sonra tekrar kesme olur ve progra sonsuz bir döngüye girer.
--------------------------------------------------------------------------------
Kesme tuzağı 3:
Pinlerin seviyesinde değişiklik olduğu zaman, bunu algılamak için
bir kesme kullanılır. Değişikliği PIC fark etmesi için pin seviyelerini bir hücre ile karşılaştırır.
Ama program başında bu portdan okuma yapmadığınız zaman, bu değişikleri PIC hiç bir zaman algılayamaz.
--------------------------------------------------------------------------------
Analog-Tuzak (Port A, Port GP):
Bazı PIC işlemcilerde İlk açılışta PORT A dijital giriş olarak ayarlanmamış.
Bu tabii dijital giriş veya çıkış olarak kullanmak mümküm değil.
Ancak PORT A dijital giriş/çıkış yaptıktan sonra çalışır.
; 16F876:
BSF STATUS, RP0 ; Bank 1
MOVLW 0x06 ; PCFG3..0 = '0110'
MOVWF ADCON1
BCF STATUS, RP0 ; Bank 0
16F628 PORT A karşılaştıcı aktif, bunu kapatmak gerek
BSF CMCON, CM0
BSF CMCON, CM1
BSF CMCON, CM2
12F629 PORT A karşılaştıcı aktif, bunu kapatmak gerek
BSF CMCON, CM0
BSF CMCON, CM1
BSF CMCON, CM2
; 12F675 PORT A karşılaştıcı ve analog giriş aktif, bunu kapatmak gerek
BSF CMCON, CM0
BSF CMCON, CM1
BSF CMCON, CM2
BSF STATUS, RP0 ; Bank 1
CLRF ANSEL ; GP0,1,2,4 ADC -> digital
BCF STATUS, RP0 ; Bank0
--------------------------------------------------------------------------------
Veri tablosu Tuzağı:
Sabit değerler genelde program bellekte tutulur. Aşagıda bir 7-Segment display çalıştıran bölüm.
Örneğin 4 göstermek için "w" ye 4 verilir. "call Segmente" çağrılır ve addwf programsayacı 4 yükseltilir.
böylece retlw B'11010100' ; 4 satıra gider ve "w" segmentin değerini verir.
; 7-Segment-Table
Segment
addwf PCL, f
retlw B'00011000' ; 0
retlw B'11011110' ; 1
retlw B'00110010' ; 2
retlw B'01010010' ; 3
retlw B'11010100' ; 4
retlw B'01010001' ; 5
retlw B'00010001' ; 6
retlw B'11011010' ; 7
retlw B'00010000' ; 8
retlw B'01010000' ; 9
Ama böyle tablolarda addwf sadece 8 bit çalıştığına ama program sayıcı daha büyük olduğunu dikkat etmek gerek.
Tablo içinde XXXFF şeklinde Komutadresi olmaması gerek. addwf böyle adreslerin üzerinden değil,
istenilen hedefin 256 Byte önüne atlar.
Adresleri "*.lst" dosyasında kontrol edin ve "org" komutlarıyla ayarlayın.
--------------------------------------------------------------------------------
I2C-Tuzak:
Büyük PIC lerde seri iletişim vardır (örn. PIC16F87x).
Bazen I2C arabirimde olabiliyor. I2C pinleri dahili dirençler olmadığı için, bunları pinlere harici takmak lazım.
Aksi takdirde PIC girişi "low" başka "master" kullanıyor diye olarak görürür.
PIC kontrolü ele alamaz.
--------------------------------------------------------------------------------
in/out-Tuzak:
Her Port yazmada (PORTA..PORTE, GPIO) önce Port okunuyor. Okunan Byte değiştiriliyor ve PORT geri yazılıyor.
Bunu tek bir bit yazıldığı zamanda geçerli (bsf, bcf).
İlk okumada PORT hücrelerden değil, direk pinlerden okuyor. Çıkışlarda bu fark etmez ama ama giriş ayarlanmış pinlerde
Port hücresi istenilmiyen şekilde değişebilir. Çıkış olarak değiştirildiğinde seviyeler ön görüldüğü gibi olmayabilir.
Örnek:
Bir PIC RB0 giriş 10kOhm dirençle Vss (Taprağa) bağlı, RB1 10kOhm ile Vdd (+5V) bağlı.
Bütün pinlere "0" veriliyor:
; 16Fxx RB0..7 çıkış
BSF STATUS, RP0 ; Bank 1
CLRF TRISB ; PORTB çıkış
BCF STATUS, RP0 ; Bank 0
CLRF PORTB ; bütün pinlere 0
Bütün pinlerde "0" var.
RB0 ve RB1 giriş oluyor ve RB2 "1" veriliyor.
; 16FXX RB0 ve RB1 giriş
BSF STATUS, RP0 ; Bank 1
BSF TRISB, 0 ; RB0 giriş
BSF TRISB, 1 ; RB1 giriş
BCF STATUS, RP0 ; Bank 0
; RB2 high
BSF PORTB, 2 ; RB2 high
RB0 ve RB1 giriş olduğunda, dirençlerin belirlediğig seviyeyi alır. RB0 da "0" RB "1" var. Ama PORTB hücresinde ikiside 0.
RB2 yi "1" yapıldığındaa PIC hepsini önce okuyor. RB1 den dirençten dolayı "1" okunuyor.
PIC bunu okuyor: 00000010
Sonra Bit 2 "1" veriyor: 00000110
ve sonucu PORTB hücreye yazıyor.
Ama sadec Bit 2 değil Bit 1 de "1" oluyor.
RB1 giriş olduğu için yanlış yok. Ama RB0 und RB1 çıkış yaptığımızda:
; 16Fxx RB0..7 çıkış
BSF STATUS, RP0 ; Bank 1
CLRF TRISB ; PORTB auf çıkış
BCF STATUS, RP0 ; Bank 0
RB1 değişen değeri veriliyor. RB0 "0" veriyor ve RB2 "1", ama RB1 birden "1" var, Bu istenmeyen bir sonuç.
PIC18Fxxxx-tiplerde bu problem iki farklı komutla çözüldü. Portları (z.B. PORTA oder PORTB) okumamada direk pinler okunuyor.
Diğeri ile LATX (LATA veya LATB) komutla direk hücre okunuyor.
--------------------------------------------------------------------------------
RA4-Tuzak:
RA4 bir open-Drain-Çıkış. Bunu başka çıkışlara bağlama fikri geliyor. Örenğin I2C simule temek için.
RA4 hem çıkış ve giriş kullanıldığı zaman in/out-Tuzak devreye giriyor.
--------------------------------------------------------------------------------
I/O-Hız Tuzak:
Portlara yazıldıgı zaman saykılın sonunda porta yazılıyor.
Portlardan okunduğu zaman saykılın başında portan okunuyor.
örnek:
PIC 20 MHz ile çalışıyor. Port B çıkış. PORTB ilk başta 0xFF var:
CLRF PORTB ; Port B sıfır ver
MOVFW PORTB ; Port B oku
w de hangi değer var ??
00000000 tahmin ediyorsunuz. Genelde bu değer olur ama buna garanti verilmez.
20 MHz saykıl 0,2 µs. Port B okuma yazma ile arasında en fazla 0,05 µs = 50 ns var.
Pinlere bağlı Kondensatörler bu kısa zamanda 0 çkilmesini önler.
Bir 1nF Kondensatörü sıfıra çekmek için 80ma akım gerekli.
Onun için araya NOP koymanız gerek.
Hiç yorum yok:
Yorum Gönder