重合:
指示设备工作时,设备返回ok;而此时设备主动上报数据,这两个数据可能发生重合;因此串口同时可能有多个消息到达
分批到达:
一个回复由于干扰信号的关系,分两次到达,第一次到达了11个字节的前5个字节,第二次到达了11个字节的后6个字节。
在接收事件中(On_Comm)需要对数据进行整理,将这两种问题解决后(借助于数据包头,数据包尾),还有校验码的问题
下面是我的解决方案,由于是第一编写这样的程序,没什么经验,所以希望大家能提出意见.
private static Logger logger = LogManager.GetCurrentClassLogger(); //
MSCommLib.MSCommClass mc = new MSCommLib.MSCommClass(); //实例化MSCOMM
System.Timers.Timer timer = null; //定时器
ArrayList m_bytelist = new ArrayList(); //全局变量来存放接收到的数据
byte[] m_data = new byte[11]; //一个完整的消息指令数组长度为11
private int m_second = 0; //超时时间
private void InitCommonPort()
{
try
{
mc.CommPort = 3;
mc.Settings = "38400,n,8,1";
mc.RThreshold = 1; //每接收一个字符则激发OnComm()事件
mc.DTREnable = true;
mc.Handshaking = MSCommLib.HandshakeConstants.comNone;
mc.InputMode = MSCommLib.InputModeConstants.comInputModeBinary; //二进制
mc.InBufferSize = 1024;
mc.InputLen = 0; //决定每次Input读入的字符个数,缺省为0,表示读取接收缓冲区的全部内容
//mc.InputLen = 1; //一次读取一个
mc.NullDiscard = false;
mc.PortOpen = true; //打开串口
mc.OnComm +=new MSCommLib.DMSCommEvents_OnCommEventHandler(mc_OnComm);
Console.WriteLine("串口已打开!");
logger.Debug("串口已打开!");
}
catch
{
logger.Debug("串口打开失败!");
}
}
/// <summary>
/// 初始化定时器
/// </summary>
private void InitTimer()
{
timer = new System.Timers.Timer(1000);
timer.AutoReset = true;
timer.Enabled = true;
timer.Elapsed +=new ElapsedEventHandler(timer_Elapsed);
}
/// <summary>
/// 处理接收的数据
/// </summary>
private void checkByteList()
{
byte[] t_byte = new byte[11];
int j = 0;
if(m_bytelist.Count == 0)
{
return;
}
else
{
for(int i=0;i<m_bytelist.Count;i++)
{
t_byte[j] = (byte)m_bytelist[i];
if(t_byte[0] == 0x82)
{
if(j==10)
{
if(t_byte[10] == 0x83)
{
sendMail(t_byte);
j = 0;
this.clearArray(ref t_byte);
m_bytelist.RemoveRange(0,11);
}
else //如果包尾不是以83开头,数据不合法,丢弃
{
j=0;
logger.Debug("/n错误的指令 : [" + Utilities.ByteArrayToHexString(t_byte) + "] 已被丢弃! ");
this.clearArray(ref t_byte);
m_bytelist.RemoveRange(0,11);
}
}
else
{
j++;
this.InitTimer(); //初始化定时器
if(m_second == 5) //5秒后停止
{
logger.Debug("不完整的指令 : ["+Utilities.ByteArrayToHexString(t_byte) + "]");
this.clearArray(ref t_byte);
m_bytelist.RemoveRange(0,j);
j=0;
}
}
}
else //如果包头不是以82开头,数据不合法,丢弃
{
j=0;
logger.Debug("/n错误的指令 : [" + Utilities.ByteArrayToHexString(t_byte) + "] 已被丢弃! ");
this.clearArray(ref t_byte);
m_bytelist.RemoveRange(0,1);
}
}
}
}
/// <summary>
/// clear array
/// </summary>
/// <param name="o_data"></param>
private void clearArray(ref byte[]o_data)
{
for(int i=0;i<o_data.Length;i++)
{
o_data[i] =0;
}
}
/// <summary>
/// 将消息发给上层
/// </summary>
/// <param name="inData"></param>
private void sendMail(byte[] inData)
{
}
/// <summary>
/// 从串口接收数据
/// </summary>
private void mc_OnComm()
{
byte [] t_byte = (byte[])mc.Input; //receive data and clear buffer
for(int i = 0;i<t_byte.Length;i++)
{
m_bytelist.Add(t_byte[i]);
}
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
DateTime now = DateTime.Now;
m_second = now.Second;
}
/// <summary>
/// 接收MCU主动发送的消息、解析、封装成对象消息发送给Session层
/// </summary>
protected override void process()
{
checkByteList();
}
主要的代码就这么多了,没有整理比较乱,有空的时候再整理一下了.