20 Haziran 2013 Perşembe

PIC deki tuzaklar ve çözümleri

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