Usart Kesmesi Hakkında?

Başlatan mytap, 21 Kasım 2006, 14:21:23

mytap

Usart lı piclerde  interrup registerleri aşağıdadır. Bu registerlerin kullanımı hakkında bilgi almak istiyorum.
Özelikle TXIF de tanımlanmış registerine bir bilgi geldiğinde bu register 1 oluyor yani bi bayrak kaldırıyor. Bu değişkeni sürekli kontrol etmek gerekiyor sanırım. Örnekte şöyle yapıyorum;

if TXIF=1 And TXIF="r" then serikesme ; Txif e bir bilgi gelmiş ve gelen bilginin başında "r" var ise serikesme etiketine git
-
-
-
serikesme:
hserin [deger]
TXIF=0 ; bayrak silindi
return
böyle bir program yazıyorum ama olmuyor sorun nedir acaba?

İnterrupt registerleri (16f877 için)

SYMBOL TMR1IF = PIR1.0 ' TMR1 Overflow Interrupt Flag
SYMBOL TMR2IF = PIR1.1 ' TMR2 to PR2 Match Interrupt Flag
SYMBOL CCP1IF = PIR1.2 ' CCP1 Interrupt Flag
SYMBOL SSPIF = PIR1.3  ' Synchronous Serial Port (SSP) Interrupt Flag
SYMBOL TXIF = PIR1.4   ' USART Transmit Interrupt Flag
SYMBOL RCIF = PIR1.5   ' USART Receive Interrupt Flag
SYMBOL ADIF = PIR1.6   ' A/D Converter Interrupt Flag
SYMBOL PSPIF = PIR1.7  ' Parallel Slave Port Read/Write Interrupt Flag


iyi çalışmalar....
-------------------------------------------------------- hayırlı günler, iyi çalışmalar..  --------------------------------------------------------

Ziya

gelen bilgi için rcif aktiflenir. Bilgiyi okuduğunda ise bu flag kendiliğinden silinir.

txif boolean tiptedir. "r" ile karşılaştırılmaz. gelen bilgi yanlış hatırlamıyor isem rcreg içerisinde olması lazım.

if rcif=1 And (ch=rcreg)=="r" then serikesme ; kesmeyi aktiflemiş isen bunu yapmana da gerek yok. Kesme alt programında (ch=rcreg) == "r" karşılaştırması yapman yeterli.
Bu günden sonra hiç kimse sarayda, divanda, meclislerde ve seyranda Türk dilinden başka dil kullanmaya. (13 Mayıs 1277) Karamanoğlu Mehmet Bey

mytap

Teşekkürler ziya bey. bişeydaha var burda yine tx ile rx i karıştırmışım. Özür dilerim. Ben dediğiniz gibi if rcif=1 And rcreg="r" then serikesme şeklinde kullanıyorum. Gelen veri ile kesmeyle rcreg içerisindeki bilgiyide okuyup karşılaştırma yapıyorum.  kesmenin oluştuğu andaki gittiği etikette;

serikesme:
hserin [dec,deger]
return
   end

burdaki komut kümesi doğrumudur? Protona yeni geçtim ve bir kaç usart seri I/O komudu gördüm. Seri kesmeleri aktif hale getirmek için intcon=%11010000 komudu yeterlimi?
-------------------------------------------------------- hayırlı günler, iyi çalışmalar..  --------------------------------------------------------

Veli B.

ON_INTERRUPT GOTO INT 
SYMBOL GIE  =INTCON.7
SYMBOL PEIE =INTCON.6
SYMBOL RCIE =PIE1.5
SYMBOL RCIF =PIR1.5 
.
.
GIE=1
PEIE=1
RCIE=1
.
.
.
INT:
RCTEMP =RCREG
IF RCTEMP="R" THEN  GOTO A
IF RCTEMP="F" THEN GOTO B
CONTEXT RESTORE

mytap

Sayın katana bu kodları birazdaha açıklarmısınız. Sistemde RB0 kesmeside kullanıyorum. Burda sistem kararsız bi hale geliyor. Diğer yandan goto a etiketine gidince ne yapacak? Orda
a: 
hserin [dec,deger] 
return 
end


gibi tekrar seri girişi okuyarak okuduğu değeri bir değişkene koyması mı gerekiyor? Birde sistemde RB0 kesmeside kullanıyorum 10ms gibi zaman aralıkalrında bir dış kaynaktan  kesme alıyorum. Bu RB0 kesmesi seri kesmeyi etkilermi? Diğer yandan yukardaki yazmış olduğum seri giriş okumak için kullanılan komutta işlemcimiz ne kadar oyalanır?
-------------------------------------------------------- hayırlı günler, iyi çalışmalar..  --------------------------------------------------------

Veli B.

10 ms ara ile kesme almanız etkiler mi? sorusu, mevcut sisteminizi ve yazılımınızı incelemeden yorum yapılamayacak bir konu. Bu USART baud rate+protokol, dışardan alacağınız kesme türü ve kesmenin ne kadar süre(interruptların ne kadar kapalı kalacağı) ile devam edeceğine bağlı.
ON_INTERRUPT GOTO INT
SYMBOL GIE  =INTCON.7
SYMBOL PEIE =INTCON.6
SYMBOL RCIE =PIE1.5
SYMBOL RCIF =PIR1.5

Burada tanımlamaları yapıyoruz.Detayları datasheetlerde mevcut.

GIE=1
PEIE=1
RCIE=1

Burada INTERRUPT' ların devreye alınmasını sağlıyoruz.
Dar vakitte yazdığım için aklıma gelen ilk sıraya göre yazmıştım. Fakat doğru kodlama tekniğine göre Interruptları devreye alırken en kısıtlı kontrolden en geniş kontrole doğru sıralamanız gerekir. Kapatırken ise şartlara göre değişmekle beraber en genişten en dara doğru kapatıp, gerekiyorsa müteakiben daha genişi tekrardan devreye almak doğrusudur)
Bu şartlarda doğru sıralama
RCIE=1
PEIE=1
GIE=1

şekindedir.

INT:
RCTEMP =RCREG
IF RCTEMP="R" THEN  GOTO A
IF RCTEMP="F" THEN GOTO B
CONTEXT RESTORE


Bu int rutini içerisinde, istemiş olduğunuz data alınmış ve RCREG registerı içerisindedir. RCIF nin bir an önce sıfırlanması ve üzerinde gerekiyor ise işlem yapabilmek amacı ile içerik kendi tanımlamış olduğumuz RCTEMP değişkeni içerisine kopyalanmıştır ve RCIF resetlenmiş durumdadır. Yine doğru kodlama tekniği açısından INT rutini içerisine girdiğimizde GIE kapatılmalı ve bundan emin olunmalıdır. Bu aşamada eğer 10 ms lik periyodlarla harici kaynaklardan oluşturulan kesme isteğiniz mevcut olursa, GIE kapalı olduğu için MCU buna tepki veremez ve kesme oluşmaz.
A ve B etiketlerine dallanma temsilen yazdığım satırlar idi.Bu aşamada bütün işlem bitmiş(kod yürütümü durdurulmuş, 1 byte data alımı bitmiş ve kendi değişkenimiz içerisine aktarılarak ilgili yerlerde kullanıma hazır hale gelmiştir)  ve etikete gidildiği anda gerekli icra yapılabilir duruma gelmiştir.
Sonradan farkettiğim için sona ekledim bu kısmı. INT rutini içerisinde birden fazla INTERRUPT ı kontrol etmeniz elbette mümkün( FLAG lar vasıtası ile kullanımı bu şekildedir zaten). Sadece ilgili kesmeler için INTERRUPT FLAG kontrollerine bakarak pekçok kesmeyi birbirini etkilemeyecek(engelleyebilir ama bozulmasına sebep olmaz, bu tamamen programcının hakimiyetinde olan bir noktadır) şekilde kullanabilrsiniz. Projelerimden birisinde 7 harici ve 1 dahili kesmeyi 877 üzerinde kullandım ve 3 yıldır sorunsuz çalışıyor. ;)

Ziya

Alıntı yapılan: "mytap"Teşekkürler ziya bey. bişeydaha var burda yine tx ile rx i karıştırmışım. Özür dilerim. Ben dediğiniz gibi if rcif=1 And rcreg="r" then serikesme şeklinde kullanıyorum. Gelen veri ile kesmeyle rcreg içerisindeki bilgiyide okuyup karşılaştırma yapıyorum.  kesmenin oluştuğu andaki gittiği etikette;

serikesme:
hserin [dec,deger]
return
   end

burdaki komut kümesi doğrumudur? Protona yeni geçtim ve bir kaç usart seri I/O komudu gördüm. Seri kesmeleri aktif hale getirmek için intcon=%11010000 komudu yeterlimi?
Katana hocam gerekli cevapları vermiş. Eklenecek fazla bir şey yok gibi.

Seri port kesmesini aktiflemek için 'Peripheral Interrupt Enable 1' (PIE1) registerindeki RCIE bitini de set etmeniz gerekir. Datasheette seri port ile ilgili registerleri ve bitleri ilgili yerde özet olarak tablo halinde verilmektedir. Yalnız Datasheet errata dökümanına da bakın herhangi bir yanlış yazım var mı seri portla ilgili.

Kesmeyi aktiflediğinizde program akışı sırasında seri porta bilgi gelirse program akışı ISR rutinine gider. Orada ilk olarak kesmenin hangi kaynaktan geldiğine bakmalısınız. RCIE ve INTE kesmelerini etkinleştirdiğinize göre seri porta bilgi gelmiş ise rbif 1 olur, B0 dan kesme kelmiş ise (?) intf 1 olur. Buna göre if karşılaştırması ile ilgili okuma işlemlerinizi yaparsınız. rcreg içeriğini bir değişkene aktarmalısınız. Bunu yapar yapmaz rcif silinir. extint kesmesinde (?)intf(?) flagini komutla resetlemeniz gerekir.

İsterseniz ISR rutini içerisinde kendinizin tanımladığı (boolean yada bit olarak) bir flag kullanıp seri porttan bilgi gelmiş ise set edip, ISR'de seri bilgiyi okutup bir değişkene aktardıktan sonra ana programa döndüğünüzde o tanımladığınız flagi kontrol ederek o gelen seri port bilgisi ile ne yapmak istiyorsanız ana programda yapabilirsiniz. En mantıklı yol budur. ISR rutininde fazla stack kullanan algoritma sağlıklı değildir. Hele ISR rutini içerisinde LCD'ye bilgi yazdırmak fazladan en az 3 stack tüketmenize neden olur. 877 gibi 16F serisi piclerde 8 tane olan stackı tüketmiş olabilirsiniz.
Bu günden sonra hiç kimse sarayda, divanda, meclislerde ve seyranda Türk dilinden başka dil kullanmaya. (13 Mayıs 1277) Karamanoğlu Mehmet Bey

mytap

Kontrol mantığı ile nerden ne gelmiş flaglara bakarak bulabiliyoruz bunu anladım. Bir örnekle bu ISR rutinini açıklayabilir misiniz? Ayrıca burdaki gelen bilgiyi bir değişkene nasıl almak gerekir. ISR rutinindemi olması gerek?
-------------------------------------------------------- hayırlı günler, iyi çalışmalar..  --------------------------------------------------------

mytap

RCREG usarta ait registerde 8 bitlik veri depolanabiliyor. Bu registere ben 1 wordluk bir bilgi göndermek istiyorum. Fakat alıcı taraf 255 ten sonra yani 1 byte dolduktak sonra tekrar sıfırlıyor değeri. RCREG kullanarak 1 wordluk bilgiyi nasıl alabilirim. Bu konuda bilgi verebilirmisiniz?
-------------------------------------------------------- hayırlı günler, iyi çalışmalar..  --------------------------------------------------------

Veli B.

ON_INTERRUPT GOTO INT
DIM TEMPWORD AS WORD
DIM TEMPWORD_P AS BIT
SYMBOL GIE  =INTCON.7
SYMBOL PEIE =INTCON.6
SYMBOL RCIE =PIE1.5
SYMBOL RCIF =PIR1.5
.
.
GIE=1
PEIE=1
RCIE=1
.
.
.
INT:
RCTEMP =RCREG
GOTO _RESULT
CONTEXT RESTORE 
MAIN:
.
.
.
GOTO MAIN
_RESULT:
     IF TEMPWORD_P=0 THEN
                TEMPWORD.0=RCTEMP
                TEMPWORD_P=1
     ELSE
                TEMPWORD.1=RCTEMP
                TEMPWORD_P=0
     ENDIF
GOTO MAIN

mytap

Sayın katana anladığım kadarı ile burdaki RCTEMP içeriği her bir max değerine ulaştığında TEMPWORD değişkeni bir artıyor yani kaç tane 1 bytelik veri alındığını gösteriyor ben bunu anladım bu kodlardan başka bişey anlayan varsa lütfen açıklasın

iyi çalışmalar...
-------------------------------------------------------- hayırlı günler, iyi çalışmalar..  --------------------------------------------------------

Veli B.

Alıntı yapılan: "Ziya Üstadım"İsterseniz ISR rutini içerisinde kendinizin tanımladığı (boolean yada bit olarak) bir flag kullanıp seri porttan bilgi gelmiş ise set edip, ISR'de seri bilgiyi okutup bir değişkene aktardıktan sonra ana programa döndüğünüzde o tanımladığınız flagi kontrol ederek o gelen seri port bilgisi ile ne yapmak istiyorsanız ana programda yapabilirsiniz. En mantıklı yol budur. ISR rutininde fazla stack kullanan algoritma sağlıklı değildir.

DIM TEMPWORD AS WORD

İle word tipinde bir değişken tanımlıyourz.

DIM TEMPWORD_P AS BIT
satırı ile ise bu değişkenimiz için bit düzeyinde bir pointer(işaretçi) tanımlıyoruz. RCREG isimli registerımızın(kaydedicimizin) uzunluğu byte olabilmekte; malumunuz. Elbette göndereceğiniz paket türüne göre değişmekle beraber( ben LSB("Least significant bit"~ en düşük değerlikli bit)den başlayarak MSB("Most significant bit"~en yüksek değerli bit) e doğru gönderdiğnizi varsayıyorum) 0<>7. bitleri birinci byte olarak, 8<>15. bitleri ise ikinci byte olarak göndereceksiniz.

IF TEMPWORD_P=0 THEN
                TEMPWORD.BYTE0=RCTEMP
                TEMPWORD_P=1


Programımızın koşmaya başlayacağı anda pointerımızın durumu 0 dır.İlk data alımı esnasında kesme oluşmuş ve RCREG içeriği RCTEMP e aktarılmış, müteakibende ISR den çıkılarak _RESULT etiketine gidilmiştir.Pointerımızın durumu sıfır olduğu için RCTEMP içeriği TEMPWORD isimli değişkenimizin 0<>7. bitleri üzerine yazılmış ve pointerımızın durumu değiştirilerek, bir sonraki adımda gelecek olan 8<>15. bitlerin,
ELSE    ' Pointerımızın durumu 1 ise
                TEMPWORD.1=RCTEMP
                TEMPWORD_P=0 ' pointerı tekrardan ik baytı almaya hazırla
     ENDIF

TEMPWORD değikenimizin 8<>15. bitleri üzerine yazılması zorunluluğunu sağlamıştır.

Alıntı Yap.... anladığım kadarı ile burdaki RCTEMP içeriği her bir max değerine ulaştığında TEMPWORD değişkeni bir artıyor yani kaç tane 1 bytelik veri alındığını gösteriyor ben bunu anladım bu kodlardan başka bişey anlayan varsa lütfen açıklasın
demişsiniz.
Lütfen, kinâyeli mesajlar yazmanıza lûzum yok. Proton yardım dosyalarını inceler iseniz, bu konularda, genel anlatımlar verilmiş durumda. Dolayısı ile verdiğim örnek kodtan çıkartılabilecek başka bir anlamda yok.

mytap

Konuyla ilgilendiğiniz için teşekkür ederim sanırım geceki yazdığım son msjımda yani kinayeli msjımda gerçekten bir art niyetim yoktu. Ama kırıcı bir şekilde yazdığımın farkına bugun vardım özür dilerim.

Kodlar için teşkkür ederim sorunu sanirim çözdüm. RS232 com portundan deneyeceğim umarım simülasyondaki gibi çalışır.

Son kez bişey sorcağım usart interruplarına paralel olarak bu yöntemle ADC kesmesinide kullanabilirmiyiz?


iyi çalışmalar...
-------------------------------------------------------- hayırlı günler, iyi çalışmalar..  --------------------------------------------------------

Veli B.

İlgili flagları(bayrakları) kontrol etmek şartı ile, PIC üzerinde ki bütün kesmeleri aynı anda kullanabilirsiniz.Yoğun bir kesme trafiğiniz olacak ve PIC kullanacağım diyor iseniz 18XXX ailesine geçmenizi tavsiye ederim. 18XXX serisinde kesmeleri öncelik sıralamasına koyabilirsiniz.

mytap

Bunu düşünmüştüm ve 16f877 kullanıyordum. Fakat ADC int ve diğer RB int, USART int, derken kesmeler fazlalaştı. Burda 877nin yoğun bir işlem trafiğe maruz kaldığı ortada ve buna 20Mhz xtal ile karşılık vereceğini düşünmüştüm. Fakat donanımı sağlıklı kılabilmek için sanırım 18F452 tipine geçmeliyim. Bu işlemciyi seçmemin nedeni ise 16F877 ile donanımsal pinleri aynı olması yani dizayn edilmiş bi kart tasarlamıştım.  18F452 sanırım bu iş için yeterli doğrumu düşünüyorum acaba?
Bu işlemciye geçmemin en etkili yönü pinlerin aynı olması diye düşündüm ilk etapta.
-------------------------------------------------------- hayırlı günler, iyi çalışmalar..  --------------------------------------------------------