proton basic usart kesmesi hakkında bilgiler

proton basic serial uart
proton basic uart seri iletişim

Etepic forumunda inventor rumuzlu üyenin proton basic usart kesmesi hakkında yapmış olduğu paylaşımlara aşağıdaki linkten ulaşabilirsiniz. Bilgileri bloğada ekliyorum, ete hocanın usart kesmesi ile ilgili bilgileri de aşağıda mevcut.

https://www.etepic.com/index.php?topic=911.0


inventor yazmış:
Merhaba arkadaşlar,

Son bir kaç haftadır proton ile yazdığım bir programla uğraşıyorum. İsiste sorunsuz çalışmasına rağmen gerçek devrede çalışmayan bir proje. Bu program ile uğraşırken
protonda ne kadar sorun çıkabileceğini de görmüş oldum. Kısa programlar için sıkıntı çıkarmayan pek çok konu uzun ve ağır programlarda sorun yaratabiliyor.
Burada karşılaştığım sorunlarla ve çözümleri ile ilgili bilgileri paylaşayım dedim.

İlk olarak protonda kesme konusuna değinelim. Çoğumuz programlarımızda kesme rutinini programımızın en altına yazıyoruz. Bu belki pbp dan kalan bir alışkanlık.
Kısa döngülerde bu alışkanlık protonda da kullanılabiliyor. Ama portb kesmesi ile usart kesmesini bir arada kullandığınız zaman kesinlikle KESME rutininin programın
en üstünde olması gerekiyor. Yani programınıza BASLA ile değil KESME ile başlamanız gerekiyor. KESME: satırının hemen üstüne GOTO BASLA yazarak normal çalışma
yaptırabilirsiniz. Eğer bunu yapmazsanız büyük ihtimalle benim yaşadağım bir sıkıntıyı yaşarsınız. Programınızda kullandığınız bütün DelayMs komutlarında programınız
USART kesmesi yapar. Bununla da kalmaz print at 1,1,"........" gibi komutları peş peşe kullandığınızda da kesmeye girecektir. Bu durumlarda tek yapmanız gereken KESME
rutinini programın en üstüne almak olacaktır. Bu konu protonun kendi veb sitesinde ve manualde de öneriliyor.Örnek verelim;
-----------------------------------------------------------------
GoTo BASLA
 
KES:             
Context Save
        HSerIn 5,CIK,[Wait ("~"),BILGIAL]
        HSerOut [BILGIAL]
        A=1           
CIK:
    TEMP=RCREG   ' USART Kesme bayragi sifirlandi (RCIF)
Context Restore

BASLA:   
    If A=1 Then HESAP
-----------------------------------------------------------------
Diğer bir konu da Temp=RCREG konusu. PBP da karşılaşmadığım ama protonda zaman zaman sorun çıkaran bir konu var. Temp=RCREG komutunu programın başına eklemeniz gerekiyor.
Aksi halde RCRIF set olarak geliyor. Ve sistem kesmeye gitmiyor. Genelde bizler RCREG registerini  KESME rutini içerisinde sıfırlıyoruz. RCRIF ilk açılışta SET olarak
gelince program kesmeye girmiyor. Girmeyince RCREG boşaltılamıyor ve siz usart kesmesi olacak diye bekliyorsunuz. RCRIF in niye set olarak geldiğini hala anlamış değilim
ama PBP da yazdığım bir programı protonda yazınca yine set olarak başladı. Aslında bir inceleme yapmak lazım bu konuda. Örnek verelim;

ORAN=ERead 10
If ORAN>2 Then ORAN=1
Print  $fe,1
DelayMS 200
I=0 : BILGIAL=0 : VIN=0 : VCIK=0 : A=0   : EN_Pin=0
TEMP=RCREG
'****************************************************************************************************************
GoTo BASLA
 
KES:             
Context Save
        HSerIn 5,CIK,[Wait ("~"),BILGIAL]
        HSerOut [BILGIAL]
-----------------------------------------------------------------     

Protonda kesmeleri ayarlarken de uyulması gereken kurallar var. Mesela ilk kural sıralama. Kesme ile ilgili registerları ayarlarken ilk olarak genel kesmeleri kapatmanız
gerekiyor. Sonra sırası ile önce SW kesmelerini ,sonrasında da HW kesmeleri ayarlayıp en son olarak genel kesmeyi açmalısınız.

-----------------------------------------------------------------
Symbol GIE  =INTCON.7   'genel interruptlar  aciyor
Symbol PEIE =INTCON.6   'Cevresel kesmeleri  aciyor
Symbol INTE =INTCON.4   'RB0 Kesmesini aciyor
Symbol INTF =INTCON.1   'RB0 kesme bayragi
Symbol RCIE =PIE1.5     'USART kesmesini aciyor
Symbol RCIF =PIR1.5     'USART Receive interrupt flag bit
GIE=0     'Butun kesmeler kapalı
INTE=1    'RB0 kesmesi devrede     
RCIE=1    'USART kesmesi devrede
PEIE=1    'Cevresel kesmeler devrede
GIE=1     'Butun kesmeler devrede
-----------------------------------------------------------------

Başka bir konu da On interrupt ile On_interrupt arasındaki fark. Genelde bilinen bir konu ama ben yine de bildiklerimi aktarayım. pbp da tek olan komut
On interrupt Goto .... iken bu komut protonda üç adet. İlki PBP ile aynı.
On interrupt Goto ......
Bu Software kesmesi oluyor. Protonda donanımsal kesme var. Bunu iki komut satırı ile yazabiliyoruz.
on_interrupt .......   ya da
on_hardware_interrupt ........
Burada şunu bilmek gerekiyor. Eğer yazılımsal kesme kullanıyorsak KESME rutininin hemen üstüne Disable komutunu ekliyoruz. Kesmeden çıkarken de eneble resume diyerek
çıkıyoruz. Bu pbp ile aynı. Donanımsal kesmede ise kesme rutinine girince Context Save diyoruz. Çıkarkende Context Restore yazıp çıkıyoruz. Manuale bakınca bu komutların
sadece 16f serisi için geçerli olduğunu yazmışlar. Her iki kesmeye de örnek verirsek;

-----------------------------------------------------------------
Disable
KES:             
        HSerIn 5,CIK,[Wait ("~"),BILGIAL]
        HSerOut [BILGIAL]
        A=1           
CIK:
    TEMP=RCREG   ' USART Kesme bayragi sifirlandi (RCIF)
enable
resume

-----------------------------------------------------------------
KES:             
Context Save
        HSerIn 5,CIK,[Wait ("~"),BILGIAL]
        HSerOut [BILGIAL]
        A=1           
CIK:
    TEMP=RCREG   ' USART Kesme bayragi sifirlandi (RCIF)
Context Restore
-----------------------------------------------------------------
Başka bir konu da Hserout komutunun kullanımı. Bu konu PBP için de geçerli. ETE hoca da dile getiriyor bu konuyu. Göndereceğiniz komutun sonuna mutlaka başka bilgilerde
ekleyin. Aksi halde veri zaman zaman eksik gidebiliyor.Aşağıdaki kod da 10,13 bu amaçla kullanıldı.
-----------------------------------------------------------------
GONDER:
    EN_Pin=1
    GoSub GECIKME
    KOD=118
    HSerOut [Rep $AA\5,Rep $00\5,Rep $FF\5]'uyandirma sinyali preamble
    HSerOut ["~",KOD,10,13]
    EN_Pin=0       
    Return
-----------------------------------------------------------------

Proton Delay komutlarında beklerkende donanım kesmesine girebiliyor. Bunu da aklınızın bir köşesinde bulundurun. Örneğin aşağıdaki programda 10 sn lik bekleme sırasında
gelen bir usart bilgisi anında kesmeye neden oluyor. Kesme işi tamamlandıktan sonra zaman sayacı kaldığı yerden saymaya devam ediyor.

-----------------------------------------------------------------
BASLA:
    DelayMS 10000
    '****  olcme talebi gelince yapilacaklar  ****   
     If A=1 Then
        A=0
        RCIE=0
        BILGIAL=0
-----------------------------------------------------------------
Başka bir konu da High Low komutları ile ilgili. Sanırım bu konu PBP içinde geçerli olmalı. Çoğumuz pinlerin durumunu değiştirmek için bu komutları kullanıyoruz.
Gözden kaçırdığımız nokta ise manuallerde belirtilmiş aslında. Bu komutlar kullanıldığı anda ilgili pin çıkış yapılır  diyor. Bu komutu kullanmak için zaten pini çıkış
yapmış oluyoruz ne fark eder gibi bir şey aklınıza gelebilir. Neyin farkettiğini kullandığınız picin hafızası dolmaya başladığında görüyorsunuz. Örnek verecek olursak;

-----------------------------------------------------------------
basla:
    High PORTA.1
   End

-----------------------------------------------------------------

Proton ile  derlenen yukarıdaki komutların derleme sonrasında Assembler karşılığı şu şekilde oluyor;
-----------------------------------------------------------------
basla
        bsf STATUS,5
        bcf TRISA,1
        bcf STATUS,5
        bsf PORTA,1
        end
-----------------------------------------------------------------

High Low komutları yerine porta.1=1 komutunun assembler karşılığına bakalım;
-----------------------------------------------------------------
basla
        bsf PORTA,1
        end
-----------------------------------------------------------------

 
Ete yazmış:
RF olsun kablulu alışverişler olsun hepsi için geçerli bir altın kural vardır.
Bu verici mesajını verdiği zaman alıcıda onu almaya hep haır halde beklemelidir.
Alıcı programlarda kullanılan pause ler programın orada çakılıp kalmasına sebep olur ve o anda veri gelmiş ise alıcının bu veriyi kaçırması da kaçınılmaz olur. Zira alma işini senin SERIN komutun yapacak. Program henüz SERIN komutuna gelemeden verici veriyi aktarmış ise başka bir sonuç beklenmesi doğru olmaz.

Çözüm USART kesmesi kullanmaktadır. USART kesmesi şu işe yarar. Programın bir yerde bekliyor ise ve aynı anda veri geliyor ise geri planda çalışan Pic içindeki kendi programı (ROM diyelim) veriyi alır ve Buffera (RCREG) koyar ve kesme bayrağını kaldırarak programın otomatikman alma rutinine yönlendirilmesini sağlarki tamda istediğimiz budur. Böylece program derhal alma işlemine girişir ve gelen verileri alır.

Serin komutu otomatikman programı da bloke eder ve yaklaşık 65 ms orada veri gelmesini bekler. Gelmiyor ise 65 ms sonra komutu atlar ve alttaki satıra geçer. Alttaki satırlarda Delayms 1000 komutun varki bütün sorunu bu komut çıkartıyor bence.
Bu gecikmeleri bedava dağıtılıyor gibi kullanmayın. Mantıklı yerlerde gereken süreleri verin.
O gecikmeyi kaldırıp yeniden dene diyeceğim ama yinede tekrarlıyorum. Kesin çözüm USART kesmesinde dir.
Ete



Burada biraz daha detay vermeye çalışacağım.
USART kesmesi için kullandığın 16F628A işlemcinin USART modülünü ve portunu kullanman gerekiyor.
Bu şu demek oluyor. PORTB.1 pininden Alış yani RX yapacaksın. PORTB.2 pininden ise TX yani gönderme yapacaksın. USART portunu kullandınmı bir kere bu iki pin port tarafından bloke edilir ve bu pinleri başka amaçla kullanamazsın. Örnek vereyim Bir programda yalnızca TX yapıyorsun diyelim RX pinini hiç kullanmıyor olsan bile onu başka amaçla kullanamazsın. En azından kullanmadığın bu pini boş bırakman gerekir.

USART portunu aktive etmen için ;
KodSeç
Declare hserin_pin PORTB.1Declare Hserout_pin PORTB.2    Declare Hserial_Baud 9600      Declare Hserial_RCSTA 90h       Declare Hserial_Clear OnDeclare Hserial_TXSTA 20hkomut satırlarını programın başına eklemen gerekiyor.
RX pini ise TRISB registerinde giriş olarak tanımlanmalıdır.

Bütün bunları yaptıktan sonra,
Şimdi gelelim TX yani verici programına,
Daha öncede belirtmiştim. RF sistemlerinde senkron tutturmak önemlidir. Yani verici veriyi verirken alıcıda alma konumunda hazır olmalıdır. Bu programların birinde en ufak bir gecikme olması durumunda veren vereceğini verirken alacak olan senkron tutturamadığı için alması gerekenleri alamaz.

Senkron tutturmanın en önemli şartlarından birisi Verici tarafında veri yollanmadan önce alıcı tarafındaki USART portunu uyandırmak ve programı kesmeye sevk etmek için bir Preambl denilen ön uyandırma sinyali gönderilir.
       HSEROUT [REP$AA\5,REP$00\5,REP$FF\5]'uyandirma sinyali preambl
       HSEROUT ["E","T","E",VERI1,VERI2,VERI3]
Burada ilk satırda verilen bilgiler işin uyandırma kısmıdır. ALıcı bu bilgileri ilk olarak aldığında hemen porta bilgi gelmeye başladığını anlar ve programı kesme kısmına sevk eder.
Veriler ie bir paket halinde gönderilmeli ve başına bir işaret koyularak alıcının önce bu işareti yakalaması sağlanmalıdır.
Bu örnekte işaret ETE bilgisidir. Peşinden Veri1, Veri2, Veri3 şeklinde Byte bilgisi olarak veriler sıralanır. Burada şu noktaya işaret etmek isterim. TX tarafı kaç byte yollamış ise alıcı tarafında da o kadar sayıda byte alınmalıdır. Bir taraf eksik olursa yine senkron kayabilir.
Burada görüleceği üzere veri bir paket şeklinde verilir. Her zaman TREN vagonlarına benzetirim bu sistemi.
Lokomotif işaretçi konumundadır. Vagonlar ise verileri temsil eder. Birisine vagonları bul dediğinizde o kişi önce lokomotifi arayarak peşinden gelen vagonları bulmalıdır. İşin temelinde bu fikir yatıyor. Şayet işaretçi kullanmazsanız alan taraf veriye ortadan girer ve hiç bir tutarlı bilgi alamaz.
TX tarafında kesme kullanmaya gerek yoktur. Çünki ne zaman veri yollanacağını siz belirlersiniz ve direk yukarıdakine benzer satırlar ile veriyi yollarsınız.
İşin alıcı kısmında ise Kesme kullanılması zorunludur. Ancak bu şekilde senkron yakalanır. Bu işi Serin komutu ilede yapabilirsiniz ama programda,
KodSeç
Basla:SerIn PORTB.1,84,[varl]
goto 
basla 
komutlarındanbaşka birşey olmaması gerekir. Böylece program yalnızca gelen veriye odaklanmış olur.
USART kesmesi kullanılırken ise program başka işlerle uğraşırken geri planda veri alınır ve program bu alınan veriyi değerlendirir. İşin güzel yanı buradadır.
Alıcı tarafında USART kesmesi açmak için;
Önce INTCON registerine INTCON=%11000000 değeri verilerek global kesmeler ve peripheral kesmeler aktive edilir.
Ardından USART kesmesi için PIE1 registeri 5 nolu biti (RCIE) set edilir . Bu Usart kesmesini aktive eder. Kesme oluştuğunda kesme bayrağı set edilir. Bu bayrak PIR1 registeri 5 nolu biti (RCIF) ile kontrol edilir. Önceden oluşmu kesmelerde set edilmiş kesme bayrağı ihtimaline karşın önce bu bayrak sıfırlanır. PIR1.5=0. Ancak bu bayrak aslında programcı tarafından direk ulaşılabilen bir bit değildir. Üretici (microchip) bunu otomatiğe bağlamıştır. Bunun için RCREG denilan alma registerinin içinin boşaltılması yani TEMP=RCREG şeklinde başka bir değişkene aktarılması söz konusu bayrağı otomatikmen sıfırlar. Bu nedenle BASLA satırından evvel TEMP=RCREG komutununda verilmesi uygun olacaktır.
Programa birde ON INTERRUPT GOTO KESME komutunu ekledinmi sistem tamamlanmış olacaktır. Proton da komutun yazılım şeklinde farklılıklar olabilir onları sen düzeltirsin. Ben Proton kullanmıyorum. PBP kullanırım.
Program içinde KESME şeklinde bir etiket belirliyoruz. BU etiketten önce Global gesmelerin pasif edilmesi amacı ile DISABLE komutu yer almalıdır. Böylece program kesme etiketine geldiğinde bir başka kesme oluşması engellenmiş olur ve DISABLE bunu otomatik yapar.
Program kesmeye nasıl geldi o kısmı bir kez daha yinelemek isterim. Geri planda çalışan kontrolcü USART portuna bir veri geldiğini tespit etti ve RCIF=1 yaparak kesme bayrağını set etti. Bu nedenle programda hemen kesme etiketine atlamış oldu. Demekki bir veri geliyor. Tabiiki önce Uyandırma sinyali porta ulaşacak ve program kesme etiketine gelinceye kadar bir kaç veri alınmaya devam edecektir. Bu nedenle uyandırma sinyalimiz bir kaç byte dan oluşuyor (toplamda 15 byte). Kesme etiketinde;
hSerIn ,10,ATLA,[WAIT("ETE"),VERI1,VERI2,VERI3] 
komut satırı yer alıyor. Altında ise ATLA isimli etiket yer alıyor. Komut içindeki 10 rakamı Timeout değeridir. Anlamı şu, bir veri geldiğinde 10 ms süre ile ETE bilgisini ara. gelmemiş ise ATLA isimli etikete geç demektir. Komuta timeout değeri ve atlama etiketini eklemeyebilirsiniz. O zaman yanlış (parazit gibi) bir veri geldiğinde program orada epeyce ETE bilgisini almak için beklemek zorunda kalır. BU şekilde ise belirli bir zaman peryodu koymuş olursunuz. Zaten gelecek ise bu süre içinde mutlaka gelir.
ATLA etiketi altına ise,
TEMP=RCREG
RESUME
ENABLE
komutları yer alır.
Program beklenen verileri alsada almasada mutlaka RCREG içini boşaltarak kesme bayrağını sıfırlamalıdır. Böylece yeniden ve gereksiz yere kesme oluşması engellenmiş olur.   

Basic de birde şöyle bir kural vardır. Bu kural Proton için kısmen geçerli. Ama yinede uyulmasında yarar vardır. Kesme aktive edilmiş bir programda kesme bayrağı set edilmiş ise program kesme etiketine gitmeye çalışır. Ancak o anda bir basic komutu (mesela Delayms 1000 gibi) icra ediliyor ise bu komut işlemesi bitmeden kesmeye geçmesi mümkün olmaz. Bu nedenle biz özellikle kesme kullandığımız programlarda uzun süreli Delayms (veya Pause) kullanmaktan kaçınırız. EN büyük süre 5us olmalıdır. Böylece program kesmeye gidebilmek için en fazla 5us beklemiş olurki bu ihmal edilebilecek bir süredir. Uzun gecikmeler gerekirse bir döngü kurularak gecikme adedi artırılır. Örneğin,
FOR W=0 to 1000
  Delayus 5
Next
bu döngü size 1000 adet 5us lik gecikme yaratır. Döngünün kendi komut gecikmeside eklenirse bu gecikme yaklaşık 10 ms dolayında gerçekleşir. Tahmini bir değerdir daha az da olabilir.
Kesme içinde Hserin komutu altına birde ALdı=1 şeklinde bir bit değişkeni set edilir ise ve Programın ana kısmında (BASLA etiketi altındaki komut satırlarında, IF ALDI=1 then şeklinde başlayan bir komut olursa programın herhangi bir bilgi alma durumunda alınan bilgileri ne yapacağınıza o komut altında karar verebilirsiniz ALdı=0 deyip işi bitirirsiniz.

Anlatacaklarım bu kadar. Umarım artık anlaşılmıştır.
Ete projelerinde RF_Termometre isimli bir çalışma var. Örnekleri incelemni öneririm. Bütün bu yazdıklarımı anlatıyor.

Ete



Yorumlar

Popüler Yayınlar:

grup priz ara kablo yapımı

elektrikli fırın devre bağlantı şeması

dc motor yönü değiştirme devresi

gsm sinyal seviyesi asu dbm nedir

chrome ile programsız video nasıl indirilir

fan aspiratör motoru dönüş yönü değiştirme