问题描述
发出的数据格式是以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
解决方案十五:
学习中~