none
串口读不到数据,子线程会自动退出吗? RRS feed

  • 问题

  • 1、Winform窗体主线程下创建一个子线程,用来读串口。

    CommInterface ci = new CommInterface(NetGateInterfaceInfo[i]);
    ci.Start();

    public  void  Start()
            {
                if (threadComm == null)
                {
                    threadComm = new Thread(new ThreadStart(ReadData));
                    threadComm.Start();
                }
            }

    2、子线程循环读取串口方法(这里是控制逻辑代码片段)
    private void ReadData()
            {
                IDevice dev = null;
                int iRetry = 0;
                long tTicks = 0;
                int iRead;
                List<byte> bufSend = new List<byte>();
                while (true)
                {
                    //10
                    Thread.Sleep(10);

                    if (DeviceList.Count == 0)
                    {
                        continue;
                    }
                    if (commDev.State != EN_COMM_STATE.Connected)
                    {
                        if (commDev.State == EN_COMM_STATE.Closed)
                        {
                            commDev.Start();
                        }
                        continue;
                    }
                    switch (commFlag)
                    {
                        case CommFlag.Idle: //  空闲状态
                            dev = DeviceList[0];
                            commFlag = CommFlag.Encoding;   //编码
                            iRetry = 1; //重试次数
                            break;
                        case CommFlag.Encoding:
                            bufSend = dev.GenTxBuf();
                            if (bufSend.Count == 0)         //  避免出错
                            {
                                commFlag = CommFlag.Idle;
                                DeviceList.RemoveAt(0);
                                continue;
                            }
                            tTicks = DateTime.Now.Ticks;    //当前时间记录,,Ticks = 100毫微妙+1
                            commDev.Send(bufSend);
                            commFlag = CommFlag.Tx;
                            break;
                        case CommFlag.Tx:
                            commFlag = CommFlag.Rx;
                            break;

                         //读取串口返回报文 
                        case CommFlag.Rx:


                            int sum = commDev.BytesToRead();
                            while (sum > 0)
                            {
                                iRead = commDev.ReadByte();
                                if (iRead < 0)
                                {
                                    break;
                                }
                                switch (dev.AddByte((byte)iRead))
                                {
                                    case enDeviceResult.通讯结束:
                                        DeviceList.RemoveAt(0);
                                        if (DeviceList.Count == 0)
                                        {
                                            commDev.Close();
                                        }
                                        commFlag = CommFlag.Idle;
                                        tTicks = DateTime.Now.Ticks;
                                        break;
                                    case enDeviceResult.校验错误:
                                        commFlag = CommFlag.Encoding;
                                        tTicks = DateTime.Now.Ticks;
                                        break;
                                    case enDeviceResult.校验正确:
                                        commFlag = CommFlag.Encoding;
                                        iRetry = 1;
                                        tTicks = DateTime.Now.Ticks;
                                        break;
                                    default:
                                        break;
                                }
                            }



                            //if (((DateTime.Now.Ticks - tTicks) >= 20000000) && (commFlag == CommFlag.Rx))
                            //{
                            //    if (iRetry == 0)
                            //    {
                            //        commFlag = CommFlag.Idle;
                            //        if (DeviceList.Count == 0)
                            //        {
                            //            if (CommMessage != null)
                            //            {
                            //                CommMessage(this, "通讯设备已清空!");
                            //            }
                            //            break;
                            //        }
                            //        DeviceList.RemoveAt(0);
                            //        if (DeviceList.Count == 0)
                            //        {
                            //            commDev.Close();
                            //        }
                            //    }
                            //    else
                            //    {
                            //        iRetry--;
                            //        commFlag = CommFlag.Encoding;
                            //    }
                            //}
                            break;
                    }
                }
            }



    3、子线程中两个读取串口的方法
            SerialPort spComm = new SerialPort();
            public int BytesToRead()
            {
                if (spComm.IsOpen == false)
                {
                    Close();
                    return -1;
                }
                return spComm.BytesToRead;
            }

            public int ReadByte()
            {
                if (spComm.IsOpen == false)
                {
                    Close();
                    return -1;
                }
                return spComm.ReadByte();


    问题:要采集的电表是DL645_97协议的(浙江立新),波特率是1200,偶校验。
          (1)电表波特率低,可能返回的比较少,第一次只读取了3字节。  
               有时候是“254 254 104”,这个是正确的。
               有时候是“254,254,232”,这个应该是错误的,不明白232是什么意思?

          (2)读完前三个字节,再次循环去读取数据的时候,数据读不到了。   读不到数据“貌似这个读数据的线程”会退出,以为主窗体重新显示了,跳出了断点,Why???   也就是第四次执行“ReadByte()”的时候,主窗体就会重新跳出来(开始的时候已经出来了)。

          (3)用串口调试助手手动发送报文,返回报文是没有问题的,20个字节,很完整,而且响应很快,1秒内完成。
           为什么自己写的程序去读串口一次只能读三字节。就算放大了线程Sleep的时间(5分钟),会变成四字节,第一个字节还不正确,不是“FEH”。

           (4)第四次执行“ReadByte()”的时候,主窗体就会重新跳出来(开始的时候已经出来了)。这不是说明没有读到字节,读数据的这个线程自动终止了???

            (5)改怎么样才能读取到完整的返回报文?  应该修改那里呢?

       

         }


    Science and technology is my lover.

    2014年2月28日 4:59

答案

  • 你好:

    我不懂电工方面的知识,不太清楚你是怎么判断出数字是否是正确的。我只能给你一些建议:

    1. 如果这个电表的厂商已经提供了.net方面的编程接口了,那么建议你直接使用厂商提供的API或者代码,这个你需要去咨询一下厂商。

    2.  一般读取数据的做法都是使用DataReceived事件,建议也这样做

    3. 从你的代码中看不出来问题在哪里,ReadData方法有点冗长,里面嵌套了两个while循环。我觉得你可以先把多线程扔开,先在单一线程中做一个成功读取正确数据的sample出来,然后再考虑用多线程实现,而且即使用多线程,也不建议你直接使用Thread类,建议使用BackgroundWorker。这里有一些博客供你参考:

    C#中使用SerialPort类实现简单串口编程

    C#串口通信总结


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2014年3月3日 8:49
    版主
  • hello,

    读不到数据,理当不会退出线成,除非发生例外

    读取设备时不要太快,

    "发送资料"跟"接收资料"最好不要一起进行,大部分的设备都没有支援

    通讯协定要跟厂商要资料,你才能正确的处理


    有一些基本资料要麻烦您看一下,若已经知道可以跳过

    http://www.dotblogs.com.tw/yc421206/archive/2013/04/19/101914.aspx

    http://www.dotblogs.com.tw/billchung/category/5702.aspx


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/

    2014年3月10日 2:04

全部回复

  • 你好:

    我不懂电工方面的知识,不太清楚你是怎么判断出数字是否是正确的。我只能给你一些建议:

    1. 如果这个电表的厂商已经提供了.net方面的编程接口了,那么建议你直接使用厂商提供的API或者代码,这个你需要去咨询一下厂商。

    2.  一般读取数据的做法都是使用DataReceived事件,建议也这样做

    3. 从你的代码中看不出来问题在哪里,ReadData方法有点冗长,里面嵌套了两个while循环。我觉得你可以先把多线程扔开,先在单一线程中做一个成功读取正确数据的sample出来,然后再考虑用多线程实现,而且即使用多线程,也不建议你直接使用Thread类,建议使用BackgroundWorker。这里有一些博客供你参考:

    C#中使用SerialPort类实现简单串口编程

    C#串口通信总结


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2014年3月3日 8:49
    版主
  • 既然你用了while(true),你不break或者return,或者出错,或者结束主线程,就不会循环出来!

    2014年3月6日 5:53
  • hello,

    读不到数据,理当不会退出线成,除非发生例外

    读取设备时不要太快,

    "发送资料"跟"接收资料"最好不要一起进行,大部分的设备都没有支援

    通讯协定要跟厂商要资料,你才能正确的处理


    有一些基本资料要麻烦您看一下,若已经知道可以跳过

    http://www.dotblogs.com.tw/yc421206/archive/2013/04/19/101914.aspx

    http://www.dotblogs.com.tw/billchung/category/5702.aspx


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/

    2014年3月10日 2:04