百度
360搜索
搜狗搜索

serialport类,使用C# serialport类,用委托进行串口数据接收,接收时需要数据处理和绘图,怎样同步数据防止丢失?详细介绍

本文目录一览: 如何通过SerialPort读取和写入设备COM端口数据

SerialPort中串口数据的读取与写入有较大的不同。由于串口不知道数据何时到达,因此有两种方法可以实现串口数据的读取。一、线程实时读串口;二、事件触发方式实现。
由于线程实时读串口的效率不是十分高效,因此比较好的方法是事件触发的方式。在SerialPort类中有DataReceived事件,当串口的读缓存有数据到达时则触发DataReceived事件,其中SerialPort.ReceivedBytesThreshold属性决定了当串口读缓存中数据多少个时才触发DataReceived事件,默认为1。
另外,SerialPort.DataReceived事件运行比较特殊,其运行在辅线程,不能与主线程中的显示数据控件直接进行数据传输,必须用间接的方式实现。如下:
SerialPort spSend; //spSend,spReceive用虚拟串口连接,它们之间可以相互传输数据。spSend发送数据
SerialPort spReceive; //spReceive接受数据
TextBox txtSend; //发送区
TextBox txtReceive; //接受区
Button btnSend; //数据发送按钮
delegate void HandleInterfaceUpdateDelegate(string text); //委托,此为重点
HandleInterfaceUpdateDelegate interfaceUpdateHandle;
public void InitClient() //窗体控件已在初始化
{
interfaceUpdateHandle = new HandleInterfaceUpdateDelegate(UpdateTextBox); //实例化委托对象
spSend.Open(); //SerialPort对象在程序结束前必须关闭,在此说明
spReceive.DataReceived += Ports.SerialDataReceivedEventHandler(spReceive_DataReceived);
spReceive.ReceivedBytesThreshold = 1;
spReceive.Open();
}
public void btnSend_Click(object sender,EventArgs e)
{
spSend.WriteLine(txtSend.Text);
}
public void spReceive_DataReceived(object sender,Ports.SerialDataReceivedEventArgs e)
{
byte[] readBuffer = new byte[spReceive.ReadBufferSize];
spReceive.Read(readBuffer, 0, readBuffer.Length);
this.Invoke(interfaceUpdateHandle, new string[] { Encoding.Unicode.GetString(readBuffer) });
}
private void UpdateTextBox(string text)
{
txtReceive.Text = text;
}

读写串口 类QSerialPort

背景:一个串口下位机(黑盒子)我每次发送数据,黑盒子都会发送回来状态,

测试情况1

1、自定义一个类myQSerialPort 继承QSerialPort,槽函数接收回复的状态(发送的信号量为AA,BB) (QSerialPort 改为成员变量依旧有这个问题)

定义了变量 m__myQSerialPort,有一个写方法 B(B方法组织数据并发送数据)

m_mutex.lock();//m_mute为QMutex

发送

m_mutex.unlock();

我是在线程? 发送完数据,等到接收到 回复的状态在继续执行

2、一个 线程类 myQThread 发送信号量? A , 然后主线程 发送数据,接收到信号 AA 线程继续运行,

3、主线程中有一个定时器调用 m__myQSerialPort.B(),

等到BB信号量? ,

测试结果发现有时 发送信号量完 A会出现线程不继续执行了, 最后使用串口监控软件,m__myQSerialPort.B()发送的数据和信号量完A发送的 数据被一下 发送给黑盒子了,其不能正常解析,所以就收不到 AA信号量, 线程就 不能执行了,?

串口例子

myserial::myserial()

{

? ? m_pCurrThread = new QThread;

? ? m_pSerial = new QSerialPort;

? ? this->moveToThread(m_pCurrThread);

? ? m_pSerial->moveToThread(m_pCurrThread);

? ? connect(m_pCurrThread, &QThread::started, this, &myserial::OpenSerial);

? ? connect(this, &myserial::SignalWriteData, this, &myserial::WriteData);

? ? m_pCurrThread->start();

}

void myserial::readyRead()

{

? ? qDebug()<<"readyRead = "<
<qthread::currentthreadid()<<"\n";

? ? qDebug() << m_pSerial->readAll().length();

}

void myserial::OpenSerial()

{

? ? qDebug()<<"OpenSerial = "<
<qthread::currentthreadid()<<"\n";

? ? m_pSerial->setPortName(QString("COM4"));

? ? m_pSerial->setBaudRate( 115200 );

? ? m_pSerial->setDataBits(QSerialPort::Data8);

? ? m_pSerial->setParity(QSerialPort::NoParity);

? ? m_pSerial->setStopBits(QSerialPort::OneStop);

? ? m_pSerial->open(QIODevice::ReadWrite);

? ? connect(m_pSerial, &QSerialPort::readyRead, this, &myserial::readyRead,Qt::QueuedConnection);

}

void myserial::run()

{

? ? unsigned char data[6] = {0X5E,1,1,0,6,0x66 };

? ? qDebug()<<"run = "<
<qthread::currentthreadid()<<"\n";

? ? for( int i =0;i< 30;i++)

? ? {

? ? ? ? emit SignalWriteData();

? ? ? ? QThread::sleep(1);

? ? }

}

void myserial::WriteData()

{

? ? qDebug()<<"WriteData = "<

? ? unsigned char data[6] = {0X5E,1,1,0,6,0x66 };

? ? if( m_pSerial->write( (char*)data, 6) < 0 )

? ? ? ? qDebug() <<"write fail";

}

//以上办法 是在在 槽函数中打开 串口,在构造函数中mobetothread

//以下改为在 公有的成员函数中 打开串口 然后moveToThread

#include "myserial.h"

#include

myserial::myserial()

{

? ? m_pCurrThread = new QThread;

? ? m_pSerial = new QSerialPort;

? ? this->moveToThread(m_pCurrThread);

? ? //connect(m_pCurrThread, &QThread::started, this, &myserial::OpenSerial);

? ? connect(this, &myserial::SignalWriteData, this, &myserial::WriteData);

? ? m_pCurrThread->start();

}

void myserial::readyRead()

{

? ? qDebug()<<"readyRead = "<
<qthread::currentthreadid()<<"\n";

? ? qDebug() << m_pSerial->readAll().length();

}

bool myserial::OpenSerial()

{

? ? qDebug()<<"OpenSerial = "<
<qthread::currentthreadid()<<"\n";

? ? m_pSerial->setPortName(QString("COM5"));

? ? m_pSerial->setBaudRate( 115200 );

? ? m_pSerial->setDataBits(QSerialPort::Data8);

? ? m_pSerial->setParity(QSerialPort::NoParity);

? ? m_pSerial->setStopBits(QSerialPort::OneStop);

? ? bool tf = m_pSerial->open(QIODevice::ReadWrite);

? ? //m_pSerial->moveToThread(m_pCurrThread);//都可以

? ? QMetaObject::Connection aa = connect(m_pSerial, &QSerialPort::readyRead, this, &myserial::readyRead,Qt::QueuedConnection);

? ? m_pSerial->moveToThread(m_pCurrThread);

? ? return tf;

阅读更多 >>>  linux命令行设置串口

}

void myserial::run()

{

? ? unsigned char data[6] = {0X5E,1,1,0,6,0x66 };

? ? qDebug()<<"run = "<
<qthread::currentthreadid()<<"\n";

? ? for( int i =0;i< 30;i++)

? ? {

? ? ? ? emit SignalWriteData();

? ? ? ? QThread::sleep(1);

? ? }

}

void myserial::WriteData()

{

? ? qDebug()<<"WriteData = "<
<qthread::currentthreadid()<<"\n";

? ? unsigned char data[6] = {0X5E,1,1,0,6,0x66 };

? ? if( m_pSerial->write( (char*)data, 6) < 0 )

? ? ? ? qDebug() <<"write fail";

}
</qthread::currentthreadid()<<"\n";
</qthread::currentthreadid()<<"\n";
</qthread::currentthreadid()<<"\n";
</qthread::currentthreadid()<<"\n";
</qthread::currentthreadid()<<"\n";
</qthread::currentthreadid()<<"\n";
</qthread::currentthreadid()<<"\n";

C# SerialPort类中SerialPinChange和PinChange的使用方法

RS232串行通信接口硬件上有三个信号输入引脚:
CTS:这个信号源自对方(通常是DSE类型的设备,如调制解调器),告诉你DSE已经同意你发送数据
DSR:这个信号源自对方(通常是DSE类型的设备,如调制解调器),告诉你DSE已经准备就绪,可以工作了
CD:这个信号源自对方(通常是DSE类型的设备,如调制解调器),告诉你DSE已经侦测到载波(也就是数据调制波)
在.net中,要读取这三个信号的状态,有两种方法:
(1)直接读取,代码如下
//读取CTSbool blnCTS = serialPort1.CtsHolding;//读取DSRbool blnDSR = serialPort1.DsrHolding;//读取CDbool blnCD = serialPort1.CDHolding;(2)在串口事件PinChanged处理程序中读取
private void serialPort1_PinChanged(object sender, System.IO.Ports.SerialPinChangedEventArgs e){ // 如果上面说的三个输入信号中,任意一个输入发生变化 // 都会引发PinChanged事件。因此,需要判断究竟是哪个 // 引脚信号变化引发此事件 bool b; switch (e.EventType) { case System.IO.Ports.SerialPinChange.CDChanged: b = serialPort1.CDHolding; break; case System.IO.Ports.SerialPinChange.CtsChanged: b = serialPort1.CtsHolding; break; case System.IO.Ports.SerialPinChange.DsrChanged: b = serialPort1.DsrHolding; break; default: break; }}

使用C# serialport类,用委托进行串口数据接收,接收时需要数据处理和绘图,怎样同步数据防止丢失?

用RecieveBytesThreshold=47是不靠谱的,实际调试时你会发现有时候缓冲区不到47字节就触发中断,所以一定要把RecieveBytesThreshold设为默认的1。即使你把他设成1,也会发现触发中断时缓冲区里面字节数还是可能大于1,不过这样能确保数据接收完整(47个你全部能收到)。
数据接收与处理逻辑要在RecieveBytesThreshold=1的基础上来建立,比如你可以在每次接收中断中把缓冲区的字节以续接的方式存在一个暂存数组里,等到拼满47个,就统一做一次处理。
只说原理
你的需求实际上是一个简单的生产者和消者费的关系,需要用到多线程,你可以按这个关键字去查一下 生产者 消费者 c#
1、串口数据不能固定长度的,即使你下位机发出47字节,你收到数据时也可能会分成多个部分接收。
2、serialport有数据到达时的触发事件,不需要你去定时接收数据,头部判断这个你已经弄错了,一般的方法是上位机收到数据触发时,将收到的数据放入一个缓冲区(可以是List

也可以是Queue

或者string也行),这个就是生产者。

3、在独立的消费者线程里,从缓冲区头上开始检查是否有指定起始和和结束的指令,比如说总是AB xx xx xx xx FF,如果有这种数据,处理数据比如绘图等等,然后把处理完的数据从缓冲区内删除。剩下的数据继续留在缓冲区。

举个例子,比如指令总长4字节,以AB开始,FF结束,那假定收到的是

AB D0 C0 FF AB A5

送入消费者之后,就是处理掉AB D0 C0 FF,剩下的AB A5将继续保留,等待下一次接收数据

C# serialport类编写串口通信程序,无法接收全部数据!

你可以在接受字节的程序开始时延迟等待一会,这个时间要根据数据长短不同进行调节。这是最笨的方法。楼主可以试试ReadLine()或者ReadTo()方法。
如果你收到的数据是固定字节数就简单了,直接设置ReceiveByteThreshold属性为你接收的字节数就可以了。
我和你是一样的问题,我接收的数据不确定是不是定长的,所以我在DataReceived这个事件里面第一行增加了一个Thread.Sleep(1),发现能接收大部分数据,有一个数据没接受完整,然后我把休眠时间设置成了10,好像效果还可以。
问题应该是出在这句:
bytesRead = serialPort.Read(BRecieve, 0, bytesToRead);
楼上的说法有点意思,但是不完全透彻。
其实问题在于串口返回数据时,它返回的速度可能不会太快,而程序执行是非常快的。
也就是说,当执行到Read语句时,串口根本没来得及返回那么多的数据,如你说的,只返回了9个字节。即便你指定bytesToRead大小也没有用。
解决办法:只能通过控制代码来实现你想要的功能,我认为有两种方案可供使用:
一、设置一个大小为59的缓存,写一个while循环,只有从串口读满59个字节的数据时才退出while循环,否则继续读取。
二、思想跟第一种类似,只是不写while循环,利用调用函数思想,当存满59个字节时,返回true,否则返回false,继续读取串口数据。
希望对楼主有用。

C# 串口通信 如何使用SerialPort类发送16进制数

我做过类似的工作,方法大致是这样的:
如果你想往利用SerialPort类往串口里发送16进制数是AA、AA、0B
可以这样:char commandStr[3]={(char)0xAA,(char)0xAA,(char)0x0B};这样定义了一个命令帧
利用串口类SerialPort的函数WriteToPort将commandStr写入就可以了。

Serialport类:出现“由于线程退出或应用程序请求,已放弃IO操作”的警告,请问要怎么解决啊,谢谢了

应该是你没用处理好端口关闭和端口状态判断。
具体要自己看程序,应该是代码逻辑不完整的问题,如果有线程抛出,要在等待线程消息返回后再关闭端口,或者,在县城中处理端口关闭。

C# 调用SerialPort类需要在窗口上放SerialPort控件么?

不需要,但是你必须在后台代码中声明一个
看你需要,可以放也可以不放,不放的话你自己在代码中创建一个也是可以的,诸如象
SerialPort sp=new SerialPort();sp.BaudRate=9600;sp.DataBits=8;......

如何用VB的serialport类实现485通讯的MODBUS协议

serial port是按字符接受字节的。 你可以吧inputlen设置为12,相当于一次读一桢的数据。然后把12个字符赋给var,再把var赋给字符,然后可以读取了。读入阀值设置为12
inputlen设置为12字节,判断LRC校验正确否,最后获取3字节的数据。
请LZ参阅:http://download.csdn.net/source/1070246
下的VB.NET2008 串口工程
还是 推荐 参考 书籍
Visual_Basic与_RS-232_串行通信控制
祝你顺利

网站数据信息

"serialport类,使用C# serialport类,用委托进行串口数据接收,接收时需要数据处理和绘图,怎样同步数据防止丢失?"浏览人数已经达到21次,如你需要查询该站的相关权重信息,可以点击进入"Chinaz数据" 查询。更多网站价值评估因素如:serialport类,使用C# serialport类,用委托进行串口数据接收,接收时需要数据处理和绘图,怎样同步数据防止丢失?的访问速度、搜索引擎收录以及索引量、用户体验等。 要评估一个站的价值,最主要还是需要根据您自身的需求,如网站IP、PV、跳出率等!