C# SerialPort控件做串口编程中,多个串口同时通信的问题,请大家帮忙

shamohai5566 2010-04-05 04:53:46
我是初学者,对这方面的知识不太了解,希望高手指点。用不用多线程呀?为什么我的总是出问题,不是发送不了,就是给COM8发送数据,COM3也能收到,不知道是怎么回事,我的代码如下,希望高手指点。或者给一段多个串口同时通信的代码,让小弟参考一下,不胜感激![code=C#]namespace NETTEST
{
public partial class Form_Main : Form
{
SerialPort spcom = new SerialPort();
SerialPort spcom2 = new SerialPort();
delegate void HandleInterfaceUpdateDelegate(string text); //委托
HandleInterfaceUpdateDelegate interfaceUpdateHandle;
HandleInterfaceUpdateDelegate interfaceUpdateHandle2;
public Form_Main()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
comboBox6.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
comboBox1.Text = comboBox1.Items[0].ToString();
comboBox2.Text = comboBox2.Items[0].ToString();
comboBox3.Text = comboBox3.Items[0].ToString();
comboBox4.Text = comboBox4.Items[0].ToString();
comboBox5.Text = comboBox5.Items[0].ToString();
comboBox6.Text = comboBox6.Items[0].ToString();
comboBox7.Text = comboBox7.Items[0].ToString();
comboBox8.Text = comboBox8.Items[0].ToString();
comboBox9.Text = comboBox9.Items[0].ToString();
comboBox10.Text = comboBox10.Items[0].ToString();
}

public void spcom_DataReceived(object sender, SerialDataReceivedEventArgs e)
{

byte[] readBuffer = new byte[spcom.ReadBufferSize];
spcom.Read(readBuffer, 0, readBuffer.Length);
this.Invoke(interfaceUpdateHandle, new string[] { Encoding.ASCII.GetString (readBuffer) }
}
public void spcom2_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] readBuffer = new byte[spcom2.ReadBufferSize];
spcom2.Read(readBuffer, 0, readBuffer.Length);
this.Invoke(interfaceUpdateHandle2, new string[] { Encoding.ASCII.GetString(readBuffer) });
}

//字节数组转换为十六进制
private string ByteArrayToHexString(byte[] data)
{
StringBuilder sb = new StringBuilder(data.Length * 3);
foreach (byte b in data)
sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
return sb.ToString().ToUpper();
}
//字符串转换为十六进制
private string StringToHexString(string str)
{
StringBuilder sb = new StringBuilder(str.Length * 3);
foreach (char b in str)
sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
return sb.ToString().ToUpper();
}
private void UpdateTextBox1(string text)
{
txtrev1.Text += text;
}
private void UpdateTextBox2(string text)
{
txtrev2.Text += text;
}

//发送字符串数据
private void SendStringData(SerialPort serialPort)
{
try
{
SerialPort i = serialPort;
//if (!spcom.IsOpen)
//{ spcom.Open(); }
string str = txtsend.Text.Trim();
//serialPort.WriteLine(CharToIntStr(str));// .Write //txtsend.Text.ToString().Trim()
// byte[] data= Convert .ToByte (str);
serialPort.WriteLine(StringToHexString(str));
serialPort.Write(txtsend.Text);
//spcom2.WriteLine(CharToIntStr(str));// .Write //txtsend.Text.ToString().Trim()
//// byte[] data= Convert .ToByte (str);
//spcom2.WriteLine(StringToHexString(str));
//spcom2.Write(txtsend.Text);
}
catch(Exception ex)
{
MessageBox.Show("没有找到串口,请先打开串口", "警告"+ex.Message );
}

}

//发送二进制数据
private void SendBytesData(SerialPort serialPort)
{
byte[] bytesSend = Encoding.Default.GetBytes(txtsend.Text);
spcom.Write(bytesSend, 0, bytesSend.Length);
}

private void txtrev_TextChanged(object sender, EventArgs e)
{
txtrev1.SelectionStart = txtrev1.Text.Length;
txtrev1.SelectionLength = 0;
txtrev1.ScrollToCaret();
}

private void button1_Click(object sender, EventArgs e)
{
SerialPortInitial();
SerialPortInitial2();
try
{
if (!spcom.IsOpen) spcom.Open();
if (!spcom2.IsOpen) spcom2.Open();
}
catch (Exception ex)
{
MessageBox.Show("没有找到串口,请检查后再试……", "警告" + ex.Message);
}

interfaceUpdateHandle = new HandleInterfaceUpdateDelegate(UpdateTextBox1);
spcom.DataReceived += new SerialDataReceivedEventHandler(spcom_DataReceived);
spcom.ReceivedBytesThreshold = 1;
interfaceUpdateHandle2 = new HandleInterfaceUpdateDelegate(UpdateTextBox2);
spcom2.DataReceived += new SerialDataReceivedEventHandler(spcom2_DataReceived);
spcom2.ReceivedBytesThreshold = 1;

}
private void button3_Click(object sender, EventArgs e)
{
try
{
SendStringData(spcom);
SendStringData(spcom2);
}
catch (Exception ex)
{
MessageBox.Show("没有找到串口,请检查后再试……", "警告" + ex.Message);
}

}
...全文
2646 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
aragon2008 2011-05-17
  • 打赏
  • 举报
回复
很有参考价值
doubleu2005 2010-04-11
  • 打赏
  • 举报
回复
可用serialPort.ReadLine()读出所有数据包
shamohai5566 2010-04-10
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 doubleu2005 的回复:]
如果使用多个串口同时通讯的话还是要多个SerialPort,而且最好不要在一个事件里同时操作多个SerialPort,如果有一个SerialPort卡死就无法操作其他SerialPort了,还是分别控制比较好,比如多口的下载程序就应该一个SerialPort对应一个button。可以使用SerialPort.readbyte()读取二进制数据吧
[/Quote]
你好,我用SerialPort控件时
delegate void HandleInterfaceUpdateDelegate(string text); //委托
HandleInterfaceUpdateDelegate interfaceUpdateHandle;
interfaceUpdateHandle = new HandleInterfaceUpdateDelegate(UpdateTextBox1);
spcom.DataReceived += new SerialDataReceivedEventHandler(spcom_DataReceived);
spcom.ReceivedBytesThreshold = 40;
如上使用委托,当我要接收的数据包长度是变化的时候怎么办?我这里的spcom.ReceivedBytesThreshold参数值怎么设置呀?高手请指点
ALUH 2010-04-09
  • 打赏
  • 举报
回复
考虑是不是可以开多个程序,每个程序serialport.name设成不同端口
doubleu2005 2010-04-09
  • 打赏
  • 举报
回复
如果使用多个串口同时通讯的话还是要多个SerialPort,而且最好不要在一个事件里同时操作多个SerialPort,如果有一个SerialPort卡死就无法操作其他SerialPort了,还是分别控制比较好,比如多口的下载程序就应该一个SerialPort对应一个button。可以使用SerialPort.readbyte()读取二进制数据吧
xingyuebuyu 2010-04-09
  • 打赏
  • 举报
回复
byte[] readBuffer = new byte[spcom2.BytesToRead];
spcom2.Read(readBuffer, 0, readBuffer.Length);
this.BeginInvoke(interfaceUpdateHandle2, new string[] { ByteArrayToHexString(readBuffer) });

你怎么改的,贴下你改后的代码.
xingyuebuyu 2010-04-07
  • 打赏
  • 举报
回复
byte[] readBuffer = new byte[spcom2.BytesToRead];
spcom2.Read(readBuffer, 0, readBuffer.Length);
this.BeginInvoke(interfaceUpdateHandle2, new string[] { Encoding.ASCII.GetString(readBuffer) });


只能接收ASCII码的数据,其它格式的需要你自己接收到后进行转换。

因为spcom2_DataReceived方法是在一个新的线程中执行的,所以需要使用委托,用this.BeginInvoke去调用UpdateTextBox2方法
shamohai5566 2010-04-07
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 xingyuebuyu 的回复:]
让你多个是有好处的,当你的电脑上有3个COM口时,你可以同时与个单片机进行通信,如果你要共用,那你同时只能有一个处于通信中,一个使用完后才能让下一个使用.
[/Quote]
 public void spcom2_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
byte[] readBuffer = new byte[spcom2.ReadBufferSize];
spcom2.Read(readBuffer, 0, readBuffer.Length);
this.BeginInvoke(interfaceUpdateHandle2, new string[] { Encoding.ASCII.GetString(readBuffer) });
}
catch (Exception ex)
{
MessageBox.Show(ex.Message +"系统提示");
}

}
但是为什么我的程序能接收ASCII码的数据,不能接收二进制数据呀?我要是想接收16进制的应该怎么写?还有
interfaceUpdateHandle2 = new HandleInterfaceUpdateDelegate(UpdateTextBox2);
spcom2.DataReceived += new SerialDataReceivedEventHandler(spcom2_DataReceived);
spcom2.ReceivedBytesThreshold = 1;
这里当缓存中收到数据时 是怎么调用UpdateTextBox2方法的呀?谢谢指点
shamohai5566 2010-04-07
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 shamohai5566 的回复:]
引用 14 楼 cumber 的回复:
learn
?详细一点?
[/Quote]
我还以为是个什么方法呢,呵呵。。。。很着急 有没有人指点一下呀
shamohai5566 2010-04-07
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 cumber 的回复:]
learn
[/Quote]?详细一点?
shamohai5566 2010-04-07
  • 打赏
  • 举报
回复
十分感谢xingyuebuyu,其它朋友也可以指点指点呀。多谢每一位过客
CUMBER 2010-04-07
  • 打赏
  • 举报
回复
learn
shamohai5566 2010-04-07
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 xingyuebuyu 的回复:]
byte[] readBuffer = new byte[spcom2.BytesToRead];
spcom2.Read(readBuffer, 0, readBuffer.Length);
this.BeginInvoke(interfaceUpdateHandle2, new string[] { Encoding.ASCII.GetString(readBuffer) });
……
[/Quote]
谢谢朋友的一步步指导,终于接近问题的中心了,呵呵。。。。我要接受的是单片机发过来的16进制的数据,从缓存buffer里面可以看到,但是我怎么转换之后显示呢?
private string ByteArrayToHexString(byte[] data)
{
StringBuilder sb = new StringBuilder(data.Length * 3);
foreach (byte b in data)
sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
return sb.ToString().ToUpper();
}
我用这个方法将它转换之后,赋值给String read;然后用read代替this.BeginInvoke(interfaceUpdateHandle2, new string[] { Encoding.ASCII.GetString(readBuffer) });
中的new string[] { Encoding.ASCII.GetString(readBuffer) }可以显示,但是总是假死,有时候就是真死了,不响应了,能帮我分析一下怎么样才能让我的程序正常运行,谢谢高手
shamohai5566 2010-04-06
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 xingyuebuyu 的回复:]
你如果想使用同一个串口COM1来与多个单片机进行通信,那要注意SendStringData(spcom);
在spcom发送完数据后,并且你确定spcom的数据接收完后,你要关闭COM1,这个时候才能使用spcom2,去开启COM1,然后SendStringData(spcom2);去发送数据和接收数据。两者不要混用。

interfaceUpdateHandle = new HandleI……
[/Quote]
那我要是同时与多个单片机通信是不是要用多个SerialPort,多个spcom_DataReceived(如spcom1_DataReceived、spcom2_DataReceived.。。),多HandleInterfaceUpdateDelegate对象呀?
足球中国 2010-04-06
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 xingyuebuyu 的回复:]
你如果想使用同一个串口COM1来与多个单片机进行通信,那要注意SendStringData(spcom);
在spcom发送完数据后,并且你确定spcom的数据接收完后,你要关闭COM1,这个时候才能使用spcom2,去开启COM1,然后SendStringData(spcom2);去发送数据和接收数据。两者不要混用。

interfaceUpdateHandle = new HandleI……
[/Quote]楼上不错。

网上也COM通信的例子,你可以找个看看
xingyuebuyu 2010-04-06
  • 打赏
  • 举报
回复
你如果想使用同一个串口COM1来与多个单片机进行通信,那要注意SendStringData(spcom);
在spcom发送完数据后,并且你确定spcom的数据接收完后,你要关闭COM1,这个时候才能使用spcom2,去开启COM1,然后SendStringData(spcom2);去发送数据和接收数据。两者不要混用。

interfaceUpdateHandle = new HandleInterfaceUpdateDelegate(UpdateTextBox1);
spcom.DataReceived += new SerialDataReceivedEventHandler(spcom_DataReceived);
spcom.ReceivedBytesThreshold = 1;
这个不要共用,当你使用不同的COM端口,这个部分就可以同时工作
shamohai5566 2010-04-06
  • 打赏
  • 举报
回复
哪位朋友有相关的经验呀?指点指点。走过路过的朋友也可以说一下串口编程的经验
xingyuebuyu 2010-04-06
  • 打赏
  • 举报
回复
让你多个是有好处的,当你的电脑上有3个COM口时,你可以同时与个单片机进行通信,如果你要共用,那你同时只能有一个处于通信中,一个使用完后才能让下一个使用.
shamohai5566 2010-04-06
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 jsmouse 的回复:]
做个标记
[/Quote]
做个标记是什么意思?断点吗?还是哪里出问题呀?
shamohai5566 2010-04-06
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 xingyuebuyu 的回复:]
不用多开线程了,DataReceived 事件绑定的方法本身会在一个新的线程中执行的.
你把this.Invoke改成this.BeginInvoke 异步执行
[/Quote]
您好,如果把this.Invoke改成this.BeginInvoke 异步执行之后,多个串口即SerialPort对象,
可不可以公用这几行代码呀?
interfaceUpdateHandle = new HandleInterfaceUpdateDelegate(UpdateTextBox1);
spcom.DataReceived += new SerialDataReceivedEventHandler(spcom_DataReceived);
spcom.ReceivedBytesThreshold = 1;
能帮我开一下我的程序代码吗?是哪里有问题呀?我点发送调用了两次SendStringData方法,分别发送到两个不同的textbox里面但是总是只有一个能收的。
分不多,不好意思,如果有空帮我分析一下吧,谢谢
加载更多回复(3)

110,534

社区成员

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

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

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