C# 多串口通信的诡异问题。请大神帮我分析分析。

yinyi4120 2014-08-24 04:24:22
工控机通过多串口卡接收串口数据。
总共接收六个串口数据。其中,COM1---COM4接收数据的协议时一样的,共10个byte位。前8位为数据位,第9位为CRC校验位,第10位位停止位,FF。
而COM5---COM6接收的数据协议时一样的,共8个byte位,前6位位数据位,第7位为CRC校验位,第8位为停止位,FF。
数据接收采用事件触发形式。具体实现代码如下。

public void _serialPort_DataReceived_JZ(object sender, SerialDataReceivedEventArgs e)
{
//禁止接收事件时直接退出
if (ReceiveEventFlag)
{
return;
}
try
{
string readstr = null;
int n = _serialPort.BytesToRead;
byte[] buff = new byte[n];
_serialPort.Read(buff, 0, n);
readstr = ConvertByteArrayToString(buff);
buffer_JZ.AddRange(strToToHexByte(readstr));
while ((buffer_JZ.Count >= 10) && (buffer_JZ[9] == 255))
{

if (buffer_JZ[8] != CRC_CHECK(strToToHexByte(readstr), 8))
{
buffer_JZ.RemoveAt(0);
continue;
}
buffer_JZ.CopyTo(0, binary_data_1, 0, 10);
DataReceived(sender, e, binary_data_1);
buffer_JZ.RemoveRange(0, 10);

}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}

这是COM1---COM4的接收函数

void _serialPort_DataReceived_LG(object sender, SerialDataReceivedEventArgs e)
{

//禁止接收事件时直接退出
if (ReceiveEventFlag)
{
return;
}
try
{
string readstr = null;
int n = _serialPort.BytesToRead;
byte[] buff = new byte[n];
_serialPort.Read(buff, 0, n);
readstr = ConvertByteArrayToString(buff);
buffer_LG.AddRange(strToToHexByte(readstr));
while ((buffer_LG.Count >= 8) && (buffer_LG[7] == 255))
{

if (buffer_LG[6] != CRC_CHECK(strToToHexByte(readstr), 6))
{
buffer_LG.RemoveAt(0);
continue;
}
buffer_LG.CopyTo(0, binary_data_1, 0, 8);
DataReceived(sender, e, binary_data_2);
buffer_LG.RemoveRange(0, 8);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
// throw ex;
}
}

这是COM5---COM6的接收函数。
在主窗体的代码如下:

JZ_RecePort1.openPort();
JZ_RecePort2.openPort();
JZ_RecePort3.openPort();
JZ_RecePort4.openPort();
LG_RecePort1.openPort();
LG_RecePort2.openPort();

// 接收响应事件
LG_RecePort1.DataReceived += new Port_Opera.SerialPortDataReceiveEventArgs(LG_RecePort1_DataReceived_LG);
LG_RecePort2.DataReceived += new Port_Opera.SerialPortDataReceiveEventArgs(LG_RecePort2_DataReceived_LG);
JZ_RecePort1.DataReceived += new Port_Opera.SerialPortDataReceiveEventArgs(JZ_RecePort1_DataReceived_JZ);
JZ_RecePort2.DataReceived += new Port_Opera.SerialPortDataReceiveEventArgs(JZ_RecePort2_DataReceived_JZ);
JZ_RecePort3.DataReceived += new Port_Opera.SerialPortDataReceiveEventArgs(JZ_RecePort3_DataReceived_JZ);
JZ_RecePort4.DataReceived += new Port_Opera.SerialPortDataReceiveEventArgs(JZ_RecePort4_DataReceived_JZ);


接收响应

public void JZ_RecePort1_DataReceived_JZ(object sender, SerialDataReceivedEventArgs e, byte[] bits)
{
//判断数据来自哪片CPU
if ((bits[0] & 0x01) == 0)
{
db_opera.Save_CPU_data(bits, "Table_CPU1_1", Rece_DataSet);
}
else
{
db_opera.Save_CPU_data(bits, "Table_CPU1_2", Rece_DataSet);
}
}
public void JZ_RecePort3_DataReceived_JZ(object sender, SerialDataReceivedEventArgs e, byte[] bits)
{
if ((bits[0] & 0x01) == 0)
{
db_opera.Save_CPU_data(bits, "Table_CPU3_1", Rece_DataSet);

}
else
{
db_opera.Save_CPU_data(bits, "Table_CPU3_2", Rece_DataSet);
}
}
public void LG_RecePort1_DataReceived_LG(object sender, SerialDataReceivedEventArgs e, byte[] bits)
{
if ((bits[0] & 0x01) == 0)
{
db_opera.Save_LG_data(bits, "Table_LG1_1", Rece_DataSet);

}
else
{
db_opera.Save_LG_data(bits, "Table_LG1_2", Rece_DataSet);
}
}
public void LG_RecePort2_DataReceived_LG(object sender, SerialDataReceivedEventArgs e, byte[] bits)
{
if ((bits[0] & 0x01) == 0)
{
db_opera.Save_LG_data(bits, "Table_LG2_1", Rece_DataSet);
}
else
{
db_opera.Save_LG_data(bits, "Table_LG2_2", Rece_DataSet);
}
} // 串口COM1---COM6接收数据

现在的问题是,COM1---COM4能正确接收数据,而COM5---COM6的事件无法触发,或者有时候接收到COM5,或者COM6,反正COM5与COM6数据不能同时接收上来。
且有时候接收COM1---COM4的函数会接收到COM5---COM6的数据。
求大神帮我看看。感激不尽。



...全文
256 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
於黾 2014-08-25
  • 打赏
  • 举报
回复
绑定的事件函数和贴出来的函数名称都不一样啊
rtdb 2014-08-25
  • 打赏
  • 举报
回复
while ((buffer_JZ.Count >= 10) && (buffer_JZ[9] == 255)) 你这句明显只对10个bytes生效,那COM5---COM6的8bytes就进不去了
yinyi4120 2014-08-25
  • 打赏
  • 举报
回复
引用 7 楼 Z65443344 的回复:
_serialPort_DataReceived_JZ _serialPort_DataReceived_LG 这两个又是干嘛的,在哪里调用了? 这明显是2个事件,但是没有挂在任何控件下啊.
这连个事件时在串口类中定义的。代码如下


        SerialPort _serialPort = null;
        //定义委托
        public delegate void SerialPortDataReceiveEventArgs(object sender, SerialDataReceivedEventArgs e, byte[] bits);
        //定义接收数据事件
        public event SerialPortDataReceiveEventArgs DataReceived;

        public void _serialPort_DataReceived_LG(object sender, SerialDataReceivedEventArgs e)
        {
            //禁止接收事件时直接退出
            if (ReceiveEventFlag)
            {
                return;
            }
            try
            {
                string readstr = null;
                int n = _serialPort.BytesToRead;
                byte[] buff = new byte[n];
                Console.WriteLine("ok_lg");
                _serialPort.Read(buff, 0, n);
                readstr = ConvertByteArrayToString(buff);
                Console.WriteLine(readstr);
                buffer_LG.AddRange(strToToHexByte(readstr));
                while ((buffer_LG.Count >= 8) && (buffer_LG[7] == 255))
                {

                    if (buffer_LG[6] != CRC_CHECK(strToToHexByte(readstr), 6))
                    {
                        buffer_LG.RemoveAt(0);
                        continue;
                    }
                    buffer_LG.CopyTo(0, binary_data_2, 0, 8);
                    DataReceived(sender, e, binary_data_2);
                    buffer_LG.RemoveRange(0, 8);                    
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
        #endregion
        #region 接收逻辑单元串口数据事件
        /// <summary>
        /// 接收逻辑单元串口数据事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _serialPort_DataReceived_JZ(object sender, SerialDataReceivedEventArgs e)
        {
            
            //禁止接收事件时直接退出
            if (ReceiveEventFlag)
            {                
                return;
            }
            try
            {
                string readstr = null;
                int n = _serialPort.BytesToRead;
                byte[] buff = new byte[n];
                _serialPort.Read(buff, 0, n);
                Console.WriteLine("OK");
                readstr = ConvertByteArrayToString(buff);
                Console.WriteLine(readstr+"\t\n");
                buffer_JZ.AddRange(strToToHexByte(readstr));
                while ((buffer_JZ.Count >= 10) && (buffer_JZ[9] == 255))
                {

                    if (buffer_JZ[8] != CRC_CHECK(strToToHexByte(readstr), 8))
                    {
                        buffer_JZ.RemoveAt(0);
                        continue;
                    }
                    buffer_JZ.CopyTo(0, binary_data_1, 0, 10);
                    DataReceived(sender, e, binary_data_1);
                    buffer_JZ.RemoveRange(0, 10);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
               // throw ex;
            }
        }
上面两个事件是在串口类中,在主函数中实例化类的对象
於黾 2014-08-25
  • 打赏
  • 举报
回复
_serialPort_DataReceived_JZ _serialPort_DataReceived_LG 这两个又是干嘛的,在哪里调用了? 这明显是2个事件,但是没有挂在任何控件下啊.
yinyi4120 2014-08-25
  • 打赏
  • 举报
回复
引用 4 楼 Z65443344 的回复:
绑定的事件函数和贴出来的函数名称都不一样啊
是一样的。

 public void JZ_RecePort1_DataReceived_JZ(object sender, SerialDataReceivedEventArgs e, byte[] bits)
 public void JZ_RecePort2_DataReceived_JZ(object sender, SerialDataReceivedEventArgs e, byte[] bits)
 public void JZ_RecePort3_DataReceived_JZ(object sender, SerialDataReceivedEventArgs e, byte[] bits)
 public void JZ_RecePort4_DataReceived_JZ(object sender, SerialDataReceivedEventArgs e, byte[] bits)
 public void LG_RecePort1_DataReceived_JZ(object sender, SerialDataReceivedEventArgs e, byte[] bits)
 public void LG_RecePort2_DataReceived_JZ(object sender, SerialDataReceivedEventArgs e, byte[] bits)

JZ_RecePort1.DataReceived += new Port_Opera.SerialPortDataReceiveEventArg(JZ_RecePort1_DataReceived_JZ);            JZ_RecePort2.DataReceived += new Port_Opera.SerialPortDataReceiveEventArg(JZ_RecePort2_DataReceived_JZ);            JZ_RecePort3.DataReceived += new Port_Opera.SerialPortDataReceiveEventArg(JZ_RecePort3_DataReceived_JZ);            JZ_RecePort4.DataReceived += new Port_Opera.SerialPortDataReceiveEventArgs(JZ_RecePort4_DataReceived_JZ);

LG_RecePort1.DataReceived += new Port_Opera.SerialPortDataReceiveEventAr(LG_RecePort1_DataReceived_LG);            LG_RecePort2.DataReceived += new Port_Opera.SerialPortDataReceiveEventArgs(LG_RecePort2_DataReceived_LG);
yinyi4120 2014-08-25
  • 打赏
  • 举报
回复
引用 3 楼 rtdb 的回复:
while ((buffer_JZ.Count >= 10) && (buffer_JZ[9] == 255)) 你这句明显只对10个bytes生效,那COM5---COM6的8bytes就进不去了
有两个串口接收函数,之处的代码是接收串口1-4的, 接收串口5-6的代码上面也贴出来了 while ((buffer_LG.Count >= 8) && (buffer_LG[7] == 255)) 麻烦大神仔细给我分析下呢
yinyi4120 2014-08-24
  • 打赏
  • 举报
回复
人工顶一下!
yinyi4120 2014-08-24
  • 打赏
  • 举报
回复

public void JZ_RecePort2_DataReceived_JZ(object sender, SerialDataReceivedEventArgs e, byte[] bits)
        {
            //判断数据来自哪片CPU
              if ((bits[0] & 0x01) == 0)
              {
                  db_opera.Save_CPU_data(bits, "Table_CPU2_1", Rece_DataSet);  
              }
              else
              {
                  db_opera.Save_CPU_data(bits, "Table_CPU2_2", Rece_DataSet);
              }     
        }


public void JZ_RecePort4_DataReceived_JZ(object sender, SerialDataReceivedEventArgs e, byte[] bits)
        {
            //判断数据来自哪片CPU
              if ((bits[0] & 0x01) == 0)
              {
                  db_opera.Save_CPU_data(bits, "Table_CPU4_1", Rece_DataSet);  
              }
              else
              {
                  db_opera.Save_CPU_data(bits, "Table_CPU4_2", Rece_DataSet);
              }     
        }

COM2和COM4的接收响应。之前不知怎么的没有贴上来

110,536

社区成员

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

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

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