Unity串口通信 遇到的问题与解决
Posted Yafii
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity串口通信 遇到的问题与解决相关的知识,希望对你有一定的参考价值。
一、串口通信的流程有:
1)扫描串口
2)打开串口
3)发送数据 (byte[]数据格式发送)
4)接收数据(byte[]数据格式接收)
5)处理数据
6)关闭串口
二、代码
在Unity中创建一个脚本SXPortTest.cs,并挂到Camera上。代码如下:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO.Ports;
using System.Text;
using System.Threading;
using UnityEngine;
public class SXPortTest : MonoBehaviour
private SerialPort sp;
double x;
double y;
double z;
string[] TxData = new string[5];
// Start is called before the first frame update
void Start()
TxData[3] = "5003003d00039986";
string[] portArray = ScanPorts_TryFail();//使用试错函数,可以解决COM被占用问题
Debug.Log("串口号:" + portArray.ToString());
OpenSerialPort(portArray[0], 9600, Parity.None, 8, StopBits.One);
SendData();
// Update is called once per frame
void Update()
//试错方式扫描 第三种扫描端口的方法
public string[] ScanPorts_TryFail()
List<string> tempPost = new List<string>();
bool mark = false;
for (int i = 0; i < 10; i++)
try
SerialPort sp = new SerialPort("COM" + (i + 1).ToString());
sp.Open();
sp.Close();
tempPost.Add("COM" + (i + 1).ToString());
Debug.Log("串口号i:" + i);
mark = true;
catch (System.Exception)
continue;
if (mark)
string[] portList = tempPost.ToArray();
return portList;
else
return null;
#region 发送数据
/// <summary>
/// 发送数据
///
/// 进制转换方法:5003003d00039986
/// 1)两位分割 50 03 00 3d 00 03 99 86
/// 2)转二进制 0101000
/// 3)转十进制 80
///
/// 如果 fromBase 为 16,则可以在 value 参数指定的数字前面加上“0x”或“0X”。
///
/// </summary>
/// <param name="send">byte数据</param>
/// <param name="offSet">起始位</param>
/// <param name="count">byte长度</param>
public void SendData()
byte[] Data = new byte[2];
try
if (sp.IsOpen)
for (int i = 0; i < 8; i++)
Data[0] = Convert.ToByte(TxData[3].Substring(i * 2, 2), 16);
Debug.Log("发送的数据 字节型 Data[0]:" + Data[0]);
Debug.Log("发送的数据 字节型 Data:" + Data);
sp.Write(Data, 0, 1);//循环发送(如果输入字符为0A0BB,则只发送0A,0B)
else
sp.Open();
for (int i = 0; i < 8; i++)
Data[0] = Convert.ToByte(TxData[3].Substring(i * 2, 2), 16);
sp.Write(Data, 0, 1);//循环发送(如果输入字符为0A0BB,则只发送0A,0B)
catch (Exception ex)
Debug.Log(ex);
Debug.Log("请先打开串口");//弹出提示框
#endregion
#region 打开串口 读取数据 处理数据
/// <summary>
/// 打开串口
/// </summary>
/// <param name="_portName">端口号</param>
/// <param name="_baudRate">波特率</param>
/// <param name="_parity">校验位</param>
/// <param name="dataBits">数据位</param>
/// <param name="_stopbits">停止位</param>
public void OpenSerialPort(string _portName, int _baudRate, Parity _parity, int dataBits, StopBits _stopbits)
try
sp = new SerialPort(_portName, _baudRate, _parity, dataBits, _stopbits);//绑定端口
sp.Open();
Debug.Log("串口打开");
//使用委托
//sp.DataReceived += DataReceived;
//使用线程
Thread thread = new Thread(new ThreadStart(DataReceived));
thread.Start();
catch (Exception ex)
sp = new SerialPort();
Debug.Log(ex);
/// <summary>
/// 接收数据 线程
/// </summary>
public void DataReceived()
while (true)
if (sp.IsOpen)
int count = sp.BytesToRead;
if (count > 0)
byte[] readBuffer = new byte[count]; //数据 也是byte[]类型
try
sp.Read(readBuffer, 0, count);
DataProcessing_Old(readBuffer);//数据处理
//DataProcessing_New(readBuffer);//数据处理
// DataProcessing_Test(readBuffer);//数据处理
catch (Exception ex)
Debug.Log(ex.Message);
Thread.Sleep(10);
/// <summary>
/// 接收到的数据进行 数据处理 测试的
/// </summary>
/// <param name="data">字节数组</param>
public void DataProcessing_Test(byte[] data)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
sb.Append(data[i]);
Debug.Log("Test:"+sb.ToString());
/// <summary>
///数据处理 原本的
/// </summary>
/// <param name="data">字节数组</param>
public void DataProcessing_Old(byte[] data)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
sb.AppendFormat("0:x2" + "", data[i]);//0:X2将第一个参数转换成大写的十六进制文本,长度为2,不足前面补0
Debug.Log("OLD"+sb.ToString());
/// <summary>
/// 数据处理 师兄的
/// </summary>
/// <param name="data">字节数组</param>
public void DataProcessing_New(byte[] data)
if(data.Length == 11)
if(data[0] == 80 && data[1] == 3 && data[2] == 6)
double temp3 = data[3];
double temp4 = data[4];
double temp5 = data[5];
double temp6 = data[6];
double temp7 = data[7];
double temp8 = data[8];
int temp3i = Convert.ToInt32(temp3);
int temp4i = Convert.ToInt32(temp4);
int temp5i = Convert.ToInt32(temp5);
int temp6i = Convert.ToInt32(temp6);
int temp7i = Convert.ToInt32(temp7);
int temp8i = Convert.ToInt32(temp8);
x = Convert.ToDouble(((temp3i << 8) | temp4i)) / 32768 * 180;
y = Convert.ToDouble(((temp5i << 8) | temp6i)) / 32768 * 180;
z = Convert.ToDouble(((temp7i << 8) | temp8i)) / 32768 * 180;
if (x>180)
x = x - 360;
if (y>180)
y = y - 360;
if (z>180)
z = z - 360;
#endregion
打开串口通信工具:
打开虚拟串口,我用的是VSPD虚拟串口工具,添加虚拟串口1,2
打开串口的调试器,我用的是SSCOM
打开Unity,运行,Console会有串口打开的Log
在串口调试软件中的数据发送区写上发送的数据,然后点击发送,接收区会收到发送的数据,Unity的Console上会有接收的数据显示
至此。通信完成。
三、代码解释(对于我开发过程中产生的问题的解释)
TxData[3] = "5003003d00039986";
这是我的下位机的机号,暂时我并未测试下位机通信是否正常。
Data[0] = Convert.ToByte(TxData[3].Substring(i * 2, 2), 16);
public static byte ToByte(string value, int fromBase); 是一个8位16进制的数据
如果 fromBase 为 16,则可以在 value 参数指定的数字前面加上“0x”或“0X”。
这里的数据转换过程如下:
首先分割数据,两位一组50 03 00 3d 00 03 99 86
每一个组前要加上 0X : 0X50 0X03 0X00 0X3d 0X00 0X03 0X99 0X86
转二进制:01010000 00000011 00000000 00111101 00000000 00000011 10011001 10000110
转十进制:80 3 0 61 0 3 153 137
如果传输的时候,没有加上HEX发送的话,接收到的数据就是35 30 30 33 30 30 33 64 30 30 30 33 39 39 38 36 85 76(最后两位是校验位)
0x35的二进制是 0011 0101 对应的十进制是53 对应的ASCII是5 也就是第一位。
同理 0x30的二进制是 0011 0000 对应的十进制是48 对应的ASCII是0。
sb.AppendFormat("0:x2" + "", data[i]);//0:X2将第一个参数转换成大写的十六进制文本,长度为2,不足前面补0
将接收到的8位16进制转换为两位16进制的数据。
至此结束。感谢大家观看,欢迎指正。
1.把JSON加到Unity Http 服务器通信上时,遇到的重大Bug 完美解决! 就是路径的问题!
1.
2.
3.
4.
5.
6.
7.
8.居然好了!
9.
10.
11.
12.
以上是关于Unity串口通信 遇到的问题与解决的主要内容,如果未能解决你的问题,请参考以下文章
Unity3D软硬件Unity3D与串口通信 SerialPort类完全教程
Unity学习关于串口通信插件SerialPortUtilityPro的简单使用个人案例