C#串口通信从缓存中取出的数据的问题

qinghecool 2012-12-17 03:36:17
本人用C#刚接触串口通信不久,在网上找了一些串口通信的资料,按照资料中的讲解做了个串口通信程序,但是在和下位机通信的时候接收到的数据总是不对,不知道是什么原因,哪位懂C#串口通信的大侠能指点下吗?
正确的数据格式应该是这样的:F0 55 AA 04 07 0D 01 00 02 00 03 00 04 0D 00 0F 00 13 00 04 00 14 00 98 00 03 00 0B 00 83 00 7C 00 07 00 7F 00 80 00 88 9C 9C 但是不知道为什么我用程序中的代码接收到的数据格式却是这样的:AA AA 00 00 00 00 00 00 00 AA AA 04 04 04 0F 00 00 00 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 。哪位大侠能告诉我问题出在哪里吗?
下面是我的发送程序的代码:
//处理数字转换,目的是将输入的字符按空格、“,”等分组,以便发送数据时的方便(此处转的比较麻烦,有高见者,请指点!)
comm.RtsEnable = true;
//comm.Parity = Parity.Mark;
Thread.Sleep(2);
// comm.Parity = Parity.Mark;




byte[] byteBuffer2 = new byte[9];
byteBuffer2[0] = 0xaa;
byteBuffer2[1] = 0xaa;
byteBuffer2[2] = 0x04;
byteBuffer2[3] = 0x04;
byteBuffer2[4] = 0x04;
byteBuffer2[5] = 0x0f;
byteBuffer2[6] = 0x00;
byteBuffer2[7] = 0x00;
byteBuffer2[8] = 0x00;

String strSend2 = byteBuffer2[0].ToString("X2") + " " + byteBuffer2[1].ToString("X2") + " " + byteBuffer2[2].ToString("X2") + " " + byteBuffer2[3].ToString("X2") + " " + byteBuffer2[4].ToString("X2") + " " +
byteBuffer2[5].ToString("X2") + " " + byteBuffer2[6].ToString("X2") + " " + byteBuffer2[7].ToString("X2") + " " + byteBuffer2[8].ToString("X2");

string sendBuf2 = strSend2;
string sendnoNull2 = sendBuf2.Trim();
string sendNOComma6 = sendnoNull2.Replace(',', ' '); //去掉英文逗号
string sendNOComma7 = sendNOComma6.Replace(',', ' '); //去掉中文逗号
string strSendNoComma8 = sendNOComma7.Replace("0x", ""); //去掉0x
strSendNoComma8.Replace("0X", ""); //去掉0X
string[] strArray2 = strSendNoComma8.Split(' ');

List<byte> buf2 = new List<byte>();//填充到这个临时列表中
//依次添加到列表中
int byteBufferLength2 = strArray2.Length;
for (int i = 0; i < strArray2.Length; i++)
{
byte str2 = byte.Parse(strArray2[i].ToString(), System.Globalization.NumberStyles.HexNumber);
buf2.Add(str2);

}

//转换列表为数组后发送

comm.Write(buf2.ToArray(), 0, buf2.Count);
Thread.Sleep(60);

comm.RtsEnable = false;
//Thread.Sleep(16);
comm.Parity = Parity.Mark;

接收部分的代码如下
void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
{

//更新界面
//this.Invoke((EventHandler)(delegate { richTextBox1.Text = ""; }));
//buffer.RemoveAt(0);
Thread.Sleep(500);//此处一定要有,休眠一段 时间利用缓存来接收数据,经测试75秒刚好
if (Closing) return;//如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环
try
{
Listening = true;//设置标记,说明我已经开始处理数据,一会儿要使用系统UI的。
int n = comm.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致
byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据
received_count = n;//增加接收计数
//richTextBox3.Text = received_count.ToString();
//MessageBox.Show(received_count.ToString());
comm.Read(buf, 0, n);//读取缓冲数据
builder.Length=0;//清除字符串构造器的内容

//<协议解析>
bool data_1_catched = false;//缓存记录数据是否捕获到
buffer.AddRange(buf);
if (buffer.Count >=9)
{
string data,data1;
data = "";
data1 = "";
//MessageBox.Show(buf[8].ToString("X2"));
for (int i = 0; i < n; i++)
{
data1 += buffer[i].ToString("X2") + " ";
data += buf[i].ToString("X2") + " ";
// data = n.ToString();
}
//更新界面
this.Invoke((EventHandler)(delegate { richTextBox4.Text = data; }));
this.Invoke((EventHandler)(delegate { richTextBox3.Text = data; }));
//因为要访问ui资源,所以需要使用invoke方式同步ui。
this.Invoke((EventHandler)(delegate
{
//判断是否是显示为16禁止
if (checkBox3.Checked)
{
//依次的拼接出16进制字符串
foreach (byte b in buf)
{
builder.Append(b.ToString("X2") + " ");
}
}
else
{
//直接按ASCII规则转换成字符串
builder.Append(Encoding.ASCII.GetString(buf));
}
//追加的形式添加到文本框末端,并滚动到最后。
richTextBox1.AppendText(builder.ToString());
// richTextBox1.Text=builder.ToString();
//修改接收计数
//labelGetCount.Text = "Get:" + received_count.ToString();
}));

}



}
finally
{
Listening = false;//我用完了,ui可以关闭串口了。
}

}
...全文
2392 59 打赏 收藏 转发到动态 举报
写回复
用AI写文章
59 条回复
切换为时间正序
请发表友善的回复…
发表回复
qinghecool 2013-03-26
  • 打赏
  • 举报
回复
哈哈,今天终于把这个问题解决了,高兴哈,非常感谢各位给出的回复,谢谢大家了哈。 原来是我们的该死的下位机程序在那做怪,发现我们的下位机是这样设置的:串口程序在向下位机下发数据之前要先设置为MARK验证,数据发送完以后在接收的时候要设置为NONE验证,真是坑人啊!还好,终于把问题解决了,哈哈,今天心情真是好啊
qinghecool 2013-01-18
  • 打赏
  • 举报
回复
没有解决哦。。。。。。正在这郁闷呢。。。。
skevil 2013-01-17
  • 打赏
  • 举报
回复
用串口助手看看嘛,要是串口助手那边都显示不正常的话,那就是你发送端的问题啦,发送端有问题,c#这边怎么改都没用咧。。。
qinghecool 2013-01-17
  • 打赏
  • 举报
回复
应该不是吧?3F我感觉是编码出错了,可能是解析有问题
open382000 2013-01-17
  • 打赏
  • 举报
回复
是不是循环写的多了 给死机了。。
qinghecool 2013-01-17
  • 打赏
  • 举报
回复
哪位大侠来指点指点下啊,江湖救急啊!小弟我将万分感激啊!
leafmao 2013-01-17
  • 打赏
  • 举报
回复
一个月过去了,楼主的问题还没解决吗。。。。
qinghecool 2013-01-04
  • 打赏
  • 举报
回复
引用 51 楼 leafmao 的回复:
引用 50 楼 leafmao 的回复:引用 48 楼 qinghecool 的回复:引用 45 楼 leafmao 的回复:引用 44 楼 qinghecool 的回复:串口服务器是那种工业上使用的把232信号和485信号互相转换的设备,一般我们的电脑发送的是232的信号,我的下位机是485通信的,需要把232信号转换成485信号通信,串口服务器的作用主要就是一端和电脑……
串口服务器解析出来的 数据是和发送的数据一样的,串口服务器解析数据也是后台处理的,我们是看不到它的处理逻辑的
leafmao 2012-12-28
  • 打赏
  • 举报
回复
引用 34 楼 qinghecool 的回复:
引用 33 楼 leafmao 的回复:楼主你读取串口的代码呢?这样buf是空的呀 C# code?12345678910int n = comm.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致 byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据 ……
你的3F是在哪里出现的?这是重点呀,是显示的时候? comm.Read(buf, 0, n);在这设置一个断点,然后用监视窗口查看buf里的数据
qinghecool 2012-12-28
  • 打赏
  • 举报
回复
引用 33 楼 leafmao 的回复:
楼主你读取串口的代码呢?这样buf是空的呀 C# code?12345678910int n = comm.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致 byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据 rec……
上面的代码我少复制了一行,我程序中的代码是这样的
             int n = comm.BytesToRead;
                byte[] buf = new byte[n];
                received_count = n;//增加接收计数  
             
                comm.Read(buf, 0, n);//读取缓冲数据 
leafmao 2012-12-28
  • 打赏
  • 举报
回复
楼主你读取串口的代码呢?这样buf是空的呀

int n = comm.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致  
                byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据  
                received_count = n;//增加接收计数  
              
 
                builder.Length=0;//清除字符串构造器的内容  
 
                //<协议解析>  
                bool data_1_catched = false;//缓存记录数据是否捕获到 
                buffer.AddRange(buf);
leafmao 2012-12-28
  • 打赏
  • 举报
回复
那么,楼主的3F是出现在哪里的呢?显示的时候出现的都是3F?
qinghecool 2012-12-28
  • 打赏
  • 举报
回复
引用 30 楼 leafmao 的回复:
引用 29 楼 qinghecool 的回复:引用 27 楼 leafmao 的回复:引用 26 楼 qinghecool 的回复:引用 25 楼 junzhang4008 的回复:你用的是usb转串口线吧。。。可能不稳定原因。usb转的不太稳定。 [/code] 你可以用这个测试一下: 你用两个com,中间接个转接线。COM1发送,COM2接受。看看发过去之后,回来的是……
下面是发送数据的代码:
 private void button1_Click(object sender, EventArgs e)
        {


            int n = 0;
            comm.Encoding = System.Text.Encoding.Unicode;
       
            //16进制发送  
            if (checkBox1.Checked)
            {
                
                //处理数字转换,目的是将输入的字符按空格、“,”等分组,以便发送数据时的方便(此处转的比较麻烦,有高见者,请指点!)  
                
                comm.RtsEnable = true;
          
                Thread.Sleep(2);
                comm.Parity = Parity.Mark;

                //转换列表为数组后发送  
                byte[] send1 = { 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
                comm.Write(send1, 0, send1.Length);
           
                Thread.Sleep(50);

                comm.RtsEnable = false;
               
                Thread.Sleep(2);
                comm.Parity = Parity.Mark;
               
                
                //处理数字转换,目的是将输入的字符按空格、“,”等分组,以便发送数据时的方便(此处转的比较麻烦,有高见者,请指点!)  
                comm.RtsEnable = true;
               
                Thread.Sleep(2);
                comm.Parity = Parity.Mark;

                //转换列表为数组后发送
                byte[] send2 = { 0xaa, 0xaa, 0x01, 0x01, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00 };
                comm.Write(send2, 0, send2.Length);
               
                Thread.Sleep(50);
            

                comm.RtsEnable = false;
                Thread.Sleep(10);

                comm.Parity = Parity.Mark;
                
            }
            else//ascii编码直接发送  
            {
                //包含换行符  
                if (checkBox2.Checked)
                {
                    comm.WriteLine(richTextBox2.Text);
                   // n = txSend.Text.Length + 2;
                }
                else//不包含换行符  
                {
                    comm.Write(richTextBox2.Text);
                    //n = txSend.Text.Length;
                }
            }
        }
下面是我的接收代码
  void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
          
            comm.Parity = Parity.Mark;
            comm = (SerialPort)sender;
            string s100 = "";
            Thread.Sleep(500);//此处一定要有,休眠一段 时间利用缓存来接收数据,经测试75秒刚好
            if (Closing) return;//如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环  
            try
            {
                Listening = true;//设置标记,说明我已经开始处理数据,一会儿要使用系统UI的。  

                int n = comm.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致  
                byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据  
                received_count = n;//增加接收计数  
             

                builder.Length=0;//清除字符串构造器的内容  

                //<协议解析>  
                bool data_1_catched = false;//缓存记录数据是否捕获到 
                buffer.AddRange(buf);
                if (buffer.Count >=9)
                {
                    string data,data1;
                    data = "";
                    data1 = "";
                    //MessageBox.Show(buf[8].ToString("X2"));
                    for (int i = 0; i < n; i++)
                    {
                        data1 += Convert.ToString(buf[i],16);
                        data += buf[i].ToString("X2") + " ";
                       // data = n.ToString();
                    }
                    //更新界面  
                    this.Invoke((EventHandler)(delegate { richTextBox4.Text = data; }));
                    this.Invoke((EventHandler)(delegate { richTextBox3.Text = data; }));

                  
                    //因为要访问ui资源,所以需要使用invoke方式同步ui。  
                    this.Invoke((EventHandler)(delegate
                    {
                        //判断是否是显示为16禁止  
                        if (checkBox3.Checked)
                        {
                            //依次的拼接出16进制字符串  
                            foreach (byte b in buf)
                            {
                                builder.Append(b.ToString("X2") + " ");
                            }
                        }
                        else
                        {
                            //直接按ASCII规则转换成字符串  
                            builder.Append(Encoding.ASCII.GetString(buf));
                        }
                        //追加的形式添加到文本框末端,并滚动到最后。  
                        richTextBox1.AppendText(builder.ToString());
                        comm.DiscardInBuffer();
                  
                    }));  
                
                }
                 
                
                
            }
            finally
            {
                Listening = false;//我用完了,ui可以关闭串口了。  
            }  

        }
//转换列表为数组后发送 通讯协议是这样的:软件先向下位机下发0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 这几个数据,说明我要开始下发数据了,然后再下发0xaa, 0xaa, 0x01, 0x01, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00说明这是我下发的指令,下位机接收到了0xaa, 0xaa, 0x01, 0x01, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00指令以后会回传数据,
leafmao 2012-12-28
  • 打赏
  • 举报
回复
引用 29 楼 qinghecool 的回复:
引用 27 楼 leafmao 的回复:引用 26 楼 qinghecool 的回复:引用 25 楼 junzhang4008 的回复:你用的是usb转串口线吧。。。可能不稳定原因。usb转的不太稳定。 你可以用这个测试一下: 你用两个com,中间接个转接线。COM1发送,COM2接受。看看发过去之后,回来的是不是原来的(自己发自己收)如果不是,很有可能是……
把你的解析代码贴出来看看,通讯协议是怎么定的? 干脆你代码里先什么都别做,就一个接收的程序,然后断点调试,看接收到的数据时什么
qinghecool 2012-12-28
  • 打赏
  • 举报
回复
引用 27 楼 leafmao 的回复:
引用 26 楼 qinghecool 的回复:引用 25 楼 junzhang4008 的回复:你用的是usb转串口线吧。。。可能不稳定原因。usb转的不太稳定。 你可以用这个测试一下: 你用两个com,中间接个转接线。COM1发送,COM2接受。看看发过去之后,回来的是不是原来的(自己发自己收)如果不是,很有可能是usb转串口线不稳定造成的。 原来……
我觉得还是程序在解析数据的时候出问题了,因为我在这是这样做测试的:我用我做的这个程序向下位机下发数据,下位机接收到数据以后同时向电脑和串口服务器回传数据,但是串口服务器接收到数据以后解析出来是正确的数据,而电脑接收到数据以后我用程序解析出来的数据就全是3F!向这种情况我觉得还是数据解析出了问题,
qinghecool 2012-12-28
  • 打赏
  • 举报
回复
引用 27 楼 leafmao 的回复:
引用 26 楼 qinghecool 的回复:引用 25 楼 junzhang4008 的回复:你用的是usb转串口线吧。。。可能不稳定原因。usb转的不太稳定。 你可以用这个测试一下: 你用两个com,中间接个转接线。COM1发送,COM2接受。看看发过去之后,回来的是不是原来的(自己发自己收)如果不是,很有可能是usb转串口线不稳定造成的。 原来……
我觉得还是接收到的数据的解析有问题,因为我在这用我的程序向下位机下发数据,下位机收到数据后同时向电脑和我买的串口服务器回传数据,但是串口服务器接收到数据以后解析出来是正确的数据,但是我用电脑程序接收数据以后解析出来就全部是3F,这种情况应该是数据解析方面出问题了吧?
leafmao 2012-12-28
  • 打赏
  • 举报
回复
引用 50 楼 leafmao 的回复:
引用 48 楼 qinghecool 的回复:引用 45 楼 leafmao 的回复:引用 44 楼 qinghecool 的回复:串口服务器是那种工业上使用的把232信号和485信号互相转换的设备,一般我们的电脑发送的是232的信号,我的下位机是485通信的,需要把232信号转换成485信号通信,串口服务器的作用主要就是一端和电脑直接用TCP/IP通信(通过在电脑上虚拟……
还缺少个环节,串口服务器跟单片机连接的那端,如果跟电脑连的话,要用个串口转换器,把232转成485,这样这台电脑就相当于单片机的作用了。发送数据,看数据是否有变化,这样能看出串口服务器都做了些什么。 电脑—RS232转成485的串口转换器—串口服务器—电脑;这样可以把左侧的电脑看成单片机
leafmao 2012-12-28
  • 打赏
  • 举报
回复
引用 48 楼 qinghecool 的回复:
引用 45 楼 leafmao 的回复:引用 44 楼 qinghecool 的回复:串口服务器是那种工业上使用的把232信号和485信号互相转换的设备,一般我们的电脑发送的是232的信号,我的下位机是485通信的,需要把232信号转换成485信号通信,串口服务器的作用主要就是一端和电脑直接用TCP/IP通信(通过在电脑上虚拟一个串口来实现的),另外一端和下位机用485通……
你试试这样,将两台电脑通过你买的串口服务器连接起来,看发送的数据经过串口服务器后有什么变化。
leafmao 2012-12-28
  • 打赏
  • 举报
回复
“串口服务器的作用主要就是一端和电脑直接用TCP/IP通信(通过在电脑上虚拟一个串口来实现的)” 看来问题在这,下位机发送数据用的是TCP/IP协议(这个协议我就不懂啦- -) 你的下位机对数据进行了处理,也许是按照TCP/IP协议,通过你的串口服务器可以还原真实数据。但是通过串口转换器得到的数据只是下位机经过处理后的。 你的这个串口服务器是和单片机一起提供的吗?这两个是由同个厂商提供的? 楼主是不是想以后不买串口服务器就可以直接从单片机接收数据呀
qinghecool 2012-12-28
  • 打赏
  • 举报
回复
引用 45 楼 leafmao 的回复:
引用 44 楼 qinghecool 的回复:串口服务器是那种工业上使用的把232信号和485信号互相转换的设备,一般我们的电脑发送的是232的信号,我的下位机是485通信的,需要把232信号转换成485信号通信,串口服务器的作用主要就是一端和电脑直接用TCP/IP通信(通过在电脑上虚拟一个串口来实现的),另外一端和下位机用485通信。 既然下位机是485的通信方式……
我把我的测试情况跟你详细说下吧:我用我电脑连接我们的接口(也就是转换器),接口再连接下位机,下位机的数据线同时连接到我们的接口和串口服务器上去(串口服务器只接收数据,我们的接口通过软件下发数据并接收数据),串口服务器接收数据以后用串口调试助手显示接收到的数据,而我的软件通过接口接收到数据以后再解析数据,但是现在是用串口调试助手用串口服务器接收到的数据是正常的,用我做的这个程序通过接口接收到的数据是错误的,如果是我用我做的这个程序连接串口服务器下发数据接收到的数据也是正常的,我用我们公司之前的软件通过我们的接口接收数据也是正常的。。。。。所以现在比较困惑问题究竟出在哪里。。。。。
加载更多回复(39)

110,567

社区成员

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

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

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