Seri İletişim Alıcı sorunu

Başlatan matador, 25 Temmuz 2012, 23:10:23

matador

Seri iletişimde içinden çıkamadığım ve anlayamadığım noktalar var.

char veri[20];

void  RDA_isr(void) 
{
   disable_interrupts(INT_RDA);
   printf("kesme olustu\r\n");
   gets(veri);
   printf(veri);
}



void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);

   while(true)
   {
      printf("Data Alımı Bekleniyor\r\n");
      if(bit_test(*(0x0018),1))
      {
         *(0x0018)&=0xef; *(0x0018)|=0x10;// *(0x008c)|=0x20;
         enable_interrupts(global);
         enable_interrupts(INT_RDA);
      }
   }
}


Yazdığım kod bu. Denemeleri isiste virtual terminal ile yapıyorum. Sorun ise şu Data alımı bekleniyor yazısı ilk çalışmada ekranda görünüyor fakat vericinin data göndermesine rağmen kesme alt programına işini düzgün yaptıramıyorum.
Asıl amacım uart ile haberleşen rf transreceiver modülleri ile uzaktan robot kontrolü.

ferdem

Kesme içerisinde datayı string olarak değil de karakter karakter alın, getc fonksiyonu kullanabilirsiniz. String olarak veri alırsanız sonlandırma karakteri olmadan çıkamazsınız döngüden. Forumda benim koyduğum örnek vardı, aramay bölümünden bulunabilir. İyi çalışmalar.

matador

#2
Hocam dediğinizi anladım denemeden önce kesme fonksiyonuna girmediğine dair şüphem vardı gets komutunu sildim kesme gerçekleştiğinde virtual terminale kesme olustu yazdırcak mı diye denedim olmadı program kesme fonksiyonuna sanki hiç gitmiyor gibi.




Son bir şey daha denedim bu sefer kesme programı çalıştı verici kısmı için kesme kullandım kesme programı çalıştı.  Alıcıda ki kesme hala çalışmıyor.

Verici:
void  TBE_isr(void) 
{
   disable_interrupts(INT_TBE);
   output_high(Data);
   output_low(PIN_B1);
}


void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_TBE);
   enable_interrupts(GLOBAL);

   while(true)
   {
      unsigned int say=0;
      
      
      output_low(Data);
      output_high(PIN_B1);
      
      say+=1;
      
      delay_ms(5000);
      
      printf("Merhaba\r\n");
      enable_interrupts(INT_TBE);
   }
}


Alıcı:
void  RDA_isr(void) 
{
   disable_interrupts(INT_RDA);
   disable_interrupts(GLOBAL);
   output_high(PIN_B0);
}



void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);

   while(true)
   {
      enable_interrupts(INT_RDA);
      output_low(PIN_B0);
      output_high(PIN_B1);
   }
}



Sorun çözüldü alıcı 877yi çalışma alanına ekleyince x-mirror ile ters çevirmiştim onu düz yapınca program çalıştı. Çok saçma ama düzeldi.

Bir sorum daha olacak verici kısmında int değişkeni stringe çevirip gönderiyorum gelen string ifadeyi nasıl int e dönüştürebilirim.

mesaj birleştirme:: 28 Temmuz 2012, 23:18:11

Üst üste yazıyorum kusura bakmayın.  İşin içinden tam anlamıyla çıkamadım herhangi bir karakter gönderip işlem yaptım alıcı kesmeyle. Yalnız 'A' gönderdim alıcı bir pini 1 yaptı 'B' gönderdim  kesme programı çalışmamaya başladı. Neyi kaçırıyorum nerede hata yapıyorum anlamış değilim. Benim asıl amacım 2 analoglu ve 18 butonlu bir kumanda yapmak.

ferdem

CCS C kütüphanesinde string-int veya tam tersi dünüşüm yapan fonksiyonlar var, atoi olarak bir arayın bakalım. Ben CCS C de seri kesmeyi yıllardır şu örnekteki gibi kullanı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);
}

Kolay gelsin.

Emre005

Merhaba
Hocam bende seri iletişimli uğraşıyorum bu günlerde simülasyon ortamında herşey normal bir şekilde çalışıyor fakat gerçekte denediğimde sadece bi kere kesme oluşuyor  kesme bayraklarını temizlememe rağmen sizin verdiğiniz programda da b0 birkere tersleniyor.Sorun ne olabilir ki?

matador


matador

İstediğim bilgiyi kesme ile kaydetmeyi öğrendim. Yalnız bir soru soracağım.

#int_RDA
void  RDA_isr(void) 
{  
   char kod[10];
   int veri;
   char gps[60];
   int art;
   
   disable_interrupts(GLOBAL);
   disable_interrupts(INT_RDA);
   for(veri=0;veri<7;veri++)
   {
      kod[veri]=getchar();
      putchar(kod[veri]);
      output_d(0xff);
   }
   if(kod[0]=='$'&&kod[1]=='G'&&kod[2]=='P'&&kod[3]=='R'&&kod[4]=='M'&&kod[5]=='C'&&kod[6]==',')
      {
         printf("\n\r");
         for(art=0;art<60;art++)
         {
            gps[art]=getchar();
            putchar(gps[art]);
         }
         break;
      }
   return;
}


Alıcı program böyle sorum şu: Benim istediğim $GPRMC, bilgisinden sonra gelen bilgiyi ayrı değişkene kaydedip bundan sonra ayıklamak  bunu ilk gelen veri de yapıyor. Ama daha sonra gelenlerde $GPRMC, ibaresinden sonra gelecek değerleri bir alt satıra yazması gerekirken yazmıyor. Nedeni hakkında yardım ederseniz sevinirim.


Salih

Gelen karakterlerde $GPRMC karakterini bekle, o geldikten sonra
for döngüsünü çalıştır.

matador

if(kod[0]=='$'&&kod[1]=='G'&&kod[2]=='P'&&kod[3]=='R'&&kod[4]=='M'&&kod[5]=='C'&&kod[6]==',')
      {
         printf("\n\r");
         for(art=0;art<60;art++)
         {
            gps[art]=getchar();
            putchar(gps[art]);
         }
         break;
      }
   return;


Bu kod dediğin işi yapmıyor mu usta?

Salih

Alıntı yapılan: matador - 04 Eylül 2012, 20:35:44
if(kod[0]=='$'&&kod[1]=='G'&&kod[2]=='P'&&kod[3]=='R'&&kod[4]=='M'&&kod[5]=='C'&&kod[6]==',')
      {
         printf("\n\r");
         for(art=0;art<60;art++)
         {
            gps[art]=getchar();
            putchar(gps[art]);
         }
         break;
      }
   return;



Bu kod dediğin işi yapmıyor mu usta?

Haklısın kusura bakma gözümden kaçmış.
Ben interruptları disable yapmadan çalışıyorum.
Birde disable yapmadan denermisin.

matador

Değişen bir şey olmadı. Bu sorun derleyici versiyonuyla ilgili olabilir mi? Bazen böyle çok saçma sorunlarla karşılaşıyorum.

Salih

#11
Kendi yaptığım gerçek devre üzerinde çalışan bir örneği bire bir gönderiyorum.
Alıcı devresi programı.
Gelen Data, 0XFF ve 'A' ile Başlıyor. '!' ile bitiyor. Aynı zamanda gelen karakter uzunluğunu kontrol ediyoruz.
#include <16F876A.h>
#device *=16
#device adc=8

#FUSES WDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES PUT                      //Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD
#use delay(clock=4000000)

#Use rs232(baud=2400, xmit=PIN_C6, rcv=PIN_C7, parity=N,Bits=8, Stop=2, Errors, TIMEOUT=20)

#Define  Led     output_toggle(Pin_A0)
#Define  Led1    output_toggle(Pin_A1)
#Define  Led2    output_toggle(Pin_A2)
#Define  in1on   output_high(Pin_C0)
#Define  in1off  output_low(Pin_C0)
#Define  in2on   output_high(Pin_C5)
#Define  in2off  output_low(Pin_C5)
#Define  in3on   output_high(Pin_C4)
#Define  in3off  output_Low(Pin_C4)
#Define  in4on   output_high(Pin_C3)
#Define  in4off  output_low(Pin_C3)
#Define  EnBon   output_high(Pin_C1)
#Define  EnBoff  output_low(Pin_C1)

int8 diz[6];

#DEfine AKontrol  diz[0] 
#Define Hiz       diz[1]

signed int8 a=-1;
int1 geldi=0,basla=0;

#INT_RDA
void Kesme()
{     
restart_wdt(); 
  if (basla)
   {
    a++;
    diz[a]=getc();
    if ((diz[a]=='!')&&(a==4)) geldi=1; 
   }
    else 
    {   
       if ((getc()==0XFF)&&(getc()=='A')) 
            {
               basla    =1;               
               a        =-1;
            }
    }
// led1;
}

void main()
{   
   clear_interrupt(int_RDA);
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);  
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_16,62,2);
   setup_ccp2(CCP_OFF);
   setup_ccp1(CCP_PWM);   
   input(Pin_C7);
   output_high(Pin_C2);
   output_low(Pin_C6);
   setup_wdt(WDT_18MS);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   
    if (restart_cause()==NORMAL_POWER_UP)
     {
      in1off;
      in2off;
      in3off;
      in4off;   
      enboff;   
      diz[0]=0;diz[1]=0;diz[2]=0;
      set_pwm1_duty(0); 
     }
   
while(True){  
            restart_wdt();            
            input(Pin_C7);
            if (geldi)
            {     
               output_B(diz[2]);//Kamera Kontrol B0'da
               set_pwm1_duty(hiz); 
               if (Bit_Test(AKontrol,0)) in1on; else in1off;
               if (Bit_Test(AKontrol,3)) in4on; else in4off;
               if (Bit_Test(AKontrol,4)) in3on; else in3off;
               if (Bit_Test(AKontrol,5)) in2on; else in2off;
               if (Bit_Test(AKontrol,1)) EnBon; else EnBoff;               
               geldi = 0;
               basla = 0;
               a     =-1;               
               led;
             }   
             switch(input_B()){
             case 0:output_C(5);
             case 1:output_C(15);
             Default :;    
             }
}
}

kantirici

#12
Merhaba arkadaşlar.Benimde  bugün kesme ile problemim oldu.Pic ilk anda bir sefer kesmeye giriyor,daha sonra normal şekilde veri gelirse kesmeye giriyor.Bunu bir türlü önleyemedim.neden ilk çalıştıgında kesmeye girer acaba?Ayrıca denemeyi isiste değil kartta yapıyorum.


#include <16f877a.h>     
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
//#byte RCREG = 0x1A 
#use delay (clock=4000000) 
#define use_portb_lcd TRUE    
#include <flex_lcd.c>    
#use rs232 (baud=9600, xmit=pin_C6, rcv=pin_C7, parity=N, stop=1 ,ERRORS)                                                          
unsigned   int
   i=0;
char   klavye;  
#int_rda   
void serihaberlesme_kesmesi ()
{
 
 i++;
 lcd_gotoxy(1,2);
 printf(lcd_putc,"Kesme %d",i);
 
         klavye=getchar();
         putchar(klavye); 
         putchar('P');
         lcd_gotoxy(1,1);
         printf(lcd_putc,":%c %d",klavye,i);
 if(i>25)i=0;
 }

//char c;
//while(kbhit(seri)) fgetc(seri); 

 
 


void main ( )
{
   setup_psp(PSP_DISABLED);        // PSP birimi devre dışı
   setup_spi(SPI_SS_DISABLED);     // SPI birimi devre dışı
   setup_timer_1(T1_DISABLED);     // T1 zamanlayıcısı devre dışı
   setup_timer_2(T2_DISABLED,0,1); // T2 zamanlayıcısı devre dışı
   setup_adc_ports(NO_ANALOGS);    // ANALOG giriş yok
   setup_adc(ADC_OFF);             // ADC birimi devre dışı
   setup_CCP1(CCP_OFF);            // CCP1 birimi devre dışı
   setup_CCP2(CCP_OFF);            // CCP2 birimi devre dışı
   lcd_init();   
   printf("**************** Seri iletisim Deneme *********************\n\r");
 enable_interrupts(int_rda); 
enable_interrupts(GLOBAL);  

   
   while(1) 
   {
    lcd_gotoxy(1,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;
   //   }

    delay_ms(1000);
    puts("Data Bekleniyor");
    delay_ms(1000);
   }
}



Bir başka sorum ise picin bufferını nasıl temizleriz acaba?Pcden c# ile yazdıım programla pice veri yolluyorum ve pic ile aşağıdaki kodla bu veriyi alıyorum.Fakat ilk iki karaketer sorunsuz gitmesine rağmen diğer karakterler gitmiyor ve daha önce yolladıgım verilerde sanki yeni gelmiş gibi onlarıda alıyor.

Yapmak istedigim şey seri kesme oluştugunda veri alınsın ve tüm buffer temizlensin.

void serihaberlesme_kesmesi ()
{
 
 i=0;
 char c[80];
while(kbhit(seri)){c[i]=fgetc(seri);
                           i++;}

printf("%s",c);
} 

Salih

Alıntı yapılan: kantirici - 06 Eylül 2012, 15:39:34
Merhaba arkadaşlar.Benimde  bugün kesme ile problemim oldu.Pic ilk anda bir sefer kesmeye giriyor,daha sonra normal şekilde veri gelirse kesmeye giriyor.Bunu bir türlü önleyemedim.neden ilk çalıştıgında kesmeye girer acaba?Ayrıca denemeyi isiste değil kartta yapıyorum.

İlk beslemede oluşan problem nedeniyle olabilir.
Başlangıç daki interupt ları enable yapmadan önce 500 ms kadar geçikme ver.


Alıntı Yap
Bir başka sorum ise picin bufferını nasıl temizleriz acaba?Pcden c# ile yazdıım programla pice veri yolluyorum ve pic ile aşağıdaki kodla bu veriyi alıyorum.Fakat ilk iki karaketer sorunsuz gitmesine rağmen diğer karakterler gitmiyor ve daha önce yolladıgım verilerde sanki yeni gelmiş gibi onlarıda alıyor.

Yapmak istedigim şey seri kesme oluştugunda veri alınsın ve tüm buffer temizlensin.

Bildiğim kadarıyla buffer ı temizlemene gerek yok.
PIC yeni veri geldikçe eskilerin üzerine zaten yazıyor.
Ve biz veriyi almak istediğimizde yeni veriyi veriyor.
Buffer dediğimizde yanılmıyorsam 3 bayt büyüklüğünde.


kantirici

bir 877a dan;
  
   while(1) 
   {
    delay_ms(1000); 
    printf("Deneme 54");
    output_toggle(pin_d0);
   }


ile sürekli aynı veriyi yolluyorum alıcı tarafında ise;
#int_rda   
void serihaberlesme_kesmesi ()
{
i++;
indis=0;
 do{
   klavye[indis]=getchar();

   if(klavye[indis]=='4')break;
   indis++;

 }while(1);
 
 lcd_gotoxy(1,2);
 printf(lcd_putc,"Kesme %d",i);

         printf("\n\rgelen:%s  sira:%d\n\r"klavye,i);
         lcd_gotoxy(1,1);
         printf(lcd_putc,":%c %d",klavye[0],i);
 if(i>25)i=0;
 for(v=0;v<20;v++)klavye[v]=0;
 }


ile veriyi alıyorum.Veri sonu için 4 geldimi duruyorum.Seriporttan gelen veriyi aldıgım klavye dizisini de bilgisayara yolluyorum.Hem kendi programımda hemde hyper terminalde bu kodlar ile ;
gelen:DeY[Y???Deneme 54  sira:2
"gelen:DeDeneme 54  sira:18"
gelen:De?54  sira:3


gibi bir geri dönüş alıyorum.İşin ilginç yanı arada sırada olması gereken "gelen:Deneme 54  sira:18" gibi veriyi alabiliyorum.

Sonradan diziyide sıfırlamayı denedim ama yine olmadı.