您的位置:首页 > 其它

工作项目总结(六)之串口通信

2011-07-05 11:31 471 查看
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.ToString() + "tmp------->" + CCheck.BinaryToHexString(tmp));
}));

recvbuf.Add(tmp);//添加接收数据到队列

//显示队列中全部数据
//txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "Recvbuf--->"+CCheck.BinaryToHexString(recvbuf.ge));
//提取一个完整的数据帧
tmp = getBlock(recvbuf.li);
//获取到一个数据包数据时,开始解析

if (tmp.Length >= 59)
{
this.Invoke((EventHandler)(delegate
{
txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "tmpAsync-->" + CCheck.BinaryToHexString(tmp));
}));
AsyncPacket(tmp);
}
this.Invoke((EventHandler)(delegate
{
if (tmp != null)
txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "tmp!=null->" + CCheck.BinaryToHexString(tmp));
else

txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "tmp==null->" + " ");
}));
/* *************************************************/
#region
/*******************************************
int n = 59;
//int n = comm.BytesToRead;
//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致

//int n = comm.BytesToRead;
byte[] buf = new byte
;
//声明一个临时数组存储当前来的串口数据
//received_count += n;//增加接收计数
comm.Read(buf, 0, n);//读取缓冲数据
//comm.ReadByte();
//   builder.Clear();//清除字符串构造器的内容
builder.Remove(0, builder.Length);
//因为要访问ui资源,所以需要使用invoke方式同步ui。
this.Invoke((EventHandler)(delegate
{
//判断是否是显示为16禁止
if (checkBoxHexView.Checked)
{
//依次的拼接出16进制字符串
foreach (byte b in buf)
{
builder.Append(b.ToString("X2") + " ");
}
}
else
{
//依次的拼接出16进制字符串
foreach (byte b in buf)
{
builder.Append(b.ToString("X2") + " ");
}
////直接按ASCII规则转换成字符串
//builder.Append("\r\n"+System.DateTime.Now.ToString()+"--->"+Encoding.ASCII.GetString(buf));
}
this.txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "--->" + builder.ToString());
//修改接收计数
labelGetCount.Text = "Get:" + received_count.ToString();
}));
******************************************/
#endregion
}
catch (Exception ex)
{
this.Invoke((EventHandler)(delegate
{
txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "---------->" + ex.Message);
}));
log.ConnError("数据接收出错,详细为:"+ex.Message);
}
finally
{
Listening = false;//我用完了,ui可以关闭串口了。
}
}
}

98、
  #region
public static byte[] HexStringToBinary(string hexstring)//十六进制格式转换
{

string[] tmpary = hexstring.Trim().Split(' ');
byte[] buff = new byte[tmpary.Length];
for (int i = 0; i < buff.Length; i++)
{
buff[i] = Convert.ToByte(tmpary[i], 16);//转换
}return buff;
}#endregion

#region
/// <summary>
///
/// </summary>
/// <param name="li"></param>
/// <returns></returns>
private byte[] getBlock(List<byte> li)
{
byte[] b = null;
if (li.Count < 59) return b;//总长度不足59字节

int p = li.Count;
//从右向左查找起始标志F0F1,获取下标
while ((p = li.LastIndexOf(0xF0, p - 1)) != -1)
if (li.Count >= p + 59)
if (li[p + 1] == 0xF1&&li[p+57]==0xFE&&li[p+58]==0xFF)
break;//已经找到,接收循环
if (p != -1)//p为数据块的起始位置
{
b = new byte[59];
li.CopyTo(p, b, 0, 59);//拷贝数据块到b数组
}return b;
}
public class CCheck
{
//字节数组转换为十六进制字符串
public static string BinaryToHexString(byte[] buff)
{
StringBuilder tmp = new StringBuilder();
for(int i=0;i<buff.Length;i++)
tmp.Append(buff[i].ToString("X2")+" ");
return tmp.ToString().Trim();
}}#endregion


99、
#region
/// <summary>
/// 保存TextBox文本,
        /// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SaveBtn_Click(object sender, EventArgs e)
{//创建文件
FileStream fs;
//string ax = System.DateTime.Today.Date.ToString();
string ax = System.DateTime.Now.ToShortDateString();
//string filename = "E:/" + ax + ".txt";
string filename = System.Environment.CurrentDirectory+"\\data\\" + ax + ".txt";
if (File.Exists(filename))
{
fs = File.Open(filename, FileMode.Append);
}else
{
fs = File.Create(filename);
}//fs.Close();
string fswr = "";
try
{
fswr = txGet.Text;
byte[] str = System.Text.Encoding.Default.GetBytes(fswr);
fs.Write(str, 0, str.Length);
fs.Flush();
//UpdateDataViewTbxText("\r\n" + System.DateTime.Now.ToString() + "保存成功!");
this.Invoke((EventHandler)(delegate
{
txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "---------->" + "保存成功!");
}));
}catch (IOException ex)
{
log.ConnError("保存文件失败,原因为" + ex.Message);
//UpdateDataViewTbxText("\r\n" + System.DateTime.Now.ToString() + "保存失败:" + ex.Message);
this.Invoke((EventHandler)(delegate
{
txGet.AppendText("\r\n" + System.DateTime.Now.ToString() + "---------->" + "保存失败!");
}));
}finally
{
fs.Close();
}
}#endregion

100、
  #region
/// <summary>
/// 进行包头包尾匹配
/// </summary>
/// <param name="data"></param>
/// <param name="dwLen"></param>
/// <returns></returns>
static int[] ExtractPacketLength(byte[] data)//,int[] Index
{
int[] Index = new int[2];
Index[0] = 0; Index[1] = 0;
//int StartIndex = 0, EndIndex = 0;

string datastr = DisplayByte(data);
string pattern = @"^F0F1";
Regex reg1 = new Regex(pattern);
if (reg1.IsMatch(datastr, 0))
{
Index[0] = 2;
}string pattern2 = @"FEFF{1}quot;;
Regex reg2 = new Regex(pattern2);
if (reg2.IsMatch(datastr, 56))
{
Index[1] = 56;
}return Index;
}#endregion

101、
 #region
/// <summary>
/// 校验包头和包尾,校验和,长度
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private bool ReceivePacket(byte[] data)
{
//数据包正确标识
dataState = false;
//获取数据包位置
int[] index = ExtractPacketLength(data);
//找到数据包位置
if (index[1] > index[0] && index[0] != 0)// && data.Length == 28
{
byte[] Arraybyte = new byte[index[1] - index[0]];
Array.Copy(data, index[0], Arraybyte, 0, index[1] - index[0]);
//计算校验和
byte cs = GetCS(Arraybyte);
//对比数据
if (cs == data[index[1]])
{
dataState = true;
}}return dataState;
}#endregion


102、
 #region
/// <summary>
/// 解析温度-55~100,2个字节,第一位为符号位:(+/-)xx.x
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private string GetTemp(byte[] data)
{
decimal Para = 0.1M;
string temp = null;
//符号
string Symbol = null;
byte S = (byte)(data[1] >> 4);
if (S == 0x1)
{
Symbol = "-";
}string tempStr = Symbol + (((byte)(data[0] << 4)) >> 4).ToString()
+ (data[1] >> 4).ToString() + (((byte)(data[1] << 4)) >> 4).ToString();
temp = (Convert.ToInt32(tempStr) * Para).ToString();

return temp;
}#endregion

#region
/// <summary>
/// 计算电压、电流 3字节(格式000.000)
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private string GetVacAndIac(byte[] data)
{
decimal multiplier = 0.001M;
//数据
string Effdata = null;
//数据位
string datastr = (data[0] >> 4).ToString() + (((byte)(data[0] << 4)) >> 4).ToString()
+ (data[1] >> 4).ToString() + (((byte)(data[1] << 4)) >> 4).ToString()
+ (data[2] >> 4).ToString() + "" + (((byte)(data[2] << 4)) >> 4).ToString();
Effdata = (Convert.ToDecimal(datastr) * multiplier).ToString();
return Effdata;
}#endregion

#region
/// <summary>
/// 3字节 有功、无功功率(格式+/-00000)
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private string GetPacData(byte[] data)
{
//数据
string Effdata = null;
//符号
string Symbol = null;
//符号位
byte S = (byte)(data[0] >> 4);
if (S == 0x1)
{
Symbol = "-";
}//数据位(data[2] >> 4).ToString() +
string datastr = (((byte)(data[0] << 4)) >> 4).ToString()
+ (data[1] >> 4).ToString() + "" + (((byte)(data[1] << 4)) >> 4).ToString()
+ (data[2] >> 4).ToString() + "" + (((byte)(data[2] << 4)) >> 4).ToString();
Effdata = Symbol + Convert.ToInt32(datastr).ToString();
return Effdata;
}#endregion

#region
/// <summary>
/// 解析电量 4字节
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private string GetPowerData(byte[] data)
{
decimal para = 0.01M;
string PowerData = null;
string PowerDatastr = data[0].ToString("X2")
+ data[1].ToString("X2")
+ data[2].ToString("X2")
+ data[3].ToString("X2");
PowerData = (Convert.ToDecimal(PowerDatastr) * para).ToString();

return PowerData;
}#endregion

#region
/// <summary>
/// 总运行时间hr
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private string GetHTotal(byte[] data)
{
decimal para = 0.01M;
string HTotal = null;
string HTotalstr = data[0].ToString("X2")
+ data[1].ToString("X2")
+ data[2].ToString("X2")
+ data[3].ToString("X2");

HTotal = (Convert.ToDecimal(HTotalstr) * para).ToString();

return HTotal;
}#endregion

#region
/// <summary>
/// 今日运行时间:分钟数
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private string GetTodayRunTime(byte[] data)
{
string RunTime = null;
string RunTimestr = data[0].ToString("X2")
+ data[1].ToString("X2");
RunTime = Convert.ToInt32(RunTimestr).ToString();
return RunTime;
}#endregion
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: