using System; using System.Collections; using System.Collections.Generic; using System.IO.Ports; using UnityEngine; using UnityEngine.UI; public class ComPortControl : MonoBehaviour { //COM串口 [Header("------COM串口------")] public Image imgComStatus; public Dropdown dropdownComList; public Button bntOpenCom; SerialPort sp = null; bool isAlive = true; // Use this for initialization void Start() { //打开串口 bntOpenCom.onClick.AddListener(new UnityEngine.Events.UnityAction(delegate () { ClosePort(); OpenPort(dropdownComList.options[dropdownComList.value].text); })); string[] portNames = System.IO.Ports.SerialPort.GetPortNames(); dropdownComList.AddOptions(new List(portNames)); if (portNames.Length > 0) { OpenPort(portNames[0]); } } IEnumerator WriteCOMData() { if (sp != null) { for (int i = 0; i < 15; i++) { Byte[] TxData = { 0xF3, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x3F }; sp.Write(TxData, 0, 8); Debug.Log(i + "次发串口指令成功"); yield return new WaitForSeconds(0.1f); } } else { Debug.Log("发串口指令失败"); } } #region 创建串口,并打开串口 public void OpenPort(string portName) { string openPortName = portName; //创建串口 int comNum = int.Parse(portName.Substring(3)); if (comNum > 9) { openPortName = "\\\\.\\" + portName; } try { sp = new SerialPort(openPortName, 9600, Parity.None, 8, StopBits.One); sp.ReadTimeout = 50; sp.Open(); if (sp != null && sp.IsOpen) { Debug.Log(portName + "串口已打开"); PlayerPrefs.SetString("IceBreakerComPort", portName); imgComStatus.sprite = Resources.Load("Texture/greencircle"); StartCoroutine(DataReceiveFunction()); } else { imgComStatus.sprite = Resources.Load("Texture/redcircle"); Debug.Log(portName + "串口未打开"); } } catch (Exception ex) { Debug.Log(ex.Message); } } #endregion IEnumerator DataReceiveFunction() { //应该读取的字节长度,可能多次读取才能成功 const int BYTE_ARRAY_SIZE = 36; byte[] buffer = new byte[BYTE_ARRAY_SIZE]; int len = 0; int previouseLen = 0; while (isAlive) { if (sp != null && sp.IsOpen) { try { //接收字节 byte[] recData = new byte[BYTE_ARRAY_SIZE]; len = sp.Read(recData, 0, recData.Length); if (previouseLen + len > BYTE_ARRAY_SIZE) { for (int i = 0; i < buffer.Length; i++) { buffer[i] = 0x00; } previouseLen = 0; } //和之前的字节拼接 for (int i = 0; i < len; i++) { buffer[previouseLen + i] = recData[i]; } //拼接后的长度 int newLen = previouseLen + len; string dataFromComPort = byteToHexStr(buffer, newLen); if (!string.IsNullOrEmpty(dataFromComPort) && newLen == BYTE_ARRAY_SIZE) { Debug.Log(DateTime.Now.ToShortDateString()+ "串口消息:" + dataFromComPort); } //从后往前搜 int endIndex = ByteArrayReverseIndex(buffer, 0x3f); int firstValueIndex = endIndex - 5; //如果不满足要求继续接收 if (endIndex == -1 || firstValueIndex < 0) { previouseLen = newLen; continue; } if (buffer[firstValueIndex] == 0x01) { Debug.Log("串口调试:识别到 0x01 运行"); } else if (buffer[firstValueIndex] == 0x02) { Debug.Log("串口调试:识别到 0x02 急停"); } else if (buffer[firstValueIndex] == 0x03) { Debug.Log("串口调试:识别到 0x03 复位"); } //复制3f后面的数据作为下次起点 if (endIndex > 0) { //截取3f后面的字符串 byte[] tmpBuffer = new byte[newLen - (endIndex + 1)]; for (int j = endIndex + 1; j < newLen; j++) { tmpBuffer[j - (endIndex + 1)] = buffer[j]; } //前移 for (int i = 0; i < buffer.Length; i++) { if (i < newLen - (endIndex + 1)) { buffer[i] = tmpBuffer[i]; } else { buffer[i] = 0x00; } } //下次起点 previouseLen = newLen - (endIndex + 1); } } catch (Exception ex) { //Debug.Log(ex.Message); } } yield return null; } } #region 程序退出时关闭串口 public void ClosePort() { if (sp == null) return; try { sp.Close(); isAlive = false; //dataReceiveThread.Abort(); } catch (Exception ex) { Debug.Log(ex.Message); } } #endregion /// 查找最后一个字符出现的索引 ////////////private int ByteArrayReverseIndex(byte[] buffer, byte b) { int index = -1; for (int i = 0; i < buffer.Length; i++) { if (buffer[i] == b) { index = i; } } return index; } void OnDestroy() { ClosePort(); } ////// 获取下拉列表某项的索上 //////下拉列表///某项文字///索引public static int GetDropdownIndex(Dropdown dd, string str) { int i = 0; int index = 0; foreach (var op in dd.options) { if (op.text.Equals(str)) { index = i; break; } i++; } return index; } private static string byteToHexStr(byte[] bytes, int length) { string returnStr = ""; if (bytes != null) { for (int i = 0; i < length; i++) { returnStr += bytes[i].ToString("X2"); } } return returnStr; } }