紫外工控论坛

 找回密码
 立即注册

扫一扫,访问微社区

QQ登录

只需一步,快速开始

搜索
查看: 3730|回复: 0

(SerialPort)串口编程知识整理:(二)串口编程中经常用到的进制转换和其他公共方法

[复制链接]
冰糖 发表于 2010-8-2 22:55:43 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
在进行串口编程时,经常会涉及到进制转换、计算协议校验码以及数据格式化的操作,本文整理了在实际项目中可能会用到的公共方法,分享给需要的朋友。一、以下包含了三部分的内容:

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).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
= 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, 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, 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;
            }

            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;
            }

            
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
    }
}



二、声明
     本文的内容大部分方法经过了项目测试,少量没有用到的方法不保证其正确性,希望各位朋友在使用之前测试一下。
如果发现问题,请及时反馈给本人,谢谢!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


--------------------------------------------------------------------------------------------------------------------
本站是工控技术交流站点,论坛内容均为网络收集或会员所发表,并不代表本站立场,会员拥有该内容的所有权力及责任!
本站内容如有侵犯您的版权,请按下面方式联系本站管理员,我们将及时删除处理
管理员:冰糖 QQ:5483695(请直击主题), Mail:admin#ziwai.net(#改成@) 其它非本人.
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论!

QQ|Archiver|手机版|小黑屋|紫外工控论坛. ( 苏ICP备11032118号-1 )

GMT+8, 2024-5-5 10:48 , Processed in 0.468750 second(s), 17 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表