C#串口通讯接收不到数据(在线等。。)

zhu4139365 2009-09-28 10:51:32

我的软件是与PDA通过串口通讯。
我用的是C#语言,串口通讯用的.NET的SerialPort类。
我的SerialPort打开了,为什么有时候我的软件接收不到PDA发送的数据呢?
用串口调试助手与PDA连接成功后,我的软件就能接受到PDA发送的数据了。但是有时候我的软件也能正常的接受PDA发送的数据。
配置参数如下:
BaudRate = 19200;
DataBits = 8;
DisCardNull = False;
DtrEnable = False;
Handshake = None;
Parity = None;
ParityReplace = 63;
PortName = COM1;
ReadBufferSize = 4096;
ReadTimeout = 1000;
ReceiveBytesThreshold = 1;
RtsEnable = False;
StopBits = One;
WriteBufferSize = 2048;
WriteTimeout = 1000;

...全文
2825 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
walkghost 2009-09-29
  • 打赏
  • 举报
回复
哥们,串口调试助手连接PDA之后,你的软件就能接收到数据了?你的意思是必须先用串口调试助手打开串口,关闭串口后再启用你的程序嘛?
代码整两盘上来看看?
fpcc 2009-09-29
  • 打赏
  • 举报
回复
1、首先用串口助手之类的工具,确保PDA的串口是通畅的。
2、再用串口助手测试你的程序可以正确的发送数据。
3、程序与PDA互发数据。看是否通畅。
我原来做这个也遇到过类似问题,基本这样解决的。主要原因是PDA的串口通信不稳定。所以你有时候儿会认为你的程序有问题,当然也可能是真得有问题。
trentliu 2009-09-29
  • 打赏
  • 举报
回复
串口通信本来就是不可靠的通信方式,要进行拆包,组包的操作,而且一般还要加上crc验证。这是串口通信的设计特点。

假设都不按照路子走,就只能做些特别处理

1. 接收事件里不能立刻就操作接收的数据,因为很可能触发事件时,数据并没有接收完全。
2. 接收事件里加上适当的延时,可以提高数据填满缓冲区的几率。 可提高通信质量
假设10次丢5次的话(数据未接收完全),适当延时几乎可以保证10次都收到,这是我实际的测试结果。(环境为长距离串口通信)

lljfl 2009-09-29
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 freeboy827 的回复:]
我用serialport还可以,
偶尔有错位的情况,自己处理下就行了
是不是硬件有问题啊,发指令没有响应
[/Quote]
在台式机上,一般都不会出问题(我没碰到过),笔记本上,也不是每个都有问题,在有问题的笔记本上,用串口调试助手后就不会出问题了,但重启电脑又会出现,这是因为SerialPort在进行串口参数设置时有bug
王顺起 2009-09-29
  • 打赏
  • 举报
回复
你发送的数据格式可能有问题,你程序协议发送的有问题,可以把协议拿出来看看分析一下。
zhu4139365 2009-09-29
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 fpcc 的回复:]
1、首先用串口助手之类的工具,确保PDA的串口是通畅的。
2、再用串口助手测试你的程序可以正确的发送数据。
3、程序与PDA互发数据。看是否通畅。
我原来做这个也遇到过类似问题,基本这样解决的。主要原因是PDA的串口通信不稳定。所以你有时候儿会认为你的程序有问题,当然也可能是真得有问题。
[/Quote]
按照你的做法。
用串口调试助手,PDA的串口时流畅的,能够正常发送和接受数据。
用我的程序,也能与PDA进行正常的通讯。一直都能正常发送数据。因为我的程序发送命令后,PDA会显示连接成功,但有时候即使发送成功,连接成功,但还是接收不到数据。
zhu4139365 2009-09-29
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 walkghost 的回复:]
哥们,串口调试助手连接PDA之后,你的软件就能接收到数据了?你的意思是必须先用串口调试助手打开串口,关闭串口后再启用你的程序嘛?
代码整两盘上来看看?
[/Quote]
有时候,用串口调试助手打开串口,向PDA发送响应命令后,PDA会显示连接成功,然后关闭串口调试助手,打开我的程序就能和PDA正常通讯了。
而用我的程序发送响应命令,PDA上也会显示连接成功,但有时候会接受不到PDA发送的数据。
是不是PDA的问题?
足球中国 2009-09-28
  • 打赏
  • 举报
回复
up
24K純帥 2009-09-28
  • 打赏
  • 举报
回复
up...
guyehanxinlei 2009-09-28
  • 打赏
  • 举报
回复
UP
freeboy827 2009-09-28
  • 打赏
  • 举报
回复
我用serialport还可以,
偶尔有错位的情况,自己处理下就行了
是不是硬件有问题啊,发指令没有响应
lljfl 2009-09-28
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 freeboy827 的回复:]
引用 4 楼 lljfl 的回复:
这是.NET的SerialPort类的一个bug吧,我以前也碰到过,在一般的台式电脑还可以,但在笔记本上最容易发生,建议不要用SerialPort,效率又低,还有这么大的一个bug,你最好用windowsAPI吧,我现在都改成用API了,受不了SerialPort,特别是在半双工高速通讯的时候

你的笔记本上有串口?笔记本上有BUG,说明是USB转串口不稳定
[/Quote]
我碰到这个问题并不是在一两台笔记本上,而是多台,而且我在一台防爆电脑上也碰到过,其实说白了,就是serialPort在串参数设置时有问题
lljfl 2009-09-28
  • 打赏
  • 举报
回复
笔记本有串口,这也是怪事,虽然这年头带串口的笔记本不多了,但并不代表没有,dell d630就有串口的,我们公司是做硬件的,一般都会买带串口的电脑,usb转rs232一般都不好用,特别是在进行长时间大量数据通讯时
mlhy20060406 2009-09-28
  • 打赏
  • 举报
回复
MARK
freeboy827 2009-09-28
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 lljfl 的回复:]
这是.NET的SerialPort类的一个bug吧,我以前也碰到过,在一般的台式电脑还可以,但在笔记本上最容易发生,建议不要用SerialPort,效率又低,还有这么大的一个bug,你最好用windowsAPI吧,我现在都改成用API了,受不了SerialPort,特别是在半双工高速通讯的时候
[/Quote]
你的笔记本上有串口?笔记本上有BUG,说明是USB转串口不稳定
lghndyz 2009-09-28
  • 打赏
  • 举报
回复
void __fastcall TForm1::Button2Click(TObject *Sender)
{
if (hComm!=INVALID_HANDLE_VALUE) CloseHandle(hComm);
exit(EXIT_SUCCESS);

}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
char *ComNo;
DCB dcb;
String Temp;
//取得要打开的通讯端口。
Temp = "COM"+IntToStr(1);
//转换至指针类型Char。
ComNo = Temp.c_str();
hComm = CreateFile(ComNo,GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, 0);
if (hComm == INVALID_HANDLE_VALUE) // 如果通讯端口未打开
{
MessageBox(0, "打开通讯端口错误!!","Comm Error",MB_OK);
return;
}
//
GetCommState(hComm,&dcb); // 获得当前通讯端口状态。
dcb.BaudRate = CBR_9600; // 设置速率为9600
dcb.ByteSize = 8; // 字节为8 bit
dcb.Parity = NOPARITY; // Parity 为 None
dcb.StopBits = ONESTOPBIT; // 1 个 Stop bit
//端口设置。
if (!SetCommState(hComm, &dcb)) { // 设置通讯端口状态
MessageBox (0, "通讯端口错误!!!","Set Error",MB_OK);
CloseHandle(hComm);
return;
}

}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
String Temp;
char *SendData;
int ln;
unsigned long lrc,BS;
if (hComm==0) return; //检查Handle值
Temp = mSend->Text;//取得要发送的字符串
SendData = Temp.c_str(); //字符串转换
//取得要发送的字符串数。
BS = Temp.Length();
//BS = StrLen(SendData); //也可以用此方法取得要发送的字符串长度。
//实际的发送动作。
WriteFile(hComm,SendData,BS, &lrc,NULL); // 发送数据。

}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
String Temp;
char inbuff[1024];
DWORD nBytesRead, dwEvent, dwError;
COMSTAT cs;
//取得状态
ClearCommError(hComm,&dwError,&cs);
// 数据是否大于我们准备的缓冲区
if (cs.cbInQue > sizeof(inbuff))
{
PurgeComm(hComm, PURGE_RXCLEAR); // 清除通讯端口数据。
return;
}
ReadFile(hComm, inbuff,cs.cbInQue,&nBytesRead,NULL); //接收通讯端口的数据。
//数组中的字符串接尾处接上\0.
inbuff[cs.cbInQue]= '\0';
//将数组显示在MEMO1上。
mReceive->Text = inbuff;

}
//---------------------------------------------------------------------------
我这里有一个其他编程语言的API,不过API的编程几乎都一样,你参考一下!!
lljfl 2009-09-28
  • 打赏
  • 举报
回复 1
这是.NET的SerialPort类的一个bug吧,我以前也碰到过,在一般的台式电脑还可以,但在笔记本上最容易发生,建议不要用SerialPort,效率又低,还有这么大的一个bug,你最好用windowsAPI吧,我现在都改成用API了,受不了SerialPort,特别是在半双工高速通讯的时候
风之影子 2009-09-28
  • 打赏
  • 举报
回复
jhdxhj 2009-09-28
  • 打赏
  • 举报
回复
private SerialPort _com = new SerialPort();//串口对象
/// <summary>
/// 打开串口
/// </summary>
/// <param name="strCom">串口名“COM1” </param>
/// <param name="nBot">波特率 </param>
/// <param name="nThreshold">引发消息事件的字节数 </param>
public void OpenPort(string strCom, int nBot)
{
try
{
//串口设置与打开
//_com.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(DataReceivedAddress);
_com.PortName = strCom;
_com.BaudRate = nBot;
_com.DataBits = 8;
_com.StopBits = StopBits.One;
_com.Parity = Parity.Even;
_com.Open();
}
catch (Exception ex)
{
//Application.Exit();//退出应用程序
//System.Diagnostics.Process.Start("JT.exe");//启动程序
MessageBox.Show("“" + ex.Message + "”设置硬件功能将不可用,如要使用该功能,请到主窗体的系统设置中选择正确的串口信息,并重新打开该模块!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);

}

}
OpenPort(com1, 9600);
_com.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(DataReceivedAddress);
public void DataReceivedAddress(object sender, SerialDataReceivedEventArgs e)
{


byte[] data = new byte[_com.BytesToRead];
_com.Read(data, 0, data.Length);
if (data.Length != 0)
{

DisposeRecvDataAddress(data);

}
}
public void DisposeRecvDataAddress(byte[] data)
{
string strReceive = "";
//MessageBox.Show("进来了");
try
{
for (int i = 0; i < data.Length; i++)
{
strReceive += TenToHex(data[i].ToString());
//strReceive += data[i].ToString();
}
然后把接收到的数据按照协议来处理
}
灯火斑斓 2009-09-28
  • 打赏
  • 举报
回复
请参考下面的方法。
技术要点:
(1).首先,SerialPort的ReceivedBytesThreshold先设置成1,表示只要有1个字符送达端口时便触发DataReceived事件
(2).当DataReceived触发时,先把ReceivedBytesThreshold设置成一个比较大的值,达到读取本次端口数据时,不再触发DataReceived.
(3).循环读取端口中的数据,直至读完。
(4).移除读取数据中的非法字符。
(5).触发一个后台线程处理收到的数据。
(6).在finally中把ReceivedBytesThreshold重置回1

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
if (sender.GetType() != typeof(System.IO.Ports.SerialPort))
{
return;
}
string strReceive = string.Empty;
string strCollect = string.Empty;
System.IO.Ports.SerialPort comPort = (System.IO.Ports.SerialPort)sender;

try
{
comPort.ReceivedBytesThreshold = comPort.ReadBufferSize;
while (true)
{
strReceive = comPort.ReadExisting();
if (string.Equals(strReceive, string.Empty))
{
break;
}
else
{
strCollect += strReceive;
Application.DoEvents();
Thread.Sleep(100);
}
}
strCollect = strCollect.Replace("\0", string.Empty);
strCollect = strCollect.Replace("\r\n", string.Empty);
strCollect = strCollect.Replace("\r", string.Empty);
strCollect = strCollect.Replace("\n", string.Empty);

if (!this.bIsHandleCom)
{
this.bIsHandleCom = true;
mReceiveData = strCollect;
if (ReceiveDataParserEvent != null)
ReceiveDataParserEvent(mReceiveData);
if (ThreadReceiveParser != null && !ThreadReceiveParser.IsAlive)
{
ThreadReceiveParser.Start();
}
}

}
catch (Exception ex)
{
MessageBox.Show(this, ex.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
comPort.ReceivedBytesThreshold = 1;
}
}

110,533

社区成员

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

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

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