96、串口数据包组装
//串口数据包组装;
I、首先创建类:CRecvBuf.cs
/*http://wenku.baidu.com/view/cc833787bceb19e8b8f6ba53.html*/
using System;
using System.Collections.Generic;
/// <summary>
/// 创建数据接收队列
/// CRecvBuf是一个用于缓存接收数据的类,利用List类来实现。
/// 在创建该类的实例时,要制定参数maxLength,表示队列的总容量。
/// 每当接收到一段数据,就调用Add方法将收到的数据添加到队列中,
/// Add方法中判断添加数据后字节数是否超过maxLength,并将超过部分从队首删除。
/// </summary>
class CRecvBuf
{
public List<byte> li;
public int maxLength;
public CRecvBuf(int maxLength)
{
li = new List<byte>();
this.maxLength = maxLength;
}
public void Add(byte[] b)
{
if (b.Length > maxLength)
throw new Exception("接收到得数据量超出缓冲区长度");
li.AddRange(b);
if (li.Count > maxLength)
li.RemoveRange(0, li.Count - maxLength);
}
}
97、串口通信Com源码(一部分)
public partial class SerialportSampleForm : Form
{
private SerialPort comm = new SerialPort();
private StringBuilder builder = new StringBuilder();
//避免在事件处理方法中反复的创建,定义到外面。
private long received_count = 0;//接收计数
private long send_count = 0;//发送计数
private bool Listening = false;
//是否没有执行完invoke相关操作
private bool ComClosing = false;
//是否正在关闭串口,执行Application.DoEvents, 并阻止再次invoke
private CRecvBuf recvbuf;
WriteLog log = new WriteLog();
//string a="asas";
string dataAsyncstr = null;
string buffer = null;
private bool dataState = false;//数据包校验和判断标识
DTU_PacketBuf packetbuf = new DTU_PacketBuf();
//定义委托,它定义了可以代表的方法的类型
public delegate void GreetingDelegate(string name);
public SerialportSampleForm()
{
InitializeComponent();
}
private void SerialportSampleForm_Load(object sender, EventArgs e)
{
string[] ports = SerialPort.GetPortNames();
Array.Sort(ports);
comboPortName.Items.AddRange(ports);
comboPortName.SelectedIndex =
comboPortName.Items.Count > 0 ? 0 : -1;
comboBaudrate.SelectedIndex = comboBaudrate.Items.IndexOf("9600");
recvbuf = new CRecvBuf(120);//队列长度为数据帧长度的两倍
//comm.
//初始化SerialPort对象
comm.NewLine = "\r\n";
comm.RtsEnable = true;
//根据实际情况吧。
//添加事件注册
comm.DataReceived +=comm_DataReceived;
}
void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (ComClosing)
{
return;
}
//如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环
try
{
Listening = true;
//设置标记,说明我已经开始处理数据, 一会儿要使用系统UI的。
/**************以下为按字节读取第一个字节数据
再读取剩余字节数据
将读取数据添加到队列队尾
提取完整的数据帧***********/
byte firstbyte;
byte[] tmp;
comm.ReadTimeout = 5000;//5秒内没收到数据将捕获异常
received_count += comm.BytesToRead;//增加接收计数
firstbyte = (byte)comm.ReadByte();//读取第一个字节,程序在这里堵塞
tmp = new byte[comm.BytesToRead + 1];
tmp[0] = firstbyte;
comm.Read(tmp, 1, tmp.Length - 1);//读取剩余字节到tmp数组中
this.Invoke((EventHandler)(delegate
{
txGet.AppendText("\r\n" + System.DateTime.Now.