Serial Port ile Pic'e Komut Gönderme Sorunu

Başlatan semih, 12 Aralık 2012, 13:55:23

semih

CCS C ile basit bir motor kontrol programı yazdım.Motor w tuşuna basılı tutulduğunda ileri ve s tuşuna basılı tutulduğunda geri gidiyor.ISIS'te yaptığım simülasyon sorunsuz çalışıyor.Fakat bunu c# ile kontrol etmeye çalıştığımda sorunla karşılaşıyorum.Klavyeden tuşa bastığımda motor bir tur atıp duruyor.Hatta bazen hiç hareket motorda bir hareketlenme bile yok.Acaba c# yazılımımda mı bir sorun var diye farklı bir şekilde denedim.Bu seferde tuşa bir kez basmak motoru harekte geçirmeye yetiyordu.Bu sorunsuz çalıştı.Ama tuşa basılı tuttuğum kadar çalışmasını istediğimde anla veremediğim sorunlar çıktı.İleri tuşuna basıyorum motor bazen iki tur bazen bir tur dönüyor.Tekrar bastığımda ise motor dönmğyor.Ta ki geri tuşuna basana kadar.Aşağıda c# ve ccs c kodlarını verdim.Hata yazılımda mı donanımda mı acaba?

c# Kodları

private void button1_Click(object sender, EventArgs e)
        {
             if (!serialPort1.IsOpen)
             {
                 serialPort1.Open();
             }
             veri = "w";
             serialPort1.WriteLine(veri);
         }

        private void button2_Click(object sender, EventArgs e)
        {
            if (!serialPort1.IsOpen)
            {
                serialPort1.Open();
            }
            veri = "s";
            serialPort1.WriteLine(veri);
        }
 private void button1_KeyDown(object sender, KeyEventArgs e)
        {
            timer1.Enabled = true;
            timer2.Enabled = false; 
        }

        private void button1_KeyUp(object sender, KeyEventArgs e)
        {
            timer1.Enabled = false;
            timer2.Enabled = false;
        }

        private void button2_KeyDown(object sender, KeyEventArgs e)
        {
            timer2.Enabled = true;
            timer1.Enabled = false;
        }

        private void button2_KeyUp(object sender, KeyEventArgs e)
        {
            timer2.Enabled = false;
            timer1.Enabled = false;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            timer2.Enabled = false;
            button1.PerformClick();
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            timer1.Enabled = false;
            button2.PerformClick();   
        }

        private void button1_MouseDown(object sender, MouseEventArgs e)
        {
            timer1.Enabled = true;
            timer2.Enabled = false;
        }

        private void button1_MouseUp(object sender, MouseEventArgs e)
        {
            timer1.Enabled = false;
            timer2.Enabled = false;
        }

        private void button2_MouseDown(object sender, MouseEventArgs e)
        {
            timer2.Enabled = true;
            timer1.Enabled = false;
        }

        private void button2_MouseUp(object sender, MouseEventArgs e)
        {
            timer2.Enabled = false;
            timer1.Enabled = false;
        }


CCS C Kodları

#int_timer0
void timer0_kesmesi()
{      
      output_a(0x00);     
}

void main()
{  
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
   set_timer0(1);
   enable_interrupts(INT_timer0);
   enable_interrupts(GLOBAL);
   
   while(1)
   {   
      while(getch()=='w')
      {
         delay_ms(10);
         output_low(pin_a0);
         output_high(pin_a1);
      }
      while(getch()=='s')
      {
         delay_ms(10);
         output_high(pin_a0);
         output_low(pin_a1);
      }
   }
}

yusufburak

C ile RS-232 da bi led yakıp söndürmem gerekiyor. C'de rs-232 işleminin nasıl olduğunu biliyo musunuz ?
Öğretici aranıyor :)

ziyaretci

Alıntı yapılan: yusufburak - 12 Aralık 2012, 19:30:41
C ile RS-232 da bi led yakıp söndürmem gerekiyor. C'de rs-232 işleminin nasıl olduğunu biliyo musunuz ?


 
int x;
#use rs232(baud=-,xmit=- ,rcv= -, stop= -,parity=-)

 #int_rda
Void serihaberlesme()
{
disable_interrupts(int_rda);
  x=getc();
 islemler();
}


 Void main()
{

 printf("ilk anda pc arayüze gönderilecek mesaj");
 enable_interrupts(GLOBAL);
  While(1){

    enable_interrupts(int_rda);

}

}

yusufburak

Alıntı yapılan: erkantr67 - 12 Aralık 2012, 20:21:26

 
int x;
#use rs232(baud=-,xmit=- ,rcv= -, stop= -,parity=-)

 #int_rda
Void serihaberlesme()
{
disable_interrupts(int_rda);
  x=getc();
 islemler();
}


 Void main()
{

 printf("ilk anda pc arayüze gönderilecek mesaj");
 enable_interrupts(GLOBAL);
  While(1){

    enable_interrupts(int_rda);

}

}


Teşekkür ederim kesme ile yapılmış bi program gibi :) pek anlamıyorum da programın çalışmasını anlatır mısınız ? size zahmet ?
Öğretici aranıyor :)

fatih6761

Sorun klavye çalışma mantığınız bilmemenizden kaynaklanıyor. Klavye yani Intel 8279 denetleyici, tuşa basılı tuttuğunuzda işletim sisteminden gelen ayara göre saniye 10-20 kere tuşu yollar. Yani siz tuşa basılı tuttuğunuzda PIC'e saniyede 20 kez dur-kalk komutu geliyor. Yapmanız gereken C# da bir değişken tanımlamak, motor durumunu ( çalışıyor-duruyor ) kaydetmek. Sonra W tuşu basılı olduğu sürece bu değeri değiştirmemek, S basıldığında değeri "geri" şeklinde değiştirip motora sadece 1 kez dur komutu yollamak. Yani iş C# tarafında...

yusufburak

Doğrudur :S Bu programdaki mantıkta anlattığınız gibi mi yani ? sürekli lojik 1 gönderiyoruz ama 1 kez lojik 0 gönderiyoruz ? bu mu ?
Öğretici aranıyor :)

sadogan

Alıntı yapılan: semih - 12 Aralık 2012, 13:55:23
CCS C ile basit bir motor kontrol programı yazdım.Motor w tuşuna basılı tutulduğunda ileri ve s tuşuna basılı tutulduğunda geri gidiyor.ISIS'te yaptığım simülasyon sorunsuz çalışıyor.Fakat bunu c# ile kontrol etmeye çalıştığımda sorunla karşılaşıyorum.Klavyeden tuşa bastığımda motor bir tur atıp duruyor.Hatta bazen hiç hareket motorda bir hareketlenme bile yok.Acaba c# yazılımımda mı bir sorun var diye farklı bir şekilde denedim.Bu seferde tuşa bir kez basmak motoru harekte geçirmeye yetiyordu.Bu sorunsuz çalıştı.Ama tuşa basılı tuttuğum kadar çalışmasını istediğimde anla veremediğim sorunlar çıktı.İleri tuşuna basıyorum motor bazen iki tur bazen bir tur dönüyor.Tekrar bastığımda ise motor dönmğyor.Ta ki geri tuşuna basana kadar.Aşağıda c# ve ccs c kodlarını verdim.Hata yazılımda mı donanımda mı acaba?

c# Kodları

private void button1_Click(object sender, EventArgs e)
        {
             if (!serialPort1.IsOpen)
             {
                 serialPort1.Open();
             }
             veri = "w";
             serialPort1.WriteLine(veri);
         }

        private void button2_Click(object sender, EventArgs e)
        {
            if (!serialPort1.IsOpen)
            {
                serialPort1.Open();
            }
            veri = "s";
            serialPort1.WriteLine(veri);
        }
 private void button1_KeyDown(object sender, KeyEventArgs e)
        {
            timer1.Enabled = true;
            timer2.Enabled = false; 
        }

        private void button1_KeyUp(object sender, KeyEventArgs e)
        {
            timer1.Enabled = false;
            timer2.Enabled = false;
        }

        private void button2_KeyDown(object sender, KeyEventArgs e)
        {
            timer2.Enabled = true;
            timer1.Enabled = false;
        }

        private void button2_KeyUp(object sender, KeyEventArgs e)
        {
            timer2.Enabled = false;
            timer1.Enabled = false;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            timer2.Enabled = false;
            button1.PerformClick();
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            timer1.Enabled = false;
            button2.PerformClick();   
        }

        private void button1_MouseDown(object sender, MouseEventArgs e)
        {
            timer1.Enabled = true;
            timer2.Enabled = false;
        }

        private void button1_MouseUp(object sender, MouseEventArgs e)
        {
            timer1.Enabled = false;
            timer2.Enabled = false;
        }

        private void button2_MouseDown(object sender, MouseEventArgs e)
        {
            timer2.Enabled = true;
            timer1.Enabled = false;
        }

        private void button2_MouseUp(object sender, MouseEventArgs e)
        {
            timer2.Enabled = false;
            timer1.Enabled = false;
        }


CCS C Kodları

#int_timer0
void timer0_kesmesi()
{      
      output_a(0x00);     
}

void main()
{  
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
   set_timer0(1);
   enable_interrupts(INT_timer0);
   enable_interrupts(GLOBAL);
   
   while(1)
   {   
      while(getch()=='w')
      {
         delay_ms(10);
         output_low(pin_a0);
         output_high(pin_a1);
      }
      while(getch()=='s')
      {
         delay_ms(10);
         output_high(pin_a0);
         output_low(pin_a1);
      }
   }
}

Delay_ms(10) bunlar sorunun kaynağı.
En güzeli interrupt kullanmak.
unsigned char seri_data;
#int_rda

void seri_port_int()
{
   disable_interrupts(int_rda);

  seri_data=getc();
    enable_interrupts(int_rda);
}

void main(void)
{
   enable_interrupts(int_rda);
   enable_interrupts(GLOBAL);
 
  while(TRUE)
  {
         switch (seri_data) {

    case 'w':  output_low(pin_a0);
               output_high(pin_a1);


           break;

    case 's':  output_high(pin_a0);
               output_low(pin_a1);


           break;

    default:  output_low(pin_a0);
               output_low(pin_a1);

            break; }

  }
 }

yusufburak

Öğretici aranıyor :)

ziyaretci

Alıntı yapılan: yusufburak - 12 Aralık 2012, 20:27:11

int x;
#use rs232(baud=-,xmit=- ,rcv= -, stop= -,parity=-)

 #int_rda
Void serihaberlesme()
{
disable_interrupts(int_rda);
  x=getc();
 islemler();
}


 Void main()
{

 printf("ilk anda pc arayüze gönderilecek mesaj");
 enable_interrupts(GLOBAL);
  While(1){

    enable_interrupts(int_rda);

}

}


Teşekkür ederim kesme ile yapılmış bi program gibi :) pek anlamıyorum da programın çalışmasını anlatır mısınız ? size zahmet ?




   CCS C de seri haberleşme kesmesi olarak kullanılan kesme RDA dır.  Ana programın içinde sonsuz döngüde yaptığımız işlem pic i kesme için tetikte tutmak , bütün aktif edilen kesmelere izin verdik , sonsuz döngünün içindede rda kesmesini aktif yaptık, klavyeden bir bilgi geldiğinde kesmeye götürecek ve ilk yapmamız gereken işlem bayrağı temizlemek(demin bayrak hakkındaki soru işaretimi kaldırmam da yardımcı oldunuz sağolun :) ) bayrağı temizledikten sonra klavyeden gelen komutu getc(); ile bir değişkene aktardık değişken dizi olursa daha uzun verilerle işlem yapabiliriz. Dahada ayrıntıya inmemi isterseniz söyleyin.Bilginiz var bu konularda , genel olarak anlattım o yüzden.

justice_for_all

kesme icinde bir fonksiyon cagrilmaz,kesmenin ici minimum uzunlukta olmasi gerek bu yuzden disable ve enable yapmaniza da gerek kalmaz zaten disable yapmaniz bilgi kaybetmenize sebep olabilir.
Deneyip de başaramayanları değil, yalnızca denemeye bile kalkışmayanları yargıla.   Gökhan Arslanbay

ziyaretci

Alıntı yapılan: justice_for_all - 13 Aralık 2012, 00:08:15
kesme icinde bir fonksiyon cagrilmaz,kesmenin ici minimum uzunlukta olmasi gerek bu yuzden disable ve enable yapmaniza da gerek kalmaz zaten disable yapmaniz bilgi kaybetmenize sebep olabilir.


Biraz daha açıklama yapar mısınız? Şu kesme olayını tamamen bitirmek istiyorum.

justice_for_all

#int_rda
Void serihaberlesme()
{
disable_interrupts(int_rda);
  x=getc();
 islemler();
}



bu koddaki isimler(); olmamali .Dedigim gibi kesme ici mumkun oldugu kadar kisa olmali illa isimleri kesme gelince calistircam diyosan

unsigned int1 kontrol=0;
 #int_rda
Void serihaberlesme()
{
  x=getc();
  kontrol=1;
}





while(1)
{
            if(kontrol)
             {
                   kontrol=0;
                   islemler();
              }
}



yaparsin olur biter.fonksiyonun uzun da olsa kisada olsa kesme disinda calistirirsan daha guvenli olur.
Deneyip de başaramayanları değil, yalnızca denemeye bile kalkışmayanları yargıla.   Gökhan Arslanbay

ziyaretci


semih

#13
Alıntı yapılan: sadogan - 12 Aralık 2012, 22:12:52
Delay_ms(10) bunlar sorunun kaynağı.
En güzeli interrupt kullanmak.
unsigned char seri_data;
#int_rda

void seri_port_int()
{
   disable_interrupts(int_rda);

  seri_data=getc();
    enable_interrupts(int_rda);
}

void main(void)
{
   enable_interrupts(int_rda);
   enable_interrupts(GLOBAL);
 
  while(TRUE)
  {
         switch (seri_data) {

    case 'w':  output_low(pin_a0);
               output_high(pin_a1);


           break;

    case 's':  output_high(pin_a0);
               output_low(pin_a1);


           break;

    default:  output_low(pin_a0);
               output_low(pin_a1);

            break; }

  }
 }


Kodları denedim.Fakat ben tuşa basılı tuttuğum kadar motor dönsün istiyorum.Bu yüzden timer0 kesmesi kullanarak a portunun çıkışlarını temizlemiştim.Dediğiniz kodlarda tuşa bir kez basmak dönmesi için yetiyor(Proteusta denedim).Pratikte denediğimde ise motor kımıldar gibi oluyor.rda kesmesi içinde a potrunu temizlemeye çalıştım fakat yine aynı sorun oluştu.Bir de bu rda kesmesini aynı fonksiyon içerisinde önce pasif sonra aktif hale getirmenizin sebebi nedir?

mesaj birleştirme:: 13 Aralık 2012, 14:06:16

Alıntı yapılan: fatih6761 - 12 Aralık 2012, 20:33:39
Sorun klavye çalışma mantığınız bilmemenizden kaynaklanıyor. Klavye yani Intel 8279 denetleyici, tuşa basılı tuttuğunuzda işletim sisteminden gelen ayara göre saniye 10-20 kere tuşu yollar. Yani siz tuşa basılı tuttuğunuzda PIC'e saniyede 20 kez dur-kalk komutu geliyor. Yapmanız gereken C# da bir değişken tanımlamak, motor durumunu ( çalışıyor-duruyor ) kaydetmek. Sonra W tuşu basılı olduğu sürece bu değeri değiştirmemek, S basıldığında değeri "geri" şeklinde değiştirip motora sadece 1 kez dur komutu yollamak. Yani iş C# tarafında...

C# kodunu şu şekilde değiştirdim
private void button1_Click(object sender, EventArgs e)
        {
            if (!serialPort1.IsOpen)
            {
                serialPort1.Open();
            }
            veri = "w";
            while (i == 1) ;
            {
                serialPort1.WriteLine(veri);
            }
            
         }         
        private void timer1_Tick(object sender, EventArgs e)
        {
            
            button1.PerformClick();
        }
        private void button1_MouseDown(object sender, MouseEventArgs e)
        {
            i = 1;
            timer1.Start();
        }

        private void button1_MouseUp(object sender, MouseEventArgs e)
        {
            i = 0;
            timer1.Stop();
        }
     


     Programı çalıştırdığımda ileri ya da geri butonuna basarsam motor harekete geçiyor.Fakat buradaki while döngüsü sonsuz olduğu için motor sadece ileri veya sadece geri gidiyor bu sorunu nasıl çözebilirim?

sadogan

Alıntı YapKodları denedim.Fakat ben tuşa basılı tuttuğum kadar motor dönsün istiyorum.Bu yüzden timer0 kesmesi kullanarak a portunun çıkışlarını temizlemiştim.Dediğiniz kodlarda tuşa bir kez basmak dönmesi için yetiyor(Proteusta denedim).Pratikte denediğimde ise motor kımıldar gibi oluyor.rda kesmesi içinde a potrunu temizlemeye çalıştım fakat yine aynı sorun oluştu.Bir de bu rda kesmesini aynı fonksiyon içerisinde önce pasif sonra aktif hale getirmenizin sebebi nedir?
Motoru devreden ayırıp pin_a0 ve pin_a1 durumlarını avo metre yada led ile gözlemlyin.
Motorunuz devreye girince devreinze bir şeyler oluyor gibi bir hisse kapıldım.
Tusa basınca çalışsın çekince dursun diyorsunuz, tusa basılıyken sürekli veri yollamak durumunda kalırsınız.
oysaki tusu bırakınca 'w''s' bu karekerler dışında başka bir karekter yollamanız durumunda pin_a0 ve pin_a1 low olacaktır.Yada timer0 ı rda interrupt geldiginde set_timer0(0) timer0 icerigini temizleyip timer0
interrupt tını engelemek. timer0  interrupt ı geldiğinde  seri_data='d' diyerek motoru durdurabilirsin.
Ancak timer0 tasma zamanı seriport tan arka arkaya gelen iki seri verinin süresinden daha uzun olmalıdır.
rda interrupt tı açıp kapatmaın nedeni rda interrupt ında iken harhangi bir nedenle aynı interrupt tın gelmesini engellemek için gerçi bu örenkte bu mümkün deyil .
Gelirse ne olur derseniz interrupt larda diger dallanmalar gibi stack ta yer kaplarlar 16f serileirnde 8 olanan dallanmalar için teklikeli durumlar yaratır.