Haberler:

Forum kuralları güncellendi LÜTFEN  okuyunuz:  https://bit.ly/2IjR3ME

Ana Menü

Seri İletişim Kesme Sorunu

Başlatan vitruvius, 04 Temmuz 2012, 13:43:36

vitruvius

Merhaba, seri iletişim kesmesinde ufak sorunlarım var. "A" ve "D" tuşlarına basıldığında led yakmayı ve bir değişkenin değerini değiştirmeyi çalışıyorum. Şu an şu şekilde çalışıyor program:

Tuşlara A-D-A-D-A-D sırasıyla basarsam ledler sırayla yanıp sönüyor. Tuşlara D-A-D-A-D-A sırasıyla basarsam ilk başta D'nin yaktığı ledin yanması için D'ye iki kere basmak zorunda kalıyorum. İlk bastığımda kesme için ayarladığım led yanıyor, ikinci bastığımda D'nin ledi yanıyor. Bunun kodlardaki sıradan kaynaklandığını farkettim, kodda if(getc()=='a') ile if(getc()=='d')'nin yerini değiştirince durum tam tersi oluyor.

Normal çalışmada üst üste 2 kere aynı tuşa basarsam da diğer tuşun ledini yakmam için o tuşa da 2 kere basmam gerekiyor.

Değişkeni değiştirmek için de herhangi bir tuşa iki kere basmam gerekiyor. Eğer bir tuşa basılı tutarsam da değişken 2-3 kere değişip kilitleniyor.

Bu sorunları nasıl çözebilirim acaba?

Kod:
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay (clock=4000000)
#use fast_io(b)
#define use_portb_lcd TRUE
#include <lcd.c>
#use rs232 (baud=9600, xmit=pin_C6, rcv=pin_C7, parity=N, stop=1)

int i=0;
#int_rda
void seri_haber()
{
   disable_interrupts(int_rda);
   output_high(pin_d2); // Kesme Ledi
   printf("\f\r Kesme ici");
   if(getc() == 'a')
   {
    output_high(pin_d3);
    output_low(pin_d4);
    i=i-1;
    printf("\f\r A tusuna basildi");
   }
   if(getc() == 'd')
   {
    output_high(pin_d4);
    output_low(pin_d3);
    i=i+1;   
    printf("\f\r D tusuna basildi"); 
   }
}

void main()
{
   setup_psp(PSP_DISABLED);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_CCP1(CCP_OFF);
   setup_CCP2(CCP_OFF);
   set_tris_b(0x00);
   lcd_init();
   
   printf("\r Ana fonksiyon ici");
   
   enable_interrupts(GLOBAL);
      
   while(1)
   {
      enable_interrupts(int_rda);
      output_low(pin_d2); // Kesme ledi     
      printf(lcd_putc,"\f I degeri=%d",i);
      delay_ms(100);
   }
}


Devre şemam:


Teşekkürler.

serhat1990

Telefondan giriyorum zor gözüküyor ama bir şöyle dene istersen...

#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay (clock=4000000)
#use fast_io(b)
#define use_portb_lcd TRUE
#include <lcd.c>
#use rs232 (baud=9600, xmit=pin_C6, rcv=pin_C7, parity=N, stop=1)

int i=0;
int veri=0;
#int_rda
void seri_haber()
{
   disable_interrupts(int_rda);
   veri=getc();
   output_high(pin_d2); // Kesme Ledi
   printf("\f\r Kesme ici");
   if(veri== 'a')
   {
    output_high(pin_d3);
    output_low(pin_d4);
    i=i-1;
    printf("\f\r A tusuna basildi");
   }
   if(veri== 'd')
   {
    output_high(pin_d4);
    output_low(pin_d3);
    i=i+1;   
    printf("\f\r D tusuna basildi"); 
   }
}

void main()
{
   setup_psp(PSP_DISABLED);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_CCP1(CCP_OFF);
   setup_CCP2(CCP_OFF);
   set_tris_b(0x00);
   lcd_init();
   
   printf("\r Ana fonksiyon ici");
   
   enable_interrupts(GLOBAL);
      
   while(1)
   {
      enable_interrupts(int_rda);
      output_low(pin_d2); // Kesme ledi     
      printf(lcd_putc,"\f I degeri=%d",i);
      delay_ms(100);
   }
}


Kolay gelsin...

vitruvius

Hocam teşekkür ederim, dediğiniz gibi yapınca bir tek şu sorunum kaldı. Bir tuşa basılı tutunca değer 3-5 kere değişip sistem kilitleniyor. Bu basılı tutma olayı için ne önerirsiniz? Tuşa bastıktan sonra gecikme vermeyi denedim ama sonuç aynı.

serhat1990

Sistem nasıl kitleniyor ledlermi yanıp sönmüyor yoksa ekrana bilgi mesajımı yazmıyor ?

vitruvius

Şöyle; diyelim ki D'ye basılı tuttum. D'nin ledi yanıyor, i değişkenim artıyor ve sistem donuyor. Yani elimi çektikten sonra A'ya da bassam D'ye de bassam ne ledlerde ne de değişkenin değerinde bir değişme olmuyor. Dakikalarca beklesem de düzelmiyor.

omereliusuk

while(1)
   {
if(bit_test(*(0x0018),1))
      {  //her iki tamponda doluysa hata var ! temizledik bilgi alma hatası varsa bunları imha ettik.
      *(0x0018)&=0xef; *(0x0018)|=0x10; //   *(0x008c)|=0x20;
       enable_interrupts(INT_rda);
       enable_interrupts(GLOBAL);
      }
      enable_interrupts(int_rda);
      output_low(pin_d2); // Kesme ledi     
      printf(lcd_putc,"\f I degeri=%d",i);
      delay_ms(100);
   }

vitruvius

Teşekkür ederim hocam kilitlenme sorunu kalktı yalnız kodu anlayamadım. Bit_test() ile bir değişkenin istenen bitinin durumunu öğreniyoruz. (0x0018), 0xef, 0x10; değerlerini nereden bulduk? Bir de ifadenin başına * koyunca ne anlama geliyor acaba?

Teşekkürler.

ferdem

vitruvius, seri data kesmesini bir defa aktif ettikten sonra artık ne kesme rutini içerisinde ne de while içerisinde enable/disable işlemlerine gerek yok, CCS C gerekenleri yapıyor ama içim böyle daha rahat diyorsan bilemem :)
Kilitlenme, kesme içerisindeki bir rutinin kesme öncesinde de kullanıldığı durumlarda olabiliyor. Kesme içerisindeki printf leri kaldırıp deneyebilirsin veya onları "puts" olarak kullanmayı deneyebilirsin. İyi çalışmalar.

omereliusuk

RSR kaydedicisine kaydırılarak gönderilen verinin gönderme işlemi tamamlandığında RCREG  kaydedicisinin her iki tamponu da doluysa  0x0018 adresinin 1. bitinde bulunan OERR (RCSTA<1>) 1 OLUR. Bu durum üstüne yazma hatası var demektir. bu anda tamponlardaki veri kaybolur. yine bu durumda veri alımı yapılamaz. sizin kilitlenme durumu burada başlıyor. bunu yok etmek için CREN (RCSTA <4>) biti önce 0 daha sonra 1 yapılmalıdır. artık yeni bilgiyi alabilirsiniz. kaynak  Pic Programlama Teknikleri ve 16f877a Altaş Yay. Hikmet Şahin Ayhan Dayanık Caner Altınbaşak sayfa.262  assembly olarak anlatıyor
bu bilgi ccs c kitabında yok malesef.




justice_for_all

#use rs232 (baud=9600, xmit=pin_C6, rcv=pin_C7, parity=N, stop=1, errors)


bu sekilde deneyin bide..
Deneyip de başaramayanları değil, yalnızca denemeye bile kalkışmayanları yargıla.   Gökhan Arslanbay

vitruvius

Alıntı yapılan: ferdem - 05 Temmuz 2012, 05:05:29
vitruvius, seri data kesmesini bir defa aktif ettikten sonra artık ne kesme rutini içerisinde ne de while içerisinde enable/disable işlemlerine gerek yok, CCS C gerekenleri yapıyor ama içim böyle daha rahat diyorsan bilemem :)
Kilitlenme, kesme içerisindeki bir rutinin kesme öncesinde de kullanıldığı durumlarda olabiliyor. Kesme içerisindeki printf leri kaldırıp deneyebilirsin veya onları "puts" olarak kullanmayı deneyebilirsin. İyi çalışmalar.

Hocam Serdar Çiçek'in kitabından çalışıyorum ve orada INT_RDA kesmesi için şunu demiş o yüzden öyle yaptım: ...Fakat bu kesmede; kesme fonksiyonu çıkışında, kesme pasif hale getirilmelidir. Aksi takdirde program hep kesmeye gidecektir. Örnek uygulamasında da bu işlemin yapılmasının mecburi olduğunu söylemiş ve uygulamasında bu şekilde yapmış.

@omereliusuk; teşekkür ederim bahsettiğiniz kısımları araştıracağım.

@justice_for_all; Hocam size de teşekkür ederim o şekilde yapınca da sorun kalktı. Errors kullanımını da kitapta göremedim. Bu ilave ile derleyici neleri düzeltiyor ve bu kullanımda dikkat etmem gereken şeyler var mı?

justice_for_all

Alıntı YapUsed to cause the compiler to keep receive errors in the variable RS232_ERRORS and to reset errors when they occur.

bu komut ile Derleyici rs323 hatalarını RS232_ERRORS değişkeninde tutar ve bu hatalar oluştuğunda  temizler.

Deneyip de başaramayanları değil, yalnızca denemeye bile kalkışmayanları yargıla.   Gökhan Arslanbay