一、簡介
系統(tǒng)采用之前的系統(tǒng):
相關(guān)的鏈接為
https://blog.csdn.net/u011854789/article/details/51895014
https://blog.csdn.net/weixinhum/article/details/53684151
http://www.cnblogs.com/Traveller-Lee/p/6940221.html(主要參考)
(一)WPF工程做上位機(jī)與彩屏(或單片機(jī))進(jìn)行串口通信、解決彩屏(或單片機(jī))只能發(fā)送信息不能接受信息問題。
我是在上位機(jī)的接收彩屏的信息狀態(tài)下,收到異常信息:
“System.TimeoutException”類型的未經(jīng)處理的異常在 System.dll 中發(fā)生 ? 其他信息: 操作已超時。
二、超時原因及其解決辦法
? ? ? ? 超時原因,是因為使用了SerialPort.ReadTimeout 方法和 SerialPortObj.ReadLine()方法。其中,SerialPort.ReadTimeout方法是設(shè)定讀取的時間間隔。此外, SerialPortObj.ReadLine()表示讀取接收緩存區(qū)的字節(jié),如未在SerialPort.ReadTimeout設(shè)定的時間間隔內(nèi)收到信息,則拋出異常。
? ? ? ?那么,SerialPort為什么要自帶這些方法呢?是多余了嗎?顯然不是,它是有著其他用途的。我們往后再討論SerialPort.ReadTimeout 方法和 SerialPort.ReadLine()方法的應(yīng)用場景。
? ? ? ? ?現(xiàn)在,我們回過頭來解決正常的就接收問題,我只要能夠任何時間段、任何連接狀態(tài)下,只要能夠正常接收東西即可。我采用的方法是
? ? 總之,我們在這里采用超時方法ReadLine()。附上代碼,該代碼已經(jīng)能夠與大彩屏正常收發(fā)。
MainWindow.xaml:
<Window x:Class="PortChat.MainWindow"
? ? ? ? Icon="PortChat.ico"
? ? ? ? xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
? ? ? ? xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
? ? ? ? Title="PortChat" Height="500" Width="800">
? ? <Window.Resources>
? ? ? ? <XmlDataProvider x:Key="ComPorts" Source="CommsData.xml" XPath="/Comms/Ports"/>
? ? ? ? <XmlDataProvider x:Key="ComSpeed" Source="CommsData.xml" XPath="/Comms/Baud"/>
? ? ? ? <XmlDataProvider x:Key="ComParity" Source="CommsData.xml" XPath="/Comms/Parity"/>
? ? ? ? <XmlDataProvider x:Key="ComStopBits" Source="CommsData.xml" XPath="/Comms/StopBits"/>
? ? ? ? <XmlDataProvider x:Key="ComHandshake" Source="CommsData.xml" XPath="/Comms/Handshake"/>
? ? </Window.Resources>
?
? ? <Grid ?Height="423.935" VerticalAlignment="Top" Margin="0,0, 0, 0">
? ? ? ? <Grid.ColumnDefinitions>
? ? ? ? ? ? <ColumnDefinition Width="606*"/>
? ? ? ? ? ? <ColumnDefinition/>
? ? ? ? ? ? <ColumnDefinition Width="185*"/>
? ? ? ? </Grid.ColumnDefinitions>
? ? ? ?
? ? ? ? <Label Content="串口名稱:" HorizontalAlignment="Left" Margin="30,35,0,0" VerticalAlignment="Top" Height="26" Width="70"/>
? ? ? ? <ComboBox Grid.Column="0" x:Name="CbbPortName" ItemsSource="{Binding Source={StaticResource ComPorts}}" ?HorizontalAlignment="Left" Margin="100,35,0,0" VerticalAlignment="Top" Width="120" SelectedIndex="0" Height="22"/>
?
? ? ? ? <Label Grid.Column="0" Content="波特率:" HorizontalAlignment="Left" Margin="290,35,0,0" VerticalAlignment="Top" Height="26" Width="58"/>
? ? ? ? <ComboBox Grid.Column="0" x:Name="CbbBaudRate" ItemsSource="{Binding Source={StaticResource ComSpeed}}" HorizontalAlignment="Left" Margin="360,35,0,0" VerticalAlignment="Top" Width="120" SelectedIndex="0" Height="22"/>
?
? ? ? ? <Label Grid.Column="0" Content="奇偶校驗:" HorizontalAlignment="Left" Margin="30,75,0,0" VerticalAlignment="Top" Height="26" Width="70"/>
? ? ? ? <ComboBox Grid.Column="0" x:Name="CbbPortParity" HorizontalAlignment="Left" ItemsSource="{Binding Source={StaticResource ComParity}}" Margin="100,75,0,0" VerticalAlignment="Top" Width="120" SelectedIndex="0" Height="22"/>
?
? ? ? ? <Label Grid.Column="0" Content="數(shù)據(jù)位:" HorizontalAlignment="Left" Margin="290,75,0,0" VerticalAlignment="Top" Height="26" Width="58"/>
? ? ? ? <TextBox Grid.Column="0" x:Name="TbDataBits" Text="8" HorizontalAlignment="Left" Height="23" Margin="360,75,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
?
? ? ? ? <Label Grid.Column="0" Content="停止位:" HorizontalAlignment="Left" Margin="30,115,0,0" VerticalAlignment="Top" Height="26" Width="58"/>
? ? ? ? <ComboBox Grid.Column="0" x:Name="CbbStopBits" ItemsSource="{Binding Source={StaticResource ComStopBits}}" HorizontalAlignment="Left" Margin="100,115,0,0" VerticalAlignment="Top" Width="120" SelectedIndex="0" Height="22"/>
?
? ? ? ? <Label Grid.Column="0" Content="握手方式:" HorizontalAlignment="Left" Margin="285,115,0,0" VerticalAlignment="Top" Height="26" Width="70"/>
? ? ? ? <ComboBox Grid.Column="0" x:Name="CbbHandshake" ItemsSource="{Binding Source={StaticResource ComHandshake}}" HorizontalAlignment="Left" Margin="360,115,0,0" VerticalAlignment="Top" Width="120" SelectedIndex="0" Height="22"/>
?
? ? ? ? <Label Grid.Column="0" Content="接收區(qū):" HorizontalAlignment="Left" Margin="30,175,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.235,0.269" Height="26" Width="58"/>
? ? ? ? <TextBox Grid.Column="0" x:Name="TbReceive" HorizontalAlignment="Left" Height="100" Margin="100,175,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="490"/>
? ? ? ? <Button x:Name="BtnConnect" Content="連接" HorizontalAlignment="Left" Margin="33,175,0,0" VerticalAlignment="Top" Width="75" Click="Connect_Click" Grid.Column="2" Height="22"/>
?
? ? ? ? <Label Grid.Column="0" Content="發(fā)送區(qū):" HorizontalAlignment="Left" Margin="30,305,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.235,0.269" Height="26" Width="58"/>
? ? ? ? <TextBox Grid.Column="0" x:Name="TbSend" HorizontalAlignment="Left" Height="100" Margin="100,305,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="490"/>
?
? ? ? ? <Button Content="發(fā)送" HorizontalAlignment="Left" Margin="33,305,0,0" VerticalAlignment="Top" Width="75" Click="SendData_Click" Grid.Column="2" Height="22"/>
?
? ? </Grid>
</Window>
MainWindow.xaml.cs:
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
using System.IO.Ports;
using System.Collections.Generic;
?
namespace PortChat
{
? ? /// <summary>
? ? /// MainWindow.xaml 的交互邏輯
? ? /// </summary>
? ? public partial class MainWindow
? ? {
?
? ? ? ? List<PatientsAndProtocolsList> protocolsList = new List<PatientsAndProtocolsList>();
?
? ? ? ? #region 包頭包尾指令
? ? ? ? //列表
? ? ? ? byte[] bytHomeUserListConstantData ? ? ? ? ? ? ?= new byte[] { 0xEE, 0xB1, 0x5B, 0x00, 0x01, 0x00, 0x1B, 0xFF, 0xFC, 0xFF, 0xFF };//11個數(shù)
? ? ? ? byte[] bytStudyOptionalProtocolListConstantData = new byte[] { 0xEE, 0xB1, 0x5B, 0x00, 0x02, 0x00, 0x05, 0xFF, 0xFC, 0xFF, 0xFF };//11個數(shù)
? ? ? ? byte[] bytStudySelectedBodyListConstantData ? ? = new byte[] { 0xEE, 0xB1, 0x5B, 0x00, 0x02, 0x00, 0x22, 0xFF, 0xFC, 0xFF, 0xFF };//11個數(shù)
? ? ? ? //高壓
? ? ? ? byte[] bytStudyExposeKvConstantData ? ? ? ? ? ? = new byte[] { 0xEE, 0xB1, 0x10, 0x00, 0x02, 0x00, 0x2F, 0xFF, 0xFC, 0xFF, 0xFF };//11個數(shù)
? ? ? ? //mA
? ? ? ? byte[] bytStudyExposemAConstantData ? ? ? ? ? ? = new byte[] { 0xEE, 0xB1, 0x10, 0x00, 0x02, 0x00, 0x31, 0xFF, 0xFC, 0xFF, 0xFF };//11個數(shù)
? ? ? ? //ms
? ? ? ? byte[] bytStudyExposemsConstantData ? ? ? ? ? ? = new byte[] { 0xEE, 0xB1, 0x10, 0x00, 0x02, 0x00, 0x35, 0xFF, 0xFC, 0xFF, 0xFF };//11個數(shù)
? ? ? ? //mAs
? ? ? ? byte[] bytStudExposemAsConstantData ? ? ? ? ? ? = new byte[] { 0xEE, 0xB1, 0x10, 0x00, 0x02, 0x00, 0x38, 0xFF, 0xFC, 0xFF, 0xFF };//11個數(shù)
? ? ? ? #endregion
?
? ? ? ? //總包
? ? ? ? byte[] bytListDataSend = new byte[0];
? ? ? ? byte[] bytStudyOptionalProtocolListData = new byte[0];
? ? ? ? byte[] bytStudyOptionalBodyListData = new byte[0];
? ? ? ? byte[] bytStudyExposeKvData = new byte[0];
? ? ? ? byte[] bytStudyExposemAData = new byte[0];
? ? ? ? byte[] bytStudyExposemsData = new byte[0];
? ? ? ? byte[] bytStudExposemAsData = new byte[0];
?
? ? ? ? //獲取可選體位列表數(shù)據(jù)數(shù)據(jù)并發(fā)送
? ? ? ? string strProtocolName1 = "協(xié)議1";
? ? ? ? string strProtocolNum1 = "名稱1";
? ? ? ? string strProtocolName2 = "協(xié)議2";
? ? ? ? string strProtocolNum2 = "名稱2";
? ? ? ? string strProtocolName3 = "--協(xié)faf議2";
? ? ? ? string strProtocolNum3 = "-77名稱faf2";
?
? ? ? ? //串口
? ? ? ? private static readonly SerialPort SerialPortObj = new SerialPort();
? ? ? ? string _recievedData = null;
?
? ? ? ? public MainWindow()
? ? ? ? {
? ? ? ? ? ? InitializeComponent();
? ? ? ? }
?
? ? ? ? /// <summary>
? ? ? ? /// 串口連接
? ? ? ? /// </summary>
? ? ? ? /// <param name="sender"></param>
? ? ? ? /// <param name="e"></param>
? ? ? ? private void Connect_Click(object sender, RoutedEventArgs e)
? ? ? ? {
? ? ? ? ? ? if ((BtnConnect.Content as string) == "連接")
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //端口 默認(rèn)COM3
? ? ? ? ? ? ? ? SerialPortObj.PortName = CbbPortName.Text;
? ? ? ? ? ? ? ? //波特率 默認(rèn)9600
? ? ? ? ? ? ? ? SerialPortObj.BaudRate = int.Parse(CbbBaudRate.Text);
? ? ? ? ? ? ? ? //奇偶校驗 默認(rèn)None
? ? ? ? ? ? ? ? SerialPortObj.Parity = (Parity)Enum.Parse(typeof(Parity), CbbPortParity.Text, true);
? ? ? ? ? ? ? ? //數(shù)據(jù)位 默認(rèn)8
? ? ? ? ? ? ? ? SerialPortObj.DataBits = int.Parse(TbDataBits.Text);
? ? ? ? ? ? ? ? //停止位 默認(rèn)1
? ? ? ? ? ? ? ? SerialPortObj.StopBits = (StopBits)Enum.Parse(typeof(StopBits), CbbStopBits.Text, true);
? ? ? ? ? ? ? ? //握手方式 默認(rèn)None
? ? ? ? ? ? ? ? SerialPortObj.Handshake = (Handshake)Enum.Parse(typeof(Handshake), CbbHandshake.Text, true);
?
? ? ? ? ? ? ? ? //SerialPortObj.ReceivedBytesThreshold = 1;
? ? ? ? ? ? ? ? //SerialPortObj.ReadTimeout = 500;//超過ReadTimeout未接收到,則拋出異常。
? ? ? ? ? ? ? ? //SerialPortObj.WriteTimeout = 500;
?
? ? ? ? ? ? ? ? if (!SerialPortObj.IsOpen)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? SerialPortObj.Open();
? ? ? ? ? ? ? ? }
?
? ? ? ? ? ? ? ? BtnConnect.Content = "斷開";
? ? ? ? ? ? ? ? BtnConnect.Background = Brushes.Green;
?
? ? ? ? ? ? ? ? //委托、調(diào)用數(shù)據(jù)接收方法
? ? ? ? ? ? ? ? SerialPortObj.DataReceived += Recieve;
? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? {
? ? ? ? ? ? ? ? try // just in case serial port is not open could also be acheved using if(serial.IsOpen)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? SerialPortObj.Close();
? ? ? ? ? ? ? ? ? ? BtnConnect.Content = "連接";
? ? ? ? ? ? ? ? ? ? BtnConnect.Background = Brushes.White;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? catch (Exception)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? // ignored
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? private delegate void UpdateUiTextDelegate(string text);
?
? ? ? ? private void Recieve(object sender, SerialDataReceivedEventArgs e)
? ? ? ? {
? ? ? ? ? ? // ReadLine方法要判定 讀超時。因此,不用改函數(shù),也不用設(shè)置ReadTimeout了。
? ? ? ? ? ? //_recievedData = SerialPortObj.ReadLine();
? ? ? ? ? ? //開辟接收緩沖區(qū)
? ? ? ? ? ? byte[] ReDatas = new byte[SerialPortObj.BytesToRead];
? ? ? ? ? ? SerialPortObj.Read(ReDatas, 0, ReDatas.Length); //從串口讀取數(shù)據(jù)
? ? ? ? ? ? _recievedData = System.Text.Encoding.Default.GetString(ReDatas);
? ? ? ? ? ? //實現(xiàn)數(shù)據(jù)的解碼與顯示
? ? ? ? ? ? //AddData(ReDatas);
?
? ? ? ? ? ? //調(diào)用委托,將字符信息顯示在TextBox控件上。
? ? ? ? ? ? Dispatcher.Invoke(DispatcherPriority.Send, new UpdateUiTextDelegate(WriteDate), _recievedData);
? ? ? ? }
?
? ? ? ? private void WriteDate(string text)
? ? ? ? {
? ? ? ? ? ? TbReceive.Text += _recievedData;
? ? ? ? }
?
? ? ? ? /// <summary>
? ? ? ? /// 發(fā)送指令
? ? ? ? /// </summary>
? ? ? ? /// <param name="sender"></param>
? ? ? ? /// <param name="e"></param>
? ? ? ? private void SendData_Click(object sender, RoutedEventArgs e)
? ? ? ? {
? ? ? ? ? ? //添加列表信息
? ? ? ? ? ? protocolsList.Add(new PatientsAndProtocolsList(strProtocolName1, strProtocolNum1));
? ? ? ? ? ? protocolsList.Add(new PatientsAndProtocolsList(strProtocolName2, strProtocolNum2));
? ? ? ? ? ? protocolsList.Add(new PatientsAndProtocolsList(strProtocolName3, strProtocolNum3));
?
? ? ? ? ? ? //病人檢查記錄發(fā)送
? ? ? ? ? ? bytListDataSend = GetStringToHex(protocolsList, bytHomeUserListConstantData);
? ? ? ? ? ? SerialCmdSend(bytListDataSend);
?
? ? ? ? ? ? TbSend.Text = System.Text.Encoding.Default.GetString(bytListDataSend);?
? ? ? ? ? ? //可選體位發(fā)送
? ? ? ? ? ? bytListDataSend = GetStringToHex(protocolsList, bytStudyOptionalProtocolListConstantData);
? ? ? ? ? ? SerialCmdSend(bytListDataSend);
?
? ? ? ? ? ? //已選體位發(fā)送
? ? ? ? ? ? bytListDataSend = GetStringToHex(protocolsList, bytStudySelectedBodyListConstantData);
? ? ? ? ? ? SerialCmdSend(bytListDataSend);
?
?
? ? ? ? }
?
? ? ? ? /// <summary>
? ? ? ? /// 字符轉(zhuǎn)16進(jìn)制,16進(jìn)制保存到字節(jié)
? ? ? ? /// </summary>
? ? ? ? /// <param name="str"></param>
? ? ? ? /// <param name="bytHeadTailPackageVar"></param>
? ? ? ? /// <returns></returns>
? ? ? ? private byte[] GetStringToHex( List<PatientsAndProtocolsList> protocolsList, byte[] bytHeadTailPackageVar)
? ? ? ? {
? ? ? ? ? ? //總長度
? ? ? ? ? ? //int iTotalPackageLong = 0;
? ? ? ? ? ? 包頭、包尾長度
? ? ? ? ? ? int iHeadPackageLong = 7;
? ? ? ? ? ? int iTailPackageLong = 4;
? ? ? ? ? ? 列表行:高八位
? ? ? ? ? ? //int iRowHighSize = 0x00;
? ? ? ? ? ? 列表行:低八位
? ? ? ? ? ? //int iRowLowSize = 0x02;
? ? ? ? ? ? 列表行:高八位
? ? ? ? ? ? //int iColumnHighSize = 0;//每一行的每列字節(jié)數(shù)都不固定
? ? ? ? ? ? 列表行:低八位
? ? ? ? ? ? //int iColumnLowSize = 0;//每一行的每列字節(jié)數(shù)都不固定
?
? ? ? ? ? ? byte[] bytTotalPackageVar = new byte[500];
? ? ? ? ? ? int protocolCount = 0; ??
?
? ? ? ? ? ? //拷貝包頭:7個固定的字節(jié)
? ? ? ? ? ? Array.ConstrainedCopy(bytHeadTailPackageVar, 0, bytTotalPackageVar, 0, iHeadPackageLong);
?
? ? ? ? ? ? #region ?確定總行數(shù),及其對應(yīng)的字節(jié) ?
? ? ? ? ? ? Int16 iRowsNum = 0;//總行數(shù)
? ? ? ? ? ? iRowsNum = (Int16)protocolsList.Count;
? ? ? ? ? ? byte[] byt_iRowsNum = new byte[2];
? ? ? ? ? ? byt_iRowsNum = BitConverter.GetBytes(iRowsNum);//一般是兩個字節(jié)
? ? ? ? ? ? Array.ConstrainedCopy(byt_iRowsNum, 1, bytTotalPackageVar, iHeadPackageLong, 1);//byt_iRowsNum的高八位,放到緩存區(qū)的低字節(jié)區(qū)。才符合大彩屏的指令接收要求。
? ? ? ? ? ? Array.ConstrainedCopy(byt_iRowsNum, 0, bytTotalPackageVar, (iHeadPackageLong + 1), 1);//byt_iRowsNum的低八位,放到緩存區(qū)的高字節(jié)區(qū)。
? ? ? ? ? ? #endregion
?
?
? ? ? ? ? ? #region 每行的字符內(nèi)容,及其對應(yīng)的字節(jié)數(shù)目、字節(jié)內(nèi)容
? ? ? ? ? ? int iTotalPackageStartIndex = iHeadPackageLong + byt_iRowsNum.Length;
? ? ? ? ? ? while (protocolCount < protocolsList.Count)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? string strProtocolNumVar = null;
? ? ? ? ? ? ? ? string strProtocolNameVar = null;
? ? ? ? ? ? ? ? string strEachRowContent = null;
? ? ? ? ? ? ? ? Int16 iEachRowByteNum = 0;//每行的字節(jié)數(shù)目
? ? ? ? ? ? ? ? byte[] byt_strEachRowContent = new byte[0];
? ? ? ? ? ? ? ? byte[] byt_iEachRowByteNum = new byte[0];
?
? ? ? ? ? ? ? ? #region ?確定每行的字符內(nèi)容,及其對應(yīng)的字節(jié)數(shù)目、字節(jié)內(nèi)容
? ? ? ? ? ? ? ? //字符
? ? ? ? ? ? ? ? strProtocolNumVar = protocolsList[protocolCount].StrPatientNumOrProtocolNum;
? ? ? ? ? ? ? ? strProtocolNameVar = protocolsList[protocolCount].StrPatientNameOrProtocolName;
? ? ? ? ? ? ? ? strEachRowContent = strProtocolNumVar + ";" + strProtocolNameVar + ";";//必須加上分號。
?
? ? ? ? ? ? ? ? //內(nèi)容
? ? ? ? ? ? ? ? byt_strEachRowContent = System.Text.Encoding.Default.GetBytes(strEachRowContent); //每行的字節(jié)內(nèi)容?
? ? ? ? ? ? ? ? iEachRowByteNum = (Int16)byt_strEachRowContent.Length;
? ? ? ? ? ? ? ? byt_iEachRowByteNum = BitConverter.GetBytes(iEachRowByteNum);//每行的字節(jié)數(shù)目,將數(shù)目轉(zhuǎn)成字節(jié)?
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? //拷貝
? ? ? ? ? ? ? ? Array.ConstrainedCopy(byt_iEachRowByteNum, 1, bytTotalPackageVar, iTotalPackageStartIndex, 1);//byt_iEachRowByteNum的高八位,放到緩存區(qū)的低字節(jié)區(qū)。才符合大彩屏的指令接收要求。
? ? ? ? ? ? ? ? Array.ConstrainedCopy(byt_iEachRowByteNum, 0, bytTotalPackageVar, (iTotalPackageStartIndex + 1), 1);//byt_iEachRowByteNum的低八位,放到緩存區(qū)的高字節(jié)區(qū)。
?
? ? ? ? ? ? ? ? Array.ConstrainedCopy(byt_strEachRowContent, 0, bytTotalPackageVar, (iTotalPackageStartIndex + byt_iEachRowByteNum.Length), byt_strEachRowContent.Length);
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? //下標(biāo)索引
? ? ? ? ? ? ? ? iTotalPackageStartIndex = iTotalPackageStartIndex + byt_iEachRowByteNum.Length + byt_strEachRowContent.Length;
? ? ? ? ? ? ? ? #endregion
?
? ? ? ? ? ? ? ? protocolCount++;
? ? ? ? ? ? }
? ? ? ? ? ? #endregion?
?
? ? ? ? ? ? //拷貝包尾:4個固定的字節(jié)
? ? ? ? ? ? Array.ConstrainedCopy(bytHeadTailPackageVar, iHeadPackageLong, bytTotalPackageVar, iTotalPackageStartIndex, iTailPackageLong);
? ? ? ? ? ? return bytTotalPackageVar;
? ? ? ? }
?
? ? ? ? /// <summary>
? ? ? ? /// 串口發(fā)送函數(shù)
? ? ? ? /// </summary>
? ? ? ? /// <param name="data"></param>
? ? ? ? private void SerialCmdSend(byte[] data)
? ? ? ? {
? ? ? ? ? ? //若是串口沒打開,跳出函數(shù) SerialCmdSend
? ? ? ? ? ? if (!SerialPortObj.IsOpen) return;
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //將待發(fā)送的內(nèi)容寫到緩沖區(qū)
? ? ? ? ? ? ? ? SerialPortObj.Write(data, 0, data.Length);
? ? ? ? ? ? }
? ? ? ? ? ? catch (Exception ex)
? ? ? ? ? ? {
?
? ? ? ? ? ? ? ? TbSend.Text = "Failed to SEND" + data + "\n" + ex + "\n";
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
PatientsAndProtocolsList.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
?
namespace PortChat
{
? ? //該集合可以裝用戶集合或列表集合
? ? class PatientsAndProtocolsList
? ? {
? ? ? ? public string strPatientNumOrProtocolNum;
? ? ? ? public string strPatientNameOrProtocolName;
? ? ? ? public string strPatientSex;
? ? ? ? public string strPatientAge;
? ? ? ? public string strPatientBody;
? ? ? ? public string strStudyDateTime;
? ? ? ? public string StrPatientNumOrProtocolNum
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return strPatientNumOrProtocolNum;
? ? ? ? ? ? }
? ? ? ? ? ? set
? ? ? ? ? ? {
? ? ? ? ? ? ? ? strPatientNumOrProtocolNum = value;
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? public string StrPatientNameOrProtocolName
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return strPatientNameOrProtocolName;
? ? ? ? ? ? }
? ? ? ? ? ? set
? ? ? ? ? ? {
? ? ? ? ? ? ? ? strPatientNameOrProtocolName = value;
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? public string StrPatientSex
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return strPatientSex;
? ? ? ? ? ? }
? ? ? ? ? ? set
? ? ? ? ? ? {
? ? ? ? ? ? ? ? strPatientSex = value;
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? public string StrPatientAge
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return strPatientAge;
? ? ? ? ? ? }
? ? ? ? ? ? set
? ? ? ? ? ? {
? ? ? ? ? ? ? ? strPatientAge = value;
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? public string StrPatientBody
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return strPatientBody;
? ? ? ? ? ? }
? ? ? ? ? ? set
? ? ? ? ? ? {
? ? ? ? ? ? ? ? strPatientBody = value;
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? public string StrStudyDateTime
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return strStudyDateTime;
? ? ? ? ? ? }
? ? ? ? ? ? set
? ? ? ? ? ? {
? ? ? ? ? ? ? ? strStudyDateTime = value;
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? public PatientsAndProtocolsList() { }
?
? ? ? ? /// <summary>
? ? ? ? /// 保存協(xié)議信息
? ? ? ? /// </summary>
? ? ? ? /// <param name="strProtocolNum"></param>
? ? ? ? /// <param name="strProtocolName"></param>
? ? ? ? public PatientsAndProtocolsList(string strProtocolNum, string strProtocolName)
? ? ? ? {
? ? ? ? ? ? this.strPatientNumOrProtocolNum = strProtocolNum;
? ? ? ? ? ? this.strPatientNameOrProtocolName = strProtocolName;
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 保存病人信息:5個參數(shù)
? ? ? ? /// </summary>
? ? ? ? /// <param name="strPatientNum"></param>
? ? ? ? /// <param name="strPatientName"></param>
? ? ? ? /// <param name="strPatientSex"></param>
? ? ? ? /// <param name="strPatientAge"></param>
? ? ? ? /// <param name="strPatientBody"></param>
? ? ? ? public PatientsAndProtocolsList(string strPatientNum, string strPatientName, string strPatientSex, string strPatientAge, string strPatientBody)
? ? ? ? {
? ? ? ? ? ? this.strPatientNumOrProtocolNum = strPatientNum;
? ? ? ? ? ? this.strPatientNameOrProtocolName = strPatientName;
? ? ? ? ? ? this.strPatientSex = strPatientSex;
? ? ? ? ? ? this.strPatientAge = strPatientAge;
? ? ? ? ? ? this.strPatientBody = strPatientBody;
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 保存病人信息:6個參數(shù)
? ? ? ? /// </summary>
? ? ? ? /// <param name="strPatientNum"></param>
? ? ? ? /// <param name="strPatientName"></param>
? ? ? ? /// <param name="strPatientSex"></param>
? ? ? ? /// <param name="strPatientAge"></param>
? ? ? ? /// <param name="strPatientBody"></param>
? ? ? ? /// <param name="studyDateTime"></param>
? ? ? ? public PatientsAndProtocolsList(string strPatientNum, string strPatientName, string strPatientSex, string strPatientAge, string strPatientBody, string studyDateTime)
? ? ? ? {
? ? ? ? ? ? this.strPatientNumOrProtocolNum = strPatientNum;
? ? ? ? ? ? this.strPatientNameOrProtocolName = strPatientName;
? ? ? ? ? ? this.strPatientSex = strPatientSex;
? ? ? ? ? ? this.strPatientAge = strPatientAge;
? ? ? ? ? ? this.strPatientBody = strPatientBody;
? ? ? ? ? ? this.strPatientBody = studyDateTime;
? ? ? ? }
? ? }
}
下面討論ReadTimeout方法的具體應(yīng)用場景。
三、SerialPort類ReadTimeout方法的具體應(yīng)用場景
首先,這些總結(jié)或方法是我百度的,我沒有實測過。收發(fā)往往放到不同的線程中執(zhí)行。百度了好久,網(wǎng)上也么有說ReadTimeout的應(yīng)用場景。
但是我從這篇博客了解到,如何讀內(nèi)存的關(guān)鍵信息:https://blog.csdn.net/qq_40741855/article/details/81134682
雙方通訊時,一般都需要定義通訊協(xié)議,即使最簡單的通過串口發(fā)送文本聊天的程序。
通常是在當(dāng)一方按下回車時,將其所數(shù)據(jù)的文本連同換行符發(fā)給另一方。在這個通訊事例中,協(xié)議楨是通過換行符界定的,每一楨數(shù)據(jù)都被換行符隔開,這樣就很容易識別出通訊雙發(fā)發(fā)送的信息。
在以上的例子中,可以用WriteLine()來發(fā)送數(shù)據(jù),用ReadLine()來讀取數(shù)據(jù)。WriteLine發(fā)送完數(shù)據(jù)后,會將換行符作為數(shù)據(jù)也發(fā)送給對方。ReadLine()讀取數(shù)據(jù)時,直至遇到一個換行符,然后返回一個字符串代表一行信息。換行符可以通過SerialPort 的屬性NewLine來設(shè)置。一般地,Windows將CrLn作為換行符,而在Linux下,換行符則只用一個Ln表示。
ReadLine()方法是阻塞的,直至遇到一個換行符后返回。在讀取數(shù)據(jù)時,如果一直沒有遇到換行符,那么在等待ReadTimeout時間后,拋出一個TimeoutException。默認(rèn)情況下,ReadTimeout為InfiniteTimeout。這樣,ReadLine一直處于阻塞狀態(tài),直至有新一行數(shù)據(jù)到達(dá)(這段話可以完美說明阻塞問題)。
WriteLine()方法也是阻塞的,如果另一方不能及時接收數(shù)據(jù),就會引起TimeoutException異常。
由于ReadLine()和WriteLine()方法都是阻塞式的,在程序使用SerialPort 進(jìn)行串口通訊時,一般應(yīng)該把讀寫操作交由其他線程處理,避免因為阻塞而導(dǎo)致程序不響應(yīng)。
論壇的說法:https://bbs.csdn.net/topics/350246033
ReadTimeOut的意思是從有數(shù)據(jù)開始,讀取的時間超過這個設(shè)置的值,則引發(fā)異常,比如是某些驅(qū)動級原因?qū)е伦x取時間過長導(dǎo)致的,并不是說ReadByte,ReadTo,ReadLine的超時時間,這些方法本身是一定會同步阻塞等結(jié)果的,你可以先判斷一下,比如
if(serial.BytesToRead>0) b = serial.ReadByte();
或是用
serial.ReadExisting()
讀取到一個緩存,再處理替代ReadLine或ReadTo。
替代都是發(fā)生在你的信源(對你程序的發(fā)送方)可能會正常情況的缺失\r\n或你指定字符的情況。
四、總結(jié)
好了,到這里為止,超時問題可以完美的被解決了。以上敘述可以總結(jié)為:
1、收發(fā)往往放在不同的線程,以防止被阻塞的。本文的接收采用事件方式,發(fā)送在主線程。
2、你可以不用ReadLine方法,用以下方法就能實現(xiàn)正常的接收:
? ? ? ? ? ? byte[] ReDatas = new byte[SerialPortObj.BytesToRead];
? ? ? ? ? ? SerialPortObj.Read(ReDatas, 0, ReDatas.Length); //從串口讀取數(shù)據(jù)文章來源:http://www.zghlxwxcb.cn/news/detail-493344.html
3、當(dāng)然,若你要用ReadLine方法,最好是將ReadTimeout設(shè)置為無窮大,并且能夠識別 換行符。這樣你能一直等待接收信息了,不會超時拋出異常了。
————————————————
版權(quán)聲明:本文為CSDN博主「我愛AI」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/xpj8888/article/details/84628762文章來源地址http://www.zghlxwxcb.cn/news/detail-493344.html
到了這里,關(guān)于C# SerialPort串口ReadTimeout 超時異常?!癝ystem.TimeoutException”的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!