HelloAaric 2021-10-10 14:47 采纳率: 100%
浏览 59
已结题

c# 串口自动适配波特率 通讯失败

想做一个串口的握手功能,遇到下面的问题:
当baudRateList 只有一个9600时,通讯可以成功;
但当baudRateList 中有多个波特率时,就通讯不上了。
求指教,在线等。

    using System.IO.Ports;

    public class MySerialPort : SerialPort 
    {
       // public readonly int[] baudRateList = { 9600 };
       private readonly int[] baudRateList = { 115200, 57600, 38400, 19200, 9600 };
       public string receivedString;
       public ManualResetEvent receivedFlag = new ManualResetEvent(false);

        public bool HandShake()
        {
            bool ret = false;
            int handShakeLimits = 4;
            int retryCount;
            foreach (int baudRate in baudRateList)
            {
                this.BaudRate = baudRate;
                this.Close();
                this.Open();
                this.DiscardInBuffer();
                this.DiscardOutBuffer();

                this.Write(GetInstructions.serialNum + "\n");
                // 等待100毫秒,检查 receivedFlag是否设置为true。如果没有,继续循环
                retryCount = 0;
                while (!receivedFlag.WaitOne(100))
                {
                    if (retryCount++ >= handShakeLimits)
                    {
                        receivedFlag.Reset();
                        break;
                    }
                }

                if (retryCount < handShakeLimits)
                {
                    ret = true;
                    break;
                }
            }
            return ret; 
        }

        public void GppSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            receivedFlag.Set();
            if (sender is SerialPort serialPort)
            {
                // 将缓冲区回车符前所有内容读取出来
                ReceivedString = serialPort.ReadLine();
                serialPort.DiscardInBuffer();
                serialPort.DiscardOutBuffer();
            }
        }
    }
  • 写回答

2条回答 默认 最新

  • wanghui0380 2021-10-10 16:07
    关注

    我随手写一个看看,没设备。所以只是演示如何做这种传统的异步回调的同步模拟方法

    public class MySerialPort : SerialPort
            {
    
                public MySerialPort(string portName) : base(portName)
                {
    
                }
                private readonly int[] baudRateList = { 115200, 57600, 38400, 19200, 9600 };
                public bool CheckHandShake()
                {
                    bool ret = false;
                    int handShakeLimits = 4;
                    int retryCount;
                    foreach (int baudRate in baudRateList)
                    {
                        if (this.IsOpen)
                        {
                            this.Close();
                        }
    
                        this.BaudRate = baudRate;
                        this.Open();
                        this.DiscardInBuffer();
                        this.DiscardOutBuffer();
                        this.Write("xxx" + "\n");
                        if (CheckProtcol())
                        {
                            break;
                        }
    
                    }
                    return ret;
                }
    
                private bool CheckProtcol()
                {
                    //你这里都用传统代码,所以我们也不用啥task异步一类的玩意,免得废半天劲,你来句我net2的
                    
                    ManualResetEvent receivedFlag = new ManualResetEvent(false);
                    bool Received = false;
                    SerialDataReceivedEventHandler mye = null;
    
                    //这里直接定义局部委托,使用函数式手段将逻辑封在一个方法,避免传统的vb,net1.1时代那种事件割裂逻辑,造成你原来那种看着的费劲的代码
                    mye = ((send, e) =>
                     {
                         //这里其实还有一些协议内容检查,我就不想写了,但是你那里不能已是否收到数据为基准,比如modbus你发给他不认识的,他会回发一个error封包,所以还是以双方约定的协议内容为基准,而不是以收到为基准
                         this.DataReceived -= mye;
                         Received = true;
                         receivedFlag.Set();
                     });
                    this.DataReceived += mye;
                    receivedFlag.WaitOne(400); //这里直接使用400ms超时,不需要用哪个看着郁闷的计数器,逻辑上是有符合需要的数据set就通过了,没有符合的数据最多等待400ms
                    if (!Received)
                    {
                        this.DataReceived -= mye; //如果没有复合的数据,把临时给的委托注销掉,避免后续进入
                    }
                    return Received;
    
    
                }
    
            }
    
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 4月7日
  • 已采纳回答 3月30日
  • 创建了问题 10月10日

悬赏问题

  • ¥50 三种调度算法报错 采用的你的方案
  • ¥15 关于#python#的问题,请各位专家解答!
  • ¥15 对于这个问题的解释说明
  • ¥200 询问:python实现大地主题正反算的程序设计,有偿
  • ¥15 smptlib使用465端口发送邮件失败
  • ¥200 总是报错,能帮助用python实现程序实现高斯正反算吗?有偿
  • ¥15 对于squad数据集的基于bert模型的微调
  • ¥15 为什么我运行这个网络会出现以下报错?CRNN神经网络
  • ¥20 steam下载游戏占用内存
  • ¥15 CST保存项目时失败