rs232 iletişimde kesme sorunu

Başlatan cmcnr, 19 Mart 2011, 17:23:17

cmcnr

rs232 'de int_rda kesmesini kullandığımda artık kesmeyi başarı ile çalıştırabiliyorum. Ancak bir kez kesmeye girdiğinde veri gelmese de kesmeye girmeye devam ediyor. Test için hazırladığım kodlar aşağıda. Test aşamasında yapmak istediğim, eğer veri gelirse bir kez ledi yakıp söndürmesi. Ancak ilk veri geldikten sonra led sürekli yanıp sönüyor  :o
Nerede eksiklik var fikri olan var mı?




Alıcı

#include <16f628a.h>
#fuses XT,NOPROTECT,NOCPD,NOBROWNOUT,NOPUT,NOWDT,NOLVP
#use delay(clock=4000000)

#use rs232(baud=9600, xmit=pin_B2, rcv=pin_B1)

#int_rda
void komut_al()
{
output_high(pin_b4);
delay_ms(1000);
output_low(pin_b4);
delay_ms(1000);


}

main()
{
enable_interrupts(int_rda);
enable_interrupts(GLOBAL);
while(1)
{

}
}




Verici
#include <16f628a.h>
#fuses XT,NOPROTECT,NOCPD,NOBROWNOUT,NOPUT,NOWDT,NOLVP
#use delay(clock=4000000)

#use rs232(baud=9600, xmit=pin_B2, rcv=pin_B1)

main() {



while(1)
{

if(input(pin_a0))
{

}
else
{
printf("Ac\n\r");
}



if(input(pin_a1))
{
}
else
{
printf("Kapat\n\r");
}


delay_ms(150);
}
}

JKramer

Verici için:

Butonlar için bir şeyler yapın. (Bekleme mesela, debounce diye aratabilirsiniz forumda.)

Başlangıç için printf yerine tek bir karakterle deneme yapın. (putc())

Alıcı için:

Sadece bu kesme için değil, hiçbir kesmede bekleme kullanmayın. Kesme içinde bir değişken kullanın, bunu ana programda test edin. Kabaca;

int1 kesme_durum=0;
#int_rda 
void komut_al() 
{ 
  kesme_durum=1;


} 

main() 
{ 
enable_interrupts(int_rda); 
enable_interrupts(GLOBAL); 
while(1) 
{ 
    if(kesme_durum)
    {

    }

} 
}


#use rs232(baud=9600, xmit=pin_B2, rcv=pin_B1,ERRORS)

Buffer dolduğunda kilitlenmeyi önlemek için gerekli. Eğer her gelen karakteri alırım derseniz sorun yok.

cmcnr

#2
Dediklerinizi dikkate alarak yeni kodlar yazdım. Sonuçta bir değişiklik olmadı.. Atladığım başka bir nokta olabilir mi?
Kodlar şöyle;

Alıcı
#include <16f628a.h>
#fuses XT,NOPROTECT,NOCPD,NOBROWNOUT,NOPUT,NOWDT,NOLVP 
#use delay(clock=4000000) 

#use rs232(baud=9600, xmit=pin_B2, rcv=pin_B1,ERRORS)
char c
int1 x

#int_rda
void komut_al()
{
x=1
gets(c);


}

main() 
{


enable_interrupts(int_rda);
enable_interrupts(GLOBAL);

while(1)
{
   if (x==1)
   {
   output_high(pin_b4);
   delay_ms(1000);
   output_low(pin_b4);
   delay_ms(1000);
   x=0;
   }
}

}


Verici
#include <16f628a.h>
#fuses XT,NOPROTECT,NOCPD,NOBROWNOUT,NOPUT,NOWDT,NOLVP 
#use delay(clock=4000000) 
 
#use rs232(baud=9600, xmit=pin_B2, rcv=pin_B1,ERRORS) 

main() {



while(1)
{

   if(input(pin_a0))
   {
   
   }
   else
   {
   putc('A'); 
   delay_ms(150);
   }


  
  if(input(pin_a1))
   {
   }
   else
   {
   printf("Close\n\r");
   delay_ms(150);
   }
  

}
}

Ferhat Özdemir

#3
Deneme imkanım olmadı. Yazarken imla hatası yapmadıysam çalışması gerekiyor...
Bu arada soylemeyi unuttum. Buton bağlantılarını yeni gordum. İster baglanti şekillerini değiş istersen kodlarında değişiklik yap. Ama benim onerim bağlantı şeklini değiştirmen yonunde.
Yani Butonlar ile dirençleri yer değiştirerek benim kodları denemen gerek. Aksi taktirde çalışmaz.

Verici :
#include <16f628a.h>
#fuses XT,NOPROTECT,NOCPD,NOBROWNOUT,NOPUT,NOWDT,NOLVP 
#use delay(clock=4000000) 
 
#use rs232(baud=9600, xmit=pin_B2, rcv=pin_B1,ERRORS) 

main()
{
	while(true)
	{

	   if(input(PIN_A0))
	   {
	     delay_ms(10);
		 putc('A'); //Aç Komutunu Gonder
		 while(input(PIN_A0)); //Buton bırakılana kadar bekle..
	   }
	    	  
	  if(input(PIN_A1))
	   { 
		 delay_ms(10);
	     putc('K'); //Kapat Komutunu Gonder
		 while(input(PIN_A1)); //Buton bırakılana kadar bekle..
	   }
	    
	  

	}
}




Alıcı :

#include <16f628a.h>
#fuses XT,NOPROTECT,NOCPD,NOBROWNOUT,NOPUT,NOWDT,NOLVP 
#use delay(clock=4000000) 

#use rs232(baud=9600, xmit=pin_B2, rcv=pin_B1,ERRORS)
char c
 

#int_rda
void komut_al()
{
	c = getc();
        disable_interrupts(int_rda);
}

main() 
{

 enable_interrupts(GLOBAL);

while(true)
{
   if (c == 'A')
   {
	output_high(pin_b4);
	c = 0x00;
        enable_interrupts(int_rda);
   }else if(c == 'K')
   {
    output_low(pin_b4);
    c = 0x00;
    enable_interrupts(int_rda);
	  
   }
}

}


@zamzam23 hocam ben dediğiniz olayi biliyorum yalniz bu tarz uygulama yapmiştim once. O zaman sorun vermemişti ondan ekleme geregi duymamistim. Hatirlatmaniz uzerine ekledim.

zamzam23

kesme fonksiyonu ıcerısınde kesmeyı pasif edip dısarıda tekrar aktif etmelısın aksı taktırde veri gelmesede sürelı süreklı kesmeye gırer.

bayelektronik

rda kesmesinde getc() komutu kullanarak yeniden kesmeye gitmeyi engelleyebilirsin yada rda kesme fonksiyonuna girerken kesmeyi iptal eder çıkarken aktif edersin.

ayrıca rda kesmesi içinde delay komutu kullanmak iyi değildir.

salihonur

Buradaki asıl sorun pull-up dirençlerinin yerleri ile ilgili gibi görünüyor. Butonlara seri bağladığın dirençleri buton ile besleme arasına değil de buton ile toprak arasına alırsanız sorun düzelecektir (dirençleri butonların olduğu yere butonları dirençlerin olduğu yere). Ayrıca dirençlerin 10k değeri büyük gelebilir, 1.5k ile değiştirebilirsiniz.

ferdem

#7
Alıntı yapılan: cmcnr - 19 Mart 2011, 17:23:17Ancak ilk veri geldikten sonra led sürekli yanıp sönüyor  :o
Yani kesmeden çıkamıyor, veri geldiğinde RCIF biti 1 e çekilir, kesmeden çıkılabilmesi için 0 a çekilmesi gerekir. RCIF sadece donanım tarafından temizlenebilir*, gelen byte getc() ile okunur ve bu bit donanım tarafından 0 a çekilir. bayelektronik'in dediği gibi kesme içerisinde veriyi getc() ile bir defa okursanız kesmeden çıkarsınız. Örnek kod forumumuzda var, int_rda diye aratırsanız birçok örnek başlık bulabilirsiniz. Başka başlıklarda vardı, buraya da kopyalıyorum:
//picproje.org
//CCS C seri veri kesmesi örnek kullanımı
#include <16F628A.h>
#fuses NOPROTECT, NOMCLR, NOWDT, NOLVP, INTRC_IO
#use delay(clock=4M)
#use rs232(baud=9600, xmit=PIN_b2, rcv=PIN_b1)

unsigned int veri=0;
void main(){
enable_interrupts(global);
enable_interrupts(int_rda);

   while(1){
      output_high(pin_b4);
      delay_ms(1000);
      output_low(pin_b4);
      delay_ms(1000);
   }

}

#int_rda
void seri_veri_geldi(){
veri=getc();
output_toggle(pin_b0);
}




* Flag bit RCIF is a read-only bit, which is cleared by the hardware.
16F628 datasheet http://ww1.microchip.com/downloads/en/devicedoc/40044f.pdf, syf 80

Düzenleme: Kod penceresi görüntüsü düzeltildi.