求解 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)
{

}

}
}
...全文
904 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
  • 打赏
  • 举报
回复
串口都有缓存的,不是接受到数据就立即引发事件,
它通过读取 Excel 表格中的业务数据,结合 Word 模板,自动生成多个独立的合同文件,并自动处理了表格中“合计”行的合并与中文大写金额转换。 资源名称:合同文档自动化生成脚本 (1.py) 名字真是乱起 核心功能:Excel 数据读取 → Word 模板渲染 → 表格单元格合并与金额处理 → 批量导出 Word 文档。 适用场景:财务、销售或行政部门需要根据订单或业务明细,批量制作格式统一的合同、报价单或结算单。 1. 自动把“钱”变成“大写” 它干了啥:它内置了一个翻译功能,专门把阿拉伯数字(比如 100.50)自动转换成财务专用的中文大写(比如 壹佰元伍角)。 为什么有用:写合同最怕手滑写错金额,或者大写格式不对。这个功能全自动搞定,既标准又不会出错。 2. 自动“装修”表格底部 它干了啥:生成文档后,它会自动找到表格的最后一行,把前几列合并成一个大格子,写上“合计:XXX(大写金额)”,并在最右边填上具体的数字总额。 为什么有用:平时我们做完表格,还得手动去合并单元格、算总数、填大写,非常繁琐。这个脚本直接一步到位,把表格收尾工作做得漂漂亮亮。 3. 像“发传单”一样批量做合同 它干了啥:它会看你的 Excel 表格,按照“编号”把数据归类。 如果是同一个编号的货物,它会把它们塞进同一个合同里(比如一个客户买了三样东西,会自动列三行)。 如果是不同的编号,它就生成不同的合同文件。 为什么有用:不管你有一百个还是一千个订单,它都能自动拆分,给每个客户生成一份独立的、内容准确的合同,完全不用人工去复制粘贴。

111,129

社区成员

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

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

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