Seri Haberleşme Sorunu - Veri Göndermeden Veri Alımı Yapmıyor

Başlatan serhat1990, 17 Aralık 2013, 10:12:43

serhat1990

Merhabalar PicProje Ailesi ,

C# konusunda deneyimim hiç yok sayılır . Forumda sorumun cevabını aradım yalnız ne aradığını tam olarak bilemeyince bulmak biraz zor oluyor. Seri port haberleşmesi yapmak istiyorum , haberleşme yapabiliyorum yalnız bir  takım sıkıntılar var . Çalışan bir cihazımı takıyorum , programı çalıştırıyorum . Cihaza enerji verdiğimde bir mesaj gönderiyor normalde ama benim programda bu mesajı görüntüleyemiyorum , bazen sadece soru işareti geliyor . Cihaza bir komut gönderirsem , cihazın yanıtını alabiliyorum . Yani kısacası cihaza veri göndermeden cihazdan veri alamıyorum . ( Veri alımı için serialPort1.ReadExisting(); fonksiyonunu kullanırsam veriyi alıyorum yalnız arada boşluk vs gibi istenmeyen durumlar yaşanıyor ) Cihazımı normal terminal programlarında kullanıyorum bir sıkıntı yok . C# kodunu aşağıda mevcuttur. Ayrıca veriler gelince listbox'a atıyorum. Listbox'un ekranında en son değil ilk gelen veriler gözüyor . Kaydırma kutusunu aşağıya doğru indirince son gelen verileri görebiliyorum. Bu konuda yardımlarınızı bekliyorum , saygılarımla...

/* Seri Port Haberleşmesi */ 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;              
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
 


namespace WindowsFormsApplication1
{

   

    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();

            string[] ports = SerialPort.GetPortNames();

            foreach (string port in ports)
            {
                comboBox1.Items.Add(port);
            }

            comboBox1.SelectedIndex = 0;


          
        }

        private void button1_Click(object sender, EventArgs e)      // Comport Seçimi  ve Seriport Aktif etme iÅŸlemi
        {
            string strBuffer = comboBox1.Text;
            serialPort1.PortName = strBuffer;
            serialPort1.Open();  
            serialPort1.DiscardInBuffer();    
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            CheckForIllegalCrossThreadCalls = false;
        }

        private void button2_Click(object sender, EventArgs e)      // Seriport pasif etme iÅŸlemi
        {
            serialPort1.Close();       
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {

           string gelen;

              //  gelen = serialPort1.ReadExisting();
                  gelen = serialPort1.ReadLine();
                  Response.Items.Add(gelen);

        }


        private void button8_Click(object sender, EventArgs e)      // Alınan veri bölümünü temizler...
        {
            Response.Items.Clear();
        }

        private void Send_Click(object sender, EventArgs e)         // Butona basılınca mesaj yazma bölümüne yazılan mesajı gönderir.
        {
            string strBuffer = textBox1.Text;

            serialPort1.Write(strBuffer);
        }

    }
}

Gökhan BEKEN

veriyi almak için
serialPort1.ReadExisting();
  yazmak yerine, kesme mantığıyla çalışan  DataReceived ile almanızı tavsiye ederim. Bu sayede siz sürekli takip etmek zorunda kalmazsınız. Aşağıdaki kodları çalıştırabilmek için form'a 1 adet seriport nesnesi eklemeniz gerekmektedir. Bunun dışında combobox ile com portları listelediğimiz için 1 adet combobox, ayrıca 1 adet buton ve 1 adet textbox ekleyiniz.
using System;
 
using System.Collections.Generic;
 
using System.ComponentModel;
 
using System.Data;
 
using System.Drawing;
 
using System.Text;
 
using System.Windows.Forms;
 
using System.IO.Ports;
 
namespace rs232_projesi
 
{
 
public partial class Form1 : Form
 
{
 
public Form1()
 
{
 
InitializeComponent();
 
}
 
private void Form1_Load(object sender, EventArgs e)
 
{
 
string[] portlar = SerialPort.GetPortNames();  // portları dizi halinde aldık
 
foreach (string port in portlar)
 
{
 
comboBox1.Items.Add(port.ToString()); // Portlarımızı combobox ın içine aldık.
 
}
 
CheckForIllegalCrossThreadCalls = false;
 
/*
 
Textboxlar main thread'a bağlıdır, burada oluşan bir nesnedir.
 
Seriportun datareceived eventi kendine başka bir thread açar ve sürekli dinleme yapar ki böylece yeni data geldiğinde bunu alabilelim. Bu satırı yazmazsak: Event içinde datayı alıp, başka thread'a ait textboxa yazdırmaya çalıştığımız için derleyici "Cross-thread operation not valid: Control 'textBox1' accessed from a thread other than the thread it was created on." yani "Çapraz-iş parçacığı işlemi geçersiz ; hatası verir.
 
textbox1 bu thread üzerinde oluşturulmamış ki" mealinde birşeyler söylüyor, ee o zaman nasıl mümkün? Tabiki, bu denetimi aşağıdaki kodu form_load eventine veya form constructor'ının içine yazarak devre dışı bırakırsan.
 
CheckForIllegalCrossThreadCalls = false;
 
*/
 
}
 
void seri_port_baglan()
 
{
 
if (serialPort1.IsOpen) // Bağlantıyı açıyoruz.eğer önceden bağlan butonuna basmış isek yani bağlantıyı açmışsak aşağıdaki hata mesajını verecektir.
 
{
 
MessageBox.Show("Port Açık Bulunmaktadır..", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button3);
 
return;
 
}
 
else
 
{
 
try
 
{
 
serialPort1.BaudRate = int.Parse("9600"); // Hız olarak 9600 verdik.
 
serialPort1.DataBits = int.Parse("8"); // Veri bit ini de 8 bit olarak verdik
 
serialPort1.StopBits = System.IO.Ports.StopBits.One; // Durma bitini tek sefer olarak verdik.
 
serialPort1.Parity = Parity.None; // eşlik bit ini vermedik.
 
serialPort1.PortName = comboBox1.Text; // Port adlarını comboboxtan alıyoruz.
 
serialPort1.Open(); // Bağlantıyı açıyoruz
 
MessageBox.Show("Bağlantı Başarılı");
 
}
 
catch (Exception) // Herhangi bir hata anında alttaki hata mesajını alacağız..
 
{
 
MessageBox.Show("cihazınız bağlı değil...", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button3);
 
}
 
}
 
}
 
public string trDuzelt(string a) //Türkçe karakerleri, ingilizce karakterlere çevirmek için kullanıyoruz
 
{
 
a = a.Replace("İ", "I");
 
a = a.Replace("Ü", "U");
 
a = a.Replace("Ç", "C");
 
a = a.Replace("Ş", "S");
 
a = a.Replace("Ö", "O");
 
a = a.Replace("Ğ", "G");
 
a = a.Replace("ı", "I");
 
a = a.Replace("ü", "U");
 
a = a.Replace("ş", "S");
 
a = a.Replace("ç", "C");
 
a = a.Replace("ğ", "G");
 
a = a.Replace("ö", "O");
 
return a;
 
}
 
private void seri_port_data_gonder(string gonderilecek_veri)
 
{
 
try
 
{
 
if (serialPort1.IsOpen)
 
{
 
serialPort1.Write(gonderilecek_veri);
 
System.Threading.Thread.Sleep(150);
 
//alıcı cihaza okuması için biraz süre tanımak gerek, kul yapısı sonuçta
 
}
 
}
 
catch (Exception)
 
{
 
MessageBox.Show("Sonuç: Başarısız !", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button3);
 
}
 
}
 
void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
 
{
 
byte[] buffer;
 
buffer = new byte[1];
 
serialPort1.Read(buffer, 0, 0);
 
MessageBox.Show("Gelen veri:" serialPort1.ReadExisting());
 
// her gelen veriyi otomatik görmenize gerek yoksa bu satırın başına // koyunuz
 
}
 
private void button1_Click(object sender, EventArgs e) //veri gönderme butonu
 
{
 
seri_port_data_gonder(textbox1.text+(Char)13);
 
//textboxtaki veriyi, yazdığımız fonksiyon aracılığıyla rs232 den gönderiyoruz.
 
//char13, enterin ascii kodudur.
 
}
 
}
 
}
Özel mesaj okumuyorum, lütfen göndermeyin.

serhat1990

Hocam benim programda serialport nesnesi ekli durumda . Sizin verdiğiniz kodun veri alma bloğunu ekledim aynı sonucu alıyorum . Benim kodlarım üzerinde basit bir düzenleme ile sorun çözülebilir diye düşünüyorum . Sorun hala devam ediyor , yardımları bekliyorum . Saygılarımla ...

Kabil ATICI

Alınan değeri onluk sistemde veya hex değeri olarak görüntülemeye çalış.
cihazın ascii karakter setinde rakam veya yazı olmayan bölgeden de veri gönderiyor olabilir.
ambar7

kudretuzuner

Merhaba,
Sizin kullandığınız dili bilmediğim için kodları kontrol edemiyorum.Genel prensip olarak şunları yazabilirim.Meftun arkadaşın da dediği gibi data received ile byte byte okursanız daha iyi olacak.Ayrıca PIC dataları hex olarak yollar ama PC bu hex dataların DEC değerleri ile okur yani pıc hex'31' klavye"1" yollar ama pc bunu dec49 olarak okur.VB.Net 2010 kullanmaktayım.
Amatör

serhat1990

Alıntı yapılan: kudretuzuner - 17 Aralık 2013, 12:06:59
Merhaba,
Sizin kullandığınız dili bilmediğim için kodları kontrol edemiyorum.Genel prensip olarak şunları yazabilirim.Meftun arkadaşın da dediği gibi data received ile byte byte okursanız daha iyi olacak.Ayrıca PIC dataları hex olarak yollar ama PC bu hex dataların DEC değerleri ile okur yani pıc hex'31' klavye"1" yollar ama pc bunu dec49 olarak okur.VB.Net 2010 kullanmaktayım.

Alıntı yapılan: ambar7 - 17 Aralık 2013, 12:03:40
Alınan değeri onluk sistemde veya hex değeri olarak görüntülemeye çalış.
cihazın ascii karakter setinde rakam veya yazı olmayan bölgeden de veri gönderiyor olabilir.

Cevaplar için teşekkürler Hocam. Cihaz kendi yaptığım bir ünite gönderdiği mesajın karakter olarak karşılığı var . "Ready" mesajını gönderiyor .  Yani benim bu veriyi normal şartlar altında alıyor ve ekrana yazıyor olmam gerek. Ben programımdan veri gönderince bu verinin cevabını alıyor olmam gibi bir durum var . Veri gönderince bana gelen veriyi alıyorum , veri göndermediğim durumlarda bana veri gelirse bu verileri alamıyorum .Buffer'lar ile alakalı bir sorun olabilirmi ?

kudretuzuner

Merhaba,
Sisteminizi tam olarak bilmediğim için yine genel yazacağım.Sizin PC'den PIC'e data yollayabilmeniz PIC yazılımında program PC'den data alacak şekilde beklediği zaman bildiğim kadarı bu sırada dışarıdan PC'ye data gelse bile okumuyor.Ben de böyle bir proje üstünde çalışmaktayım.Çözümü şöyle buldum her terminalden data girişinden sonra önce dış ortamdan data gelip gelmediğini kontrol ediyorum.PC'de okuyorum ve PIC  PC'den data alacak konuma geliyorum.Tekrar data girişinde tekrar dış ortamı okuyorum görüyorum tekrar PIC  PC'den data alacak konuma geçiyor.PC yazılımında boş bir data belli aralıklarla otomatik olarak yollayarak sürekli dış ortamdan data gelip gelmediğini kontrol etmek mümkün olabilir gibi geliyor bana. 
Amatör

Gökhan BEKEN

Cihazınızda sorun olma, BaudRate uyuysuzluğu ihtimali nedir?
Daha önce terminal programı ile denediniz mi cihazı?
Özel mesaj okumuyorum, lütfen göndermeyin.

serhat1990

Alıntı yapılan: serhat1990 - 17 Aralık 2013, 10:12:43
Cihazımı normal terminal programlarında kullanıyorum bir sıkıntı yok .

Hocam mesajımda belirtmiştim kullanıyorum böyle bir ihtimal yok . Bir çok terminal programı ile çalıştım / çalışıyorum kullandığım bir cihaz .

serhat1990

Sorunum hala devam etmekte , bu konuda yardımlarınızı bekliyorum . Şunu bir türlü anlayamıyorum . Bağladığım cihaz herhangi bir sorgulama olmadan veri gönderince bunu görüntüleyemiyor fakat ben cihaza sorgu gönderdiğimde bu sorgunun cevabını görüntülüyorum . Sadece veri gönderme sonrasında belli bir süre dinleme aktif diğer durumlarda pasif oluyor olma gibi bir ihtimal var mıdır ?

İyi çalışmalar dilerim .

olemiss

private void button1_Click() fonksiyonunun sonuna aşağıdaki kodu ekleyip test edin, sonuçları buraya yazın lütfen:
serialPort1.Handshake = Ports.Handshake.RequestToSend;
Yazılım Mühendisi, Çevirmen.

serhat1990

Hocam şuan yanımda ekipmanım yok yarın deneyip sonucu yazacağım teşekkürler ...

serhat1990

Hocam bahsettiğiniz kodu ekledim fakat sonuç değişmedi .

muhittin_kaplan

serhat kolay gelsin.

data recieve olayı nı başka bir Thread ile yapılmalı, çünki program bir iş yaparken devamlı serportu dinlemeli.

eğer bir timer a yada olaya (event) bağlanırsa bu data rec olayı eksik, kesintili anlamsız bilgiler gelir.

sonrasında "gönderim yapan" cihazın nasıl bir formatta bilgi bönderdiği bilinmeli, eğer string bilgi gönderip readbyte yaparsanız problem yaşarsınız.
readexisting, eğer veri varsa okur.

örnekleyecek olursak

http://msdn.microsoft.com/tr-tr/library/system.io.ports.serialport.readline(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2

c# kodu incelendiğinde kod ile

Thread readThread = new Thread(Read);


Thread oluşturulmuştur.

readThread.Start();


ile bu işlem başlatılmıştır.

public static void Read()
{
    while (_continue)
    {
        try
        {
            string message = _serialPort.ReadLine();
            Console.WriteLine(message);
        }
        catch (TimeoutException) { }
    }
}


ilede read olayı na okuma blogu yerleştirilmiştir. Yapmamız gereken datarecieve olayına Thread ile birleştirmemizdir. aşağıda konuyla alakalı birkaç çözüm yolu belirtilmiş.

http://www.codeproject.com/Questions/228124/serial-port-using-threading

serhat1990

Hocam yanıtlarınız için çok teşekkür ederim , en kısa sürede deneyip sonuçlarını yazacağım . Bilgileri string olarak gönderiyorum Hocam cihazımdan.