cmovies
|
分享:
▲
▼
你说的是 Modbus RTU 的 CRC16 吧!? 每个 Packet 的最后两个 Byte 就是 CRC16
/* Table of CRC values for high-order byte */ unsigned char auchCRCHi[] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 } ;
/* Table of CRC values for low-order byte */ unsigned char auchCRCLo[] = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40} ;
/* The function return the CRC as a type unsigned short. */ /* CRC Generation Function */ WORD CRC16(BYTE *puchMsg, int usDataLen) { BYTE uchCRCHi = 0xFF; /* high CRC byte initialized */ BYTE uchCRCLo = 0xFF; /* low CRC byte initialized */ WORD uIndex; /* will index index into lookup */
while (usDataLen--) /* pass through message buffer */ { uIndex = uchCRCHi ^ *puchMsg++; uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex]; uchCRCLo = auchCRCLo[uIndex]; } return (uchCRCHi << 8 | uchCRCLo); }
|
|
x0
[1 楼]
From:台湾中华电信HINET | Posted:2007-03-09 01:52 |
|
|
cmovies
|
分享:
▲
▼
table 就是上面两个表接在一起, 只是它要求将 auchCRCHi, auchCRCLo 放在 256 bytes 的边界上 这个 CRC 副程式的参数好像是 R0(uchCRCHi), R1(uchCRCLo) 这样新的资料要加入CRC时不是要先计算 R0 跟新资料的 XOR?
我比较喜欢用下面的程式:
; /* Table of CRC values for high-order byte */ auchCRCHi equ $ db 00h, C1h, 81h, 40h, 01h, C0h, 80h, 41h, 01h, C0h db 80h, 41h, 00h, C1h, 81h, 40h, 01h, C0h, 80h, 41h db 00h, C1h, 81h, 40h, 00h, C1h, 81h, 40h, 01h, C0h db 80h, 41h, 01h, C0h, 80h, 41h, 00h, C1h, 81h, 40h db 00h, C1h, 81h, 40h, 01h, C0h, 80h, 41h, 00h, C1h db 81h, 40h, 01h, C0h, 80h, 41h, 01h, C0h, 80h, 41h db 00h, C1h, 81h, 40h, 01h, C0h, 80h, 41h, 00h, C1h db 81h, 40h, 00h, C1h, 81h, 40h, 01h, C0h, 80h, 41h db 00h, C1h, 81h, 40h, 01h, C0h, 80h, 41h, 01h, C0h db 80h, 41h, 00h, C1h, 81h, 40h, 00h, C1h, 81h, 40h db 01h, C0h, 80h, 41h, 01h, C0h, 80h, 41h, 00h, C1h db 81h, 40h, 01h, C0h, 80h, 41h, 00h, C1h, 81h, 40h db 00h, C1h, 81h, 40h, 01h, C0h, 80h, 41h, 01h, C0h db 80h, 41h, 00h, C1h, 81h, 40h, 00h, C1h, 81h, 40h db 01h, C0h, 80h, 41h, 00h, C1h, 81h, 40h, 01h, C0h db 80h, 41h, 01h, C0h, 80h, 41h, 00h, C1h, 81h, 40h db 00h, C1h, 81h, 40h, 01h, C0h, 80h, 41h, 01h, C0h db 80h, 41h, 00h, C1h, 81h, 40h, 01h, C0h, 80h, 41h db 00h, C1h, 81h, 40h, 00h, C1h, 81h, 40h, 01h, C0h db 80h, 41h, 00h, C1h, 81h, 40h, 01h, C0h, 80h, 41h db 01h, C0h, 80h, 41h, 00h, C1h, 81h, 40h, 01h, C0h db 80h, 41h, 00h, C1h, 81h, 40h, 00h, C1h, 81h, 40h db 01h, C0h, 80h, 41h, 01h, C0h, 80h, 41h, 00h, C1h db 81h, 40h, 00h, C1h, 81h, 40h, 01h, C0h, 80h, 41h db 00h, C1h, 81h, 40h, 01h, C0h, 80h, 41h, 01h, C0h db 80h, 41h, 00h, C1h, 81h, 40h
; /* Table of CRC values for low-order byte */ auchCRCLo equ $ db 00h, C0h, C1h, 01h, C3h, 03h, 02h, C2h, C6h, 06h db 07h, C7h, 05h, C5h, C4h, 04h, CCh, 0Ch, 0Dh, CDh db 0Fh, CFh, CEh, 0Eh, 0Ah, CAh, CBh, 0Bh, C9h, 09h db 08h, C8h, D8h, 18h, 19h, D9h, 1Bh, DBh, DAh, 1Ah db 1Eh, DEh, DFh, 1Fh, DDh, 1Dh, 1Ch, DCh, 14h, D4h db D5h, 15h, D7h, 17h, 16h, D6h, D2h, 12h, 13h, D3h db 11h, D1h, D0h, 10h, F0h, 30h, 31h, F1h, 33h, F3h db F2h, 32h, 36h, F6h, F7h, 37h, F5h, 35h, 34h, F4h db 3Ch, FCh, FDh, 3Dh, FFh, 3Fh, 3Eh, FEh, FAh, 3Ah db 3Bh, FBh, 39h, F9h, F8h, 38h, 28h, E8h, E9h, 29h db EBh, 2Bh, 2Ah, EAh, EEh, 2Eh, 2Fh, EFh, 2Dh, EDh db ECh, 2Ch, E4h, 24h, 25h, E5h, 27h, E7h, E6h, 26h db 22h, E2h, E3h, 23h, E1h, 21h, 20h, E0h, A0h, 60h db 61h, A1h, 63h, A3h, A2h, 62h, 66h, A6h, A7h, 67h db A5h, 65h, 64h, A4h, 6Ch, ACh, ADh, 6Dh, AFh, 6Fh db 6Eh, AEh, AAh, 6Ah, 6Bh, ABh, 69h, A9h, A8h, 68h db 78h, B8h, B9h, 79h, BBh, 7Bh, 7Ah, BAh, BEh, 7Eh db 7Fh, BFh, 7Dh, BDh, BCh, 7Ch, B4h, 74h, 75h, B5h db 77h, B7h, B6h, 76h, 72h, B2h, B3h, 73h, B1h, 71h db 70h, B0h, 50h, 90h, 91h, 51h, 93h, 53h, 52h, 92h db 96h, 56h, 57h, 97h, 55h, 95h, 94h, 54h, 9Ch, 5Ch db 5Dh, 9Dh, 5Fh, 9Fh, 9Eh, 5Eh, 5Ah, 9Ah, 9Bh, 5Bh db 99h, 59h, 58h, 98h, 88h, 48h, 49h, 89h, 4Bh, 8Bh db 8Ah, 4Ah, 4Eh, 8Eh, 8Fh, 4Fh, 8Dh, 4Dh, 4Ch, 8Ch db 44h, 84h, 85h, 45h, 87h, 47h, 46h, 86h, 82h, 42h db 43h, 83h, 41h, 81h, 80h, 40h
CRC16: xrl a, uchCRCHi ; uIndex = uchCRCHi ^ *puchMsg++; mov r7, a mov dptr, #auchCRCHi movc a, @a+dptr xrl a, uchCRCLo mov uchCRCHi, a ; uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex]; mov dptr, #auchCRCLo mov a, r7 movc a, @a+dptr mov uchCRCLo, a ; uchCRCLo = auchCRCLo[uIndex]; ret
SendReadHolding: mov uchCRCHi, #0FFh mov uchCRCLo, #0FFh ; mov a, #01h ; Address call SendChar call CRC16 mov a, #03h ; Function Code = 03 (Read Holding Registers) call SendChar call CRC16 ; mov a, #00h call SendChar call CRC16 mov a, #00h ; Register Address 0000h call SendChar call CRC16 ; mov a, #00h call SendChar call CRC16 mov a, #01h ; Regisetr Count 0001h call SendChar call CRC16 ; mov a, uchCRCHi call SendChar mov a, uchCRCLo call SendChar ret
|
|
x0
[3 楼]
From:台湾中华电信HINET | Posted:2007-03-11 00:23 |
|
|
cmovies
|
分享:
▲
▼
51 本身就有偶同位的 P 位元可以使用(P 位元为 ACC 的偶同位) 因此你只要先将 SCON 设成 9-bit UART (SCON=D0h) 然后传送部分: ; 偶同位 mov a, #01h mov c, p mov tb8, c call SendChar ; 奇同位 mov a, #01h mov c, p cpl c mov tb8, c call SendChar
为何要把最后收到的资料放在最低位址? 一般要做这个必须要知道有多大的空间可以放及目前要放几个 然后使用 xch 指令来做, 例如用简单的范例来说(假设ACC为收到的资料) ; 范例一: 确定只有三个Bytes空间 xch a, 70h xch a, 71h xch a, 72h ; 范例二: 使用 R0, R2 来指定位址及空间大小 mov r0, #70h mov r2, #3 Serial_Shift: xch a, @r0 inc r0 djnz r2, Serial_Shift
|
|
x0
[5 楼]
From:台湾中华电信HINET | Posted:2007-03-13 01:39 |
|
|
|