我使用C#中的串行端口功能与一块硬件进行通信。一切都写得很好,串口,串口总是连接。
由于某种原因,串行端口数据接收处理程序并不总是读取即将出现的数据(每8次中有1次无法读取任何内容或调用事件函数本身)。另一方面一切都很好。我只收到串口的一个字母,即1,2,3等
这是我的代码:
串口设置:
//Create new serial port
SerialPort SerPort = new SerialPort("COM4");
private void SetupSerial()
{
SerPort.BaudRate = 9600;
SerPort.Parity = Parity.None;
SerPort.StopBits = StopBits.One;
SerPort.DataBits = 8;
SerPort.Handshake = Handshake.None;
SerPort.ReadTimeout = 4000;
SerPort.WriteTimeout = 6000;
SerPort.Open();
SerPort.DataReceived += new SerialDataReceivedEventHandler(HandleSerialData);
lblStatus.Text = "Successfully connected to COM port with no errors!";
}
我的写入串口功能:
private void WriteToSerial( string data )
{
byte[] MyMessage = Encoding.UTF8.GetBytes(data);
SerPort.Write(MyMessage, 0, MyMessage.Length);
string time = "[" + DateTime.Now.ToString("HH:mm") + "]";
bool debug = chkDebug.Checked;
if (debug ) f.DebugText = time + " Wrote bytes to serial: " + data;
}
My Recieve事件功能:
//Called everytime serial data is recieved
private void HandleSerialData(object sender, SerialDataReceivedEventArgs e)
{
try
{
//Store recieved data in variable
SerialPort sp = (SerialPort)sender;
string data = sp.ReadExisting().ToString();
bool debug = chkDebug.Checked;
string time = "[" + DateTime.Now.ToString("HH:mm") + "]";
if( debug ) f.DebugText = time + " Recieved serial data: " + data;
switch ( data )
{
case "1":
//If Battery is already on
if( Battery1[0] == "ON")
{
Battery1[0] = "OFF"; //ON or OFF
Battery1[2] = DateTime.Now.ToString("h:mm tt"); //End time
WriteLogFile("1");
lblST1.Text = "n/a";
lblET1.Text = "n/a";
if (debug) f.DebugText = time + " Battery 1 testing switched OFF.";
}
else
{
Battery1[0] = "ON"; //ON or OFF
Battery1[1] = DateTime.Now.ToString("h:mm tt"); //Start time
Battery1[5] = DateTime.Now.ToString("d/MM/yyyy"); //Start date
plcRespond = true;
lblST1.Text = Battery1[1];
if (debug) f.DebugText = time + " Battery 1 testing switched ON.";
}
break;
case "2":
//If Battery is already on
if (Battery2[0] == "ON")
{
Battery2[0] = "OFF";
Battery2[2] = DateTime.Now.ToString("h:mm tt"); //End time
WriteLogFile("2");
lblST2.Text = "n/a";
lblET2.Text = "n/a";
if (debug) f.DebugText = time + " Battery 2 testing switched OFF.";
}
else
{
Battery2[0] = "ON"; //ON or OFF
Battery2[1] = DateTime.Now.ToString("h:mm tt"); //Start time
Battery2[5] = DateTime.Now.ToString("d/MM/yyyy"); //Start date
plcRespond = true;
lblST2.Text = Battery2[1];
if (debug) f.DebugText = time + " Battery 2 testing switched ON.";
}
break;
case "3":
//If Battery is already on
if (Battery3[0] == "ON")
{
Battery3[0] = "OFF"; //ON or OFF
Battery3[2] = DateTime.Now.ToString("h:mm tt"); //End time
WriteLogFile("3");
lblST3.Text = "n/a";
lblET3.Text = "n/a";
if (debug) f.DebugText = time + " Battery 3 testing switched OFF.";
}
else
{
Battery3[0] = "ON"; //ON or OFF
Battery3[1] = DateTime.Now.ToString("h:mm tt"); //Start time
Battery3[5] = DateTime.Now.ToString("d/MM/yyyy"); //Start date
plcRespond = true;
lblST3.Text = Battery3[1];
if (debug) f.DebugText = time + " Battery 3 testing switched ON.";
}
break;
case "4":
//If Battery is already on
if (Battery4[0] == "ON")
{
Battery4[0] = "OFF"; //ON or OFF
Battery4[2] = DateTime.Now.ToString("h:mm tt"); //End time
WriteLogFile("4");
lblST4.Text = "n/a";
lblET4.Text = "n/a";
if (debug) f.DebugText = time + " Battery 4 testing switched OFF.";
}
else
{
Battery4[0] = "ON"; //ON or OFF
Battery4[1] = DateTime.Now.ToString("h:mm tt"); //Start time
Battery4[5] = DateTime.Now.ToString("d/MM/yyyy"); //Start date
plcRespond = true;
lblST4.Text = Battery4[1];
if (debug) f.DebugText = time + " Battery 4 testing switched ON.";
}
break;
case "5":
//If Battery is already on
if (Battery5[0] == "ON")
{
Battery5[0] = "OFF"; //ON or OFF
Battery5[2] = DateTime.Now.ToString("h:mm tt"); //End time
WriteLogFile("5");
lblST5.Text = "n/a";
lblET5.Text = "n/a";
if (debug) f.DebugText = time + " Battery 5 testing switched OFF.";
}
else
{
Battery5[0] = "ON"; //ON or OFF
Battery5[1] = DateTime.Now.ToString("h:mm tt"); //Start time
Battery5[5] = DateTime.Now.ToString("d/MM/yyyy"); //Start date
plcRespond = true;
lblST5.Text = Battery5[1];
if (debug) f.DebugText = time + " Battery 5 testing switched ON.";
}
break;
case "6":
//If Battery is already on
if (Battery6[0] == "ON")
{
Battery6[0] = "OFF"; //ON or OFF
Battery6[2] = DateTime.Now.ToString("h:mm tt"); //End time
WriteLogFile("6");
lblST6.Text = "n/a";
lblET6.Text = "n/a";
if (debug) f.DebugText = time + " Battery 6 testing switched OFF.";
}
else
{
Battery6[0] = "ON"; //ON or OFF
Battery6[1] = DateTime.Now.ToString("h:mm tt"); //Start time
Battery6[5] = DateTime.Now.ToString("d/MM/yyyy"); //Start date
plcRespond = true;
lblST6.Text = Battery6[1];
if (debug) f.DebugText = time + " Battery 6 testing switched ON.";
}
break;
}
SerPort.DiscardInBuffer();
SerPort.DiscardOutBuffer();
}
catch (Exception ex)
{
MessageBox.Show("Error recieving COM data! " + ex.Message);
}
}
有没有更好的方法来读取不使用ReadExisting的串行数据?或者使用更可靠的功能?
答案 0 :(得分:1)
过去ReadExisting
我遇到了问题。如果在读取缓冲区时有更多数据到达,我不知道ReadExisting中会发生什么。
在串口甚至处理程序中,我使用以下代码。因为它确定了首先读取的长度,所以在下一个函数调用期间将读取到达的新数据,因此可以按照发送数据的速率清空缓冲区。
private void HandleSerialData(object sender, SerialDataReceivedEventArgs e)
{
int lengthToRead = sp.BytesToRead;
byte[] rxBytes = new byte[lengthToRead];
sp.Read(rxBytes, 0, lengthToRead);
functionThatInterpratesData(rxBytes);
}
这也具有可重复使用的好处,因为您将字节数组转换为字符串,或者您已将其单独编码。
我会创建一个函数将字节数组转换为字符串(SO上有很多例子),另一个函数用来处理case语句。