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);
            }
        }
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值