gpt4 book ai didi

使用 C 预处理器计算 8 位 CRC?

转载 作者:太空狗 更新时间:2023-10-29 15:06:19 25 4
gpt4 key购买 nike

我正在为只有几个字节 RAM 的微型 8 位微 Controller 编写代码。它有一个简单的工作就是传输 7 个 16 位字,然后是这些字的 CRC。字的值是在编译时选择的。 CRC具体是“除法的余数字 0 到字 6 作为无符号数除以多项式 x^8+x²+x+1(初始值 0xFF)。”

是否可以使用 C 预处理器在编译时计算这些字节的 CRC?

#define CALC_CRC(a,b,c,d,e,f,g)    /* what goes here? */

#define W0 0x6301
#define W1 0x12AF
#define W2 0x7753
#define W3 0x0007
#define W4 0x0007
#define W5 0x5621
#define W6 0x5422
#define CRC CALC_CRC(W0, W1, W2, W3, W4, W5, W6)

最佳答案

可以设计一个在编译时执行 CRC 计算的宏。像

 // Choosing names to be short and hopefully unique. #define cZX((n),b,v) (((n) & (1 << b)) ? v : 0) #define cZY((n),b, w,x,y,z) (cZX((n),b,w)^CzX((n),b+1,x)^CzX((n),b+2,y)^cZX((n),b+3,z)) #define CRC(n) (cZY((n),0,cZ0,cZ1,cZ2,cZ3)^cZY((n),4,cZ4,cZ5,cZ6,cZ7))
应该可以工作,如果 (n) 可以被评估为编译时常量,将会非常有效;它将简单地评估为一个常量本身。另一方面,如果 n 是一个表达式,该表达式最终将被重新计算八次。即使 n 是一个简单的变量,生成的代码也可能比最快的非基于表的编写方式大得多,并且可能比最紧凑的编写方式慢。< p>

顺便说一句,我真正希望在 C 和 C++ 标准中看到的一件事是一种指定重载的方法,只有当特定参数可以作为编译时常量进行评估时,这种重载才会用于声明为内联的函数。语义将是这样的,即没有“保证”在编译器可能能够确定值的每种情况下都会使用任何此类重载,但可以保证(1)不会使用此类重载在任何情况下,必须在运行时评估“编译时常量”参数,以及 (2) 在此类重载中被视为常量的任何参数在从它调用的任何函数中都将被视为常量。在很多情况下,如果函数的参数是常量,则可以编写一个函数来评估编译时常量,但运行时评估绝对是可怕的。例如:

#define bit_reverse_byte(n) ( (((n) & 128)>>7)|(((n) & 64)>>5)|(((n) & 32)>>3)|(((n) & 16)>>1)|  (((n) & 8)<<1)|(((n) & 4)<<3)|(((n) & 2)<<5)|(((n) & 1)<<7) )#define bit_reverse_word(n) (bit_reverse_byte((n) >> 8) | (bit_reverse_byte(n) << 8))

在 PIC 上用 C 语言简单呈现一个非循环单字节位反转函数大约需要 17-19 条单周期指令;一个字位反转将是 34,或者大约 10 加上一个字节反转函数(将执行两次)。最佳的汇编代码大约是 15 条用于字节反转的单周期指令或 17 条用于字反转的单周期指令。为某个字节变量b 计算bit_reverse_byte(b) 需要数十条指令,总计数十个周期。计算一些 16 位字的 bit_reverse_word(w)w` 可能需要数百条指令,需要数百或数千个周期才能执行。如果可以在将扩展到总共四个指令(基本上只是加载结果)但在内联的场景中使用函数调用的场景中使用类似于上述公式的方法将函数标记为内联扩展,那将是非常好的扩张将是令人发指的。

关于使用 C 预处理器计算 8 位 CRC?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9379587/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com