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

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日

悬赏问题

  • ¥66 换电脑后应用程序报错
  • ¥50 array数据同步问题
  • ¥15 pic16F877a单片机的外部触发中断程序仿真失效
  • ¥15 Matlab插值拟合差分微分规划图论
  • ¥15 keil5 target not created
  • ¥15 C/C++数据与算法请教
  • ¥15 怎么找志同道合的伙伴
  • ¥20 如何让程序ab.eXe自已删除干净硬盘里的本文件自己的ab.eXe文件
  • ¥50 爬虫预算充足,跪巨佬
  • ¥15 滑块验证码拖动问题悬赏