欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

untiy 串口通信

发布时间:2024/1/8 编程问答 41 豆豆
生活随笔 收集整理的这篇文章主要介绍了 untiy 串口通信 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

untiy的串口通信是垃圾中的垃圾,只能使用线程监听串口消息,而不能使用c#提供的更方便安全的注册委托的方法,根本原因是mono没有完全实现c#的using System.IO.Ports下的内容,导致unity中只能用被阉割过的串口

首先,引入命名空间

using System.IO.Ports;

这是一个最简单的开启串口的演示

SerialPort s = new SerialPort{//串口的名字 波特率 数据位 停止位 验证位 必须和硬件中设置相同,否则无法正常通信PortName = "COM1",//串口的名字可以通过设备管理器的 “端口”查看BaudRate = 115200,//波特率DataBits = 8,//数据位StopBits = StopBits.One,//停止位Parity = Parity.None,//验证位DtrEnable = true,RtsEnable = true,ReadTimeout = 1000};s.Open();

对于一个串口,我们可以通过一个线程监听串口发过来的消息

//接上放代码,打开一个串口s.Open();//监听当前串口的消息Thread recT = new Thread(SerialPort_DataReceived);recT.IsBackground = true;recT.Start();//接收线程的方法public void SerialPort_DataReceived(){while (true){if (s.IsOpen){var length = s.BytesToRead;byte[] bytestest = new byte[length];s.Read(bytestest, 0, length); //得把数据读出来,不然缓存区域会一直有数据//处理数据}}}

关闭串口

s.Close();

对于纯c# 代码,可以使用委托更优雅的接收串口消息,因为线程接收的方式可以能出现数据粘包
但这个委托在Untiy中无法使用

SerialPort s;private void Awake(){s.DataReceived += ReceiveData; }private void ReceiveData(object sender, SerialDataReceivedEventArgs e){//读取串口缓冲区的字节数据byte[] result = new byte[s.BytesToRead];}

以下是批量查找串口,批量接收消息,批量关闭

批量查找

/// <summary>/// 获取本地可用串口列表/// </summary>/// <param name="ignoreCom1">是否忽略串口1 PC机默认有COM1</param>/// <returns>返回串口名称列表</returns>public List<SerialPort> GetPorts(bool ignoreCom1 = true){Ports = new List<SerialPort>();string[] proteNames = System.IO.Ports.SerialPort.GetPortNames();foreach (string protName in proteNames){if (ignoreCom1 && protName == "COM1") continue;// if ( protName != "COM4"&&protName != "COM5") continue;var s = new SerialPort{PortName = protName,BaudRate = 115200,DataBits = 8,StopBits = StopBits.One,Parity = Parity.None,DtrEnable = true,RtsEnable = true,ReadTimeout = 1000};Ports.Add(s);}return Ports;}

批量接收

/// <summary>/// 打开串口(包括新启动和再次启动)/// </summary>/// <returns></returns>public bool Start(){try{GetPorts();如果串口开启了就关闭//Stop();foreach (SerialPort p in Ports){try{//开启当前的串口p.Open();//监听当前串口的消息Thread recT = new Thread(SerialPort_DataReceived);recT.IsBackground = true;recT.Start(p);threadsDic.Add(p, recT);}catch (Exception ex){Console.WriteLine($"打开串口{p.PortName}时发生错误{ex.Message}");}}return true;}catch (Exception e){Console.WriteLine(DateTime.Now.ToShortDateString() + e.Message + e.StackTrace);return false;}}/// <summary>/// 接收信号触发事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>public void SerialPort_DataReceived(object obj){while (true){SerialPort tempPort = obj as SerialPort;//更新最后获取信号的时间//UpdateSignalTime?.Invoke(DateTime.Now, 0);//进行数据分包if (tempPort.IsOpen){var length = tempPort.BytesToRead;//对异常数据进行分包if (length > 32) //这里是32位是因为我规定的硬件发送一条数据为32个字节{byte[] bytestest = new byte[length];tempPort.Read(bytestest, 0, length); //得把数据读出来,不然缓存区域会一直有数据ShuntPacker(tempPort, bytestest);continue;}//少包丢弃else if (length < 32){continue;}byte[] bytes = new byte[length];tempPort.Read(bytes, 0, length); //得把数据读出来,不然缓存区域会一直有数据//处理一个包的数据OnePackerHandle(tempPort, bytes);}else{Console.WriteLine("串口非正常关闭");}}}

批量关闭

/// <summary>/// 关闭所有串口 清空缓存数据 清空监听线程/// </summary>/// <returns></returns>public void StopAllSerialPort(){foreach (SerialPort p in Ports){StopOneSerialPort(p);}lastStr = null;ReceivedData = null;lock (lockAck){if (AckCache != null && AckCache.Count > 0){AckCache.Clear();}}}/// <summary>/// 关闭一个串口/// </summary>/// <param name="serialPort"></param>public void StopOneSerialPort(SerialPort serialPort){try{if (serialPort != null && serialPort.IsOpen){//关闭串口serialPort.Close();//关闭接收线程threadsDic[serialPort].Abort();threadsDic.Remove(serialPort);}}catch (Exception e){// LogInfo.WriteErrorLog(e.Message + "|||" + e.StackTrace);}}

总结

以上是生活随笔为你收集整理的untiy 串口通信的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。