0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

了解和使用Maxim 1-Wire和iButton产品的循环冗余校验

星星科技指导员 来源:ADI 作者:ADI 2023-05-16 11:23 次阅读

所有1-Wire器件(包括iButton器件)在只读存储器(ROM)中包含一个8字节的唯一注册号。该注册号用作1-Wire总线上的唯一网络地址。为确保数据通信的完整性,每个注册号的一个字节为1-Wire CRC字节。本应用笔记解释了如何计算这种8位1-Wire CRC。它还继续解释用于验证保存在设备内存中的记录的 16 位 CRC。1-Wire CRC和CRC-16均在选定的1-Wire器件的硬件中生成,以验证数据。®®

介绍

Maxim iButton产品是一系列器件,它们都按照称为1-Wire协议的特定命令序列通过单线进行通信。每个器件的一个关键特性是在制造时写入每个部件的唯一 8 字节 ROM 代码。此 8 字节代码的组件如图 1 所示。最低有效字节包含标识 iButton 产品类型的系列代码。例如,DS1990A的家族代码为01十六进制,DS1922L的家族代码为41十六进制。由于相同或不同系列类型的多个器件可以同时驻留在同一条1-Wire总线上,因此主机必须确定如何正确访问其位于1-Wire总线上的每个器件。家庭代码提供了此信息。接下来的 6 个字节包含一个唯一的序列号,允许将同一系列代码中的多个设备相互区分。这个唯一的序列号可以看作是1-Wire总线上每个器件的“地址”。整个设备集合加上主机,形成了一种微型局域网或MicroLAN;它们都通过单根公共线路进行通信。每个器件的ROM代码中的最高有效字节包含一个循环冗余校验(CRC)值,该值基于该部分的前7个字节的数据。当主机系统开始与设备通信时,首先读取 8 字节 ROM,首先读取 LSB。如果主机计算的CRC与ROM数据第7字节中包含的CRC一致,则可以认为通信有效。如果不是这种情况,则发生了错误,应再次读取ROM代码。

wKgaomRi9yuAeXv6AAA7RAFf83c175.gif

图1.iButton系统配置使用1-Wire CRC。

一些iButton产品除了具有主机系统可以使用适当命令访问的8字节ROM之外,还具有高达8kB的随机存取存储器(RAM)。即使iButton设备没有板载CRC硬件,如果主机能够计算ROM代码的CRC值,那么也可以开发使用CRC在设备的RAM部分存储和检索数据的程序。数据可以正常方式写入设备;然后,主机计算的CRC值将附加并与数据一起存储。当从iButton设备检索此数据时,该过程将反转。主机将为数据字节计算的 CRC 值与作为该数据的 CRC 存储在内存中的值进行比较。如果值相等,则从iButton设备读取的数据可以被视为有效。为了利用CRC的强大功能来验证1-Wire总线上的串行通信,必须了解CRC是什么以及它们是如何工作的。此外,硬件或软件实现都需要一种由主机计算CRC值的实用方法。

背景

可以通过多种方式检查串行数据是否存在错误。一种常见的方法是在每个正在检查的数据包中包含额外的位,以指示是否发生了错误。例如,对于 8 位 ASCII 字符的数据包,每个 ASCII 字符都会附加一个额外的位,指示该字符是否包含错误。假设数据由 11010001 位字符串组成。一 9千位将被附加,因此 1 的总位数始终是奇数。因此,将附加一个 1,数据包将变为111010001。带下划线的字符表示使完整的 9 位数据包具有奇数位数所需的奇偶校验位值。如果接收到的数据是111010001的,则假定该信息是正确的。但是,如果收到的数据是111010101,其中 7千左边的位被错误地接收,1 的总数不再奇数,并且检测到错误条件并采取适当的措施。这种类型的方案称为奇偶校验。同样,也可以选择1的总数始终等于偶数,因此称为偶数奇偶校验。但是,此方案仅限于检测奇数位错误。在上面的示例中,如果数据损坏并变得111011101,其中 6千和 7千左边的位是错误的,奇偶校验看起来是正确的;然而,无论使用偶数奇偶校验还是奇偶校验,都不会检测到错误。

描述

马克西姆1线CRC

在以最少的硬件量定位串行数据流中的错误时,最有效的错误检测方案是CRC。本文介绍了Maxim产品中使用的CRC函数的操作和性质,而不涉及证明语句和描述的数学细节。CRC属性背后的数学概念在参考文献中有详细的描述。CRC最容易理解的是考虑该功能,因为它实际上是内置在硬件中的,通常表示为带有反馈的移位寄存器排列,如图2所示。或者,CRC 有时被称为虚拟变量 X 中的多项式表达式,每个项都有二进制系数。系数直接对应于移位寄存器实现中显示的反馈路径。硬件描述的移位寄存器中的级数或多项式表达式中存在的最高阶系数表示计算的 CRC 值的大小。数字数据通信中常用的CRC代码包括CRC-16和CRC-CCITT,每个代码都计算16位CRC值。Maxim 1-Wire CRC幅度为8位,用于检查写入每个64-Wire产品的1位ROM代码。该ROM代码由写入最低有效字节的8位家族代码,写入接下来48个字节的唯一6位序列号以及基于ROM的前56位计算然后写入最高有效字节的CRC值组成。图2中由异或门表示的反馈路径的位置,或多项式表达式中系数的存在,决定了CRC的属性以及算法定位数据中某些类型错误的能力。对于1-Wire CRC,可检测的错误类型包括:

64 位数字内任意位置的任何奇数错误。

64 位数字内的任何位置的所有双位错误。

可以包含在 8 位“窗口”中的任何错误集群(1-8 位不正确)。

大多数较大的错误群集。

输入数据与图2中移位寄存器第八级的输出是非或的。移位寄存器在数学上可以视为分频电路。输入数据是除数,带有反馈的移位寄存器充当除数。结果商被丢弃,其余部分是该特定输入数据流的CRC值,该值在最后一个数据位移入后驻留在移位寄存器中。从移位寄存器实现中可以明显看出,最终结果(CRC值)以一种非常复杂的方式依赖于所呈现位的过去历史。因此,需要极其罕见的错误组合才能逃脱这种方法的检测。

wKgZomRi9yyANun2AAAZtuDKZ5Q491.gif

图2.马克西姆 1 线 8 位 CRC。

示例2中的示例在显示每个数据位后计算CRC值。移位寄存器电路在计算开始时始终复位为0。计算从 64 位 ROM 的 LSB 开始,这是本例中的 02 十六进制系列代码。输入所有56个数据位(序列号+族码)后,移位寄存器中包含的值为A2十六进制,即该输入流的1-Wire CRC值。如果已经计算出的CRC值(在本例中为A2十六进制)现在用作接下来8位数据的移位寄存器的输入,则输入整个64位数据后移位寄存器中的最终结果应全部为0。对于1-Wire CRC算法,此属性始终成立。如果移位寄存器中出现的任何 8 位值也用作输入流中的下一个 8 位,则移位寄存器中出现的结果在 8千数据位已移入始终为 00 十六进制。这可以通过观察8千移位寄存器的级始终等于输入数据位,使得控制反馈的EXOR门的输出和移位寄存器第一级的下一个状态值始终等于逻辑0。这导致移位寄存器在每个数据位显示时简单地从左向右偏移 0,直到整个寄存器在 0 之后用 8 填充千位。Maxim 1-Wire 64位ROM的结构利用这一特性来简化用于读取ROM的器件的硬件设计。清除主机中的移位寄存器,然后读取64个ROM位,包括CRC值。如果发生了正确的读数,则移位寄存器再次全为0,这是一个容易检测到的情况。如果移位寄存器中保留非零值,则必须重复读取操作。

到目前为止,讨论主要围绕CRC工艺的硬件表示,但显然,与硬件方法并行的软件解决方案是计算1-Wire CRC值的另一种方法。示例 1 中给出了如何对过程进行编码的示例。请注意,具有常数18十六进制的A寄存器的XRL(异或)是由于在第四级和第五级之后1-Wire CRC中存在EXOR反馈门,如图2所示。另一种软件解决方案是简单地构建一个查找表,该查找表可以直接访问当前存储在CRC寄存器中的任何8位值和任何8位模式的新数据。对于CRC寄存器的当前值为00十六进制的简单情况,可以计算输入字节的256个不同位组合并将其存储在矩阵中,其中矩阵的索引等于输入字节的值(即索引为I = 0到255)。可以证明,如果CRC寄存器的当前值不是00十六进制,那么对于任何当前CRC值和任何输入字节,查找表值与简化情况相同,但索引到表中的计算采用以下形式:

新CRC = 表 [I] 表示 I = 0 至 255;
其中 I = (当前 CRC) EXOR (输入字节)

对于当前CRC寄存器值为00十六进制的情况,公式简化为简单情况。第二种方法可以减少计算时间,因为操作可以基于字节完成,而不是前面示例中面向位的命令。但是,存在内存容量权衡,因为查找表必须存储并消耗 256 字节,而第一个示例除了程序代码之外几乎没有存储。示例 3 显示了此类代码的示例。表 1 显示了使用查找表方法重复的前面的示例。1-Wire CRC的两个特性有助于调试用于计算CRC值的代码。对于硬件实现,已经提到了第一个属性。如果将CRC寄存器的当前值用作数据的下一个字节,则生成的CRC值始终为00十六进制(请参阅上面的解释)。可用于确认代码正确操作的第二个属性是输入 CRC 寄存器当前值的 1 补码。对于1-Wire CRC算法,得到的CRC值始终为35十六进制或53十进制。其原因可以通过观察输入1的补码数据时CRC寄存器的操作来解释,如表2所示。

例 1.汇编语言程序

DO_CRC:	PUSH ACC	;save accumulator
	PUSH B	;save the B register
	PUSH ACC	;save bits to be shifted
	MOV B,#8	;set shift = 8 bits ;

CRC_LOOP:	XRL A,CRC	;calculate CRC
	RRC A	;move it to the carry
	MOV A,CRC	;get the last CRC value
	JNC ZERO	;skip if data = 0
	XRL A,#18H	;update the CRC value
;
ZERO:	RRC A	;position the new CRC
	MOV CRC,A	;store the new CRC
	POP ACC	;get the remaining bits
	RR A	;position the next bit
	PUSH ACC	;save the remaining bits
	DJNZ B,CRC_LOOP	;repeat for eight bits
	POP ACC	;clean up the stack
	POP B	;restore the B register
	POP ACC	;restore the accumulator
	RET

例 2.1-Wire CRC的计算示例

wKgaomRi_VCAACC7AAA0_7IpFO0831.png

CRC价值 输入值
00000000 0
00000000 1
10001100 0 2
01000110 0___
00100011 0
10011101 0
11000010 0 0
01100001 0___
10111100 0
01011110 0
00101111 1 字节
00010111 1___
00001011 1
00000101 0
10001110 0 1
01000111 0___
10101111 0
11011011 0
11100001 0 8
11111100 1___
11110010 1
11110101 1
01111010 0 字节
00111101 1___
00011110 1
10000011 0
11001101 0 1
11101010 0___
01110101 0
10110110 0
01011011 0 0
10100001 0___
11011100 0
01101110 0
00110111 0 0
10010111 0___
11000111 0
11101111 0
11111011 0 0
11110001 0___
11110100 0
01111010 0
00111101 0 0
10010010 0___
01001001 0
10101000 0
01010100 0 0
00101010 0___
00010101 0
10000110 0
01000111 0 0
10101101 0___
11011010 0
01101101 0
10111010 0 0
01011101 0___
10100010 = A2 十六进制 = [00000001B81C (序列号) + 02(家庭代码)] 的 CRC 值]
10100010 0
01010001 1
00101000 0 2
00010100 0___
00001010 0
00000101 1
00000010 0 Å
00000001 1___
00000000 = 00 十六进制 = A2 的 CRC 值 [(CRC) + 00000001B81C(序列号)+ 02(家庭代码)]

例 3.1线CRC查找功能


Var
	CRC : Byte;
Procedure Do_CRC(X: Byte);
{
	This procedure calculates the cumulative Maxim 1-Wire CRC of all bytes passed to it.
The result accumulates in the global variable CRC.
}
Const
	Table : Array[0..255] of Byte = (

	0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
	157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
	35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
	190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
	70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
	219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
	101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
	248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
	140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
	17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
	175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
	50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
	202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
	87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
	233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
	116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53);

Begin
	CRC := Table[CRC xor X];
End;
当前 CRC 值 (= 当前表索引) 输入数据 新指数(= 当前 CRC 异或输入数据) 表 (新索引) (= 新的 CRC 值)
0000 0000 = 00 十六进制 0000 0010 = 02 十六进制 (00 H xor 02 H) = 02 十六进制 = 2 十进制 表[2]= 1011 1100 = BC 十六进制 = 188 dec
1011 1100 = BC 十六进制 0001 1100 = 1C 十六进制 (BC H xor 1C H) = A0 十六进制 = 160 dec 表[160]= 1010 1111 = AF 十六进制 = 175 dec
1010 1111 = 自动对焦六角 1011 1000 = B8 十六进制 (自动对焦 H xor B8 H) = 17 十六进制 = 23 十进制 表[23]= 0001 1110 = 1E 十六进制 = 30 dec
0001 1110 = 1E 十六进制 0000 0001 = 01 十六进制 (1E H xor 01 H) = 1 F 十六进制 = 31 dec 表[31]= 1101 110 = 直流十六进制 = 220 dec
1101 1100 = 直流十六进制 0000 0000 = 00 十六进制 (直流高或 00 小时)= 直流十六进制 = 220 十进制 表[220]= 1111 0100 = F4 十六进制 = 244 dec
11110100 = F4 十六进制 0000 0000 = 00 十六进制 (F4 H xor 00 H) = F4 十六进制 = 244 dec 表 [244]= 0001 0101 = 15 十六进制 = 21 十进制
0001 0101 = 15 十六进制 0000 0000 = 00 十六进制 (15 H xor 00 H) = 15 十六进制 = 21 十进制 表[21]= 1010 0010 = A2 十六进制 = 162 dec
1010 0010 = A2 十六进制 10100010 = A2 十六进制 (A2 H xor A2 H) = 十六进制 = 0 十进制 表[0]=0000 0000 = 00 十六进制 = 0 十进制

CRC寄存器与1的CRC寄存器补充相结合

X0 X1 X2 X3 X4 X5 X6 X7 X7*
1 X0 X1 X2 X3* X4* X5 X6 X6*
1 1 X0 X1 X2* X3 X4* X5 X5*
1 1 1 X0 X1* X2* X3 X4* X4*
0 1 1 1 X0* X1* X2 X3 X3*
1 0 1 1 0 X0* X1* X2 X2*
1 1 0 1 0 1 X0* X1* X1*
0 1 1 0 1 0 1 X0* X0*
0 0 1 1 0 1 0 1 最终 CRC 值 = 35 十六进制,53 十进制
注:X我* = X 的补码我

CRC-16 计算 iButton 设备中的 RAM 记录

如介绍中所述,除了在所有iButton设备中找到的唯一8字节ROM代码外,某些iButton设备还具有RAM。由于RAM中存储的数据量可能比8字节ROM码大,Maxim建议使用16位CRC值来保证数据的完整性,而不是用于ROM的8位1-Wire CRC。建议的特定CRC通常称为CRC-16。移位寄存器和多项式表示如图3所示。该图显示,对于 16 位 CRC,移位寄存器包含 16 个阶段,多项式表达式具有 16 阶项。如前所述,iButton设备不计算CRC值。主机必须生成该值,然后将 16 位 CRC 值追加到实际数据的末尾。由于iButton设备的“通信通道”(即两个金属接触面)的不确定性,数据传输可能会遇到通常分为三类的错误。首先,短暂的间歇性连接会导致数据中出现少量位错误,正常的CRC-<>函数旨在检测这些错误。第二种类型的错误发生在完全失去联系时,例如当iButton设备从阅读器上移开时。

这会导致数据的最后一部分被读取为逻辑 1,因为主机不会将任何与 iButton 设备的连接解释为所有 1。在大多数情况下,正常的CRC-16功能也可以检测到这种情况。第三种类型的错误是由读卡器短路引起的,这可能是由iButton设备未正确插入或在读卡器中明显倾斜引起的。读取器短路会导致主机将数据读取为全部 0。使用 CRC 时,这可能会导致问题,因为确定数据有效性的方法是读取数据加上存储的 CRC 值,并查看在主机上计算的结果 CRC 是否为 0000 十六进制(对于 16 位 CRC)。如果读取器短路,则数据加上与数据一起存储的CRC值将读取为全为0,并且发生了错误读取,但主机计算的CRC错误地指示了有效的读取。为避免这种情况,Maxim建议将计算出的CRC-16值(CRC-16*)的补码与写入RAM的数据一起存储。使用未互补的CRC-16值,从iButton器件检索数据的过程与1-Wire CRC外壳类似。也就是说,如果主机中的CRC寄存器初始化为0000十六进制,然后从iButton设备读取所有数据加上与数据一起存储的CRC-16值,则主机的计算结果应具有0000十六进制,作为最终结果。相反,如果CRC-16值的补码与iButton中的数据一起存储,则主机上的CRC寄存器初始化为0000十六进制,并读取实际数据加上存储的CRC-16*值。生成的 CRC 值应为 B001 十六进制才能有效读取。这极大地改善了系统的操作,因为它不能再被阅读器的短路所愚弄。CRC-16功能具有这些特性的原因可以用类似于1-Wire CRC外壳的方式显示出来(见图3和图5)。16 位 CRC 的操作在理论上与前面描述的 8 位版本相同,但 CRC 的属性发生了变化,因为 16 位值现在可用于错误检测。对于CRC-16功能,可检测的错误类型包括:

数据记录中任何位置的任何奇数错误。

数据记录中任意位置的所有双位错误。

可能包含在 16 位“窗口”内的任何错误簇(1-16 位不正确)。

大多数较大的错误群集。

chaijie_default.png

图3.CRC-16 硬件描述和多项式。

CRC-16 功能的硬件实现从图 3 中给出的描述中很简单。示例 4 显示了一个软件解决方案,该解决方案类似于使用单位操作计算 CRC-16 值的硬件操作。和以前一样,可以通过使用查找表开发计算量较少的软件解决方案。8位1-Wire CRC查找表的基本概念也适用于CRC-16外壳。但是,需要对 8 位情况的过程进行轻微修改,因为如果像以前一样将 CRC-16 函数的整个 16 位结果映射到一个表中,则该表将有 2 个16或 65,536 个条目。示例 5 显示了另一种方法,其中计算 16 位 CRC 值并将其存储在两个 256 个条目表中,一个包含高位字节,另一个包含生成的 CRC 的低位字节。对于任何当前的 16 位 CRC 值(表示为当前高阶字节的Current_CRC16_Hi和当前低阶字节的Current_CRC16_Lo)以及任何新的输入字节,确定索引到高阶字节表中以定位新的高阶字节 CRC 值 (New_CRC16_Hi) 的公式如下:

New_CRC16_Hi = CRC16_Tabhi[I] 表示 I = 0 到 255;其中 I = (Current_CRC16_Lo) EXOR(输入字节)

确定索引的公式 进入低位字节表,用于定位新的低位字节 CRC 值 (New_CRC16_Lo) 表示为:

New_CRC16_Lo = (CRC16_Tablo[I]) EXOR (Current_CRC16_Hi) 对于 I = 0 到 255;
其中 I = (Current_CRC16_Lo) EXOR(输入字节)

图 4 显示了此方法工作原理的示例。

例 4.用于CRC-16计算的汇编语言

crc_lo data 20h ; lo byte of crc calculation (bit addressable)
crc_hi data 21h ; hi part of crc calculation



;---------------------------------------------------------------------------
;	CRC16 subroutine.
;	- accumulator is assumed to have byte to be crc'ed
;	- two direct variables are used crc_hi and crc_lo
;	- crc_hi and crc_lo contain the CRC16 result
;---------------------------------------------------------------------------
crc16:			; calculate crc with accumulator
	push b	; save value of b
	mov b, #08h	; number of bits to crc.
crc_get_bit:
	rrc a	; get low order bit into carry
	push acc	; save a for later use
	jc crc_in_1	;got a 1 input to crc
	mov c, crc_lo.0	;xor with a 0 input bit is bit
	sjmp crc_cont	;continue
crc_in_1:
	mov c, crc_lo.0	;xor with a 1 input bit
	cpl c	;is not bit.
crc_cont:
	jnc crc_shift	; if carry set, just shift
	cpl crc_hi.6	;complement bit 15 of crc
	cpl crc_lo.1	;complement bit 2 of crc
crc_shift
	mov a, crc_hi	; carry is in appropriate setting
	rrc a ; rotate	it
	mov crc_hi, a	; and save it
	mov a, crc_lo	; again, carry is okay
	rrc a ; rotate	it
	mov crc_lo, a	; and save it
	pop acc	; get acc back
	djnz b, crc_get_bit	; go get the next bit
	pop b	; restore b
	ret
	end

例 5.使用查找表的CRC-16汇编语言

crc_lo data 40h	; any direct address is okay
crc_hi data 41h
tmp data 42h



;---------------------------------------------------------------------------
;	CRC16 subroutine.
;	- accumulator is assumed to have byte to be crc'ed
;	- three direct variables are used, tmp, crc_hi and crc_lo
;	- crc_hi and crc_lo contain the CRC16 result
;	- this CRC16 algorithm uses a table lookup
;---------------------------------------------------------------------------
crc16:
	xrl a, crc_lo	; create index into tables
	mov tmp, a	; save index
	push dph	; save dptr
	push dpl	;
	mov dptr, #crc16_tablo	; low part of table address
	movc a, @a+dptr	; get low byte
	xrl a, crc_hi	;
	mov crc_lo, a	; save of low result
	mov dptr, #crc16_tabhi	; high part of table address
	mov a, tmp	; index
	movc a, @a+dptr	;
	mov crc_hi, a	; save high result
	pop dpl	; restore pointer
	pop dph	;
	ret	; all done with calculation
crc16_tablo:
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h
	db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h
crc16_tabhi:
	db 000h, 0c0h, 0c1h, 001h, 0c3h, 003h, 002h, 0c2h
	db 0c6h, 006h, 007h, 0c7h, 005h, 0c5h, 0c4h, 004h
	db 0cch, 00ch, 00dh, 0cdh, 00fh, 0cfh, 0ceh, 00eh
	db 00ah, 0cah, 0cbh, 00bh, 0c9h, 009h, 008h, 0c8h
	db 0d8h, 018h, 019h, 0d9h, 01bh, 0dbh, 0dah, 01ah
	db 01eh, 0deh, 0dfh, 01fh, 0ddh, 01dh, 01ch, 0dch
	db 014h, 0d4h, 0d5h, 015h, 0d7h, 017h, 016h, 0d6h
	db 0d2h, 012h, 013h, 0d3h, 011h, 0d1h, 0d0h, 010h
	db 0f0h, 030h, 031h, 0f1h, 033h, 0f3h, 0f2h, 032h
	db 036h, 0f6h, 0f7h, 037h, 0f5h, 035h, 034h, 0f4h
	db 03ch, 0fch, 0fdh, 03dh, 0ffh, 03fh, 03eh, 0feh
	db 0fah, 03ah, 03bh, 0fbh, 039h, 0f9h, 0f8h, 038h
	db 028h, 0e8h, 0e9h, 029h, 0ebh, 02bh, 02ah, 0eah
	db 0eeh, 02eh, 02fh, 0efh, 02dh, 0edh, 0ech, 02ch
	db 0e4h, 024h, 025h, 0e5h, 027h, 0e7h, 0e6h, 026h
	db 022h, 0e2h, 0e3h, 023h, 0e1h, 021h, 020h, 0e0h
	db 0a0h, 060h, 061h, 0a1h, 063h, 0a3h, 0a2h, 062h
	db 066h, 0a6h, 0a7h, 067h, 0a5h, 065h, 064h, 0a4h
	db 06ch, 0ach, 0adh, 06dh, 0afh, 06fh, 06eh, 0aeh
	db 0aah, 06ah, 06bh, 0abh, 069h, 0a9h, 0a8h, 068h
	db 078h, 0b8h, 0b9h, 079h, 0bbh, 07bh, 07ah, 0bah
	db 0beh, 07eh, 07fh, 0bfh, 07dh, 0bdh, 0bch, 07ch
	db 0b4h, 074h, 075h, 0b5h, 077h, 0b7h, 0b6h, 076h
	db 072h, 0b2h, 0b3h, 073h, 0b1h, 071h, 070h, 0b0h
	db 050h, 090h, 091h, 051h, 093h, 053h, 052h, 092h
	db 096h, 056h, 057h, 097h, 055h, 095h, 094h, 054h
	db 09ch, 05ch, 05dh, 09dh, 05fh, 09fh, 09eh, 05eh
	db 05ah, 09ah, 09bh, 05bh, 099h, 059h, 058h, 098h
	db 088h, 048h, 049h, 089h, 04bh, 08bh, 08ah, 04ah
	db 04eh, 08eh, 08fh, 04fh, 08dh, 04dh, 04ch, 08ch
	db 044h, 084h, 085h, 045h, 087h, 047h, 046h, 086h
	db 082h, 042h, 043h, 083h, 041h, 081h, 080h, 040h

wKgaomRi9zCARtbWAAA7_IBErRY724.gif

图4.CRC-16的计算和表查找方法的比较。

实施例6给出了一种有趣的中间方法。该代码使用图 16 所示的公式对整个当前 CRC 值和输入字节进行操作,从而为每个输入的字节生成一个 CRC-5 值。还显示了方程的推导,使用字母字符表示当前的 16 位 CRC 值,使用数字字符表示传入字节的位。八班后的结果得出所示方程。然后,这些方程可用于预先计算新CRC值的大部分。例如,请注意,数量ABCDEFGH01234567(定义为所有这些位的EXOR)是当前CRC的传入数据字节和低位字节的奇偶校验。与上述逐位方法和查找表方法相比,此方法减少了计算时间和内存空间。最后,提到了可用作测试用例的 CRC-16 函数的两个属性,以帮助调试任何先前方法的代码。第一个特性与1-Wire CRC外壳相同。如果CRC寄存器的当前16位内容也用作接下来的16位输入,则生成的CRC值始终为0000十六进制。CRC-16函数的第二个特性也类似于1-Wire CRC情况,如果CRC寄存器当前1位内容的16补码也用作下一个16位输入,则得到的CRC值始终为B0 01十六进制。这两个CRC-16特性的证明与1-Wire CRC外壳的证明类似。

例 6.高速CRC-16计算的汇编语言程序

lo equ 40h ; low byte of CRC
hi equ 41h ; high byte of CRC



crc16:
	push acc	; save the accumulator.
	xrl a, lo
	mov lo, hi	; move the high byte of the CRC.
	mov hi, a	; save data xor low(crc) for later
	mov c, p
	jnc crc0
	xrl lo, #01h	; add the parity to CRC bit 0
crc0:
	rrc a	; get the low bit in c
	jnc crc1
	xrl lo, #40h	; need to fix bit 6 of the result
crc1:
	mov c, acc.7
	xrl a, hi	; compute the results for other bits.
	rrc a	; shift them into place
	mov hi, a	; and save them
	jnc crc2
	xrl lo, #80h	; now clean up bit 7
crc2:
	pop acc	; restore everything and return
	ret

wKgZomRi9zGAdGnPAACz2SJ5lbE695.gif

图5.高速CRC-16计算方法。

审核比较:郭婷


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    30

    文章

    5028

    浏览量

    117723
  • 存储器
    +关注

    关注

    38

    文章

    7148

    浏览量

    161992
  • 1-Wir
    +关注

    关注

    0

    文章

    2

    浏览量

    5822
收藏 人收藏

    评论

    相关推荐

    基于C++模板技术的1-wire总线编程

    这是一个比较简单的 1-wire 总线 C++ 模板库。这个库由 4 个部分组成:11-wire 协议链路层接口类:ow_t定义了 1-wire 协议的操作集合:reset, enu
    发表于 11-22 23:40

    1-Wire 总线读写器

    Maxim Dallas 1-Wire 专用读写器DS9097/DS9490 淘宝网{:23:}
    发表于 07-10 14:30

    Maxim 1-Wire 读写器

    本公司自主研发并生产的1-Wire 单总线器件读写器,可兼容DS9097,采用USB接口,USB供电。提供DS2502/DS2502 ALL IN ONE 编程器,无需外部电源,连接USB接口就可以编程,和外部输入12V电源说Byebye淘宝网输入DS9097/DS9490搜索,保证最低价。。。
    发表于 07-10 14:35

    1-Wire 编程器

    `可对DALLAS 1-Wire器件进行编程,无论是DS18B20,还是EPROM 还是EEPROM,还是IButton纽扣等等。。兼容Maxim软件,采用USB接口,完全替代DS9097以及DS9097E25。`
    发表于 07-10 15:05

    1-Wire接口

    1-Wire接口要适应12V供电的芯片有什么?
    发表于 11-12 11:20

    Maxim带冷端补偿的1-Wire热电偶数字转换器

      Maxim Integrated Products, Inc.推出带有冷端补偿的1-Wire热电偶数字转换器MAX31850/MAX31851,现已开始提供样品。该系列器件集成了构建完备的热电偶
    发表于 11-13 16:23

    如何访问1-Wire API

    任何组件在创建者来实现这一点。有人知道如何访问1-Wire API吗?谢谢 以上来自于百度翻译 以下为原文I have been looking for a 1-wire component
    发表于 07-29 15:25

    如何使用FlexIO块访问1-wire设备?

    我的 MCU 是 RT1052,现在我需要访问一个温度传感器 DS18B20,这是一个具有单线协议的设备。使用延迟功能访问 1-wire 协议的方法不适用于 RTOS。 从参考手册来看,1-wire
    发表于 04-23 06:43

    循环冗余校验码的单片机及CPLD 实现

    循环冗余校验(CRC)是一种可靠性很高的串行数据校验方法。介绍循环冗余
    发表于 04-16 14:19 16次下载

    用XML实现1-Wire标签

    Dallas Semiconductor 所有1-Wire®器件以及iButton®产品在出厂前都被指定了各自唯一的64 位1-Wire 网络地址值这个地址值光刻在每片
    发表于 04-17 12:03 25次下载

    理解和运用Maxim iButton产品中的循环冗余校验

    摘要:全部1-Wire®器件,包括iButton®器件,都具有唯一的8字节注册码,储存在只读存储器(ROM)中。该注册码在1-Wire总线上用作唯一的网络地址。为确保数据通信的完整性,每个注
    发表于 04-30 14:20 978次阅读
    理解和运用<b class='flag-5'>Maxim</b> <b class='flag-5'>iButton</b><b class='flag-5'>产品</b>中的<b class='flag-5'>循环</b><b class='flag-5'>冗余</b><b class='flag-5'>校验</b>

    1-Wire双向电平转换器应用

    FPGA、微处理器、DS2482-100和DS2480B是常见的1-Wire主机器件。1-Wire/iButton从器件由Maxim生产,该系列器件的典型工作电压为2.8V至5.25V
    发表于 10-08 11:00 2429次阅读
    <b class='flag-5'>1-Wire</b>双向电平转换器应用

    循环冗余校验奇偶校验累加和校验等知识分享

    CRC校验循环冗余校验)是数据通讯中最常采用的校验方式。在嵌入式软件开发中,经常要用到CRC
    的头像 发表于 11-08 09:31 8476次阅读
    <b class='flag-5'>循环</b><b class='flag-5'>冗余</b><b class='flag-5'>校验</b>奇偶<b class='flag-5'>校验</b>累加和<b class='flag-5'>校验</b>等知识分享

    如何计算该8位1-Wire CRC

    的硬件中生成,以验证数据。 介绍 Maxim iButton产品是一系列器件,它们均按照称为1-Wire协议的特定命令序列,通过一
    的头像 发表于 05-14 11:47 2601次阅读
    如何计算该8位<b class='flag-5'>1-Wire</b> CRC

    了解 1-Wire 的简单性

    做得更好:了解 1-Wire 的简单性
    的头像 发表于 12-29 10:02 756次阅读
    <b class='flag-5'>了解</b> <b class='flag-5'>1-Wire</b> 的简单性