近期用到串口,遇到的一些坑,记录一下。先看代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO.Ports;
using System.Text;
using System.Threading;
using System.Xml;
using UnityEngine;
public class RecieveSport : MonoBehaviour
{
public SerialPort port = null;
private Thread tPort = null;
private bool canRecieveMsg = true;
public static RecieveSport _instance;
public string tempMsg = "";
public List<byte> listReceive = new List<byte>();
string str;
char[] strchar = new char[100];//接收的字符信息转换为字符数组信息
// Use this for initialization
void Start()
{
if (_instance == null)
{
_instance = this;
}
port = new SerialPort();
OpenPort(LoadXml());
}
string LoadXml()
{
//创建xml文档
XmlDocument xml = new XmlDocument();
xml.Load(System.IO.Directory.GetCurrentDirectory() + "\\IP.xml");
//得到objects节点下的所有子节点
XmlNodeList xmlNode = xml.SelectSingleNode("HeadSelect").ChildNodes;
//Debug.Log(((XmlElement)xmlNode[2]).GetAttributeNode("com").Value.ToString());
//遍历所有子节点
return ((XmlElement)xmlNode[2]).GetAttributeNode("com").Value.ToString();
}
// Update is called once per frame
void Update()
{
}
public bool OpenPort(string portName)
{
if (this.port != null && this.port.IsOpen == false)
{
try
{
this.port = new SerialPort(portName, 9600);
this.port.ReadTimeout = 500;
this.port.WriteTimeout = 500;
this.port.Open();
this.tPort = new Thread(new ThreadStart(PortReceive));
this.tPort.IsBackground = true;
this.tPort.Start();
return true;
}
catch (Exception err)
{
throw err;
}
}
else
{
throw new System.Exception("串口已经打开");
}
}
void OnApplicationQuit()
{
canRecieveMsg = false;
}
void PrintData()
{
for (int i = 0; i < listReceive.Count; i++)
{
strchar[i] = (char)(listReceive[i]);
str = new string(strchar);
}
Debug.Log(str);
listReceive.Clear();
}
/// <summary>
/// 按字节进行读取,每次读一个字节存放在List里,
/// </summary>
void DataReceive()
{
while (port != null && port.IsOpen)
{
Thread.Sleep(500);
try
{
byte addr = Convert.ToByte(port.ReadByte());
port.DiscardInBuffer();
listReceive.Add(addr);
PrintData();
}
catch
{
//listReceive.Clear();
}
}
}
/// <summary>
/// 可以读取多个字符,即字节数组;但是需要的平台的是.net 4.6
/// 将 Scripting Runing Vision 和Api Compatibility都改为.Net 4.6
/// </summary>
private void PortReceive()
{
try
{
while (canRecieveMsg)
{
Thread.Sleep(25);//这行是设定读取间隔,可以根据需要不使用
if (!port.IsOpen)
return;
int datalength = port.BytesToRead;
if (datalength == 0)
{
continue;
}
int i = 0;
StringBuilder sb = new StringBuilder();
while (i < datalength)
{
byte[] ds = new byte[1];
int len = port.Read(ds, 0, 1);
sb.Append(Encoding.UTF8.GetString(ds, 0, len));
i += len;
}
Debug.Log(sb.ToString());
//ProcessMsg(sb.ToString());
//这里sb就是串口获取的数据
}
}
catch { }
}
public void DataSend(string data)
{
port.Write(data);
}
private void OnGUI()
{
string test = "woshinibaba";
if(GUILayout.Button("SendMessage"))
{
DataSend(test);
}
}
}
补充:XML文档
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<HeadSelect>
<IP ip="192.168.xx.xx">
</IP>
<PORT port="8631">
</PORT>
<COM com="COM2">
</COM>
</HeadSelect>
坑在代码里也注释了,
1、接收多个字符的时候代码运行环境和api应该是.net4.6。
2、还有就是Read()方法不会一次读完
3、线程的Sleep()方法是为了匹配程序的执行速度和返回速度。
tisp:代码复制即可运行。如果又说错的地方,欢迎指正!