C# SerialPort串口通信中DataReceived事件不能触发

snailiest 2014-03-09 01:13:52
各位大神,我先描述下我的问题。
在一个自己编写的类(CCeSerialPort)中实例化了SerialPort,其他的串口配置什么的都操作了。


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;

using System.IO.Ports;

namespace test
{
public class CCeSerialPort
{
// private long received_count = 0; //接收计数
//private long send_count = 0; //发送计数

//串口通信需要使用的资源
private List<Byte> buffer = new List<byte>(1024);
public byte[] binary_data_buffer = null;

public SerialPort comport1 = new SerialPort();
//设备编号,实例化该类时必须给该属性初始化
public String deviceNumber;

//public event DataReceivedEventHandler DataReceived;

public CCeSerialPort()
{
RS232ComportInit();
comport1.DataReceived += new SerialDataReceivedEventHandler(comport_DataReceived);
}

//串口1的初始化
public void RS232ComportInit()
{
comport1.BaudRate = 9600;
comport1.DataBits = 8;
//comport1.StopBits = 0;
comport1.Parity = System.IO.Ports.Parity.None;
comport1.PortName = "COM1";
//读写超时
comport1.ReadTimeout = 500;
comport1.WriteTimeout = 500;
}
public void comport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// 具体内容就不说了。
}

}
}


然后在需要使用的窗体中对CCeSerialPort进行实例化。

问题来了:
单步执行过程中,我能监测到comport1.DataReceived += new SerialDataReceivedEventHandler(comport_DataReceived);语句正确执行,但是comport_DataReceived方法一直不能执行。
另外,发送数据是很流程的。

整体来说就是接收不到数据,但是发送数据正常。

一共就40分,全部奉上,谢谢大家。
...全文
1362 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
yinyi4120 2015-03-14
  • 打赏
  • 举报
回复
引用 15 楼 jsjrj01 的回复:
我遇到的问题是,有时候触发DataReceived 有时候不触发。。。。
我也是这个问题,最后怎么解决的?
别逗我乐 2014-12-19
  • 打赏
  • 举报
回复
我遇到的问题是,有时候触发DataReceived 有时候不触发。。。。
别逗我乐 2014-12-19
  • 打赏
  • 举报
回复
困惑的路过。。。。
snailiest 2014-03-14
  • 打赏
  • 举报
回复
引用 9 楼 yanran_hill 的回复:
同意8楼的说法,另外你在调用 comport1.DataReceived += new SerialDataReceivedEventHandler(comport_DataReceived); 的时候,没有看到对应的 comport1.DataReceived -= new SerialDataReceivedEventHandler(comport_DataReceived); 操作,是不需要吗?同样的我只看到了RS232ComportInit方法,是不是有必要再增加一个RS232ComportDispose方法呢?
谢谢提示。 我想知道为何要增加?谢谢。
snailiest 2014-03-14
  • 打赏
  • 举报
回复
引用 8 楼 wyd1520 的回复:
public CCeSerialPort() { RS232ComportInit(); comport1.DataReceived += new SerialDataReceivedEventHandler(comport_DataReceived); //. //this.comport1.DataReceived += new SerialDataReceivedEventHandler(comport1_DataReceived); } void comport1_DataReceived(object sender, SerialDataReceivedEventArgs e) { //throw new NotImplementedException(); } try { comport1.Open(); } catch (Exception ex) { comport1 = new SerialPort(); 这里你重新new后没有对事件进行绑定呀 System.Windows.Forms.MessageBox.Show(ex.Message); } 而你的事件是在构构函数里实现绑定的。。。
我也是在网上找的代码,说实话,也不是特别的清楚。第一次用串口。 问题我找到了,具体原因不清楚。 是这样的: 在主窗体中,实例化该类,其他窗体中也实例化该类,另外,在窗体之间传递这个类。 不知道为何,就是不行。 后来,我在主窗体中实例化这个类,其他窗体中定义这个类,但不实例化,只是在窗体切换时传递引用,其他代码都没动,然后就能收到数据了。 原因应该是对引用的处理上,为何引起的我不清楚原理。 说的特别的乱,主要是自己都快给搞晕了。
yanran_hill 2014-03-10
  • 打赏
  • 举报
回复
同意8楼的说法,另外你在调用 comport1.DataReceived += new SerialDataReceivedEventHandler(comport_DataReceived); 的时候,没有看到对应的 comport1.DataReceived -= new SerialDataReceivedEventHandler(comport_DataReceived); 操作,是不需要吗?同样的我只看到了RS232ComportInit方法,是不是有必要再增加一个RS232ComportDispose方法呢?
jiminlove 2014-03-10
  • 打赏
  • 举报
回复
先用程序发送数据,然后用串口调试助手接受数据看下数据是否有返回。针对8楼说的情况单步调试一下看下是否会跑到catch (Exception ex)里去!
defygravity 2014-03-10
  • 打赏
  • 举报
回复
是否真的有数据返回?看你这是上位机的通信程序。有能监控串口通信的软件。
本拉灯 2014-03-09
  • 打赏
  • 举报
回复
public CCeSerialPort() { RS232ComportInit(); comport1.DataReceived += new SerialDataReceivedEventHandler(comport_DataReceived); //. //this.comport1.DataReceived += new SerialDataReceivedEventHandler(comport1_DataReceived); } void comport1_DataReceived(object sender, SerialDataReceivedEventArgs e) { //throw new NotImplementedException(); } try { comport1.Open(); } catch (Exception ex) { comport1 = new SerialPort(); 这里你重新new后没有对事件进行绑定呀 System.Windows.Forms.MessageBox.Show(ex.Message); } 而你的事件是在构构函数里实现绑定的。。。
snailiest 2014-03-09
  • 打赏
  • 举报
回复
怎么没人关注呢?给个提示也好。 给了提示,只要找到原因就结贴。 谢谢大家了。
snailiest 2014-03-09
  • 打赏
  • 举报
回复
我把整个代码都贴出来,写的比较菜,见笑了。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;

using System.IO.Ports;

namespace test
{
    public class DataReceivedEventArgs : EventArgs
    {
        public string DataReceived;
        public DataReceivedEventArgs(string m_DataReceived)
        {
            this.DataReceived = m_DataReceived;
        }
    }

    public delegate void DataReceivedEventHandler(DataReceivedEventArgs e);

    public class CCeSerialPort
    {
        // private long received_count = 0;    //接收计数
        //private long send_count = 0;        //发送计数

        //串口通信需要使用的资源
        private List<Byte> buffer = new List<byte>(1024);
        public byte[] binary_data_buffer = null;

        public SerialPort comport1 = new SerialPort();
        //设备编号,实例化该类时必须给该属性初始化
        public String deviceNumber;

        //public event DataReceivedEventHandler DataReceived;

        public CCeSerialPort()
        {
            RS232ComportInit();
            comport1.DataReceived += new SerialDataReceivedEventHandler(comport_DataReceived);
            //this.comport1.DataReceived += new SerialDataReceivedEventHandler(comport1_DataReceived);

        }

        void comport1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            //throw new NotImplementedException();
        }

        //串口1的初始化
        public void RS232ComportInit()
        {
            comport1.BaudRate = 9600;
            comport1.DataBits = 8;
            //comport1.StopBits = 0;
            comport1.Parity = System.IO.Ports.Parity.None;    //设置奇偶校验位,默认为None
            comport1.PortName = "COM1";
            //读写超时
            comport1.ReadTimeout = 500;
            comport1.WriteTimeout = 500;

            //comport1.DataReceived += new SerialDataReceivedEventHandler(comport_DataReceived);
        }

        public void comport_open()
        {
            try
            {
                comport1.Open();
            }
            catch (Exception ex)
            {
                comport1 = new SerialPort();
                System.Windows.Forms.MessageBox.Show(ex.Message);
            }
        }

        public void comport_close()
        {
            if (comport1.IsOpen)
                comport1.Close();
        }
        //发送函数
        //暂时用不到,先放着
        public void send_Data(string str)
        {
            //先生成命令,再发送
            string command = Data_Frame_Makeup(str, deviceNumber);
            byte[] byteCommand = HexStringToByteArray(command);
            if (!comport1.IsOpen) comport1.Open();
            //comport1.Write(command); 
            //comport1.Write("1112223A1");
            comport1.Write(byteCommand, 0, byteCommand.Length);
        }

        //数据格式转换
        //字符串——》16进制字节
        public byte[] HexStringToByteArray(string s)
        {
            //s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            return buffer;
        }
        //16进制字节——》字符串
        public 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();
        }

        //累加和校验
        public static byte checksum(byte[] array, int Len)
        {
            byte check_sum = 0;
            int i = 0;
            for (i = 0; i < Len; i++)
            {
                check_sum += array[i];
            }
            return check_sum;
        }
        //生成发送数据
        public string Data_Frame_Makeup(string data, string sn)
        {
            //string str = ByteArrayToHexString(HexStringToByteArray(data.Length.ToString()));
            //string str

            //string str = System.Text.Encoding.ASCII.GetString(System.Text.Encoding.Default.GetBytes(data), 0, 1);
            //byte[] bytStr = System.Text.Encoding.Default.GetBytes(data.Length.ToString().PadLeft(2,'0'));

            //string str = System.Text.Encoding.ASCII.GetString(bytStr, 0, 1);
            byte[] bytStr = HexStringToByteArray((data.Length / 2 + 4).ToString().PadLeft(2, '0'));
            string str = ByteArrayToHexString(bytStr).Trim();

            string strCommand = "79" + sn + str + data;
            //strCommand += data;


            //int dataLength = data.Length/2 + 1;
            byte tempCheckSum = checksum(HexStringToByteArray(strCommand), strCommand.Length / 2);
            //if (0 == tempCheckSum)
            //{
            //    strCommand += "00";
            //}
            //else
            //{
            //    strCommand += Convert.ToString(tempCheckSum, 16);
            //}
            strCommand += Convert.ToString(tempCheckSum, 16).PadLeft(2, '0').Trim();
            //strCommand += tempCheckSum.ToString().PadLeft(2, '0').Trim();
            return strCommand;
        }

        public void comport_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            int temp = comport1.BytesToRead;         //先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致
            byte[] buf = new byte[temp];             //声明一个临时数组存储当前来的串口数据
            comport1.Read(buf, 0, temp);             //读取缓冲数据
            buffer.AddRange(buf);                    //缓存数据
            bool data_Catch = false;                 //缓存数据是否捕获
            //协议解析
            while (buffer.Count >= 5)                //完整性检查--->至少要包含头(1字节)+ 设备编号(2字节)+长度(1字节)+校验(1字节)
            {
                if ((0x79 == buffer[0]) & (deviceNumber == (buffer[1].ToString("X2") + buffer[2].ToString("X2"))))             //查找数据头0x79,不是则执行else语句
                {
                    int dataLength = buffer[3];                         //获取数据长度
                    binary_data_buffer = new byte[dataLength + 1];
                    if (buffer.Count < dataLength + 1)                  //数据长度判断
                        break;                                          //  如果数据不够时,什么都不做

                    buffer.CopyTo(0, binary_data_buffer, 0, dataLength + 1);
                    //确保数据长度足够,数据头标志找到,开始计算校验
                    byte sum_temp = checksum(binary_data_buffer, dataLength);
                    if (sum_temp != (binary_data_buffer[dataLength]))   //如果校验失败,将binary_data_buffer清空
                    {
                        //binary_data_buffer = null;
                        buffer.RemoveRange(0, dataLength + 1);
                        continue;
                    }

                    data_Catch = true;                                  //将标志置位,说明数据读到完整的正确数据

                    buffer.RemoveRange(0, dataLength + 1);              //正确分析到一条数据,从缓存中移除数据
                }
                else
                {
                    buffer.RemoveAt(0);     //如果数据开始不是头,则删除数据
                }
                //解析数据
                if (data_Catch)
                {
                    string data = binary_data_buffer[4].ToString("X2");

                    if (data == "11")
                    {
                        //this.data_class._fuYang = binary_data_buffer[4].ToString("X2") + "." + binary_data_buffer[5].ToString("X2") + binary_data_buffer[6].ToString("X2");
                        ////this.data_class._hengGun = binary_data_buffer[6].ToString("X2") + "." + binary_data_buffer[7].ToString("X2") + binary_data_buffer[8].ToString("X2");
                        //this.data_class._fangWei = binary_data_buffer[7].ToString("X2") + "." + binary_data_buffer[8].ToString("X2") + binary_data_buffer[9].ToString("X2");
                        //UpdateReceiveTextBox(lbl1, this.data_class._fuYang);
                        ////UpdateReceiveTextBox(lbl2, this.data_class._hengGun);
                        //UpdateReceiveTextBox(lbl3, this.data_class._fangWei);
                    }
                    if (data == "33")
                    {
                        //this.data_class._jingDu = binary_data_buffer[3].ToString("X2") + binary_data_buffer[4].ToString("X2") + "." + binary_data_buffer[5].ToString("X2") + binary_data_buffer[6].ToString("X2");
                        //this.data_class._weiDu = binary_data_buffer[7].ToString("X2") + binary_data_buffer[8].ToString("X2") + "." + binary_data_buffer[9].ToString("X2") + binary_data_buffer[10].ToString("X2");
                        //UpdateReceiveTextBox(lbl6, "N:" + this._jingDu);
                        //UpdateReceiveTextBox(lbl8, "S:" + this._weiDu);
                    }
                }
            }//end while            

            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


            //已调试通过
            //***************************************
            //int bytes = comport1.BytesToRead;

            //byte[] buffer = new byte[bytes];

            //comport1.Read(buffer, 0, bytes);

            //string data = ByteArrayToHexString(buffer);
            //// Display the text to the user in the terminal
            //UpdateReceiveTextBox(data);
            // *****************************************/
        }

    }
}

snailiest 2014-03-09
  • 打赏
  • 举报
回复
每次实例化CCeSerialPort的时候我就进行了comport1.Open()操作
snailiest 2014-03-09
  • 打赏
  • 举报
回复
引用 1 楼 snailiest 的回复:
补充说明一下,如果在窗体中,直接实例化SerialPort类,按照上边的用法,我是能接受到数据的。 但这样的话,我每个需要使用到串口通信的窗体都要做好多重复代码,貌似不应该这样用吧?后来才按照上边的做法写的代码。
我打开过了。发帖时把那段代码删除了。
51Crack 2014-03-09
  • 打赏
  • 举报
回复
没见到comport1.Open
snailiest 2014-03-09
  • 打赏
  • 举报
回复
补充说明一下,如果在窗体中,直接实例化SerialPort类,按照上边的用法,我是能接受到数据的。 但这样的话,我每个需要使用到串口通信的窗体都要做好多重复代码,貌似不应该这样用吧?后来才按照上边的做法写的代码。

110,535

社区成员

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

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

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