串口通讯中,为何读出数据读出时候,老是读取其中的一部分,不能一次完全读出,而是残留到下次才能读出。

问题描述

发出的数据格式是以ASCII为2的STX为开头,以2个空格结束的字符串。格式如下STX“ABCDEFGH”字符串空格空格但是接受数据的时候,总是收不到后面的空格。年月日时分秒毫秒16进制数字的显示ASCII格式的显示2008/06/0513:39:42125-41-42-43-44-45-46-47-48ABCDEFGH<--第一次没有收到2个空格(20H20H)2008/06/0513:39:46828-20-20-41-42-43-44-45-46-47-48ABCDEFGH<--第二次,收到第一次的2个空格(20H20H),但是这次的2个空格没有受到2008/06/0513:39:48937-20-20-41-42-43-44-45-46-47-48ABCDEFGH2008/06/0513:40:25437-20-20-41-42-43-44-45-46-47-48ABCDEFGH2008/06/0513:40:30156-20-20-41-42-43-44-45-46-47-48ABCDEFGH2008/06/0513:40:42203-41-42-43-44-45-46-47-48ABCDEFGH<--再次重新启动程序,第一次没有收到2个空格(20H20H)2008/06/0513:48:58734-20-20-41-02-43-44-45-46-47-48ACDEFGH<--第二次,收到第一次的2个空格(20H20H)我采用的是MSComm控件来实现串口通信的。我设定的RTheshold是3。我设定的STheshold是3。我对MSComm不熟悉,希望能得到高手的指点和帮助。

解决方案

解决方案二:
你读出来的长度和设置的缓冲区大小有关的.是否一次读出,这并不重要,一般情况下如果数据包比较长的话不会将缓冲区的大小(一次读出的大小),作为你是否读取完的标志.即使你的单元是固定的也不可能,因为COM的通讯某些程度上完全是不可预料的,不可能预先知道它这次会送几个给你.而是通过读取自定义协议的标志位来确认数据是否读完的.正如你所设计的'两个空格'处理时,你不能要求COM那边按照你规定的单元来送出数据的,COM其实是一个很低级的接口,他只知道做最简单的出和入动作,.而是必须将这些数据尽可能的取出来,缓存起来,由你自己的程序来重新按照'结束标志'组织,分段.
解决方案三:
学习一下
解决方案四:
我用AccessPort131测试的结果是,AccessPort完全可以做到正确的一口气读出。但是我自己的软件就做不到。希望高手能指点一下。
解决方案五:
引用3楼zhangpuwei的回复:

我用AccessPort131测试的结果是,AccessPort完全可以做到正确的一口气读出。但是我自己的软件就做不到。希望高手能指点一下。

未必,它也可能是组合几次的结果!
解决方案六:
有道理,一般来说,做这样的软件(串口通讯,Sokcet通讯)都要考虑头尾,粘包、半包等情况。不可能对方每一次都会正确的把数据一次性发送出来的。
解决方案七:
你的缓冲区设的过小。缓冲区设置多少合理,是要根据你的实际数据量来算的,不管你设置多少,你的代码中都要连续去读通讯端口发过来的数据,找到报文头和报文尾,拼合报文,这样才是合理的。
解决方案八:
不明白你RTheshold为什么会是3,RTheshold设置为3,则当接收缓冲内字节个数达到或超过该值后就会使MSComm控件产生OnComm事件,这样没接收到3个字节,才能触发一次OnComm事件。如果你知道应答信息的长度是固定的,那可以一次性读入,你在发送指令前,修改RTheshold的值,为应答信息的长度。如果不能确定应答信息的长度,需要解码应答信息才知道应答信息长度的,你可以设置RTheshold为1(单个单个接收,并记录到数组中,等取到记录长度的信息后,根据后续长度,重设置RTheshold)或是根据你定义的协议分段进行处理。
解决方案九:
“第二次,收到第一次的空格”,应该不是缓冲区设的太小,你查下你设置的InputLen是否正确。InputLen=0的时候是读取接收缓冲区中的全部信息
解决方案十:
引用8楼yanlongwuhui的回复:

“第二次,收到第一次的空格”,应该不是缓冲区设的太小,你查下你设置的InputLen是否正确。InputLen=0的时候是读取接收缓冲区中的全部信息

解决方案十一:
LZ:贴出你的代码。
解决方案十二:
按你的叙述,应设置RTheshold=10
解决方案十三:
用.net2.0的SerialPortclassusingSystem.IO.ports;SerialPortmyPort=newSerialPort();myPort.PortName="com1";//端口名myPort.BaudRate=115200;//速率myPort.DataBits=8;//数据位 myPort.StopBits=StopBits.One;//停止位myPort.Parity=Parity.None;//奇偶校验myPort.RtsEnable=true;// 打开RTS,这步很重要在指定的时间内接收串口数据并写入二进制文件。publicvoidgetRawData(SerialPortport,stringfileName,intseconds){FileStreamf1;try{port.open();//打开端口}catch(Exceptionerr){    Console.WriteLine(err.ToString()); //端口打开失败,返回return;  }try{f1=newFileStream(fileName,FileMode.Append);}catch(Exceptionerr){Console.WriteLine(err.ToString()); //文件打开失败,返回return;}  Console.WriteLine("Datawillbeloggedfrom"+port.PortName+"for"+seconds+"seconds...");BinaryWriterb1=newBinaryWriter(f1);DateTimenow=DateTime.Now; //获取当前系统时间while(((TimeSpan)(DateTime.Now-now)).TotalSeconds<seconds) 检测当前时间是否到了指定结束时间长度{b1.Write((byte)port.ReadByte());//写串口数据到文件}b1.Close();f1.Close();  port.Close();}发送数据到端口publicvoidsendData(SerialPortport){try{port.Open();}catch{return};byte[]s=newbyte[]{250,255,16,0,241}; port.Write(s,0,5); //参数1:字节数组;参数2:数组起始位;参数3:发送数据长度            //在这个例子里是从250开始,到241结束port.Close();}通常从serialport获得的包都有规则,或者说叫协议。比如255是一个包的开始,250是一个包的结束。获取一个完整的包你要自己来定义这部分代码。
解决方案十四:
PublicClassForm1InheritsSystem.Windows.Forms.FormDimstrDataAsString#Region"WindowsFormDesignergeneratedcode"PublicSubNew()MyBase.New()'ThiscallisrequiredbytheWindowsFormDesigner.InitializeComponent()'AddanyinitializationaftertheInitializeComponent()callEndSub'Formoverridesdisposetocleanupthecomponentlist.ProtectedOverloadsOverridesSubDispose(ByValdisposingAsBoolean)IfdisposingThenIfNot(componentsIsNothing)Thencomponents.Dispose()EndIfEndIfMyBase.Dispose(disposing)EndSub'RequiredbytheWindowsFormDesignerPrivatecomponentsAsSystem.ComponentModel.IContainer'NOTE:ThefollowingprocedureisrequiredbytheWindowsFormDesigner'ItcanbemodifiedusingtheWindowsFormDesigner.'Donotmodifyitusingthecodeeditor.FriendWithEventsAxMSComm1AsAxMSCommLib.AxMSCommFriendWithEventsTextBox1AsSystem.Windows.Forms.TextBoxFriendWithEventsButton1AsSystem.Windows.Forms.ButtonFriendWithEventsLabel1AsSystem.Windows.Forms.LabelFriendWithEventsButton2AsSystem.Windows.Forms.Button<System.Diagnostics.DebuggerStepThrough()>PrivateSubInitializeComponent()DimresourcesAsSystem.Resources.ResourceManager=NewSystem.Resources.ResourceManager(GetType(Form1))Me.AxMSComm1=NewAxMSCommLib.AxMSCommMe.TextBox1=NewSystem.Windows.Forms.TextBoxMe.Button1=NewSystem.Windows.Forms.ButtonMe.Label1=NewSystem.Windows.Forms.LabelMe.Button2=NewSystem.Windows.Forms.ButtonCType(Me.AxMSComm1,System.ComponentModel.ISupportInitialize).BeginInit()Me.SuspendLayout()''AxMSComm1'Me.AxMSComm1.Enabled=TrueMe.AxMSComm1.Location=NewSystem.Drawing.Point(376,128)Me.AxMSComm1.Name="AxMSComm1"Me.AxMSComm1.OcxState=CType(resources.GetObject("AxMSComm1.OcxState"),System.Windows.Forms.AxHost.State)Me.AxMSComm1.Size=NewSystem.Drawing.Size(38,38)Me.AxMSComm1.TabIndex=1''TextBox1'Me.TextBox1.Location=NewSystem.Drawing.Point(8,32)Me.TextBox1.Multiline=TrueMe.TextBox1.Name="TextBox1"Me.TextBox1.ScrollBars=System.Windows.Forms.ScrollBars.VerticalMe.TextBox1.Size=NewSystem.Drawing.Size(248,216)Me.TextBox1.TabIndex=3Me.TextBox1.Text="TextBox1"''Button1'Me.Button1.Location=NewSystem.Drawing.Point(304,48)Me.Button1.Name="Button1"Me.Button1.Size=NewSystem.Drawing.Size(112,32)Me.Button1.TabIndex=4Me.Button1.Text="Button1"''Label1'Me.Label1.Location=NewSystem.Drawing.Point(264,16)Me.Label1.Name="Label1"Me.Label1.Size=NewSystem.Drawing.Size(120,24)Me.Label1.TabIndex=5Me.Label1.Text="Label1"''Button2'Me.Button2.Location=NewSystem.Drawing.Point(304,88)Me.Button2.Name="Button2"Me.Button2.Size=NewSystem.Drawing.Size(112,32)Me.Button2.TabIndex=6Me.Button2.Text="Button2"''Form1'Me.AutoScaleBaseSize=NewSystem.Drawing.Size(6,14)Me.ClientSize=NewSystem.Drawing.Size(472,266)Me.Controls.Add(Me.Button2)Me.Controls.Add(Me.Label1)Me.Controls.Add(Me.Button1)Me.Controls.Add(Me.TextBox1)Me.Controls.Add(Me.AxMSComm1)Me.Name="Form1"Me.Text="Form1"CType(Me.AxMSComm1,System.ComponentModel.ISupportInitialize).EndInit()Me.ResumeLayout(False)EndSub#EndRegionPrivateSubForm1_Load(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesMyBase.LoadAxMSComm1.Settings="9600,N,8,1"AxMSComm1.RThreshold=1AxMSComm1.InputMode=MSCommLib.InputModeConstants.comInputModeBinaryAxMSComm1.PortOpen=TrueEndSubPrivateSubAxMSComm1_OnComm(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesAxMSComm1.OnCommDimbytInput()AsByteDimintInputLenAsIntegerSelectCaseAxMSComm1.CommEvent'CasecomEvReceiveCase2'此处添加处理接收的代码'AxMSComm1.InputMode=comInputModeBinary'二进制接收intInputLen=AxMSComm1.InBufferCountReDimbytInput(intInputLen)bytInput=AxMSComm1.InputDimiAsIntegerFori=0ToUBound(bytInput)IfLen(Hex(bytInput(i)))=1ThenstrData=strData&"0"&Hex(bytInput(i))ElsestrData=strData&Hex(bytInput(i))EndIfNextIfMid(strData,17,2)="20"AndMid(strData,19,2)="20"AndLen(strData)=20ThenTextBox1.Text=strDatastrData=""EndIfEndSelectEndSub'清除PrivateSubButton2_Click(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesButton2.ClickstrData=""TextBox1.Text=""EndSubEndClass

解决方案十五:
学习中~

时间: 2024-08-01 08:24:48

串口通讯中,为何读出数据读出时候,老是读取其中的一部分,不能一次完全读出,而是残留到下次才能读出。的相关文章

请问各位大神,在c#串口通讯中,怎么把接收到的数据保存在Excel表格中?

问题描述 请问各位大神,在c#串口通讯中,怎么把接收到的数据保存在Excel表格中? 本人最近做一个项目时需要把串口接收到的数据进行分析,数据量较大,比如5秒钟保存一次,连续工作一天,本人刚接触c#,串口通讯协议已写好,现在的问题是怎么把数据保存在Excel表格中以便分析?各位大神有没有用C#做过项目,求指教,最好有源代码!本人刚进论坛,没分,如果满意的话以后再补给你!!!!!!!!!急!!!!!! 解决方案 C#操作Excel(创建.打开.读写.保存)几种方法的总结 C#基于微软EXCEL类库

源代码-串口通讯中的一些问题

问题描述 串口通讯中的一些问题 用的龚建伟的源代码 串口控件做的 每次运行接受数据时出现这个问题 但是能发数据 应该不是程序的问题 用别的程序也是这个问题 请问怎么办? 解决方案 关于串口通讯查询与中断两种方式C#串口通讯 解决方案二: 此类问题,一般是程序的问题,可能是内存操作越界了. 既然已经明确是接收的问题,可以试试先将接收后的处理部分注释掉,看看还是不是会出现问题.如果是,则仔细看看接收部分:如果不是,则说明是接收后的数据处理有问题.

mfc-VS2010MFC串口通讯清除接收框的内容时怎么做到保留发送框内容?

问题描述 VS2010MFC串口通讯清除接收框的内容时怎么做到保留发送框内容? VS2010MFC,串口通讯中,点击清除接收框按钮时,怎么做到保留发送框内容? 解决方案 点击接收之后,把发送框内容写到文件里,保存 解决方案二: 你不调用SetDlgItemText(IDC_EDIT_SEND, TEXT(""));这之类的调用就可以吧~

请教串口通讯的一个问题

问题描述 我现在要做的是写一个串口程序,负责对U-boot进行操作,但是在U-boot源码中没有找到对命令解析这一块的代码,因此问题如下:在串口通讯中,发送端要向接受端发送一个命令,如:ls等等,这个命令是直接以字符串或二进制形式发送,还是以一个包的形式发送? 解决方案 解决方案二:"这个命令是直接以字符串或二进制形式发送,还是以一个包的形式发送?"那要看你和下位机通信的定义啊,解决方案三:这个命令是直接以字符串或二进制形式发送,还是以一个包的形式发送?----------------

串口通讯问题SeriaPort.ReadExisting();读出来乱码,请教各位大神处理方法!

问题描述 串口通讯问题SeriaPort.ReadExisting();读出来乱码,请教各位大神处理方法!求解决方法,在此谢谢各位了!这是串口调试工具读的:这是我用ReadExisting()读的一下是我Read出来后转换的 解决方案 解决方案二:既然发送的是ASCII码,你应该按ASCII码转换啊,为啥一会Unicode,一会UTF8的,那不是瞎转换吗解决方案三:还有STX是个特殊符号,是不能按ASCII码转换的比如CR对应的是0x0D,表示结束符这东西没有对应的字母,直接显示本来就是乱码你需

串口 枚举注册表-delphi中spccom串口通讯问题

问题描述 delphi中spccom串口通讯问题 /串口接收数据 //------------------------------------------------------------------------------ procedure TFormMain.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;BufferLength: Word); var CRC:Word; pbuf:pchar; idx:integer; begin

串口通讯 16进制转换-串口数据校验及ID提取怎么处理?

问题描述 串口数据校验及ID提取怎么处理? 现在有一份通讯规约 同步字/` 长度 / 命令字/ 数据区 / 校验 0xAA - - - - 1字节 1字节 1字节 0-253字节 1字节 长度计算范围:命令字-校验 校验计算范围:同步字-数据区 校验算法:字节累加和,丢弃溢出 数据区:如果没有数据,可以为空 对齐方式:大端对齐 串口波特率:9600 8数据位 无校验 1位停止位 协议指令和数据: 1.实时上传进出门数据 同步字 /长度 /命令字 / 数据区 /校验 0xAA - 0x02 进出门

用函数读出数据表内容放入二维数组

//用函数读出数据表内容放入二维数组 //动态sql语句 //以读出点击次数表为例. function list_hit($fields,$where,$order,$direction,$limit,$conn) { if ($fields=="") {$fields="hit_id,banner_id,hit_ip,hit_time";} if ($order=="") {$direction="";} $sql=&quo

VC 控制台程序串口通讯,串口收到数据如何发送消息给主线程?

问题描述 VC 控制台程序串口通讯,串口收到数据如何发送消息给主线程? 用CSerialPort类实现串口通讯,该类在收到数据后会调用::sendmessage函数,该函数的第一个参数是窗口句柄,但是控制台没有窗口句柄,该怎么发送消息?main函数里怎么响应消息? 解决方案 sendmessage wm_copydata 解决方案二: 控制台程序可以调用http://blog.csdn.net/coredoor/article/details/8582001