工作项目总结(六)之串口通信
2011-07-05 11:31
471 查看
96、串口数据包组装
97、串口通信Com源码(一部分)
98、
99、
100、
101、
102、
//串口数据包组装; 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
相关文章推荐
- 工作项目总结(七)之USB通信
- 同一个项目的不同的项目工作经验总结--程序员丙
- 同一个项目的不同的项目工作经验总结--设计文档编写经验总结
- 团队项目个人工作总结(4月18日)
- 团队项目个人工作总结(4.20)
- 构建企业级项目管理体系(08)-PMO的工作职责总结 推荐
- 同一个项目的不同的项目工作经验总结--程序员丁
- 珈伟工作项目总结(引言)
- 工作项目总结(八)之TCP/IP通信
- 2013暑假项目实训工作内容总结
- 同一个项目的不同的项目工作经验总结--程序员甲
- 温家宝-政府少上项目也要确保对养老保险投入-温家宝-养老保险-养老保险工作总结表彰大会
- 队项目个人工作总结(4月25日)
- 通信项目阶段总结-IM聊客户端
- 2012工作及项目总结。
- 队项目个人工作总结(4月27日)
- 同一个项目的不同的项目工作经验总结--设计文档编写经验总结
- Volley和网络数据通信工作总结
- 转:十年总结(四):在北京的第一份工作和第一个项目