1.功能描述
按照设定时间对接收数据进行断帧(换行)
应用于需要接收完整数据包的场景,例如下位机发送一包数据为1秒,每100ms发送一组数据
大部分用于接收十六进制数据时
2.代码部分
步骤1:添加计时器,设置默认时间为500ms
步骤2:去掉断帧复选框默认使能
步骤3:设置断帧复选框时间集合
步骤4:开启HEX接收数据选择框时
//当开启HEX接收时事件
private void checkBox16_CheckedChanged(object sender, EventArgs e)
{
//启动与禁用断帧功能
if (checkBox16.Checked == true)
{
comboBox16.Enabled = true;//使能断帧时间复选框
//设定定时参数
timer4.Interval = Convert.ToUInt16(comboBox16.Text, 10);
//启动定时器4
timer4.Start();
}
else
{
comboBox16.Enabled = false;
//停止定时器4
timer4.Stop();
}
}
步骤5:编写定时器事件
定义局部变量声明
//断帧定时器事件
private void timer4_Tick(object sender, EventArgs e)
{
Timer4_Flag = true;//置位定时器4标志位
}
步骤6:串口接收事件中添加代码
//断帧功能
if (Timer4_Flag == true)
{
Timer4_Flag = false;
textBox1.AppendText("\r\n");
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
}
步骤7:断帧复选时间设置
//断帧复选框事件_选择断帧时间
private void comboBox16_SelectedIndexChanged(object sender, EventArgs e)
{
//设定定时参数
//将组合框中的数据转换为整型赋值给定时器参数
timer4.Interval = Convert.ToUInt16(comboBox16.Text, 10);
}
3.完整代码
//用于串口通讯断帧
bool Timer4_Flag = false;
//串口接收事件
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//接收格式为ASCII码
if (!checkBox16.Checked)//复用框没有被选择时
{
try
{
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
string str = serialPort1.ReadExisting();//将接收到的数据存在自定义的字符串变量中
textBox1.AppendText(str + "\r\n");
//统计接收字节数
UInt32 RBytes = Convert.ToUInt32(textBox7.Text, 10);//定义接收字节数变量,并初始化为已接收字节数
RBytes += (UInt32)str.Length;//加ASCII码字节数
textBox7.Text = Convert.ToString(RBytes, 10);//显示总接收字节数
}
catch
{
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
textBox1.AppendText("ASCII格式接收错误!\r\n");
}
}
//接收格式为HEX
else
{
try
{
//断帧功能
if (Timer4_Flag == true)
{
Timer4_Flag = false;
textBox1.AppendText("\r\n");
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
}
//textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->"); //此处被断帧功能替代换行
byte[] data = new byte[serialPort1.BytesToRead];//定义接收缓冲区,长度为串口接收的数据长度
serialPort1.Read(data, 0, data.Length);//形参,起始位置,终止位置,将读取的数据存放在缓冲区
//遍历用法
foreach (byte Member in data)//循环函数
{
string str = Convert.ToString(Member, 16).ToUpper();//转化为十六进制大写
textBox1.AppendText((str.Length == 1 ? "0" + str : str) + " ");//数据+空格“”
}
//textBox1.AppendText("\r\n"); //此处被断帧功能替代换行
//统计接收字节数
UInt32 RBytes = Convert.ToUInt32(textBox7.Text, 10);//定义接收字节数变量,并初始化为已接收字节数
RBytes += (UInt32)data.Length;//加HEX字节数
textBox7.Text = Convert.ToString(RBytes, 10);//显示总接收字节数
}
catch
{
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
textBox1.AppendText("HEX格式接收错误!\r\n");
}
}
}
//当开启HEX接收时事件
private void checkBox16_CheckedChanged(object sender, EventArgs e)
{
//启动与禁用断帧功能
if (checkBox16.Checked == true)
{
comboBox16.Enabled = true;//使能断帧时间复选框
//设定定时参数
timer4.Interval = Convert.ToUInt16(comboBox16.Text, 10);
//启动定时器4
timer4.Start();
}
else
{
comboBox16.Enabled = false;
//停止定时器4
timer4.Stop();
}
}
//断帧定时器事件
private void timer4_Tick(object sender, EventArgs e)
{
Timer4_Flag = true;//置位定时器4标志位
}
//断帧复选框事件_选择断帧时间
private void comboBox16_SelectedIndexChanged(object sender, EventArgs e)
{
//设定定时参数
//将组合框中的数据转换为整型赋值给定时器参数
timer4.Interval = Convert.ToUInt16(comboBox16.Text, 10);
}
}
4.测试结果
当下位机为500m定时发送,上位机设置断帧为500ms断帧时,接收的十六进制数据为500ms一帧数据,当设置上位机断帧时间为1s时,接收的十六进制一帧数据为下位机发送的两帧数据。
参考自B站硬件家园