c# rs232 odbiór danych WF

0

Cześć.
Mam pewien problem otóż napisałem prosty program w c# (Windows Form ) który komunikuję się z moim układem. Wybieram port com w ComboBox klikam połącz i wysysałam po rs 232 dane string "polaczono) na co mój układ odpowiada "ok" i tutaj mam problem jak odebrać dane i na nie zareagować i ewentualnie wyświetlić błąd jeżeli układ nie odpowie?
Pozdrawiam i dziękuje za każda wskazówkę ;)

0

Najlepiej użyj jakiejś biblioteki która ukryje pewne niemiłe aspekty komunikacji asynchronicznej i wystawie odbiór danych od urządzenia pod zwykłym C#'owym event'em. To może nie najpopularniejsze ale demonstruje jak bardzo może być to proste: https://github.com/genielabs/serialport-lib-dotnet/

Ważna rzecz jest taka że wątek użyty przez tą bibliotekę nie może bezpośrednio operować na GUI. Jeżeli chcesz zmienić GUI to musisz to robić przez Invoke (https://docs.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls?view=netframeworkdesktop-4.8).

Powodzenia!

0

Dziękuję za odpowiedź, w takim razie dużo nauki mnie czeka, myślałem że da się prościej ;)

0

Już odbieram dane z rs232 i wyświetlam w Rich TextBox . Nie wiem jak zrobić działanie na zasadzie program w c# wysyła string do układu a układ odpowiada OK. W jakie sposób po wysłaniu stringu czekać na odpowiedź układu?

serialPort1.Write(polaczenie);
//tutaj chcę czekać na odpowiedź układu czy dostał odpowiedź a jak nic nie dostanę wyświetlić błąd
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            var serialPort = (SerialPort)sender;
            var data = serialPort.ReadExisting();
            SetText(data);
        }
delegate void SetTextCallback(string text);
        private void SetText(string text)
        {
            
            if (this.rtxtDataArea.InvokeRequired)
            {
              

                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
               
            }
            else
            {
                this.rtxtDataArea.AppendText(text);
               
            }
        }
0

W jaki sposób odczekać sekundę ale nie blokować programu to znaczy żeby w trakcie czekania był wstanie odebrać dane z rs232?

0

Zrobiłem taką protezę otóż działa to w taki sposób że jak od komentuję MessageBox.Show("komunikat "); to wyświetli mi się on i klikam ok w tym czasie program odbierze OK i wykonuję mi się if jednak jak za komentuję MessageBox.Show("komunikat "); to program zawiesza się w while (_tick < 3 ). Może kolega podpiwedzieć mniej więcej jak to zrobić bo nie jestem pewny czy mam dobrą koncepcję pomijając już wykonanie.
Pozdraiwiam

while (_tick < 3 )
                    {
//MessageBox.Show("komunikat ");
                    if (datainput == "OK")
                    {
                        MessageBox.Show("Polaczono ");
                        return;
                    }

                }
              if (_tick>=3)  MessageBox.Show("Blad Polaczenia");
private void timer1_Tick(object sender, EventArgs e)
        {
            _tick++;
        }

edit. skorzystałem z:

await Task.Delay(500);

edit 2:
Prawei moja funkcja działa dobrze lecz czasami odebrany string nie jest cały otóż wysyłam do PC "OK/n" , jednak czasami podczas pracy programu dostaję string "K/n" lub "/n" nie wiem czym jest to spowodowane. Oczywiście sprawdzałem to na terminalu i układ wysyła dane dobre. Zauważyłem że im mniej ustawię task.delay to problem staje się mneijszy.

string polaczenie = "programowanie" + "\r";
            datainput = "no";
            serialPort1.Write(polaczenie);


            // await Task.Delay(500);

            await Task.Delay(30);
            if (datainput == "OK\n")
            {
                // MessageBox.Show("Polaczono ");
                progressBar1.Value = 100;
            }
            else
            {
                //  MessageBox.Show("Blad Polaczenia");
                progressBar1.Value = 60;
            }
0

Programowanie asynchroniczne, zadania (Task), ale chyba nie obie metody naraz - to, moim zdaniem, rozwiąże Twój problem.

0

jeżeli dobrze rozumiem to muszę zrobić cos w stylu tego opisu?
https://docs.microsoft.com/pl-pl/dotnet/csharp/programming-guide/concepts/async/

0

O tym myślałem. Tam kody wykonywane asynchronicznie mają dość duże oczekiwanie - Task.Delay(3000).Wait(). Nic wtedy nie robią i można je przeplatać, aby wykorzystać te przerwy. Gdybyś chciał przeplatać kody coś robiące, to można np tak:

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncBreakfast
{
    class Program
    {
        const int n = 805_457_000;

        static void Main(string[] args)
        {
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();

            Coffee cup = PourCoffee();
            Console.WriteLine("coffee is ready");

            Task<Bacon> baconTask = Task.Run(() => FryBacon(3) );
            Task<Egg> eggsTask = Task.Run(() => FryEggs(2));
            Task<Toast> toastTask = Task.Run(() => ToastBread(2));

            Juice oj = PourOJ();
            Console.WriteLine("oj is ready");

            baconTask.Wait();
            Bacon bacon = baconTask.Result;
            Console.WriteLine("bacon is ready");

            eggsTask.Wait();
            Egg eggs = eggsTask.Result;
            Console.WriteLine("eggs are ready");

            toastTask.Wait();

            Toast toast = toastTask.Result;
            ApplyButter(toast);
            ApplyJam(toast);
            Console.WriteLine("toast is ready");


            Console.WriteLine("Breakfast is ready!");

            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
            string elapsedTime = string.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
            Console.WriteLine("Czas wykonania " + elapsedTime);

            Console.ReadKey();
        }

        private static Juice PourOJ()
        {
            Console.WriteLine("Pouring orange juice");
            return new Juice();
        }

        private static void ApplyJam(Toast toast) =>
            Console.WriteLine("Putting jam on the toast");

        private static void ApplyButter(Toast toast) =>
            Console.WriteLine("Putting butter on the toast");

        private static Toast ToastBread(int slices)
        {
            for (int slice = 0; slice < slices; slice++)
            {
                Console.WriteLine("Putting a slice of bread in the toaster");
            }
            Console.WriteLine("Start toasting...");
            for (int i = 0; i < n; i++) { }
            Console.WriteLine("Remove toast from toaster");

            return new Toast();
        }

        private static Bacon FryBacon(int slices)
        {
            Console.WriteLine($"putting {slices} slices of bacon in the pan");
            Console.WriteLine("cooking first side of bacon...");
            for (int i = 0; i < n; i++) { }
            for (int slice = 0; slice < slices; slice++)
            {
                Console.WriteLine("flipping a slice of bacon");
            }
            Console.WriteLine("cooking the second side of bacon...");
            for (int i = 0; i < n; i++) { }
            Console.WriteLine("Put bacon on plate");

            return new Bacon();
        }

        private static Egg FryEggs(int howMany)
        {
            Console.WriteLine("Warming the egg pan...");
            for (int i = 0; i < n; i++) { }
            Console.WriteLine($"cracking {howMany} eggs");
            Console.WriteLine("cooking the eggs ...");
            for (int i = 0; i < n; i++) { }
            Console.WriteLine("Put eggs on plate");

            return new Egg();
        }

        private static Coffee PourCoffee()
        {
            Console.WriteLine("Pouring coffee");
            return new Coffee();
        }
    }

    internal class Toast
    {
        public Toast()
        {
        }
    }

    internal class Bacon
    {
        public Bacon()
        {
        }
    }

    internal class Egg
    {
        public Egg()
        {
        }
    }

    internal class Juice
    {
    }

    internal class Coffee
    {
    }
}
0

@Sadam2: Wywołuję funkcję FryBacon i dodaję ją do task dzięki czemu wykonuje się w tle?

Task<Bacon> baconTask = Task.Run(() => FryBacon(3));

W tym miejscu czekam na rezultat funkcji? ale z tego ro rozumiem nie blokująco?

 baconTask.Wait();

Do czego służy klasa Bacon?

 internal class Bacon
    {
        public Bacon()
        {
        }
    }

Tak wygląda u mnie funkcja przycisku otwierająca port i sprawdzająca czy połączona się z układem:

private async void btnOpen_Click(object sender, EventArgs e)
        {
            try
            {
               
                serialPort1.PortName = cBoxCOMPORT.Text;
                serialPort1.BaudRate = 115200;//Convert.ToInt32(CBoxBaudRate.Text);
                serialPort1.DataBits = 8;// Convert.ToInt32(CBoxDataBits.Text);
                serialPort1.StopBits = StopBits.One;
                serialPort1.Parity = Parity.None;
                serialPort1.Open();
                serialPort1.DataReceived += SerialPortDataReceived;

                string polaczenie = "programowanie" + "\r";
                datainput = "no";
                serialPort1.Write(polaczenie);


              

                await Task.Delay(200);
                if (datainput == "OK\n")
                {
                    // MessageBox.Show("Polaczono ");
                    progressBar1.Value = 100;
                }
                else
                {
                    //  MessageBox.Show("Blad Polaczenia");
                    progressBar1.Value = 60;
                }




                btnOpen.Enabled = false;
                btnClose.Enabled = true;
                bntSendData.Enabled = true;
            }

          catch (Exception err)
            {
                MessageBox.Show(err.Message,"blad", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
0

@henryxxl: Trochę inaczej. W przykładzie na asynchroniczność, który podałeś, występuje Task.Delay... .Zastąp to pętlą for trwającą mniej więcej tyle samo (wszystkie tego wystąpienia) i zobacz wynik. Ilość obrotów tej pętli dobrałem na swojej maszynie - na Twojej może być inna. Cały przykład, który podałem, to jest jakby realizacja tego ich przykładu asynchronicznego w sytuacji, gdy nie ma zysku czasowego z asynchroniczności. Klasy Toast, Bacon i Egg niepotrzebnie mają konstruktory ale reszta, jak mi się zdaje, oddaje podany tam przebieg.

Funkcja FryBacon wykonuje się w tle równolegle do FryEggs i ToastBread. Na rezultat FryBacon czekasz blokująco - ale czekasz, bo chcesz wyświetlić wynik. W trakcie tego czekania nadal wykonują się FryEggs I ToastBread.

Dołóż sobie przycisk do wyświetlania jakiegoś komunikatu, wydłuż znacznie czas oczekiwania na odpowiedź i sam zobacz, czy oczekiwanie blokuje Ci interfejs użytkownika.

1 użytkowników online, w tym zalogowanych: 0, gości: 1