C#串口问题 – 太简单到失败,但是
好的,这应该很简单.我正在尝试从串行设备读取字符.这样,如果我发送一个空格字符,它会回显一串数字和EOL.而已.
我正在使用Unity 3.3(.Net 2.0支持),而’串行端口’是一个Prolific串口转USB适配器.顺便说一句:使用Hyperterminal,一切都很完美,所以我知道它不是驱动程序,也不是硬件. 我可以打开端口了.好像我可以用port.Write(“”)发送我的空间;但是,如果我甚至尝试调用ReadChar,ReadByte或ReadLine(如轮询),它会冻结,直到我拔掉USB,我的控制台输出什么都没显示(异常被捕获). 所以我设置了一个DataReceviedHandler,但它永远不会被调用. 我读过一些人们用Arduinos等做过这类事情的帖子(这不是Arduino而是嘿),只使用ReadLine.他们的代码对我不起作用(迄今为止这些作者都没有答案). 那么,有什么提示吗?我需要使用不同的线程吗?如果您知道任何Unity(单声道)编码,那么这些行的任何提示都会受到高度赞赏. 此代码是http://plikker.com/?p=163和http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx#Y537的mashup using UnityEngine; using System.Collections; using System.IO.Ports; using System; public class SerialTest : MonoBehaviour { SerialPort stream; void Start () { try { stream = new SerialPort("COM3",9600); stream.Parity = Parity.None; stream.StopBits = StopBits.One; stream.DataBits = 8; stream.Handshake = Handshake.None; stream.DataReceived += new SerialDataReceivedEventHandler(DataReceviedHandler); stream.Open(); Debug.Log("opened ok"); // it DOES open ok! } catch (Exception e){ Debug.Log("Error opening port "+e.ToString()); // I never see this message } } void Update () { // called about 60 times/second try { // Read serialinput from COM3 // if this next line is here,it will hang,I don't even see the startup message Debug.Log(stream.ReadLine()); // Note: I've also tried ReadByte and ReadChar and the same problem,it hangs } catch (Exception e){ Debug.Log("Error reading input "+e.ToString()); } } private static void DataReceviedHandler( object sender,SerialDataReceivedEventArgs e) { SerialPort sp = (SerialPort)sender; // It never gets here! string indata = sp.ReadExisting(); Debug.Log("Data Received:"); Debug.Log(indata); } void OnGUI() // simple GUI { // Create a button that,when pressed,sends the 'ping' if (GUI.Button (new Rect(10,10,100,20),"Send")) stream.Write(" "); } } 解决方法
使用正确的设置确保打开正确的端口.以下是如何配置它的示例:
serial = new SerialPort(); serial.ReadBufferSize = 8192; serial.WriteBufferSize = 128; serial.PortName = "COM1"; serial.BaudRate = 115200; serial.Parity = Parity.None; serial.StopBits = StopBits.One; // attach handlers // (appears to be broken in some Mono versions?) serial.DataReceived += SerialPort_DataReceived; serial.Disposed += SerialPort_Disposed; serial.Open(); 我推荐开源RealTerm终端,它具有丰富的功能,可以帮助您调试.尝试使用此类软件手动编写一个字节,如果有效,则问题出在您的程序中.否则可能是驱动程序问题(但更可能不是). [编辑] 调用 由于我从未使用过Unity,因此我不确定如何调用Update,但我认为它会定期在前台线程上触发(否则你的应用程序不会冻结). 您链接的示例(Arduino and Unity example)显示Arduino正在连续发送数据,这就是他们的Update方法不断接收数据的原因(不需要向设备发送空格字符).如果他们拔下设备,他们的应用程序也会挂起. 好吧,也许不是,因为在.NET 1.1中,ReadTimeout的默认值不是无限的,就像在.NET 2.0中一样. 那么,你能做的是: 一个.将ReadTimeout属性设置为合理的值. .NET 2.0中的默认值是InfiniteTimeout,它不适合您的需要.缺点:您的更新方法在每次调用时仍会挂起一段时间,但不会无限期. 湾有人说事件没有在MONO SerialPort中实现,所以我想只使用DataReceived不是一个选项. C.将您的发送逻辑也移动到Update方法,这样您根本不读取数据,直到读取它为止: private volatile bool _shouldCommunicate = false; void Update () { if (_shouldCommunicate) // this is a flag you set in "OnGui" { try { stream.Write(" "); Debug.Log(stream.ReadLine()); } catch (Exception e){ Debug.Log("Error reading input "+e.ToString()); } } } void OnGUI() // simple GUI { if (GUI.Button (new Rect(10,"Send")) _shouldCommunicate = true; } 请注意,如果您的设备没有发送数据,它也会在stream.ReadLine()处阻塞,因此请确保将ReadTimeout设置为合理的值.你也想在某个时候停止发送,但我把它留给你. d.像现在一样在OnGui中发送空间,但在读取之前总是检查缓冲区中是否有数据: void Update () { // called about 60 times/second try { // call our new method Debug.Log(ReadLineNonBlocking()); } catch (Exception e){ Debug.Log("Error reading input "+e.ToString()); } } private StringBuilder sb = new StringBuilder(); string ReadLineNonBlocking() { int len = stream.BytesToRead; if (len == 0) return ""; // read the buffer byte[] buffer = new byte[len]; stream.Read(buffer,len); sb.Append(ASCIIEncoding.ASCII.GetString(buffer)); // got EOL? if (sb.Length < 2 || sb[sb.Length-2] != 'r' || sb[sb.Length-1] != 'n') return ""; // if we are here,we got both EOL chars string entireLine = sb.ToString(); sb.Length = 0; return entireLine; } 免责声明:这是我的头脑,未经测试,所以可能会有一些语法错误,我相信你会处理. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |