Veri Alırken Program Kilitleniyor

Başlatan vitruvius, 12 Haziran 2011, 20:44:27

vitruvius

Merhaba, ortam sıcaklığını bilgisayara aktaracak bir proje üzerinde çalışıyorum. C#'ta yazdığım arayüz programı ile veriyi alabiliyorum ancak bu esnada yazdığım program kilitleniyor.
Veriyi timer'da her saniye alıyorum. Bunun sebebi ne olabilir? Teşekkürler.

C# kodları
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.Collections;

namespace SıcaklıkProje
{
    public partial class Form1 : Form
    {
        public Form1()
        {            
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {            
            comboBox1.DataSource = System.IO.Ports.SerialPort.GetPortNames();
            comboBox1.SelectedItem = 1;            
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (!serialPort1.IsOpen)
            {
                serialPort1.PortName = comboBox1.SelectedItem.ToString();
                serialPort1.Open();
            }

            else
            { MessageBox.Show("Port Açık Değil!"); }

            button1.Enabled = false;
            button3.Enabled = true;
            button2.Enabled = true;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            { serialPort1.Close(); }

            button2.Enabled = false;
            button1.Enabled = true;
            button3.Enabled = false;
        }

        private void button3_Click(object sender, EventArgs e)
        {            
            timer1.Enabled = true;
            button3.Enabled = false;
            button4.Enabled = true;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {       
     
            double Ortalama = 0;
            string veri = serialPort1.ReadLine();
            ArrayList VeriList = new ArrayList();

            listBox1.Items.Add(veri);

            VeriList.Add(veri);
            label1.Text = veri.ToString();

            Ortalama = VeriGetAvarage(VeriList);
            label3.Text = Ortalama.ToString();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            timer1.Enabled = false;
            button4.Enabled = false;
            button3.Enabled = true;
        }

        private double VeriGetAvarage(ArrayList Veri)
        {

            double sum = 0;
            int countVeri = 1;

            for (int i=0; i<Veri.Count; i++) {

                sum = sum + Veri.IndexOf(i);
                countVeri++;

            }

            return sum / countVeri;

        }

    }
}


CCS C kodları:

#include <16f877A.h>
#device ADC=10
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay (clock=4000000)
#use fast_io(a) // Port yönlendirme a portu için geçerli
#define use_portb_lcd TRUE
#include <lcd.c>
#use rs232 (baud=9600,rcv=PIN_C7, xmit=PIN_C6, parity=N, stop=1) //rs 232 için
unsigned long int bilgi;
float gerilim, sicak;
int i;
void main ()
{
setup_psp(PSP_DISABLED);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_CCP1(CCP_OFF);
setup_CCP2(CCP_OFF);
set_tris_a(0x01); // RA0 giriş olarak yönlendirildi
setup_adc(adc_clock_div_32);
setup_adc_ports(AN0); // RA0/AN0 girişi analog
lcd_init();
set_adc_channel(0); //RA0/AN0 ucundaki sinyal A/D işemine sokulacak
delay_us(100);
printf(lcd_putc,"\f    Proje I");
delay_ms(800);
printf(lcd_putc,"\nSicaklik Sensoru");
delay_ms(1000);
printf(lcd_putc,"\f Ogretim Uyesi");
printf(lcd_putc,"\n Doc. Dr. Abdullah BAL");
delay_ms(450);
while (i<23) // Kayan yazı
{
i++;
lcd_send_byte(0, 0x1E);
delay_ms(100);
}
delay_ms(100);
printf(lcd_putc,"\f  Baris Yakut");
printf(lcd_putc,"\n   07013038");
delay_ms(1800);
printf(lcd_putc,"\fSicaklik=");
while (1)
{
bilgi=read_adc(); // ADC sonucu okunuyor ve bilgi değişkenine aktarılıyor
gerilim=(0.0048828125*bilgi)*1000; //Dijitale çevirme işlemine uğrayan sinyalin mv değeri
sicak=(gerilim/10)-0.3;
lcd_gotoxy(10,1);
printf(lcd_putc,"%5.1f'C"sicak);
delay_ms(100);
printf("Sicaklik: %.1f\n\r",sicak);
delay_ms(1000);
}
}


C# dosyası:
https://rapidshare.com/files/1152727530/Sae_caklae_kProje.zip

Teşekkürler.


Klein

string veri = serialPort1.ReadLine();

ReadLine fonksiyonu while döngüsü gibi çalışır.  veri gelene kadar veya timeout  vermişsen timeout kadar döngüde kalır.
Bunun yerine
string veri = serialPort1.ReadExisting();

fonksiyonunu kullanırsan  fonksiyonu çağırdığın anda tamponda ne varsa hepsini alırsın.

eğer veriyi timer ile değil  seri port nesnesinin  "DataReceived()" olayının içerisinde alırsan , veriyi beklemek zorunda kalmazsın.
Veriyi  bu event içinde okur tampona alırsın. Timer veya Thread ile  tampondaki veriyi işlersin.
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;

namespace CarFinder_V1_Test
{
    public partial class Form1 : Form
    {
        string buf;
        bool rx_ok=false;
        public Form1()
        {
            InitializeComponent();
        }


        private void button1_Click(object sender, EventArgs e)
        {
            sport.Open();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            sport.Close();
        }

        private void button3_Click(object sender, EventArgs e)
        {
//            sport.WriteLine(textBox1.Text + "\r\x001A");
            sport.WriteLine(textBox1.Text);
        }

        private void button5_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = buf;
        }

        private void button4_Click(object sender, EventArgs e)
        {
        }

        private void sport_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            buf = sport.ReadExisting();

            rx_ok=true;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (buf != null && rx_ok)
            {
                richTextBox1.Text = buf + richTextBox1.Text;
                buf = null;
                rx_ok=false;
            }

        }

        private void label13_Click(object sender, EventArgs e)
        {

        }

        private void labelclick(object sender, EventArgs e)
        {
            string s="AT";
            s=((Label)sender).Text;
            sport.WriteLine(s + "\r");
        }

        private void button4_Click_1(object sender, EventArgs e)
        {
            sport.WriteLine("\x001A");
        }

        private void button5_Click_1(object sender, EventArgs e)
        {
            sport.WriteLine("\r");

        }

        private void button6_Click(object sender, EventArgs e)
        {
            sport.WriteLine(richTextBox2.Text);
        }

        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {

        }

    }
}

vitruvius

Merhaba

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            string veri = serialPort1.ReadExisting();
        }


Bahsettiğiniz kısmı silip bu kısmı ekledim. Ancak C#'ta amatör olduğumdan timer'da bunu çağıramadım. O kısım hakkında biraz daha bilgi verebilir misiniz? Timer kullanmamın sebebi,
belli bir zaman aralığında değerleri almak istemem.

Klein

string veri = serialPort1.ReadExisting();


sadece bu kısmı timer olayı içine eklersen belirli zaman aralığında  tamponda ne varsa alırsın. Diğer kısmı eklemene gerek yok.

Ama verim önemli , timer bekleyemem. Veri alındığında haberim olsun dersen.
seri port nesnesinin events bölümünden DataReceived olayını aktif edip bu olayın içerisinde

string veri = serialPort1.ReadExisting();


kodunu işletirsen , veriyi string_veri tamponuna alabilirsin.
Fakat bu stringi aynı fonksiyon içerisinde herhangi bir nesneye yazamazsın.
Yani DataReceived olayı içinde Label1.text = string_veri diyemezsin.  Bunu anck Timer olayı veya yeni bir thread içerisinde yaparsın.
Çünkü senin form olaylarını işleten thread ile  ,seri port olayını işleten thread farklı.

Bu işi timer ile nasıl yapabileceğine ilişkin örnek yukarıda var.
Ama sen şimdilik DataReceived olayını pas geç. Veri alışverişini  gerçekleştir , iyileştirmeleri sonra yaparsın.
Bunun için kendi kodunda "ReadLine()" komutunu yazdığın yere "ReadExisting()" yazman yeterli.

vitruvius

Hocam teşekkür ederim kilitlenme sorunum çözüldü. Ancak şu an iki proje üzerinde çalışıyorum. Birisi bilgisayardan veri yollamak, diğeri de veri almak. Mesela bu sıcaklık olayında devrenin adaptörünü takar takmaz arayüz programımda "Başlat" butonuna tıkayıp (Yukardaki kodlarda button3) veri alımına başlamam gerekiyor. Aksi halde devre adaptörünü taktıktan 5 sn sonra falan "Başlat" butonuna basarsam veri alamıyorum. Bunun sebebi ne olabilir? Teşekkürler.

Klein

Koddan anladığım kadarıyla:
Devreden veri alırken sorgu yapmıyorsun. devre sürekli veri basıyor.
Aynı şekilde PC tarafı bu veriyi sürekli alıyor ama Timer açık olmadığı için veriyi işlemiyorsun.
Eğer durum bu ise , veriyi alma değil işleme sorunun olabilir.
Yani:
Devreyi bağladın. 5-10 sn bekledin. bu arada devre veri gönderdi , PC de bu veriyi tampona aldı. tamponda 5-10 tane veri birikti.
Eğer sen bu veriyi ayıklayamıyorsan , veri almadığını düşünüyor olabilirsin.
Eğer durum bu ise:
Veriyi gönderirken başına ve sonuna başlangıç ve bitiş karakterleri ekle.  hatta CRC , en azından LRC ekle.  Veriyi aldığında başlangıç ve bitiş karakterlerini  alıp almadığına bak. eğer bu bilgiler varsa , LRC veya CRC hesaplat , bu da tutuyorsa başlangıç ve bitiş karakterleri arasındaki karakterleri işle.