usart kesmesi, neden hep iki gönderim arasını es geçiyor?

Başlatan fryrmnd, 14 Eylül 2011, 17:02:01

fryrmnd

proteusta iki 16f877a yı seri bağlayıp aşağıdaki kodlarla denedim. pic basic pro  komutları  sırayla işlediğinden dolayı mı alıcı da 2 gönderim arasını sürekli atlıyor.

verici:
DEFINE LCD_DREG		PORTB	
DEFINE LCD_DBIT			4		
DEFINE LCD_EREG		PORTB	
DEFINE LCD_EBIT			3		
DEFINE LCD_RSREG	PORTB	
DEFINE LCD_RSBIT		2				
DEFINE LCD_BITS			4	
DEFINE LCD_LINES		2

DEFINE OSC 4
INTCON=%11000000
CMCON=7
ADCON1=7

DEFINE HSER_RCSTA 90h   
DEFINE HSER_TXSTA 20h   
DEFINE HSER_BAUD  2400 
DEFINE HSER_SPBRG 25 


PORTA=0
PORTB=0
PORTD=0
PORTE=0
TRISA=0
TRISB=0
TRISD=0
TRISE=0
TRISC=%10000000




SYMBOL GIE=INTCON.7
SYMBOL PEIE=INTCON.6
SYMBOL RCIE=PIE1.5
SYMBOL RCIF=PIR1.5

VERITX VAR BYTE



PAUSE 300
LCDOUT $FE,1

VERITX=5

BASLA:

lcdout $fe,1
LCDOUT $FE,$80,"VERICI"

PAUSE 5000

LCDOUT $FE,1
LCDOUT $FE,$80,"YOLLANIYOR"
HSEROUT [VERITX]
pause 2000
goto basla


END



alıcı:
DEFINE LCD_DREG		PORTB	
DEFINE LCD_DBIT			4		
DEFINE LCD_EREG		PORTB	
DEFINE LCD_EBIT			3		
DEFINE LCD_RSREG	PORTB	
DEFINE LCD_RSBIT		2				
DEFINE LCD_BITS			4	
DEFINE LCD_LINES		2

DEFINE OSC 4

CMCON=7
ADCON1=7

DEFINE HSER_RCSTA 90h   
DEFINE HSER_TXSTA 20h   
DEFINE HSER_BAUD  2400 
DEFINE HSER_SPBRG 25 


PORTA=0
PORTB=0
PORTD=0
PORTE=0
TRISA=0
TRISB=0
TRISD=0
TRISE=0
TRISC=%10000000



SYMBOL GIE=INTCON.7
SYMBOL PEIE=INTCON.6
SYMBOL RCIE=PIE1.5
SYMBOL RCIF=PIR1.5



TEMP VAR BYTE
VERIRX VAR BYTE

ON INTERRUPT GOTO KESME

GIE=1
PEIE=1
RCIE=1



PAUSE 300
LCDOUT $FE,1

BASLA:


IF VERIRX=5 THEN
lcdout $fe,1
LCDOUT $FE,$80,"ALINDI"
verirx=0
pause 1000


ENDIF 


lcdout $FE,$80,"BEKLENIYOR"


GOTO BASLA

DISABLE
KESME:
GIE=0
TEMP=RCREG


HSERIN [VERIRX]

RCIF=0

GIE=1

RESUME
ENABLE




ete

Normal şartlarda Verici programda bu kadar pause komutu olması pek iyi bir şey değil.
Alıcının alma şansını artırabilmek için pause miktarlarını azaltmanızda yarar var. Aslında ALıcı kısmında Usart kesmesi kullandığınız için çok önemli değilmiş gibi gözüksede yollama ile alma arasında bir senkron yakalamak için verici kısımdaki pause leri azaltmakta yarar var.

Alıcı kısımda ise iki önemli kusur var. Bunlar sırası ile;
- Kesme kullanılan programlarda Pause komutunu kullanmamak gerekiyor. Çünki pause 1000 gibi bir komut çalışırken Usart portuna veri gelse pause komutu bitmeden program oraya (kesme alt programına) gidemeyecektir. Pause süresi bittikten sonra gidecek ama orada veri çoktan yollanmış yada alınbmış olacaktır. Kısaca veriyi program kaçıracaktır. Peki çözüm nedir mümkün olduğunca kısa pauseus lar kullanıp döngü içinde süreyi uzatmak gerekir.
Sizin örneğinize göre Pause 1000 yerine;
FOR I= 0 to 10000
  pauseus 5
next
şeklinde bir döngü kursanız işiniz hallolur. Bu durumda program kesme oluştuğu anda en fazla 5us gecikme ile veri almaya gidebilir. Bu gecikmeyide elimine etmek için preambl ve uyandırma sinyali kullanmanızda yarar vardır.
Veren program asıl bilgiyi vermeden önce 5 byte $AA , 5 Byte $FF ve 5 Byte $00 bilgisini yollarsa veri kaybı olmadan gelen bilgiler kolaylıkla alınabilir. Bu nedenle verici programa aşağıdaki satırıda ilave etmenizde yarar vardır;
HSEROUT [REP$AA\5,REP$00\5,REP$FF\5]

Ayrıca veri paketi başında bir işaretçi kullanırsanız verileriniz daha kolay alınır ve ayıklanır. Mesela,
HSEROUT [VERITX]  yerine
HSEROUT ["F","R","Y",VERITX] kullanırsanız paket başı işlemci tarafından kolaylıkla bulunur.
Tabiiki alıcıda bu konuda bir değişiklik yapıp

HSERIN [VERIRX] yerine

HSERIN [WAIT("FRY"),VERIRX] komutunu kullanmanız gerekecek.

İkinci kusur ise USART kesme bayrağının silinmesi için  RCREG registerinin okunması gerekmektedir.
Siz bu okumayı alma işleminden önce yapmışsınız. Bu yeniden kesme oluşumunu engelleyebilir. Yada sistem yanlış çalışır. Bu nedenle okuma işlemini Hserin komutlarından sonra yapmanız gerekir. Hatta orada yer alan  RCIF=0 satırınıda silebilirsiniz bir işe yaramıyor çünki.

Ete

Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

fryrmnd

kusurları anladım Ete hocam.  peki diyelimki vericinin yolladığı verinin ilk birkaç biti ana döngüdeki komut işlenme süresinden vs dolayı kaçtı,daha doğrusu kaçabilirmi.(yanılmıyorsam asm de dahi böyle bir ihtimal var) böyle bir sorun istemezsek ne yapabiliriz. aynı veriyi garanti olsun diye birkaç kere mi yollamalı yada alıcının alıp almadığını  mı test etmeye çalışmalı. demek istediğim sonuçta usart kesmesi ile bir program yazmak. yani ana döngüde bayağı  bir kod olabilir. bilmiyorum belki "lcdout" komutu sırasında bile verinin ilk birkaç biti kaçabilir gibime geliyor. sanırım derdimi anlatabildim. teşekkürler.

ete

Veri başına uyandırma ve preambl koyulmasının amacı bu tür kusurları önlemek zaten. Koyun onları veri kaybınız olmaz.
Tabiiki diğer dediklerimide yapmanız şartı ile .
Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com