加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C#串口问题 – 太简单到失败,但是

发布时间:2020-12-16 01:43:23 所属栏目:百科 来源:网络整理
导读:好的,这应该很简单.我正在尝试从串行设备读取字符.这样,如果我发送一个空格字符,它会回显一串数字和EOL.而已. 我正在使用Unity 3.3(.Net 2.0支持),而’串行端口’是一个Prolific串口转USB适配器.顺便说一句:使用Hyperterminal,一切都很完美,所以我知道它不
好的,这应该很简单.我正在尝试从串行设备读取字符.这样,如果我发送一个空格字符,它会回显一串数字和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终端,它具有丰富的功能,可以帮助您调试.尝试使用此类软件手动编写一个字节,如果有效,则问题出在您的程序中.否则可能是驱动程序问题(但更可能不是).

[编辑]

调用SerialPort.ReadLine实际上应该阻止该线程,直到收到SerialPort.NewLine. ReadChar和ReadByte也将挂起,直到收到至少一个字节.你需要确保你实际上是从另一方接收角色,如果你的应用被卡住而无法发送空间,你就不会收到它们.

由于我从未使用过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;
 }

免责声明:这是我的头脑,未经测试,所以可能会有一些语法错误,我相信你会处理.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读