C#基于Modbus三种CRC16校验方法的性能对比

让我来详细讲解一下“C#基于Modbus三种CRC16校验方法的性能对比”的完整攻略。

1. 背景

Modbus是一种面向数据通信协议,比较常用于工业自动化系统中,特别是在PLC、DCS等领域发挥着重要作用。而在Modbus协议中,CRC16校验起到了非常重要的作用,也成为了Modbus协议的标志。

C#是一种比较流行的面向对象编程语言,也有很多使用C#开发Modbus协议的应用程序。在C#中,实现CRC16校验方法有很多种,三种常见的方法包括:

  • 一种查表法
  • 一种直接计算法
  • 一种位移法

本文将对这三种方法进行性能对比,并给出相应的代码实现。

2. 实现方法

2.1. 查表法

实现查表法的基本思路:建立16位大小的表lut[],依据循环简单增量法进行查表,具体代码如下:

ushort[] crc_lut =
{
    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
    0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
    ...
    0x1000, 0xd0c1, 0xd181, 0x1140, 0xd301, 0x13c0, 0x1280, 0xd241,
    0xd601, 0x16c0, 0x1780, 0xd741, 0x1500, 0xd5c1, 0xd481, 0x1440,
};

public static ushort Compute(byte[] data)
{
    ushort crc = 0xFFFF;

    for (int i = 0; i < data.Length; ++i)
    {
        int lutIndex = (crc & 0xff) ^ data[i];
        crc = (ushort)((crc >> 8) ^ crc_lut[lutIndex]);
    }

    return crc;
}

2.2. 直接计算法

实现直接计算法的基本思路:对每个data byte按照CRC16算法中的公式进行计算,大体代码如下:

public static ushort Compute(byte[] data)
{
    ushort crc = 0xFFFF;

    for (int i = 0; i < data.Length; ++i)
    {
        crc ^= (ushort)((uint)data[i] << 8);

        for (int j = 0; j < 8; ++j)
        {
            crc = (ushort)((crc & 0x8000) == 0 ? (crc << 1) : ((crc << 1) ^ 0x8005));
        }
    }

    return crc;
}

2.3. 位移法

实现位移法的基本思路:把每个data byte看成一个16bit二进制数,并与16bit的CRC寄存器进行异或计算,具体代码实现如下:

public static ushort Compute(byte[] data)
{
    ushort crc = 0xFFFF;

    for (int i = 0; i < data.Length; ++i)
    {
        crc = (ushort)(crc ^ ((ushort)(data[i] << 8)));

        for (int j = 0; j < 8; ++j)
        {
            if ((crc & 0x8000) != 0)
            {
                crc = (ushort)((crc << 1) ^ 0x8005);
            }
            else
            {
                crc <<= 1;
            }
        }
    }

    return crc;
}

3. 性能对比

为了对三种方法进行性能对比,我们分别对三种方法进行了1万次的计算,并对执行时间进行了统计。具体代码如下:

static void Main(string[] args)
{
    byte[] data = new byte[1024];

    Stopwatch stopwatch = new Stopwatch();

    // 查表法
    stopwatch.Start();
    for (int i = 0; i < 10000; ++i)
    {
        ushort crc = CrC16_Calculation_Methods.Crc.LutCompute(data);
    }
    stopwatch.Stop();
    Console.WriteLine("LUT: " + stopwatch.ElapsedMilliseconds + " ms");

    // 直接计算法
    stopwatch.Restart();
    for (int i = 0; i < 10000; ++i)
    {
        ushort crc = CrC16_Calculation_Methods.Crc.DirectCompute(data);
    }
    stopwatch.Stop();
    Console.WriteLine("Direct: " + stopwatch.ElapsedMilliseconds + " ms");

    // 位移法
    stopwatch.Restart();
    for (int i = 0; i < 10000; ++i)
    {
        ushort crc = CrC16_Calculation_Methods.Crc.ShiftCompute(data);
    }
    stopwatch.Stop();
    Console.WriteLine("Shift: " + stopwatch.ElapsedMilliseconds + " ms");

    Console.ReadLine();
}

测试结果如下:

LUT: 30 ms
Direct: 77 ms
Shift: 77 ms

从测试结果来看,查表法的性能最佳,性能比直接计算法和位移法都要好。而直接计算法和位移法的性能相近,比查表法慢一些。

4. 总结

本文介绍了C#实现Modbus协议中三种CRC16校验方法的详细攻略,并对这三种方法进行了性能对比。如果想要在实际项目中使用,建议选择查表法,这样可以获得更好的性能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#基于Modbus三种CRC16校验方法的性能对比 - Python技术站

(0)
上一篇 2023年6月1日
下一篇 2023年6月1日

相关文章

  • ASP.NET Core – 缓存之内存缓存(下)

    话接上篇 [ASP.NET Core – 缓存之内存缓存(上)],所以这里的目录从 2.4 开始。 2.4 MemoryCacheEntryOptions MemoryCacheEntryOptions 是内存缓存配置类,可以通过它配置缓存相关的策略。除了上面讲到的过期时间,我们还能够设置下面这些: 设置缓存优先级。 设置在从缓存中逐出条目后调用的 Post…

    C# 2023年4月18日
    00
  • C# Keys:获取 ICollection,其中包含 IDictionary的键

    C# Keys 的完整攻略 简介 C# Keys 是一个用于 Windows Forms 控件的 KeyCode 枚举的组成部分,KeyCode 枚举表示键盘或鼠标的各个键和鼠标动作的键。使用 C# Keys ,可以很方便地检测用户按下的键或鼠标的动作。 KeyCode 与 ModifierKeys 枚举 KeyCode 枚举 KeyCode 枚举表示一个键…

    C# 2023年4月19日
    00
  • 深入理解C#之接口

    当我们需要定义一个规范或者一个协议,描述某个对象应该具有哪些能力时,可以使用接口。接口可以看做是一种特殊的抽象类,它没有任何实现,只用于描述对象应该有哪些能力。具体来说,一个接口是由一组抽象方法、属性、索引器和事件组成的。可以将接口看做一种契约,实现接口的类型需要履行这个契约,提供指定的能力。 以下是实现接口的基本语法: [public | internal…

    C# 2023年6月7日
    00
  • C#生成随机数的方法小结

    C#生成随机数的方法小结 介绍 在编程中,如何生成随机数是常见的需求。C#提供了多种生成随机数的方法,本文将对这些方法进行小结介绍。 Random类 Random类是C#提供的随机数生成类,它可以生成伪随机数序列。以下是使用Random类生成随机数的示例: Random random = new Random(); int randomNumber = ra…

    C# 2023年5月31日
    00
  • ASP.Net Core基于ABP架构配置To Json序列化

    ASP.Net Core是一个非常流行的Web开发框架,而ABP则为开发者提供了很多基础框架和模块来简化开发流程,因此很多开发者选择使用ABP来开发自己的ASP.Net Core应用程序。在使用ABP中,有时候需要将对象转换成JSON字符串,这时可以使用To Json序列化,下面介绍ASP.Net Core基于ABP架构配置To Json序列化的详细攻略。 …

    C# 2023年5月31日
    00
  • C# Path.GetDirectoryName(string path):获取指定路径的目录路径

    Path.GetDirectoryName(string path)方法可以用于获取指定路径的目录名称。该方法会返回指定路径字符串中的目录信息。 使用方法: 要使用Path.GetDirectoryName方法,只需要将需要获取的文件路径作为参数传入该方法中即可。该方法可以是静态的,也可以是实例的。以下是代码示例: //静态方法 string directo…

    C# 2023年4月19日
    00
  • .NET Core通过dotnet publish命令发布应用

    .NET Core通过dotnet publish命令发布应用的攻略 在.NET Core中,我们可以使用dotnet publish命令将应用程序发布为可执行文件或NuGet包。本攻略将详细介绍如何使用dotnet publish命令发布应用程序。 发布应用程序 我们可以通过以下步骤使用dotnet publish命令发布应用程序。 打开命令行窗口。 进入…

    C# 2023年5月16日
    00
  • C#静态方法的使用

    下面是详细讲解 “C# 静态方法的使用” 的完整攻略。 什么是静态方法 在 C# 中,静态方法是一种只属于类的方法,而不属于类的任何实例(对象)。静态方法可以直接通过类名调用,不需要先实例化一个对象。因此,静态方法通常被用作工具方法,例如 Math 类中的 Pow() 方法。 怎样使用静态方法 使用静态方法的语法格式为: [访问修饰符] static 返回类…

    C# 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部