在C#中使用SerialPort类实现串口通信 遇到多线程问题

http://blog.21ic.com/user1/1949/archives/2010/66360.html



在.NET work 2.0中提供了SerialPort类,该类主要实现串口数据通信等。本文章将本人在学习过程中从网络上搜集到的相关信息写出来供大家参考。

下面主要介绍该类的主要属性(表1)和方法(表.2)。

如果需要了解更多的信息请登录http://msdn.microsoft.com/zh-cn/library/system.io.ports.serialport(VS.80).aspx查看。

相关文章

《使用System.IO.Ports读取COM口数据》

http://www.devasp.net/net/articles/display/727.html

使用SerialPort类的方法:

方法一:

首先要添加

using System.IO;
using System.IO.Ports;

1...在类的内部定义SerialPort com;

2...打开串口

            com = new SerialPort();
            com.BaudRate = 115200;
            com.PortName = "COM1";
            com.DataBits = 8;
            com.Open();//打开串口

3...发送数据

            Byte[] TxData ={1,2,3,4,5,6,7,8 };
            com.Write(TxData, 0, 8);

4...接收数据

     4.1使用事件接收

     this.com.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.OnDataReceived);

private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)

    4.2使用线程接收

     接收数据启动一个线程,使其接收。

在类的内部定义

        Thread _readThread;
        bool _keepReading;

打开串口后启动线程

            _keepReading = true;
            _readThread = new Thread(ReadPort);
            _readThread.Start();

线程函数

view plaincopy to clipboardprint?
private void ReadPort()   
{   
    while (_keepReading)   
    {   
        if (com.IsOpen)   
        {   
            byte[] readBuffer = new byte[com.ReadBufferSize + 1];   
            try 
            {   
                // If there are bytes available on the serial port,   
                // Read returns up to "count" bytes, but will not block (wait)   
                // for the remaining bytes. If there are no bytes available   
                // on the serial port, Read will block until at least one byte   
                // is available on the port, up until the ReadTimeout milliseconds   
                // have elapsed, at which time a TimeoutException will be thrown.   
                int count = com.Read(readBuffer, 0, com.ReadBufferSize);   
                String SerialIn = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count);   
                if (count != 0)   
                    //byteToHexStr(readBuffer);   
                    Thread(byteToHexStr(readBuffer,count));   
            }   
            catch (TimeoutException) { }   
        }   
        else 
        {   
            TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);   
            Thread.Sleep(waitTime);   
        }   
    }   

        private void ReadPort()
        {
            while (_keepReading)
            {
                if (com.IsOpen)
                {
                    byte[] readBuffer = new byte[com.ReadBufferSize + 1];
                    try
                    {
                        // If there are bytes available on the serial port,
                        // Read returns up to "count" bytes, but will not block (wait)
                        // for the remaining bytes. If there are no bytes available
                        // on the serial port, Read will block until at least one byte
                        // is available on the port, up until the ReadTimeout milliseconds
                        // have elapsed, at which time a TimeoutException will be thrown.
                        int count = com.Read(readBuffer, 0, com.ReadBufferSize);
                        String SerialIn = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count);
                        if (count != 0)
                            //byteToHexStr(readBuffer);
                            Thread(byteToHexStr(readBuffer,count));
                    }
                    catch (TimeoutException) { }
                }
                else
                {
                    TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);
                    Thread.Sleep(waitTime);
                }
            }
        }

方法二:使用C#自带的SerialPor控件。

1...在“工具箱”的“组件”中选择SerialPor控件添加。

2...设置串口并打开

serialPort1.PortName = "COM1";

serialPort1.BaudRate = 9600;

serialPort1.Open();

3...写入数据可以使用Write或者下面的函数

serialPort1.WriteLine(str);

4...添加数据接收的事件

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)

使用中的一些常见问题

C#中SerialPort类中DataReceived事件GUI实时处理方法(来自wanglei_wan@yahoo.com.cn 的看法)
MSDN:从 SerialPort 对象接收数据时,将在辅助线程上引发 DataReceived 事件。由于此事件在辅助线程而非主线程上引发,因此尝试修改主线程中的一些元素(如 UI 元素)时会引发线程异常。如果有必要修改主 Form 或 Control 中的元素,必须使用 Invoke 回发更改请求,这将在正确的线程上执行.进而要想将辅助线程中所读到的数据显示到主线程的Form控件上时,只有通过Invoke方法来实现 
下面是代码实例: 
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
   int SDateTemp = this.serialPort1.ReadByte();
   //读取串口中一个字节的数据
   this.tB_ReceiveDate.Invoke(   
//在拥有此控件的基础窗口句柄的线程上执行委托Invoke(Delegate)
//即在textBox_ReceiveDate控件的父窗口form中执行委托.
new MethodInvoker(            
/*表示一个委托,该委托可执行托管代码中声明为 void 且不接受任何参数的任何方法。 在对控件的 Invoke 方法进行调用时或需要一个简单委托又不想自己定义时可以使用该委托。*/
delegate{                 
    /*匿名方法,C#2.0的新功能,这是一种允许程序员将一段完整代码区块当成参数传递的程序代码编写技术,通过此种方法可 以直接使用委托来设计事件响应程序以下就是你要在主线程上实现的功能但是有一点要注意,这里不适宜处理过多的方法,因为C#消息机制是消息流水线响应机制,如果这里在主线程上处理语句的时间过长会导致主UI线程阻塞,停止响应或响应不顺畅,这时你的主form界面会延迟或卡死      */                   
this.tB_ReceiveDate.AppendText(SDateTemp.ToString());//输出到主窗口文本控件
this.tB_ReceiveDate.Text += " ";}
    )
    );
}

如何知道当前电脑有哪个串口

在窗体上添加一个comboBox控件。

然后使用comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames()); 或者

string[] portList = System.IO.Ports.SerialPort.GetPortNames();
            for (int i = 0; i < portList.Length; ++i)
            {
                string name = portList[i];
                comboBox1.Items.Add(name);
            }

具体请参考http://msdn.microsoft.com/zh-tw/library/system.io.ports.serialport.getportnames.aspx


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux平台上,使用C++语言可以通过多线程实现串口通信。下面是一个简单的示例代码,演示了如何使用多线程在Linux上进行串口通信。 首先,你需要安装一个串口库,比如使用SerialPort库。你可以在终端使用以下命令安装它: ```bash sudo apt-get install libserial-dev ``` 下面是一个使用SerialPort实现多线程串口通信的示例代码: ```cpp #include <iostream> #include <SerialPort.h> #include <thread> // 串口通信线程函数 void serialThread(SerialPort* serialPort) { while (true) { // 读取串口数据 std::string data = serialPort->readLine(); // 处理接收到的数据 // ... // 如果需要在子线程发送数据,可以调用 serialPort->write(data); // 退出线程的条件 if (data == "exit") { break; } } } int main() { // 打开串口设备 SerialPort serialPort("/dev/ttyUSB0"); // 配置串口参数,比如波特率等 serialPort.setBaudRate(BaudRate::B_9600); serialPort.setParity(Parity::None); serialPort.setDataBits(DataBits::D_8); serialPort.setStopBits(StopBits::S_1); // 创建串口通信线程 std::thread t(serialThread, &serialPort); // 主线程发送数据 while (true) { std::string data; std::cin >> data; // 发送数据到串口 serialPort.write(data); // 退出主线程的条件 if (data == "exit") { break; } } // 等待串口通信线程结束 t.join(); return 0; } ``` 上面的代码通过创建一个单独的线程来处理串口通信。在主线程,你可以从终端输入数据,并通过串口发送出去。在串口通信线程,你可以通过读取串口数据来接收来自外部设备的数据。 请注意,上述示例代码仅用于演示多线程串口通信的基本概念,并没有完整的错误处理和数据处理逻辑。在实际应用,你可能需要添加更多的代码来处理异常情况和实现特定的通信协议。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值