weixin_44485203 2022-05-23 16:17 采纳率: 0%
浏览 100
已结题

使用C#编写的上位机,与下位机板卡总是连接失败

使用C#编写的上位机软件,尝试使用9600bps进行连接,但是在选择确认可以连通的COM口后,却大部分连接失败,只要极少数情况可以连接成功,而不是完全无法连通,具体代码如下,请帮忙看看,该部分代码是否存在问题,能否帮忙提点意见,谢谢

namespace IonosphericScintillationMonitor.UI
{
public partial class ConnectNovatelReceiverStatusForm : Form
{
private string portName;
private int baudRate;

    public ConnectNovatelReceiverStatusForm()
    {
        InitializeComponent();
        this.FormBorderStyle = FormBorderStyle.FixedDialog;
        //this.ControlBox = false;//不显示最小、最大和关闭按钮   
        this.MinimizeBox = false;
        this.MaximizeBox = false;         
        this.StartPosition = FormStartPosition.CenterScreen;
        InitializeSerialPort();            
    }

    private void InitializeSerialPort()
    {
        //注册表中与串口设置相关的名称/值对的名称
        const string PORTNAME_VALUE = "PortName";
        const string BAUDRATE_VALUE = "BaudRate";          

        string rootName = "HKEY_CURRENT_USER";
        string keyName = rootName + "\\" + "Software" + "\\"
             + "IonosphericScintillationMonitor" + "\\" + "ComSet";

        //读取注册表中串口的默认值
        try
        {
            this.portName = (string)Registry.GetValue(keyName, PORTNAME_VALUE, null);
            this.baudRate = Convert.ToInt32(Registry.GetValue(keyName, BAUDRATE_VALUE, null));                                
        }
        catch (SecurityException e)
        {
            BaseSupportTools.PrintExceptionMessage(e);
        }
        catch (IOException e)
        {
            BaseSupportTools.PrintExceptionMessage(e);
        }
        catch (ArgumentException e)
        {
            BaseSupportTools.PrintExceptionMessage(e);
        }            
    }

    public void CreateConnect()
    {           
        SerialPort serialPort = new SerialPort(portName, 9600, Parity.None, 8, StopBits.One);

        int failConnectCount = 0;
        try
        {
            serialPort.Open();
            bool isConnect = false;                
            this.prgConnectStatus.Value = 20;
            this.prgConnectStatus.Refresh();//ProgressBar控件立即刷新显示
            this.lblConnectStatus.Text = "以9600bps正在尝试连接中。。。";
            this.lblConnectStatus.Refresh();//lable控件立即刷新显示
            //以9600bps的默认速率进行首次连接
            while (!isConnect)
            {
                isConnect = TryConnect(serialPort);
                //间隔1s后重连或进行下一步
                System.Threading.Thread.Sleep(1000);
                failConnectCount++;
                if (failConnectCount > 20)
                {
                    if (MessageBox.Show("Novatel接收机连接失败", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error) == DialogResult.OK)
                    {
                        //彻底退出程序
                        System.Environment.Exit(0);
                    }
                }
            }               
                      
            this.prgConnectStatus.Value = 40;
            this.prgConnectStatus.Refresh();//ProgressBar控件立即刷新显示
            this.lblConnectStatus.Text = "重置通信波特率为" + baudRate + "bps。。。";
            this.lblConnectStatus.Refresh();//lable控件立即刷新显示

            //重置通信速率为 baudRate bps
            TrySerialConfig(serialPort, baudRate);
            serialPort.Close();
            
            this.prgConnectStatus.Value = 60;
            this.prgConnectStatus.Refresh();//ProgressBar控件立即刷新显示
            this.lblConnectStatus.Text = "重置通信波特率为" + baudRate + "bps成功";
            this.lblConnectStatus.Refresh();//lable控件立即刷新显示
            System.Threading.Thread.Sleep(1500);
            
            this.prgConnectStatus.Value = 80;
            this.prgConnectStatus.Refresh();//ProgressBar控件立即刷新显示
            this.lblConnectStatus.Text = "以" + baudRate + "bps正在尝试重新连接中。。。";
            this.lblConnectStatus.Refresh();//lable控件立即刷新显示
            System.Threading.Thread.Sleep(1000);

            //以 baudRate bps的速率进行再次连接
            failConnectCount = 0;
            serialPort.BaudRate = baudRate;
            serialPort.Open();
            while (!isConnect)
            {
                isConnect = TryConnect(serialPort);
                //间隔1s后重连或进行下一步
                System.Threading.Thread.Sleep(1000);
                if (failConnectCount > 5)
                {
                    if (MessageBox.Show("Novatel接收机连接失败", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error) == DialogResult.OK)
                    {
                        //彻底退出程序
                        System.Environment.Exit(0);
                    }
                }
            }

            //开启GPS、北斗系统和关闭GLONASS系统
            serialPort.WriteLine("assignall  gps  auto");
            System.Threading.Thread.Sleep(1000);
            serialPort.WriteLine("assignall  beidou  auto");
            System.Threading.Thread.Sleep(1000);
            serialPort.WriteLine("assignall  glonass  idle");
            System.Threading.Thread.Sleep(1000);
            //发送指令
            serialPort.WriteLine("log bestposb ontime 1");
            System.Threading.Thread.Sleep(1000);
            serialPort.WriteLine("log bestvelb ontime 1");
            System.Threading.Thread.Sleep(1000);
            serialPort.WriteLine("log ionutcb ontime 1");
            System.Threading.Thread.Sleep(1000);
            serialPort.WriteLine("log psrdopb ontime 1");
            System.Threading.Thread.Sleep(1000);
            serialPort.WriteLine("log satvis2b ontime 60");
            System.Threading.Thread.Sleep(1000);
            serialPort.WriteLine("log rangecmpb ontime 0.2");
            System.Threading.Thread.Sleep(1000);

            this.prgConnectStatus.Value = 100;
            this.prgConnectStatus.Refresh();//ProgressBar控件立即刷新显示
            this.lblConnectStatus.Text = "Novatel接收机连接成功!";
            this.lblConnectStatus.Refresh();//lable控件立即刷新显示
            serialPort.Close();//关闭串口
            System.Threading.Thread.Sleep(1000);
            this.Close();//关闭串口

        }
        catch (System.IO.IOException e)
        {
            BaseSupportTools.PrintExceptionMessage(e);
            MessageBox.Show("当前串口已被占用", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //彻底退出程序
            System.Environment.Exit(0);
        }
    }

    /// <summary>
    /// 尝试以目前的串口设置连接Novatel接收机
    /// </summary>
    /// <param name="serialPort">串口实例</param>
    /// <returns></returns>
    private static bool TryConnect(SerialPort serialPort)
    {
        serialPort.Write("log versionb once");//发送指令
        serialPort.Write("\r");
        serialPort.Write("\n");
        System.Threading.Thread.Sleep(1000);//延迟1s
        int bytesCount = serialPort.BytesToRead;
        int tempData = 0;
        bool isFindHeaderSync1 = false;
        bool isFindHeaderSync2 = false;
        bool isFindHeaderSync3 = false;
        bool isConnect = false;
        int headerLength = 0;
        int availableByteCount = 0;//有效字节计数   
        byte[] temp2Bytes = new byte[2];
        for (int ix = 0; ix < bytesCount; ix++)
        {
            tempData = serialPort.ReadByte();
            //寻找帧头
            if (!isFindHeaderSync1)
            {
                if (tempData == 0xAA)
                {
                    isFindHeaderSync1 = true;
                }
            }
            else if ((isFindHeaderSync1) && (!isFindHeaderSync2))
            {
                if (tempData == 0x44)
                {
                    isFindHeaderSync2 = true;
                }
            }
            else if ((isFindHeaderSync1) && (isFindHeaderSync2) && (!isFindHeaderSync3))
            {
                if (tempData == 0x12)
                {
                    isFindHeaderSync3 = true;
                    availableByteCount = 3;//帧头3个字节检测成功了
                    continue;
                }
            }

            //判断帧头是否寻找成功
            if ((isFindHeaderSync1) && (isFindHeaderSync2) && (isFindHeaderSync3))
            {
                if (availableByteCount == 3)
                {
                    headerLength = tempData;
                    availableByteCount++;
                }
                else if (availableByteCount == 4)
                {
                    temp2Bytes[0] = (byte)tempData;
                    availableByteCount++;
                }
                else if (availableByteCount == 5)
                {
                    temp2Bytes[1] = (byte)tempData;
                    int messageId = BitConverter.ToInt16(temp2Bytes, 0);
                    if (messageId == 37)//即VERSION
                    {
                        isConnect = true;//连接成功                           
                    }
                    availableByteCount++;
                }

            }
        }
        return isConnect;
    }

    /// <summary>
    /// 尝试重置Novatel接收机的波特率
    /// </summary>
    /// <param name="serialPort">串口实例</param>
    /// <param name="baudRate">重置后的波特率</param>
    /// <returns></returns>
    private static bool TrySerialConfig(SerialPort serialPort, int baudRate)
    {
        bool isSerialConfig = false;
        string command = "serialconfig com1 " + baudRate + " n 8 1 n on";
        serialPort.Write(command);//发送指令           
        serialPort.Write("\r");
        serialPort.Write("\n");
        System.Threading.Thread.Sleep(1000);//延迟1s
        bool isSendSuccess1 = false;
        bool isSendSuccess2 = false;
        bool isSendSuccess3 = false;
        int bytesCount = serialPort.BytesToRead;
        int tempData = 0;
        for (int ix = 0; ix < bytesCount; ix++)
        {
            tempData = serialPort.ReadByte();
            if (!isSendSuccess1)
            {
                //寻找'<'
                if (tempData == 0x3C)
                {
                    isSendSuccess1 = true;
                }
            }
            else if ((isSendSuccess1) && (!isSendSuccess2))
            {
                //寻找'O'
                if (tempData == 0x4F)
                {
                    isSendSuccess2 = true;
                }
            }
            else if ((isSendSuccess1) && (isSendSuccess2) && (!isSendSuccess3))
            {
                //寻找'K'
                if (tempData == 0x4B)
                {
                    isSendSuccess3 = true;
                }
            }

            //判断“<OK”是否寻找成功
            if ((isSendSuccess1) && (isSendSuccess2) && (isSendSuccess3))
            {
                isSerialConfig = true;
            }
        }
        return isSerialConfig;
    }

}

}

  • 写回答

2条回答 默认 最新

  • 品铭工作室 2022-05-26 11:15
    关注

    扫了一下代码,估计是串口对象SerialPort 在上一次连接后,没有正常关闭(测试:如果第一次连接成功,再次连接不成功能,尝试退出进程,再看是否连接成功来判断 是否属于该问题, 并不代表退出后,二运行后能连接上就是这个问题), 把SerialPort serialPort 1.对象做成全局对象,2.每执行一个动作,打印对象状态, 通过这种方式打到出问题的地方(建议你先把try去掉) , 第二种可能 上次一连接没有正常关闭(串口连接被独占了),这个时候再连接变会失败, csdn查一下SerialPort 说明,看看对象丢失后,是否为自动close(我觉得不会), 最好写个测试:不停进行open->close 操作,open-> wirt byte->close ,看看硬件是否有问题

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 6月2日
  • 赞助了问题酬金20元 5月25日
  • 创建了问题 5月23日

悬赏问题

  • ¥15 非科班怎么跑代码?如何导数据和调参
  • ¥15 福州市的全人群死因监测点死亡原因报表
  • ¥15 打开powerpont询问是否安装officeplus不小心点了不安装以后再也不提示是否安装了
  • ¥15 Altair EDEM中生成一个颗粒,并且各个方向没有初始速度
  • ¥15 系统2008r2 装机配置推荐一下
  • ¥500 服务器搭建cisco AnyConnect vpn
  • ¥15 用大厂网站防红自己网站
  • ¥15 悬赏Python-playwright部署在centos7上
  • ¥15 psoc creator软件有没有人能远程安装啊
  • ¥15 快速扫描算法求解Eikonal方程咨询