【问题标题】:How to Read and Write from the Serial Port如何从串口读取和写入
【发布时间】:2010-11-17 14:27:45
【问题描述】:

我刚刚开始学习如何通过 C# GUI 从我的硬件发送和接收数据。

谁能详细说明如何读取串口数据?

【问题讨论】:

  • Managing serial ports in C# 的可能重复项
  • 反过来:链接的帖子是这个帖子的副本。请将此问题用作规范副本。

标签: c# serial-port


【解决方案1】:

SerialPort (RS-232 Serial COM Port) in C# .NET
本文介绍如何使用 .NET 中的SerialPort 类来读取和写入数据,确定您的机器上可用的串行端口,以及如何发送文件。它甚至涵盖了端口本身的引脚分配。

示例代码:

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());
    }
  }
}

【讨论】:

  • 嗨,我正在尝试相同的方法,但没有调用事件处理程序方法!
  • @PrashantPimpale 你能解决你的问题吗?
  • @mrid 是的!我只是断开设备并喝了杯茶然后开始!在其他情况下,您使用的连接器可能有问题。
【解决方案2】:

我花了很多时间来使用SerialPort 类,并最终决定改用SerialPort.BaseStream 类。可以看源码:SerialPort-sourceSerialPort.BaseStream-source 深入了解。 我创建并使用了如下所示的代码。

  • 核心功能 public int Recv(byte[] buffer, int maxLen) 名称和工作方式类似于“知名”套接字的recv()

  • 意思是

    • 一方面它没有任何数据超时并抛出TimeoutException
    • 另一方面,当收到任何数据时,
      • 它接收数据直到maxLen字节
      • 或 UART 数据流中的短超时(理论 6 毫秒)

.

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

【讨论】:

  • 是的,尤其是ReadAsync方便多了。
【解决方案3】:

请注意,SerialPort.DataReceived 事件的使用是可选的。您可以使用SerialPort.ReadTimeout 设置适当的超时时间,并在向端口写入内容后连续调用SerialPort.Read(),直到获得完整响应。

此外,您可以使用SerialPort.BaseStream 属性来提取底层Stream 实例。使用Stream 的好处是您可以轻松地使用各种装饰器:

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.

更多信息请查看:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多