iT邦幫忙

0

C# SerialDataReceivedEventHandler為何經常逾時?

  • 分享至 

  • xImage

通常用 new SerialPort都會用new SerialDataReceivedEventHandler(fun)弄個array來接收硬體回傳資料,但是為何硬體會在fun裡面的 catch (Exception exc)常常給我訊息"作業逾時"??

在SerialPort的ReadTimeout增加到3000 or 5000也是一樣為何呢?

void link()
{
_Port=new SerialPort("COM22", 9600, Parity.None, 8, StopBits.Two);
_Port.ReadTimeout = 5000;
_Port.DataReceived += new SerialDataReceivedEventHandler(fun);
_Port.Open();
_CharList[0] = new List<char>();
}

void fun()
{
try
    {
    for (int i = 0; i < 20; i++) _CharList[0].Add((char)Convert.ToByte(_Port.ReadByte()));
    }
catch (Exception exc){}//常常"作業逾時"
}
canrong iT邦新手 2 級 ‧ 2023-05-04 15:21:40 檢舉
雖然沒有用過SerialPort,但CODE看起來是在使用SerialPort.ReadByte方法時沒有考慮到IO基本的問題,資料流末端傳回-1以及當設備未送出資料時依舊使用ReadByte去接收DATA,它會一直聽資料流,直到設定的TIME OUT時間,就報錯了。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

1
ntustzeus
iT邦新手 2 級 ‧ 2023-05-05 09:25:29
最佳解答

接收SerialPort資料時,要先確認收的格式長什麼樣子,常見的接收方式:

  • 判斷Header/Tail,即什麼符號開始,什麼符號結尾
  • 自己計算Timout,比如說超過20ms就當做一筆資料已完整接收

下面這段程式每次固定要讀20個byte才會結束,若是設備回覆的速度和時機與你想的不同,有可能例如讀到第15個byte時沒資料了,那就只能timeout了

try
    {
    for (int i = 0; i < 20; i++) _CharList[0].Add((char)Convert.ToByte(_Port.ReadByte()));
    }
catch (Exception exc){}//常常"作業逾時"

可以考慮初始化時設定
_Port.ReceivedBytesThreshold = 1;

這樣fun()中每次只會收到1個byte,可以保証每次_Port.ReadByte()都有資料,收到後放到List裡,然後再自己用上面的方式判斷資料已結束

DataReceived一種可能的作法是(ReceivedBytesThreshold如果大於1時)
總之儘量不要一次用loop讀取固定數量的byte,因為你不能確定設備是怎麼丟出來的

        void mSerialRs232_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                while (_Port.BytesToRead > 0)
                {
                    this.mSerialRs232RecvByte = Convert.ToByte(_Port.ReadByte());
                }
            }
            catch (Exception)
            {

            }
        }
rabbit iT邦新手 4 級 ‧ 2023-05-08 08:21:24 檢舉

感謝

我要發表回答

立即登入回答