求解 c# SerialPort 接收老是要过很久才能收到

dading_105 2012-03-05 05:50:31
程序如下,电脑发下去之后,设备马上有返回,但是我的接收事件要等很久才能收到,高手指点

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Threading;

namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
SerialPort SP1 = new SerialPort();
List<string> xieyi = new List<string>();

public Form1()
{

InitializeComponent();
SP1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);

}



private void Form1_Load(object sender, EventArgs e)
{
string rdline;
int i;
comboBox1.SelectedItem=comboBox1.Items[0];
comboBox2.SelectedItem = comboBox2.Items[0];

try
{
FileStream sFile = new FileStream(".\\d645.txt", FileMode.Open);
StreamReader sr = new StreamReader(sFile);

rdline = sr.ReadLine();
while(rdline!=null)
{
xieyi.Add(rdline);
rdline = sr.ReadLine();
}

label1.Text = xieyi[0];

for (i=1;i<xieyi.Count;i++)
{
checkedListBox1.Items.Add(xieyi[i].Substring(0,4));
checkedListBox1.SetItemChecked(i-1, true);

}

}
catch (Exception ee)
{
MessageBox.Show("加载文件失败:"+ee);
}



}

private void button1_Click(object sender, EventArgs e)
{
try
{

SP1.PortName = comboBox1.SelectedItem.ToString();
SP1.BaudRate = Convert.ToInt32(comboBox2.SelectedItem.ToString());
SP1.Parity = Parity.Even;

SP1.ReceivedBytesThreshold = 1;
SP1.Open();
}
catch (Exception ee) { MessageBox.Show(comboBox1.SelectedItem.ToString() + "失败:"+ee); }

}

private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{

}

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{

}

private void button2_Click(object sender, EventArgs e)
{

}

private void label2_Click(object sender, EventArgs e)
{

}

private void button2_Click_1(object sender, EventArgs e)
{
int i=0;
while (checkedListBox1.GetItemChecked(i))
{
string s = xieyi[i+1];
int len = s.Length / 2;
byte[] bytes = new byte[len];
for (int j = 0; j < len; j++)
{
bytes[j] = Convert.ToByte((s.Substring(j * 2, 2)), 16);
}

try
{
SP1.Write(bytes, 0, len);
}
catch (Exception ee) { MessageBox.Show(comboBox1.SelectedItem.ToString() + "失败:" + ee); }
Thread.Sleep(1000);
richTextBox1.Text += "\r\n";

i++;
if (i >= checkedListBox1.Items.Count)
break;

}
}

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{

string tmpstr = "";
for (int i = 0; i < SP1.BytesToRead; i++)
{
tmpstr += Convert.ToString(SP1.ReadByte(), 16) + " ";

}
safeAddtrText(tmpstr);
}

public delegate void _SafeAddtrTextCall(string text);

private void safeAddtrText(string text)
{
if (this.InvokeRequired)
{
_SafeAddtrTextCall call =
delegate(string s)
{
richTextBox1.Text += s;
};

this.Invoke(call, text);
}
else
{
richTextBox1.Text += text;

}
}

private void richTextBox1_TextChanged(object sender, EventArgs e)
{

}

}
}
...全文
804 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
chicxl9881 2012-03-07
  • 打赏
  • 举报
回复
SP1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
SP1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
SP1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
SP1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
SP1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
多写几次,就可以了。我试过。
最好采用接收线程来接收数据。
dading_105 2012-03-07
  • 打赏
  • 举报
回复
csdn太强大了
jshi123 2012-03-06
  • 打赏
  • 举报
回复
在for循环中,SP1.BytesToRead是不断变化的,每次调用ReadByte(),BytesToRead就会减1,
所以如果缓冲区有2个以上数据的时候,你的循环方式就读不到后面的数据。

byte[] readBuffer = new byte[SP.BytesToRead];
int byteLength = SP.Read(readBuffer, 0, SP.BytesToRead);
tmpstr = BitConverter.ToString(readBuffer).Replace('-', ' ');
jshi123 2012-03-06
  • 打赏
  • 举报
回复
按11楼的方式改下试试
dading_105 2012-03-06
  • 打赏
  • 举报
回复
现在把
Thread.Sleep(1000);
改成
for (int q = 0; q < 1000000; q++)
{
Application.DoEvents();
}
现在发送马上有返回
但是最后一个字节老是出不来,必须要发下条指令的时候才能出现上条返回指令的最后一个字节
zw_l_1989 2012-03-06
  • 打赏
  • 举报
回复

private void comPort_DataReceiveed(object sender, SerialDataReceivedEventArgs e)
{
if (bClosing)
{
return;
}
try
{
bListening = true;
int n = comPort.BytesToRead;
byte[] receiveByte = new byte[n];
comPort.Read(receiveByte, 0, n);
AddItemToListBox(receiveByte);
ReceiveCount += n;
ChangStatus("接收成功!");
}
finally
{
bListening = false;
}
}
火星大能猫 2012-03-06
  • 打赏
  • 举报
回复

string tmpstr = "";
for (int i = 0; i < SP1.BytesToRead; i++)
{
tmpstr += Convert.ToString(SP1.ReadByte(), 16) + " ";

}


再者,用string拼接效率极低,尤其是byte的拼接,
你就算要用这个方法,也得用stringbuilder,效率会提高不少.
byte[] readBuffer = new byte[comport.ReadBufferSize];
int bytLength = comport.Read(readBuffer, 0, comport.ReadBufferSize);
string msgRec = myEncode.GetString(readBuffer, 0, bytLength);//接收到的信息
dading_105 2012-03-06
  • 打赏
  • 举报
回复
现在把
Thread.Sleep(1000);
改成
for (int q = 0; q < 1000000; q++)
{
Application.DoEvents();
}
但是最后一个字节老是出不来,必须要发下条指令的时候才能出现上条返回指令的最后一个字节
dading_105 2012-03-06
  • 打赏
  • 举报
回复
2。DataReceived方法越快越好(慢的话会导致缓冲区中的待读数据越来越多,最后溢出),所以最好把Invoke改成BeginInvoke,防止长时间同步等待UI线程更新界面。

4。发送过程中不要用Thread.Sleep(1000); 这样会阻塞UI线程(当此时有接收数据到达,会因为要更新界面而被迫等待1秒),改成循环Application.DoEvents(); 并在循环中判断等待的时间是否超过1秒。

能不能帮我改下这2点
dading_105 2012-03-06
  • 打赏
  • 举报
回复
能不能帮我改下,我是新手
NbaDennis 2012-03-06
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 jshi123 的回复:]

1。检查波特率、奇偶校验等两边是否一致。
2。DataReceived方法越快越好(慢的话会导致缓冲区中的待读数据越来越多,最后溢出),所以最好把Invoke改成BeginInvoke,防止长时间同步等待UI线程更新界面。
3。DataReceived中的for循环:for (int i = 0; i < SP1.BytesToRead; i++),应把SP1.BytesToRead提到循环……
[/Quote]

读取数据时,先sleep(100);
jshi123 2012-03-06
  • 打赏
  • 举报
回复
tmpstr = readBuffer.Aggregate("", (s, b) => s+b.ToString("x")+ ' ');
dading_105 2012-03-06
  • 打赏
  • 举报
回复
我想每个字节一个空格,但是现在是返回的数据是 2个字节一个空格
FEFE FEFE 6800 0000 0000 0068 8116 52C3 3333 3333 3333 3333 3333 3333 3333 3333 3333 3333 7816
FEFE FEFE 6800 0000 0000 0068 8116 52C3 3333 3333 3333 3333 3333 3333 3333 3333 3333 3333 7816
jshi123 2012-03-06
  • 打赏
  • 举报
回复
1。检查波特率、奇偶校验等两边是否一致。
2。DataReceived方法越快越好(慢的话会导致缓冲区中的待读数据越来越多,最后溢出),所以最好把Invoke改成BeginInvoke,防止长时间同步等待UI线程更新界面。
3。DataReceived中的for循环:for (int i = 0; i < SP1.BytesToRead; i++),应把SP1.BytesToRead提到循环外:int bytesToRead = SP1.BytesToRead; 这样缓冲区中有多个数据时才能正确执行。
4。发送过程中不要用Thread.Sleep(1000); 这样会阻塞UI线程(当此时有接收数据到达,会因为要更新界面而被迫等待1秒),改成循环Application.DoEvents(); 并在循环中判断等待的时间是否超过1秒。
upc_xiaowei 2012-03-05
  • 打赏
  • 举报
回复
我使用的时候马上就得到了啊
stonespace 2012-03-05
  • 打赏
  • 举报
回复
还有ReceivedBytesThreshold属性,
stonespace 2012-03-05
  • 打赏
  • 举报
回复
可以设置serialport的ReadBufferSize 和WriteBufferSize 属性来改变缓冲大小,
stonespace 2012-03-05
  • 打赏
  • 举报
回复
串口都有缓存的,不是接受到数据就立即引发事件,

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧