webentwicklung-frage-antwort-db.com.de

Lesen und Schreiben über den seriellen Port

Ich lerne gerade, wie ich Daten von meiner Hardware über die C # GUI senden und empfangen kann.

Kann jemand bitte ein Detail schreiben, wie manDaten von der seriellen Schnittstelle liest?

35
CHIENSION

SerialPort (serieller RS-232-COM-Port) in C # .NET
Dieser Artikel beschreibt, wie Sie mit der Klasse SerialPort in .NET Daten lesen und schreiben, bestimmen, welche seriellen Anschlüsse auf Ihrem Computer verfügbar sind, und wie Sie Dateien senden. Es deckt sogar die Pinbelegungen am Port selbst ab.

Beispielcode:

using System;
using System.IO.Ports;
using System.Windows.Forms;

namespace SerialPortExample
{
  class SerialPortProgram
  {
    // Create the serial port with basic settings
    private SerialPort port = new SerialPort("COM1",
      9600, Parity.None, 8, StopBits.One);

    [STAThread]
    static void Main(string[] args)
    { 
      // Instatiate this class
      new SerialPortProgram();
    }

    private SerialPortProgram()
    {
      Console.WriteLine("Incoming Data:");

      // Attach a method to be called when there
      // is data waiting in the port's buffer
      port.DataReceived += new 
        SerialDataReceivedEventHandler(port_DataReceived);

      // Begin communications
      port.Open();

      // Enter an application loop to keep this thread alive
      Application.Run();
    }

    private void port_DataReceived(object sender,
      SerialDataReceivedEventArgs e)
    {
      // Show all the incoming data in the port's buffer
      Console.WriteLine(port.ReadExisting());
    }
  }
}
75
Robert Harvey

Ich habe viel Zeit damit verbracht, die SerialPort -Klasse zu verwenden, und habe die Verwendung der SerialPort.BaseStream -Klasse abgeschlossen. Sie können den Quellcode sehen: SerialPort-source und SerialPort.BaseStream-source für ein tieferes Verständnis. 

  • Die Kernfunktion public int Recv(byte[] buffer, int maxLen) Hat einen Namen und funktioniert wie recv() des bekannten Sockels. 

  • Es bedeutet das 

    • in einer Hand hat es keine Zeit für keine Daten und wirft TimeoutException.
    • Wenn dagegen Daten empfangen wurden, wird
      • es empfängt Daten entweder bis maxLen Bytes 
      • oder kurzes Timeout (theoretisch 6 ms) im UART - Datenfluss

.

public class Uart : SerialPort

    {
        private int _receiveTimeout;

        public int ReceiveTimeout { get => _receiveTimeout; set => _receiveTimeout = value; }

        static private string ComPortName = "";

        /// <summary>
        /// It builds PortName using ComPortNum parameter and opens SerialPort.
        /// </summary>
        /// <param name="ComPortNum"></param>
        public Uart(int ComPortNum) : base()
        {
            base.BaudRate = 115200; // default value           
            _receiveTimeout = 2000;
            ComPortName = "COM" + ComPortNum;

            try
            {
                base.PortName = ComPortName;
                base.Open();
            }
            catch (UnauthorizedAccessException ex)
            {
                Console.WriteLine("Error: Port {0} is in use", ComPortName);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Uart exception: " + ex);
            }
        } //Uart()

        /// <summary>
        /// Private property returning positive only Environment.TickCount
        /// </summary>
        private int _tickCount { get => Environment.TickCount & Int32.MaxValue; }


        /// <summary>
        /// It uses SerialPort.BaseStream rather SerialPort functionality .
        /// It Receives up to maxLen number bytes of data, 
        /// Or throws TimeoutException if no any data arrived during ReceiveTimeout. 
        /// It works likes socket-recv routine (explanation in body).
        /// Returns:
        ///    totalReceived - bytes, 
        ///    TimeoutException,
        ///    -1 in non-ComPortNum Exception  
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="maxLen"></param>
        /// <returns></returns>
        public int Recv(byte[] buffer, int maxLen)
        {
            /// The routine works in "pseudo-blocking" mode. It cycles up to first 
            /// data received using BaseStream.ReadTimeout = TimeOutSpan (2 ms).
            /// If no any message received during ReceiveTimeout property, 
            /// the routine throws TimeoutException 
            /// In other hand, if any data has received, first no-data cycle
            /// causes to exit from routine.

            int TimeOutSpan = 2;
            // counts delay in TimeOutSpan-s after end of data to break receive
            int EndOfDataCnt;
            // pseudo-blocking timeout counter
            int TimeOutCnt = _tickCount + _receiveTimeout; 
            //number of currently received data bytes
            int justReceived = 0;
            //number of total received data bytes
            int totalReceived = 0;

            BaseStream.ReadTimeout = TimeOutSpan;
            //causes (2+1)*TimeOutSpan delay after end of data in UART stream
            EndOfDataCnt = 2;
            while (_tickCount < TimeOutCnt && EndOfDataCnt > 0)
            {
                try
                {
                    justReceived = 0; 
                    justReceived = base.BaseStream.Read(buffer, totalReceived, maxLen - totalReceived);
                    totalReceived += justReceived;

                    if (totalReceived >= maxLen)
                        break;
                }
                catch (TimeoutException)
                {
                    if (totalReceived > 0) 
                        EndOfDataCnt--;
                }
                catch (Exception ex)
                {                   
                    totalReceived = -1;
                    base.Close();
                    Console.WriteLine("Recv exception: " + ex);
                    break;
                }

            } //while
            if (totalReceived == 0)
            {              
                throw new TimeoutException();
            }
            else
            {               
                return totalReceived;
            }
        } // Recv()            
    } // Uart
1
Yakov

Beachten Sie, dass die Verwendung eines Ereignisses SerialPort.DataReceived optional ist. Mit SerialPort.ReadTimeout können Sie das richtige Timeout einstellen und fortlaufend SerialPort.Read() aufrufen, nachdem Sie etwas an einen Port geschrieben haben, bis Sie eine vollständige Antwort erhalten. 

Darüber hinaus können Sie mit SerialPort.BaseStream property eine zugrunde liegende Stream -Instanz extrahieren. Der Vorteil einer Stream ist, dass Sie verschiedene Dekorateure problemlos verwenden können:

var port = new SerialPort();
// LoggingStream inherits Stream, implements IDisposable, needen abstract methods and 
// overrides needen virtual methods. 
Stream portStream = new LoggingStream(port.BaseStream);
portStream.Write(...); // Logs write buffer.
portStream.Read(...); // Logs read buffer.

Weitere Informationen finden Sie unter:

0
Leonid Vasilev