pcbway

rs kesmesi string ifade alış verişi ile sağlamak

Başlatan fm, 28 Ocak 2013, 22:07:26

fm

Merhaba bir konuda yardımınıza ihtiyacım var. Amacım iki pik arasında rs kesmesini string ifade kullanarak gerçekleştirmek. Ancak bir türlü gerçekleştiremedim.

Yapmak istediğim; buton1 e bastığım anda pik2 ye string bilgi göndericek, pik2 rs kesmesine girip lcd ekranda gelen string bilgiyi lcd2 de gösterip led2 yi yakacak ve 2 saniyelik beklemeden sonra sistem eski haline dönecek. String bilgiyi gönderiyor ama sanırım alıcı olan pik gelen bilgiyi almıyor. Program kodunu ve tasarımı ekledim. Yardım ederseniz çok sevinirim..

yazici67

29 Ocak 2013, 02:51:46 #1 Son düzenlenme: 29 Ocak 2013, 02:52:51 yazici67
Aslında hata belli. Gözünüzden kaçtı herhalde ya da aklınız C# Vb.Net vs. ye gitti.
if(giris == \"gonder\")
Bu kod C# için istediğiniz gibi çalışır yani giris bir string ise string her harfi \"gonder\" ile test edilir. Ama C için düşünürsek, giris bir string değil, char* ( char pointer, işaretçi ) olur. giris == \"gonder\" ifadesi yanlıştır. giris içinde sayısal olarak ayrılan dizinin adresi vardır. Bunun yerine giris dizisinin elemanlarını kontrol etmelisiniz:
int8 dogru = 0;
dogru = (giris[0] == \'g\') &
        (giris[1] == \'o\') &
        (giris[2] == \'n\') &
        (giris[3] == \'d\') &
        (giris[4] == \'e\') &
        (giris[4] == \'r\');
if(dogru)
{
    bayrak = 1;
}
Şeklinde kullanabilirsiniz. Eğer çok uzun oldu diyorsanız strcmp kullanabilirsiniz.
// include\'ların peşine bu satırı ekleyin
#include \"string.h\"

// değişkenlerin tanımlandığı alanda gonder string\'ini const olarak belirtin
// boylece RAM de yer kaplamamış olur
const char gonder[] = \"gonder\";
char giris[20];

// rda kesmesi içinde
gets(giris);
// strcmp fonksiyonu, string\'ler aynı ise 0 döndürür. Detayı için internette arayabilirsiniz.
if(strcmp(giris, gonder) == 0)
{
    bayrak = 1;
}

fm

hocam çok teşekkür ederim. bunu hiç bilmiyordum. sayenizde öğrenmiş oldum. tekrar teşekkür ederim...

yazici67


fm

Hocam eğer deneme imkanınız varsa bir kodu deneyebilir misiniz? kod üzerinde söylediğiniz değişiklikleri yaptım. ayrıca string ifade gmndermek için printf komutunu yerine puts komutu kullandım. Bu sefer alıcı pik sinyali aldı. Ancak lcd ekranda yazdırma işlemini 8 kere butona bastıktan sonra yaptı.

yazici67


fm

Şemayı ekledim. Hocam programıda tekrar atayım. Veri alış verişi oluyor. Bu seferde kesme fonksiyonu sonlanmıyor.

yazici67

30 Ocak 2013, 00:51:12 #7 Son düzenlenme: 30 Ocak 2013, 00:52:44 yazici67
Tamam, sorun kalmadı. Ve tamamen CCS C nin suçu. Açıklama:
Normal şartlarda puts ve gets komutları birbirinin eşidir. Yani puts ile gönderilen veri gets ile alınır.
Ancak CCS bu konuda fonksiyonları farklı uygulamış.

puts komutu gönderme yaparken veri + CR(13) + LF(10) kullanıyor
gets fonksiyonu ise veri + CR(13) bekliyor. Yani veri + CR geldiğinde gets işlemi bitiyor ve alıcı PIC
işleme devam ediyor. O işlemi bitirmeden gelen LF, RX tamponuna yazılmış oluyor. Tampon boş olmadığı için
tekrar kesme oluşuyor. Ancak tamponda sadece LF(10) verisi var. Dolayısıyla gets CR(13) gelene kadar bekliyor. Karşı taraftan bu veri (CR) gelmediği için program kilitleniyor.

Şemada bir değişiklik yok. Yazılımda birkaç nokta değişti.
#include <16F877A.h>
#include <string.h>

#FUSES NOWDT                   
#FUSES XT                       
#FUSES NOBROWNOUT               
#FUSES NOLVP                   
#FUSES NOPUT
#FUSES NODEBUG
#FUSES WRT_50%
#FUSES NOCPD
#FUSES NOPROTECT

#use delay(clock=4000000)

#use fast_io(a)
#use fast_io(b)
#use fast_io(d)

#define use_portb_lcd TRUE
#include <lcd.c>

#use rs232(baud=9600, xmit=pin_C6, rcv=pin_C7, parity=N, uart1)

char bayrak;

char veri[]= \"gonder\";
char giris[20];
char *p;

#INT_RDA
void seri_haberlesme()

   gets (giris) ;
   
   if (strcmp (giris, veri) == 0)
      bayrak = 1;
}

   
void main()
{
   setup_adc_ports (NO_ANALOGS) ;
   setup_adc (ADC_OFF) ;
   setup_psp (PSP_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) ;
   setup_CCP1 (CCP_OFF) ;
   setup_CCP2 (CCP_OFF) ;
   set_tris_b (0x00) ;
   output_b (0x00) ;
   
   set_tris_c (0x80) ;
   
   set_tris_d (0x01) ;
   output_d (0x00) ;
   
   lcd_init () ;
   
   enable_interrupts (int_rda) ;
   enable_interrupts (GLOBAL) ;
   
   bayrak = 0;
   
   while (1)
   {
      printf (lcd_putc, \"\\f\\rLUTFEN, \") ;
      printf (lcd_putc, \"\\n\\rBUTONA BASIN\") ;
     
      output_low (pin_d1) ;
     
      if (input(pin_d0))
      {
         delay_ms(50);
         while(input(pin_d0));   // buton bırakılana kadar bekle
         // yoksa sinyal çok defa gider ve diğer pik
         // kesmeden çıkamaz
         
         p = veri;
         
         do
         {
            putc(*p);   // veri dizisinin tüm elemanlarını yolla
         } while(*(++p) != \'\\0\');
         
         putc(13); // gets için sonlandırma kodu. klavyedeki Enter tuşu
         /*
            Açıklama:
            Sorunun kaynağı tamamen CCS C derleyicisi.
            Dökümanlar incelendiğinde puts-gets komutlarının birbirinin
            eşi olması gerektiği görülür. Ama birbirlerini karşılamıyorlar.
            Çünkü puts komutu gönderme yaparken veri+CR(13)+LF(10) kullanıyor
            gets fonksiyonu ise veri+CR(13) bekliyor. Sonradan gelen LF
            tekrar kesmeye neden oluyor ancak tekrar CR gelmediği için
            gets fonksiyonunda program kilitleniyor.
            Sorunun çözümü tüm veriyi tek tek yollamak. Yukarıdaki şekil en
            düzgün şeklidir.
         */
         
         delay_ms (200) ;
      }

      if (bayrak == 1)
      {
         // printf (lcd_putc, \"\\fSINYAL: %s\", giris) ;
         output_high (pin_d1) ;
         delay_ms (1000) ;
         output_low (pin_d1) ;
         delay_ms (200);
         
         bayrak = 0;
      }
   }
}

fm

Hocam çok teşekkür ederim.

\"puts komutu gönderme yaparken veri + CR(13) + LF(10) kullanıyor
gets fonksiyonu ise veri + CR(13) bekliyor. Yani veri + CR geldiğinde gets işlemi bitiyor ve alıcı PIC
işleme devam ediyor. O işlemi bitirmeden gelen LF, RX tamponuna yazılmış oluyor. Tampon boş olmadığı için
tekrar kesme oluşuyor. Ancak tamponda sadece LF(10) verisi var. Dolayısıyla gets CR(13) gelene kadar bekliyor. Karşı taraftan bu veri (CR) gelmediği için program kilitleniyor.\"

Burda bahsettiğiniz kısım ile daha önce hiç karşılaşmadım. Bunu nasıl anladınız ve çalışabileceğim bir kaynak tavsiye edebilir misiniz?

Bir sorum daha olucak size. Lcd ekranında ana fonksiyonda butona basmadığım zamanlarda Lütfen butona basın yazısı sürekli koddan dolayı kendni tekrarlıyor. Butona basılmadığı durumlara ekranda yanıp sönmesi yerine sürekli kalması için ne yapmalıyım?

yazici67

CCS C derleyicisi ile ilgili bilgileri Reference Manual\'den edinebilirsiniz:
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf
Eğer hedef platformun (burada PIC) yapısını iyi bilirseniz çözüm bulmanız daha kolay oluyor.
Sorunuza gelince, basit bir bayrak değişkeni ile yapılabilir.
Mantığı : lcd_durum adında bir değişken tutarsınız. LCD ye istenilen metin basıldığında bu değişkene 0 yüklersiniz. 1 için butona basın mesajı, 2 için sinyal mesajı gösterilecek ise switch-case yapısıyla halledilir. Örnek Kod :
#include <16F877A.h>
#include <string.h>

#FUSES NOWDT                   
#FUSES XT                       
#FUSES NOBROWNOUT               
#FUSES NOLVP                   
#FUSES NOPUT
#FUSES NODEBUG
#FUSES NOCPD
#FUSES NOPROTECT

#use delay(clock=4000000)

#use fast_io(a)
#use fast_io(b)
#use fast_io(d)

#define use_portb_lcd TRUE
#include <lcd.c>

#use rs232(baud=9600, xmit=pin_C6, rcv=pin_C7, parity=N, uart1)

char bayrak;

char lcd_durum = 0;

char veri[]= \"gonder\";
char giris[20];
char *p;

#int_RDA
void seri_haberlesme()
{
   
    gets (giris);
   
    if (strcmp (giris, veri) == 0)
    {
        bayrak = 1;
        lcd_durum = 2; // sinyali yazdır
    }
}

   
void main()
{
    setup_adc_ports (NO_ANALOGS);
    setup_adc (ADC_OFF);
    setup_psp (PSP_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);
    setup_CCP1 (CCP_OFF);
    setup_CCP2 (CCP_OFF);
    set_tris_b (0x00);
    output_b (0x00);
   
    set_tris_c (0x80);
   
    set_tris_d (0x01);
    output_d (0x00);
   
    lcd_init ();
   
    enable_interrupts (int_rda);
    enable_interrupts (GLOBAL);
   
    bayrak = 0;
   
    while (1)
    {
        switch (lcd_durum)
        {
            case 0: // yazılması gereken birşey yok ise devam et.
            break;

            case 1: // durum = 1 ise butona basın mesajını göster.
            printf (lcd_putc, \"\\f\\rLUTFEN, \") ;
            printf (lcd_putc, \"\\n\\rBUTONA BASIN\") ;
            lcd_durum = 0;
            break;
           
            case 2: // durum 2 ise sinyali yazdır.
            printf (lcd_putc, \"\\fSINYAL: %s\", giris) ;
            lcd_durum = 0;
            break;
        }

       
        output_low (pin_d1);
       
        if (input (pin_d0))
        {
            delay_ms (50) ;
            while (input (pin_d0)); // buton bırakılana kadar bekle
            // yoksa sinyal çok defa gider ve diğer pik
            // kesmeden çıkamaz
           
            p = veri;
           
            do
            {
                putc ( * p); // veri dizisinin tüm elemanlarını yolla
            } while ( * (++p) != \'\\0\');

           
            putc (13); // gets için sonlandırma kodu. klavyedeki Enter tuşu
            /*
            Açıklama:
            Sorunun kaynağı tamamen CCS C derleyicisi.
            Dökümanlar incelendiğinde puts - gets komutlarının birbirinin
            eşi olması gerektiği görülür. Ama birbirlerini karşılamıyorlar.
            Çünkü puts komutu gönderme yaparken veri + CR (13) + LF (10) kullanıyor
            gets fonksiyonu ise veri + CR (13) bekliyor. Sonradan gelen LF
            tekrar kesmeye neden oluyor ancak tekrar CR gelmediği için
            gets fonksiyonunda program kilitleniyor.
            Sorunun çözümü tüm veriyi tek tek yollamak. Yukarıdaki şekil en
            düzgün şeklidir.
            */
           
            delay_ms (200);
        }

        if (bayrak == 1)
        {
            output_high (pin_d1);
            delay_ms (1000);
            output_low (pin_d1);
            delay_ms (200);
           
            bayrak = 0;
        }
    }
}


fm

Hocam çok teşekkür ederim. Eline sağlık. Sana danışmak istediğim bir şey daha var. Yardımlarınla yapmak istediğim şeye biraz daha yaklaştım. Tasarımı ve kodu ekledim.
Sormak istediğim kodu incelediğin zaman seninde görecenin gibi rs kesmesinde bi şeçme yaptırmam gerekiyor. Kesme fonksiyonu her çalıştığında string ifade giris1 e atanıyor. Orda sırası ile giris1 veri1 ile ve giris2 veri2 ile karşılaştırılacak şekilde bi sıralı düzen kodu nasıl yazabilirim?

yazici67

Yapmak istediğinizi tam olarak anlayamadım. Karşı taraftan iki farklı string mi geliyor? Bunlar art arda mı?

fm

Hocam 3 ya da daha fazla denetleyici olacak. Denetleyicilerden 1 tanesi seçici olacak. diğer denetleyiciler aynı işi yapan devrelerde olacak. Bu aynı işten kastın akım ve gerilim okumak.
Mesela şeçici denetleyicinin dışında A ve B adında 2 tane daha denetleyici olsun. Enerji verildiğinde şeçici denetleyici önce A denetleyicisine sinyal göndercek. A denetleyicisi sırası ile önce volt bilgisini seçici devreye gönderecek ve seçici denetleyici bunu yazdıracak. Ardından akım bilgisi seçici denetleyiciye gelecek ve bu yazdırılacak. Sonra sinyal B denetleyicisine gönderilip aynı iş tekrarlanacak. Tam durumu ben de kavrayamadığım için anladığım bu. İnş açıklayabilmişimdir.

yazici67

Bu durumda RS232 yerine I2C kullanabilirsiniz. Aynı hatta birden fazla denetleyici olduğunda donanımsal sorunlar olabilir.
Eğer imkan varsa I2C ile yapmaya çalışın. I2C tam istediğiniz gibi, hatta yalnızca 1 master ( sizin deyiminizle seçici ) olabilir. Diğerleri slave\'dir. Yani değer okuyacak olanlar. Ancak farklı cihazlarla haberleşebilmek için en az iki farklı yazılım olması gerekir. Burada master cihazın yazılımı ayrı olacak. Diğer yazılımlar ise aynı yazılım olacak ama ID sistemine göre çalışacak.
Eğer boşta pin varsa slave olacak cihazlardan 2 veya 3 pin ayırın. Bu pinler ID pinleri olacak. Mesela 1. slave PIC\'in bu üç pini 000 olacak, I2C hattından 000 yollandığında hemen bu PIC tetiklenecek, diğer slave PIC\'in üç pini 001 olacak, hattan 001 gelirse doğrudan bu PIC tetiklenecek. Bu sistemi bir deneyin, olmazsa beraber yazarız.
İyi çalışmalar...

fm

Hocam teşekkürederim. Bir göz atayım ben bu konuya tekrar teşekküer ederim..