首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在C#中使用SerialPort端口对象的dataReceived事件?

如何在C#中使用SerialPort端口对象的dataReceived事件?
EN

Stack Overflow用户
提问于 2009-01-22 02:44:34
回答 7查看 123.8K关注 0票数 22

我正在尝试创建一个小应用程序来收集从连接到COM10的外部传感器接收的数据。我已经成功地创建了一个小型C#控制台对象和应用程序,它打开端口并使用for循环将数据流式传输到一个固定的时间段内的文件。

我想将此应用程序转换为使用dataReceived事件进行流式处理。在阅读了Top 5 SerialPort Tips之后,我似乎仍然不能让它工作,并且不知道我错过了什么。我重写了控制台应用程序,以便所有代码都在Main中,并粘贴到下面。有人能告诉我为什么在我知道有数据被硬件发送到端口的情况下事件处理程序port_OnReceiveDatazz没有被调用吗?

谢谢

感谢@Gabe@Jason Down@abatishchev的所有建议。我被难住了,似乎不能让事件处理程序工作。也许这和这个设备有关。我可以只在线程中读取端口并将数据直接流式传输到文件中。

代码

代码语言:javascript
复制
namespace serialPortCollection
{   class Program
    {
        static void Main(string[] args)
        {
            
            const int bufSize = 2048;
            Byte[] buf = new Byte[bufSize]; //To store the received data.

            SerialPort sp = new SerialPort("COM10", 115200);
            sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler

            sp.Open();
            sp.WriteLine("$"); //Command to start Data Stream

            // Wait for data or user input to continue.
            Console.ReadLine();
           
            sp.WriteLine("!"); //Stop Data Stream Command
            sp.Close();
        }
        
       // My Event Handler Method
        private static void port_OnReceiveDatazz(object sender, 
                                   SerialDataReceivedEventArgs e)
        {
            SerialPort spL = (SerialPort) sender;
            const int bufSize = 12;
            Byte[] buf = new Byte[bufSize];
            Console.WriteLine("DATA RECEIVED!");
            Console.WriteLine(spL.Read(buf, 0, bufSize));
        }
    }
}
EN

回答 7

Stack Overflow用户

发布于 2009-01-21 19:11:58

首先,我建议您使用以下构造函数,而不是您当前使用的构造函数:

代码语言:javascript
复制
new SerialPort("COM10", 115200, Parity.None, 8, StopBits.One);

接下来,你真的应该删除这段代码:

代码语言:javascript
复制
// Wait 10 Seconds for data...
for (int i = 0; i < 1000; i++)
{
    Thread.Sleep(10);
    Console.WriteLine(sp.Read(buf,0,bufSize)); //prints data directly to the Console
}

而只是循环,直到用户按下一个键或其他东西,如下所示:

代码语言:javascript
复制
namespace serialPortCollection
{   class Program
    {
        static void Main(string[] args)
        {
            SerialPort sp = new SerialPort("COM10", 115200);
            sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler

            sp.Open();
            sp.WriteLine("$"); //Command to start Data Stream

            Console.ReadLine();

            sp.WriteLine("!"); //Stop Data Stream Command
            sp.Close();
        }

       // My Event Handler Method
        private static void port_OnReceiveDatazz(object sender, 
                                   SerialDataReceivedEventArgs e)
        {
            SerialPort spL = (SerialPort) sender;
            byte[] buf = new byte[spL.BytesToRead];
            Console.WriteLine("DATA RECEIVED!");
            spL.Read(buf, 0, buf.Length);
            foreach (Byte b in buf)
            {
                Console.Write(b.ToString());
            }
            Console.WriteLine();
        }
    }
}

此外,请注意对data received事件处理程序的修订,它现在应该实际打印缓冲区。

更新1

我刚刚在我的机器上成功地运行了以下代码(使用COM33和COM34之间的零调制解调器电缆)

代码语言:javascript
复制
namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread writeThread = new Thread(new ThreadStart(WriteThread));
            SerialPort sp = new SerialPort("COM33", 115200, Parity.None, 8, StopBits.One);
            sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler

            sp.Open();
            sp.WriteLine("$"); //Command to start Data Stream

            writeThread.Start();

            Console.ReadLine();

            sp.WriteLine("!"); //Stop Data Stream Command
            sp.Close();
        }

        private static void port_OnReceiveDatazz(object sender, 
                                   SerialDataReceivedEventArgs e)
        {
            SerialPort spL = (SerialPort) sender;
            byte[] buf = new byte[spL.BytesToRead];
            Console.WriteLine("DATA RECEIVED!");
            spL.Read(buf, 0, buf.Length);
            foreach (Byte b in buf)
            {
                Console.Write(b.ToString() + " ");
            }
            Console.WriteLine();
        }

        private static void WriteThread()
        {
            SerialPort sp2 = new SerialPort("COM34", 115200, Parity.None, 8, StopBits.One);
            sp2.Open();
            byte[] buf = new byte[100];
            for (byte i = 0; i < 100; i++)
            {
                buf[i] = i;
            }
            sp2.Write(buf, 0, buf.Length);
            sp2.Close();
        }
    }
}

更新2

考虑到最近关于这个问题的所有流量。我开始怀疑您的串行端口配置不正确,或者设备没有响应。

我强烈建议您尝试使用其他方式与设备通信(我经常使用超级终端)。然后,您可以尝试所有这些设置(比特率、奇偶校验、数据位、停止位、流控制),直到找到可以工作的设置。设备的文档也应指定这些设置。一旦我弄清楚了这些设置,我就会确保我的.NET SerialPort被正确地配置为使用这些设置。

关于配置串行端口的一些提示:

请注意,当我说你应该使用下面的构造函数时,我的意思是使用那个函数,而不一定是那些参数!您应该为您的设备填写参数,下面的设置是常见的,但您的设备可能会有所不同。

代码语言:javascript
复制
new SerialPort("COM10", 115200, Parity.None, 8, StopBits.One);

将.NET SerialPort设置为与您的设备使用相同的流控制也很重要(正如其他人之前所说的那样)。你可以在这里找到更多信息:

http://www.lammertbies.nl/comm/info/RS-232_flow_control.html

票数 8
EN

Stack Overflow用户

发布于 2009-06-08 12:36:27

我之前使用的调制解调器也遇到了同样的问题,然后有一天就停止了引发DataReceived事件。

在我的例子中,非常随机的解决方案是启用RTS,例如

代码语言:javascript
复制
sp.RtsEnable = true;

不知道为什么它在这个特定的工具包上工作(真的不是一个通讯员),也不知道为什么它工作了然后停止了,但它可能有一天会帮助其他人,所以只是发布它以防万一……

票数 4
EN

Stack Overflow用户

发布于 2009-01-21 18:57:17

顺便说一下,您可以在事件处理程序中使用下一步代码:

代码语言:javascript
复制
switch(e.EventType)
{
  case SerialData.Chars:
  {
    // means you receives something
    break;
  }
  case SerialData.Eof:
  {
    // means receiving ended
    break;
  }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/466474

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档