在进行串口编程时,经常会涉及到进制转换、计算协议校验码以及数据格式化的操作,本文整理了在实际项目中可能会用到的公共方法,分享给需要的朋友。
一、以下包含了三部分的内容:
1、进制转换:
主要包括了串口通讯中比较常用的16进制、byte、压缩BCD码、long、ASCII、Float等之间的转换方法。
ConvertHelper.cs 进制转换 /* ---------------------------------------------------------------- // Copyright (C) 北京****科技有限公司 // 版权所有。 // // 文件名:ConvertHelper // 文件功能描述:进制转换 // // // 创建标识:** 2008-05-04 // // 修改标识: // 修改描述: // // 修改标识: // 修改描述://---------------------------------------------------------------- */ using System; using System.Collections.Generic; using System.Text; using System.IO; namespace LY{ /// <summary> /// 进制转换 /// </summary> public static class ConvertHelper { #region 进制转换 /// <summary> /// 整形转化成字节 /// </summary> /// <param name="i"></param> /// <returns></returns> public static byte IntToByte( int i) { return Convert.ToByte(i % 0x100 ); } /// <summary> /// 16进制转化成BCD /// </summary> /// <param name="b"> byte </param> /// <returns> 返回BCD码 </returns> public static byte HexToBCD( byte b) { int r1 = b % 0x10 ; // b = 0x12 -> r1 = 0x02 int r2 = b / 0x10 ; // b = 0x12 -> r2 = 0x01 if (r1 > 9 ) // r1 = 0x0A -> r1 = 0x00 r1 = 0 ; if (r2 > 9 ) // r2 = 0x0A -> r2 = 0x00 r2 = 0 ; return Convert.ToByte(r1 + 10 * r2); // 0x12 -> 12 } /// <summary> /// 16进制转化成BCD /// </summary> /// <param name="i"> int </param> /// <returns> 返回BCD码 </returns> public static byte HexToBCD( int i) { return HexToBCD(IntToByte(i)); } /// <summary> /// Double转换为压缩BCD /// </summary> /// <param name="d"> 0-100内的双精度浮点数字 </param> /// <returns> 返回压缩BCD码 </returns> public static string DoubleToBCD( double d) { string [] strs = d.ToString( " F2 " ).Split( ' . ' ); string temp1 = int .Parse(strs[ 0 ]).ToString( " D2 " ); string temp2 = int .Parse(strs[ 1 ]).ToString( " D2 " ); return string .Format( " {0} {1} " , temp1, temp2); } /// <summary> /// long转换为BCD /// </summary> /// <param name="val"></param> /// <returns></returns> public static long ToBCD( long val) { long res = 0 ; int bit = 0 ; while (val >= 10 ) { res |= (val % 10 << bit); val /= 10 ; bit += 4 ; } res |= val << bit; return res; } /// <summary> /// BCD转换为long /// </summary> /// <param name="vals"></param> /// <returns></returns> public static long FromBCD( long vals) { long c = 1 ; long b = 0 ; while (vals > 0 ) { b += ((vals & 0xf ) * c); c *= 10 ; vals >>= 4 ; } return b; } /// <summary> /// BCD转化成16进制 /// </summary> /// <param name="b"></param> /// <returns></returns> public static byte BCDToHex( byte b) { int r2 = b % 100 ; // b = 12 -> r2 = 12 // 123 -> r2 = 23 int r1 = r2 % 10 ; // r2 = 12 -> r1 = 2 r2 = r2 / 10 ; // r2 = 12 -> r2 =1 return Convert.ToByte(r1 + 0x10 * r2); } /// <summary> /// BCD转化成16进制 /// </summary> /// <param name="i"></param> /// <returns></returns> public static byte BCDToHex( int i) { return BCDToHex(IntToByte(i)); } /// <summary> /// btye转化成16进制字符 /// </summary> /// <param name="b"> byte </param> /// <returns></returns> public static string ToHexString( byte b) { return Convert.ToString(b, 16 ); } /// <summary> /// int转化成16进制字符 /// </summary> /// <param name="num"> int </param> /// <returns></returns> public static string ToHexString( int num) { return Convert.ToString(num, 16 ); } /// <summary> /// 16进制字符串转换成字节数组 /// </summary> /// <param name="s"></param> /// <returns></returns> public static byte [] HexStringToByteArray( string s) { s = s.Replace( " " , "" ); byte [] buffer = new byte [s.Length / 2 ]; for ( int i = 0 ; i < s.Length; i += 2 ) { buffer[i / 2 ] = ( byte )Convert.ToByte(s.Substring(i, 2 ), 16 ); } return buffer; } /// <summary> /// 字节数组转换成16进制字符串 /// </summary> /// <param name="data"></param> /// <returns></returns> public static string ByteArrayToHexString( byte [] data) { StringBuilder sb = new StringBuilder(data.Length * 3 ); foreach ( byte b in data) { sb.Append(Convert.ToString(b, 16 ).PadLeft( 2 , ' 0 ' ).PadRight( 3 , ' ' )); } return sb.ToString().Trim().ToUpper(); } /// <summary> /// ASCII转16进制 /// </summary> /// <param name="ascii"> ASCII </param> /// <returns></returns> public static string ASCIIToHex( string ascii) { char [] cs = ascii.ToCharArray(); StringBuilder sb = new StringBuilder(); for ( int i = 0 ; i < cs.Length; i ++ ) { string hex = (( int )cs[i]).ToString( " X " ); sb.AppendFormat( " {0} " , hex); } return sb.ToString().TrimEnd( ' ' ); } /// <summary> /// HEX to ASCII /// </summary> /// <param name="hex"></param> /// <returns></returns> public static string HexToASCII( string hex) { if (hex.Length % 2 == 0 ) { int iValue; byte [] bs; string sValue = string .Empty; string result = string .Empty; int length = hex.Length / 2 ; for ( int i = 0 ; i < length; i ++ ) { iValue = Convert.ToInt32(hex.Substring(i * 2 , 2 ), 16 ); // 16进制->10进制 bs = System.BitConverter.GetBytes(iValue); // int->byte[] sValue = System.Text.Encoding.ASCII.GetString(bs, 0 , 1 ); // byte[]-> ASCII result += char .Parse(sValue).ToString(); } return result.PadLeft(length, ' 0 ' ); } return string .Empty; } /// <summary> /// ASCII To Float /// </summary> /// <param name="ascii"></param> /// <returns></returns> public static float ASCIIToFloat( string ascii) { if (ascii.Length == 8 ) { byte [] arr = new byte [ 4 ]; for ( int i = 0 ; i < 4 ; i ++ ) { arr[i] = Convert.ToByte(ascii.Substring(( 3 - i) * 2 , 2 ), 16 ); } float f = BitConverter.ToSingle(arr, 0 ); return f; } return 0f; } /// <summary> /// Hex to Float /// </summary> /// <param name="hex"></param> /// <returns></returns> public static float HexToFloat( string hex) { string ascii = HexToASCII(hex); float f = ASCIIToFloat(ascii); return f; } #endregion }}2、校验码计算:
包括了16进制异或和、16进制累加、16进制ASCII累加三种类型的校验码计算方法。
CheckHelper.cs 代码校验码计算 /* ---------------------------------------------------------------- // Copyright (C) 北京****科技有限公司 // 版权所有。 // // 文件名:CheckHelper // 文件功能描述:校验码计算 // // // 创建标识:** 2008-05-04 // // 修改标识: // 修改描述: // // 修改标识: // 修改描述://---------------------------------------------------------------- */ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LY{ /// <summary> /// 校验码计算 /// </summary> public static class CheckHelper { #region 校验码计算的方法 /// <summary> /// 返回协议验证码,默认命令字的开始位置为第二位 /// </summary> /// <param name="hex"> 协议串/param> /// <returns> 16进制字符串表示的异或计算结果 </returns> private static string HexXorToString( string hex) { string [] hexTemp = hex.Split( ' ' ); int k = 0 ; for ( int i = 0 ; i < hexTemp.Length; i ++ ) { int j = Convert.ToInt32(hexTemp[i], 16 ); if (i == 1 ) { k = j; } else if (i > 1 ) { k = k ^ j; } } string hexResult = string .Format( " {0:X} " , k % 256 ); // 保证得到一个字节长度的值 if (hexResult.Length == 1 ) { hexResult = string .Format( " 0{0} " , hexResult); } return hexResult; } /// <summary> /// 返回协议验证码 /// </summary> /// <param name="hex"> 协议串 </param> /// <param name="cmdIndex"> 命令字的开始位置 </param> /// <returns> 验证码 </returns> private static string HexXorToString( string hex, int cmdIndex) { string [] hexTemp = hex.Split( ' ' ); int k = 0 ; for ( int i = cmdIndex; i < hexTemp.Length; i ++ ) { int j = Convert.ToInt32(hexTemp[i], 16 ); if (i == cmdIndex) { k = j; } else if (i > cmdIndex) { k = k ^ j; } } string hexResult = string .Format( " {0:X} " , k % 256 ); // 保证得到一个字节长度的值 if (hexResult.Length == 1 ) { hexResult = string .Format( " 0{0} " , hexResult); } return hexResult; } /// <summary> /// 16进制相加的值 /// </summary> /// <param name="hex1"></param> /// <param name="hex2"></param> /// <returns></returns> private static string HexAddToString( string hex1, string hex2) { int h1 = Convert.ToInt32(hex1, 16 ); int h2 = Convert.ToInt32(hex2, 16 ); int sum = (h1 + h2) % 256 ; // 保证得到一个字节长度的值 string hexResult = string .Format( " {0:X} " , sum); if (hexResult.Length == 1 ) { hexResult = string .Format( " 0{0} " , hexResult); } return hexResult; } /// <summary> /// 返回带验证码的协议命令 /// </summary> /// <param name="hex"> 协议串 </param> /// <returns> 带验证码的协议命 </returns> public static string GetSendProtocol( string hex) { string hexTemp = string .Empty; hexTemp = HexXorToString(hex); string hexResult = string .Empty; string hexTemp1 = HexAddToString(hexTemp, " 37 " ); string hexTemp2 = HexAddToString(hexTemp, " D5 " ); string hexTemp3 = HexAddToString(hexTemp, " 9E " ); hexResult = string .Format( " {0} {1} {2} {3} " , hex, hexTemp1, hexTemp2, hexTemp3); return hexResult; } /// <summary> /// 返回带验证码的协议命令 /// </summary> /// <param name="hex"> 协议串 </param> /// <param name="cmdIndex"> 命令字的开始位置 </param> /// <returns> 带验证码的协议命 </returns> public static string GetSendProtocol( string hex, int cmdIndex) { string hexTemp = string .Empty; hexTemp = HexXorToString(hex, cmdIndex); string hexResult = string .Empty; string hexTemp1 = HexAddToString(hexTemp, " 37 " ); string hexTemp2 = HexAddToString(hexTemp, " D5 " ); string hexTemp3 = HexAddToString(hexTemp, " 9E " ); hexResult = string .Format( " {0} {1} {2} {3} " , hex, hexTemp1, hexTemp2, hexTemp3); return hexResult; } /// <summary> /// 得到校验码 /// </summary> /// <param name="message"> 16进制ASCII </param> /// <returns></returns> private static string GetChecksum( string message) { char [] chars = message.ToCharArray(); ushort c; ushort total = 0 ; for ( int i = 0 ; i < chars.Length; i ++ ) { total += ( ushort )chars[i]; } c = ( ushort )( 0 - total); string hex = Convert.ToString(c, 16 ); return hex.ToUpper(); } /// <summary> /// 检查校验码是否相等 /// </summary> /// <param name="message"> 16进制ASCII </param> /// <param name="checksum"> 16进制校验码 </param> /// <returns> 是否相等 </returns> private static bool CalculateChecksum( string message, string checksum) { char [] chars = message.ToCharArray(); ushort c = Convert.ToUInt16(checksum, 16 ); ushort total = 0 ; for ( int i = 0 ; i < chars.Length; i ++ ) { total += ( ushort )chars[i]; } if (( ushort )(c + total) == 0 ) return true ; return false ; } #endregion }}3、字符串格式化:
主要是针对协议中涉及到的金额、数量、时间等字符串的处理。
FormatHelper.cs 字符串格式化 /* ---------------------------------------------------------------- // Copyright (C) 北京****科技有限公司 // 版权所有。 // // 文件名:FormatHelper // 文件功能描述:字符串格式化 // // // 创建标识:** 2008-05-04 // // 修改标识: // 修改描述: // // 修改标识: // 修改描述://---------------------------------------------------------------- */ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Test{ /// <summary> /// 字符串格式化 /// </summary> public static class FormatHelper { #region 格式化字符串 /// <summary> /// 将字符数组装换成字符串 /// </summary> /// <param name="array"> 数组 </param> /// <param name="startIndex"> 开始位置 </param> /// <param name="count"> 长度 </param> /// <returns> 拼接字符串 </returns> public static string GetStringByArray( string [] array, int startIndex, int count) { int index = array.Length; if (startIndex < 0 || startIndex > index) { return string .Empty; } int endIndex = startIndex + count; if (endIndex < 0 || endIndex > index) { return string .Empty; } if (startIndex > endIndex) { return string .Empty; } string result = string .Empty; result = string .Join( " " , array, startIndex, count); return result; } /// <summary> /// 将BCDto日期 /// </summary> /// <param name="now"></param> /// <returns></returns> public static DateTime GetDateTimeByBCD( string now) { string [] tempNow = now.TrimEnd( ' ' ).Split( ' ' ); string dt = string .Format( " {6}{0}-{1}-{2} {3}:{4}:{5} " , tempNow[ 0 ], tempNow[ 1 ], tempNow[ 2 ], tempNow[ 3 ], tempNow[ 4 ], tempNow[ 5 ], DateTime.Now.Year.ToString().Substring( 0 , 2 )); DateTime result; bool done = DateTime.TryParse(dt, out result); if (done) { return result; } return DateTime.Now; } /// <summary> /// 返回格式化的日期时间字符串 /// </summary> /// <param name="current"></param> /// <returns></returns> public static string GetBCDDateTime(DateTime current) { string result = current.ToString( " yy MM dd HH mm ss " ); return result; } /// <summary> /// 将字符串转换成对应的数值/100 /// </summary> /// <param name="value"></param> /// <returns></returns> public static decimal GetValueByString( string value) { string tempValue = value.Replace( " " , "" ); return decimal .Divide( decimal .Parse(tempValue), 100 ); } /// <summary> /// 返回对应的整型字符串 /// </summary> /// <param name="i"></param> /// <returns></returns> public static string BinaryToIntString( int i) { string result = string .Empty; if (i < 0 || i > 999999 ) { return " 00 00 00 " ; } else if (i < 100 ) { return string .Format( " 00 00 {0} " , i.ToString( " D2 " )); } else if (i >= 100 && i < 1000 ) { return string .Format( " 00 0{0} {1} " , i.ToString().Substring( 0 , 1 ), i.ToString().Substring( 1 , 2 )); } else if (i >= 1000 && i < 10000 ) { return string .Format( " 00 {0} {1} " , i.ToString().Substring( 0 , 2 ), i.ToString().Substring( 2 , 2 )); } else if (i >= 10000 && i < 100000 ) { return string .Format( " 0{0} {1} {2} " , i.ToString().Substring( 0 , 1 ), i.ToString().Substring( 1 , 2 ), i.ToString().Substring( 3 , 2 )); } else if (i >= 100000 && i < 1000000 ) { return string .Format( " {0} {1} {2} " , i.ToString().Substring( 0 , 2 ), i.ToString().Substring( 2 , 2 ), i.ToString().Substring( 4 , 2 )); } return " 00 00 " ; } /// <summary> /// 整形格式化为两位小数 /// </summary> /// <param name="value"></param> /// <returns></returns> public static string IntFormatString( int value) { return value.ToString( " D2 " ); } #endregion }}转载于:https://www.cnblogs.com/deepwishly/archive/2010/04/23/2551247.html
相关资源:串口编程中SerialPort类介绍以及应用