usart kesmesi

Başlatan zihnisinir, 30 Eylül 2020, 09:16:06

zihnisinir

merhaba hocam
belli bir zamandır pic basic ile uğraşıyorum ama daha tam bir hakimiyet sağlamış değilim üzerinde o yüzden en basitten başlayarak kimi devreler yaptım  ve sonuç verdiler ama usart kesmesinde takıldım kaldım. kaç gündür forumları geziyorum, okuyorum ama sonuç yok. en sonunda yeniden tasarlamaya karar verdim ama bu seferde kafam hep dah aöncekinde takılı kalıyor. o yüzden de yardıma ihtiyacım olduğunu düşünüyorum. yardım ederseniz sevinirim.

ete

KOnu usart kesmesi bunu anladım da yardımı ne için istiyorsun yada neresi için istiyorsun onu anlamadım. Ders notlarında okadar uzun ve açık anlattımki herkes anlamış. Sende iyice okursan anlarsın gibime geliyor.
Temel amaç, RX pininden bir bilgi geldiği zaman kesme oluşturmak ve o bilgiyi belirli bir kural çerçevesinde almak. Bir kaç temel kriter var.
1. Birincisi , USART kesmesi nasıl aktive edilir. Burada anlatmayacağım sen araştır ve bul ders notlarıma bakıver.
2. Kesme içinde ne yapılır, Burada HSERIN komutu ilee gelen bilgi alınır. Ancak RX pinindeki en ufak parazit bile kesme yaratabilir. Gelen bilginin doğru bilgi olduğunu belirlemek için Bilgi başı tanımlayıcı kullanırız "ETE" gibi. WAIT ("ETE") . Ardından kaç byte gelecek ise onların sayısı kadar byte değişkeni kullanırız. Bilg1,Bilgi2... gibi.
3. Kesmeden çıkmadan önce ne yapılır. Kesme bayrağı sıfırlanmalıdır. Her kesme oluştuğğunda o kesmeye ait bayrak (FLAG) set edilir. İŞlemci buradan kesme olduğunu anlar ve KESME etiketine gider. Kesmeden çıkmadan o bayrağın tekrar reset edilmesi gerekir. USRT kesme bayrağı direk ulaşılabilir bir bayrak değildir. Yani direk bayrağı sıfırlayamazsın. Bunun yerine RCREG registerini okuyarak o registeri boşaltırsan bayrak da otomatik silinmiş oluyor. Bu nedenle orada kesmeden çıkmadan önce TEMP=RCREG şeklinde bir komut koyarak bayrağı sıfırlamış oluyoruz.

Gerisi rutin işler. Hepsi bu kadar.
Ete
 

zihnisinir

hocam bu söylediklerinizi yaptım, okudum da ama yeterli cevabı bulamadım ya da anlayamadım diyelim.. velhasıl ben usart'a en temelden  başladım yani bir butona bastığımda tx pininden(16F628A'da portb nin 2. pini) sağlıklı bir şekilde sinyal göndermek istiyorum. ama Hserout komutunu yazdığım an da entegrenin tx-rx pinleri çıkış oluyorlar, programda hali ile şu basit komutu bile uygulayamıyor.

    @ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _CP_OFF
  porta=0
  trisa=0
  portb=0
  trisb=%10000000
  
  CMCON=7
  OPTION_REG.7=1
  INTCON.7=1
  
temp var word   
symbol rx=portb.1    
symbol buton=portb.7
symbol cikis=portb.2

DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 25  '9600 baud @ 4mhz
DEFINE HSER_CLROERR 1 ' Clear overflow automatically


cikis=0
buton=0
rx=0

clear 
pause 250

basla:

if buton=1 then 
toggle cikis 
pause 250
gosub send
endif 


SEND:
 
HSEROUT [REP$AA\5,REP$00\5,REP$FF\5]
HSEROUT ["A","R","A",buton]
RCREG=TEMP

RETURN
goto basla 
end

burada ne yanlışlık var en basitinden mesela.

ete

USART kesmesi kullanınca PORTB.1 pini giriş olarak ayarlanması zorunludur. BU RX pinidir ve program içinde başka bir amaçla kullanılamaz. Benzer şekilde TX pinide çıkış olur ve yine program içinde başka amaçla kullanılamaz.
Bir programda    Define OSC 4  şeklinde komut satırı verilerek programın hangi frekansta çalışacağı belirtilmelidir. Aksi halde Seri portdan bilgi yollanırken hangi frekans'a göre bitlerin yollanacağı karambolde kalır.

Devrede 1 adet buton mevcut ve anladığım kadarı ile dahilii pullup lar iptal edilip Buton LOW da bekleyecek şekilde kullanılmış. Yani butona basınca PORTB.7 pinine HIGH verecek şekilde.
Peki o buton pininde PULL_DOWN direnci varmıdır? yoksa eklenmelidir.
Bu işlemcilere dahaili pullup direnci yerleştirilerek buton kullanımında HIGH da bekleyen buton kullanılması ve butona basınca pine LOW uygulayan sistemler desteklenmiştir. Sen tersini yapmışsın. Pull-down direnci önemli.

Buton kontrolünü ;
if buton=1 then 
toggle cikis 
pause 250
gosub send
endif 
şeklinde yaparsan sen elini butondan çekinceye kadar o yeniden butona basar ve Toggle komutu nedeni ile çıkışı göremeyebilirsin. Doğrusu aşağıdaki şekilde olmalı.
if buton=1 then 
  toggle cikis 
  gosub send
  While Buton=1:wend
  pause 250
endif 

Ete

zihnisinir

#4
'****************************************************************
'*  Name    : verici.BAS                                      *
'*  Author  : [select VIEW...EDITOR OPTIONS]                    *
'*  Notice  : Copyright (c) 2020 [select VIEW...EDITOR OPTIONS] *
'*          : All Rights Reserved                               *
'*  Date    : 30.09.2020                                        *
'*  Version : 1.0                                               *
'*  Notes   :                                                   *
'*          :                                                   *
'****************************************************************
@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _CP_OFF
define OSC 4
trisa=0:porta=0
trisb=%10000010:portb=0
CMCON=7
OPTION_REG.7=1
INTCON=0
  
temp var word   
'symbol giris=portb.1 bu gereksiz
symbol cikis=portb.3  'TX pinini normal çıkış pini gibi kullanmamalısın başka bir pin kullandım    
symbol buton=portb.7


DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 25  '9600 baud @ 4mhz
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

clear 
pause 250

basla:
if buton=1 then 
  high cikis 
  gosub send
  While Buton=0:wend
  low cikis
  pause 250
endif 
 goto basla

SEND:
 
HSEROUT [REP$AA\5,REP$00\5,REP$FF\5]
HSEROUT ["A","R","A",buton]

RETURN
end






söyleediklerinizi yaptım söylediklerinizden farklısını da yaptım ama sonuç değişmedi. ya ben çok fazla baktığım için göremiyorum ya da temel bir konu var onu anlamadım. ama sorun ne olursa olsun çözemedim..

zihnisinir

portb'yi portb=0 olarakta yaptim. pek çok versiyon ile denedim dediğim gibi..

ete

#6
Programda hata var.

Üzerinde düzelttim. Bu şekilde dene. Birde bu devrede na yapıyorsunda olmuyor yada olmadığını nasıl anlıyorsun?
Bu bir haberleşme işidir ve sen haberleşmeyi led yakarak göremeye çalışıyorsun gibi geliyor bana.
Komut o kadar hızlı o ledi açar kaparki sen sürekli sönük olarak görürsün.
Led yerine oraya skop bağla ve sonucu skop ekranında gör nasıl data çıkıyor.
Bu arada CIKIS pinini değiştirp PORTB.3 e verdim. Oraya led bağlasan daha iyi olacak.
TX yada RX pinlerini program içinde başka amaçlarla kullanmaman gerekiyor.
Sen HIGH (yada LOW) CIKIS diyerek amaca ters düşen bir iş yapmış oluyorsun.
Ete

zihnisinir

Teşekkür ederim tecrübelerinizi paylaştığınız için.Şimdi ben verdiğiniz temel üzerinden vericiyi de alıcıyı da geliştirmeyi hedefliyorum..

zihnisinir

#8
Merhaba hocam .. Her zamanki gibi forumu hem incelemeye hem devam ediyorum hem de derslerinize bakarak pic üzerinde çalışmalara. Neticede usart kesmesi ve TMRO kesmelerini kullandığım bir alıcı-verici devresi yapmaya çalıştım(şimdilik kabl bağlantısı var, yazılım kısmından sonra modülünü de ekleyeceğim). Şu an ki hali ile de istediğim gibi çalışmamakta.. yardımcı olursanız sevinirim.


bu vericidir
 @ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _CP_OFF & _PWRTE_ON 
define OSC 4
trisa=0
trisb=%11100000:portb=0
CMCON=7
OPTION_REG.7=1
INTCON=0
  
sayac var word  
symbol buton=portb.0
symbol butonpat=portb.6
symbol butonpat2=portb.5
symbol cikis=porta.0
symbol cikis1=porta.1
symbol cikis2=porta.2

DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 25  '9600 baud @ 4mhz
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

clear 


basla:

if buton=1 then 
  cikis=1
   gosub send
    else 
     cikis=0
      endif
  
  if butonpat=1 then 
   cikis1=1
    gosub send
     else 
      cikis1=0
        endif

  if butonpat2=1 then
   cikis2=1  
    gosub send
     else 
      cikis2=0             

  endif
  goto basla
 

SEND: 
HSEROUT [REP$AA\5,REP$00\5,REP$FF\5]
HSEROUT [porta.0,5,"A","R","A",BUTON]
 return 
 end

zihnisinir

bu alıcı

 @ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _CP_OFF & _PWRTE_ON
 
 define OSC4
PORTA=0:PORTB=0
TRISA=%000000001:TRISB=0
OPTION_REG=%11000101 'tum kesmeler ve tmro kesmesi acik  1/4 
CMCON=7 

DEFINE HSER_RCSTA 90h   ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h   ' Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 25    '9600 baud @ 4mhz
DEFINE HSER_CLROERR 1   ' Clear overflow automatically

SYMBOL GIE  =INTCON.7   'genel interruptları açıyor
SYMBOL PEIE =INTCON.6   'peripheral interruptları açıyor
SYMBOL RCIE =PIE1.5     'USART Recive interrupt enable bit
SYMBOL RCIF =PIR1.5     'USART Receive interrupt flag bit
 
CLEAR

TMRO var byte         
temp var byte
sayac var word
symbol giris2=porta.0
symbol cikis1=portb.3




 on interrupt goto KESME
 PEIE=1:RCIE=1:GIE=1  

 
 INTCON.5=1 'tmr kesmesini aciyor 
 'INTCON.2=1  BU TARTISMALI SORULABILIR 
  
  

 disable
 KESME:
  GIE=0
     if INTCON.2=1 and porta.0=1 then 
          SAYAC=SAYAC+1
          IF SAYAC=61 then  	    
           SAYAC=0 
           tmr0=tmr0+1  
             for sayac=50 to 58  'bu yaptigim sadece komutu takip etmek icin. silinebilir yine de 
              gosub gonderme
                PORTb.3=1
                  sayac=0  
               IF tmr0=60 THEN  	         	   
                    tmr0=0
                     INTCON.5=0 
                       'INTCON.2=0         	   ' dakika sifirlaniyor
                ENDIF     
                next sayac  
                 endif
                  endif 
                         
         RESUME
         ENABLE
  
      
    gonderme:
      GIE=0
    'HSEROUT [REP$AA\5,REP$00\5,REP$FF\5]'uyandirma siny
    hSerIn 10,dene,[WAIT("ARA"),sayac] 
    temp=RCREG
    temp=0 
       
    dene:             
    RCIF=0
    GIE=1
    Resume
    enable
    end

zihnisinir




hocam kısaca yapmak istediğim şeyi söyleyeyim. Amacım ac butonuna basıp ra.0 portundan çıkış almak ve o port aktif hale gelincede ledi yakabilmek. led yanınca da tmro a göre her 1 dakika da bir yanıp sönmesini istiyorum ama ne yazık ki olmuyor. butona bastığımda rx ayağı sarı işareti veriyor. bunu vermezden önce de sadece sinyal algılanıyordu ama ışık yanmıyordu. nasıl çözüm olabilirim acaba ya da nerede yanlış yaptım ?

ete

bacağın sarı gözükmesi demek çıkış olan pir pine çıkan değerin aksine bir değer geldiğini gösteriyor. TX==>RX pinine bağlanması gerek. Her iki tarafta da RX pinleri giriş olarak ayarlanmalıdır.
TX pinide de çıkış olacak elbette.
Programları ve simulasyon dosyasını buraya koy bakayım. Temel prensibim şöyle kişi bir şeyler karalayacak tabiiki anlamsız şeyler olmamalı. Bu şekilde olursa eksikleri bulur tamamlar ve açıklamalı doğru programı veririm. Böylece hem doğrusunu görür ve en önemlisi önceden yaptıkların ile karşılaştırıp nerede hata yaptığını görerek işi öğrenirsin 

Ete

zihnisinir

#12
hocam yukardaki iki yorumda yazmıştım. kodları yeniden gönderiyorum. İlginize teşekkürler..

verici kodu:

'****************************************************************
'*  Name    : UNTITLED.BAS                                      *
'*  Author  : [select VIEW...EDITOR OPTIONS]                    *
'*  Notice  : Copyright (c) 2020 [select VIEW...EDITOR OPTIONS] *
'*          : All Rights Reserved                               *
'*  Date    : 1.10.2020                                         *
'*  Version : 1.0                                               *
'*  Notes   :                                                   *
'*          :                                                   *
'****************************************************************
 @ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _CP_OFF & _PWRTE_ON 
define OSC 4
trisa=0
trisb=%11100000:portb=0
CMCON=7
OPTION_REG.7=1
INTCON=0
  
sayac var word  
symbol buton=portb.0
symbol butonpat=portb.6
symbol butonpat2=portb.5
symbol cikis=porta.0
symbol cikis1=porta.1
symbol cikis2=porta.2

DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 25  '9600 baud @ 4mhz
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

clear 


basla:

if buton=1 then 
  cikis=1
   gosub send
    else 
     cikis=0
      endif
  
  if butonpat=1 then 
   cikis1=1
    gosub send
     else 
      cikis1=0
        endif

  if butonpat2=1 then
   cikis2=1  
    gosub send
     else 
      cikis2=0             

  endif
  goto basla
 

SEND: 
HSEROUT [REP$AA\5,REP$00\5,REP$FF\5]
HSEROUT [porta.0,5,"A","R","A",BUTON]
 return 
 end
''return
 'send2:
'HSEROUT [REP$AA\5,REP$00\5,REP$FF\5]
''hserout ["R","C","C", butonpat]
'return

'send3:
'HSEROUT [REP$AA\5,REP$00\5,REP$FF\5]
'hserout ["a","b","c", butonpat2]
'return
'end


alıcı kodu:
 @ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _CP_OFF & _PWRTE_ON
 
 define OSC4
PORTA=0:PORTB=0
TRISA=%000000001:TRISB=0
OPTION_REG=%11000101 'tum kesmeler ve tmro kesmesi acik  1/64
CMCON=7 

DEFINE HSER_RCSTA 90h   ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h   ' Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 25    '9600 baud @ 4mhz
DEFINE HSER_CLROERR 1   ' Clear overflow automatically

SYMBOL GIE  =INTCON.7   'genel interruptları açıyor
SYMBOL PEIE =INTCON.6   'peripheral interruptları açıyor
SYMBOL RCIE =PIE1.5     'USART Recive interrupt enable bit
SYMBOL RCIF =PIR1.5     'USART Receive interrupt flag bit
 
CLEAR

TMRO var byte         
temp var byte
sayac var word
symbol giris2=porta.0
symbol cikis1=portb.3




 on interrupt goto KESME
 PEIE=1:RCIE=1:GIE=1  

 
 INTCON.5=1 'tmr kesmesini aciyor 
 'INTCON.2=1  BU TARTISMALI SORULABILIR 
  
  

 disable
 KESME:
  GIE=0
     if INTCON.2=1 and porta.0=1 then 
          SAYAC=SAYAC+1
          IF SAYAC=61 then  	    
           SAYAC=0 
           tmr0=tmr0+1  
             for sayac=50 to 58  'bu yaptigim sadece komutu takip etmek icin. silinebilir yine de 
              gosub gonderme
                PORTb.3=1
                  sayac=0  
               IF tmr0=60 THEN  	         	   
                    tmr0=0
                     INTCON.5=0 
                       'INTCON.2=0         	   ' dakika sifirlaniyor
                ENDIF     
                next sayac  
                 endif
                  endif 
                         
         RESUME
         ENABLE
  
      
    gonderme:
      GIE=0
    'HSEROUT [REP$AA\5,REP$00\5,REP$FF\5]'uyandirma siny
    hSerIn 10,dene,[WAIT("ARA"),sayac] 
    temp=RCREG
    temp=0 
       
    dene:             
    RCIF=0
    GIE=1
    Resume
    enable
    end

hocam alıcı ve verici kodları bu şekildedir. şemada yukarıda zaten. ben yeniden tx-rx ayarlarını da gözden geçireceğim..

zihnisinir

define OSC 4
trisa=0
trisb=%010100010:portb=0
CMCON=7
OPTION_REG.7=1
INTCON=0
hocam vericiyi bu şekilde

alıcıyı ise
 
 define OSC4
PORTA=0:PORTB=0
TRISA=%000000001:TRISB=%000000010
OPTION_REG=%11000101 'tum kesmeler ve tmro kesmesi acik  1/4 
CMCON=7 
bu şekilde değiştirdim. şimdi sarı hata vermiyor ama fatal eror veriyor bir süre sonra hem de çok yavaş çalışıyor.

ete

Yaptığın işe yeterince dikkat etmediğiniz görüyorum. Üstelik örnekler olmasına rağmen alakasız şeyler yazmışsınki buda ilgili konuları yeterince okumadığını gösteriyor.
Bir BYTE değişkeni yada registeri 8 bitliktir ona 7 bitlik yada 9 bitlik değer vermezsin. Verirsen işler karışır derleyici kendine yeten kısmını alır eksik varsa sıfır ile doldurur.
TRISB lere kaç bit değer vermişsin bir bak istersen.
Derlerde ve mesajlarda bağıra bağıra söyledik. Bir pin giriş yapılacak ise ona ait BIT TRIS registerine 1 yapılmalıdır. Bak bakalım ButonPAT ları tris registerinde tanımlamışmısın!!!!
Daha USART olayını çözmeden çift kesme ile çalışmaya kalkışmışsın buda bir hata. Hadi bunuda geçtik Alıcı programda kim ne yapıyor belli değil. Kim o çıkış ledini yaktıracak varmı öyle bir komut?? yok elbette.
Her neyse daha söyleyecek çok şey var en iyisi çalışan programları ve benim isteyip de senin vermedin simulasyon dosyasını ilişikte veriyorum. Versiyon uyuşmazlığı olursa pdf dosyasını açıp şemayı oradan görebilirsin.
Yaptığım şey şu daha doğrusu çalışma senaryosu şöyle;
Verici tarafında BUTON'a basılırsa karşıya 10 rakamı yollanıyor.
Verici tarafında BUTONPAT tuşuna (PORTB.6) basınca karşıya 20 rakamı yollanıyor.
Verici tarafında BUTONPAT2 tuşuna basınca karşıya 30 rakamı yollanıyor.
Bu sayade basılan butonları yollanan rakam değerleri ile ayırmış bulunuyoruz.
Alıcı tarafında şayet gelen VERI=10 ise Çıkış ledini yakıyoruz. Led yandı kim söndürecek? Onuda gelen VERI=20 ise yapıyoruz. Yaniş VER=20 ise yanan led sönüyor.
Gelen Veri=30 ise Led 3 defa flash yapıyor. Buradanda farklı bir butona basıldığını anlayabiliyoruz. Uamrım sende ne olup bittiğini anlayabilirsin.
Programları baştan sona incele ki gereken komutlar nerede nasıl verilmiş göresin.

Ete

Powered by EzPortal