By Charles Ader
;********************************************************************
;
; Compiled with MAPLAB 4.12.12
;
;********************************************************************
LIST p=16C54 ; PIC16C54 is the target processor
crc_hi equ 00EH
crc_lo equ 00FH
STATUS equ 3 ; STATUS register F3
CARRY equ 0 ; Carry bit in status register
;********************************************************************
; CRC Test Program
;********************************************************************
org 0h
start clrf crc_hi
clrf crc_lo
movlw 080H ; crc_hi:crc_lo = 00 00
call CRC16
movlw 075H ; crc_hi:crc_lo = A0 01
call CRC16
movlw 08AH ; crc_hi:crc_lo = 27 A0
call CRC16
movlw 00BH ; crc_hi:crc_lo = DF A6
call CRC16
movlw 075H ; crc_hi:crc_lo = BD 1E
call CRC16
movlw 0C7H ; crc_hi:crc_lo = EF FC
call CRC16
movlw 0AAH ; crc_hi:crc_lo = D3 AE
call CRC16
movlw 075H ; crc_hi:crc_lo = C3 D2
call CRC16
movlw 0C7H ; crc_hi:crc_lo = BA 82
call CRC16
movlw 055H ; crc_hi:crc_lo = F3 7B
call CRC16
movlw 043H ; crc_hi:crc_lo = 1C 73
call CRC16
movlw 01CH ; crc_hi:crc_lo = 14 1c
call CRC16
movlw 014H ; crc_hi:crc_lo = 00 14
call CRC16
goto start ; crc_hi:crc_lo = 00 00
;********************************************************************
;
; CRC-16 (x^16+x^15+x^2+x^0)
; No tables, No loops, No temporary registers used.
;
; Input: W = Data byte for CRC calculation
; crc_hi:crc_lo 16 bit CRC register
;
; Output: crc_hi:crc_lo updated.
;
; Notes: CARRY is trashed.
; DIGIT CARRY is trashed.
; ZERO is trashed.
; W is zero on exit.
;
; 30 instructions, 31 machine cycles per byte.
;
; Copyright (C) February 8, 2000. All Right Reserved.
; Charles Ader, PO Box 940 Pleasanton, California, USA.
;
; This code started out as an example program found in
; Dallas Semiconductor Application Note 27:
;
; Understanding and Using Cyclic Redundancy Checks
; with Dallas Semiconductor iButton(TM) Products.
;
; The application note shows an 8051 assembly language
; routine that calculates the same CRC as the hardware
; in the DS5001/2 secure micro.
;
;********************************************************************
CRC16 xorwf crc_lo,W ;W = input XOR old crc_lo
xorwf crc_hi,W ;Swap old crc_hi with W
xorwf crc_hi,F ;
xorwf crc_hi,W ;new crc_hi = input XOR old crc_lo
movwf crc_lo ;new crc_lo = old crc_hi
;
; Calculate parity of crc_hi, (input XOR old crc_lo),
; an place the result in carry.
;
; Save crc_hi in W and use crc_hi as a temp
; location so we can test bits.
;
; Note: We use INCF STATUS,F to compliment
; carry. This is safe because the XORWF
; will clear the zero flag if any of the
; INCF instructions are going to execute.
;
; The INCF can be executed a maximum of
; four times after the XORWF before the
; bits to the left of zero in status will
; be affected.
;
; We use INCF at most three time here.
;
movf crc_hi,W ;Save crc_hi in W
swapf crc_hi,F ;Trade nibbles
xorwf crc_hi,F ;XOR high half byte with low
rrf crc_hi,F ;Initialize Carry
btfsc crc_hi,0
incf STATUS,F ;Compliment carry
btfsc crc_hi,1
incf STATUS,F ;Compliment carry
btfsc crc_hi,2
incf STATUS,F ;Compliment carry
movwf crc_hi ;Restore crc_hi from W
;
; Use the parity of crc_hi, (input XOR crc_lo),
; to complete the CRC calculation.
;
movlw 001H
btfsc STATUS,CARRY ; If carry
xorwf crc_lo,F ; flip bit 0 of crc_lo
movlw 040H
rrf crc_hi,F ; shift parity into crc_hi
btfsc STATUS,CARRY ; if shift out is one
xorwf crc_lo,F ; flip bit 6 of crc_lo
rlf crc_hi,W ; unshift crc_hi into W
xorwf crc_hi,F ; combine them
rrf crc_hi,F ; shift parity back into crc_hi
movlw 080H
btfsc STATUS,CARRY ; if shift out is one
xorwf crc_lo,F ; flip bit 7 of crc_lo
retlw 0
;********************************************************************
; Power on reset
;********************************************************************
org 01FFH
goto start
end
-------------End CRC16.ASM------------------
Here is the same CRC16 routine for the x86 and 8051
----------CRC16.C for x86 start------------------------
#include <stdio.h>
/********************************************************************
CRC-16 (x^16+x^15+x^2+x^0)
No tables, No jumps.
Input: c = Data byte for CRC calculation
usp_crc = pointer to 16 bit CRC register
Output: CRC at pointer usp_crc is updated
Copyright (C) February 11, 2000. All Right Reserved.
Charles Ader, PO Box 940 Pleasanton, California, USA.
This code started out as an example program found in
Dallas Semiconductor Application Note 27:
Understanding and Using Cyclic Redundancy Checks
with Dallas Semiconductor iButton(TM) Products.
The application note shows an 8051 assembly language
routine that calculates the same CRC as the hardware
in the DS5001/2 secure micro.
********************************************************************/
void crc16(unsigned short *usp_crc, unsigned char c)
{
unsigned short crc; /* use a local temp so the compiler will */
/* handle all the x86 pointer crap. */
crc = *usp_crc;
_asm {
mov al,c
mov cx,crc
XOR AL,CL
MOV CL,CH
MOV CH,AL
LAHF
NOT AH
RCR AH,1
RCR AH,1
AND AH,1
XOR CL,AH
RCR AX,1
SBB AH,AH
AND AH,0x40
XOR CL,AH
MOV AH,AL
XOR AL,CH
RCL AH,1
RCR AL,1
MOV CH,AL
RCR AL,1
AND AL,0x80
XOR CL,AL
mov crc,cx
}
*usp_crc = crc;
}
/******************************************************
* MAIN FUNCTION *
*******************************************************/
main()
{
unsigned int crc;
while(1) {
crc = 0; /* crc = 0x0000 */
crc16(&crc,0x80); /* crc = 0xA001 */
crc16(&crc,0x75); /* crc = 0x27A0 */
crc16(&crc,0x8A); /* crc = 0xDFA6 */
crc16(&crc,0x0B); /* crc = 0xBD1E */
crc16(&crc,0x75); /* crc = 0xEFFC */
crc16(&crc,0xC7); /* crc = 0xD3AE */
crc16(&crc,0xAA); /* crc = 0xC3D2 */
crc16(&crc,0x75); /* crc = 0xBA82 */
crc16(&crc,0xC7); /* crc = 0xF37B */
crc16(&crc,0x55); /* crc = 0x1C73 */
crc16(&crc,0x43); /* crc = 0x141C */
crc16(&crc,0x1C); /* crc = 0x0014 */
crc16(&crc,0x14); /* crc = 0x0000 */
}
} /* end of main */
----------CRC16.C for x86 end ------------------------
----------CRC16.A51 for 8051 start---------------------
;
; From Dallas Application note 27
;
; CRC-16 (x^16+x^15+x^2+x^0)
; No tables, No loops, No temporary registers used.
;
; This code is from Dallas Semiconductor Application Note 27:
;
; Understanding and Using Cyclic Redundancy Checks
; with Dallas Semiconductor iButton(TM) Products.
;
; This routine that calculates the same CRC as the hardware
; in the DS5001/2 secure micro.
;-----------------------------------------------------------------------
NAME CRC_test
?DT?CRC_test SEGMENT DATA
rseg ?DT?CRC_test
CRCH: ds 1
CRCL: ds 1
?CO?CRC_test SEGMENT CODE
RSEG ?CO?CRC_test
public CRC_test
CRC_test:
mov CRCH,#0
mov CRCL,#0
mov A,#080H
call CRC16
mov A,#075H
call CRC16
mov A,#08AH
call CRC16
mov A,#00BH
call CRC16
mov A,#075H
call CRC16
mov A,#0C7H
call CRC16
mov A,#0AAH
call CRC16
mov A,#075H
call CRC16
mov A,#0C7H
call CRC16
mov A,#055H
call CRC16
mov A,#043H
call CRC16
ljmp CRC_test
;CALCULATE CRC16 IN PARALLEL TO THE GREATEST EXTENT PRACTICAL
; INPUT: BYTE TO BE INCUDED IN CRC CALCULATION IS IN ACC
; OUTPUT: CRCH:CRCL UPDATED TO INCLUDE THE NEW BYTE
;
CRC16:
PUSH ACC ;save this in case the caller needs
it
XRL A,CRCL
MOV CRCL,CRCH ;put the high byte of the crc in its
dest..
MOV CRCH,A ;save data xor low(crc) for later
MOV C,P
JNC CRC0
XRL CRCL,#001H
CRC0:
RRC A ;get the low bit in c
JNC CRC1
XRL CRCL,#040H
CRC1:
MOV C,ACC.7
XRL A,CRCH ;compute the results for bits P...U
RRC A ;shift them into place
MOV CRCH,A ;and save them
JNC CRC2
XRL CRCL,#080H
CRC2:
POP ACC ;and restore everything and return
RET
end
----------CRC16.A51 for 8051 end ---------------------
Comments:
xorwf Crc16 + 0, W; W = input XOR old crc_lo( writren at C, see above
)[Hynek];
xorwf Crc16 + 1, W; Swap old crc_hi with W;
xorwf Crc16 + 1, F;
xorwf Crc16 + 1, W; new crc_hi = input XOR old crc_lo;
movwf Crc16 + 0; new crc_lo = old crc_hi;
; Calculate parity of crc_hi, ( input XOR old crc_lo ), ;
; an place the result in carry.;
; Save crc_hi in W and use crc_hi as a temp;
; location so we can test bits.;
swapf Crc16 + 1, W; Save crc_hi in W[Hynek];
xorwf Crc16 + 1, W; XOR high half byte with low[Hynek];
btfsc W, 1; Compute parity of bits 0 - 3 at bit 0[Hynek];
xorlw 1; b0 ^= b1[Hynek];
btfsc W, 2; [Hynek];
xorlw 1; b0 ^= b2[Hynek];
btfsc W, 3; [Hynek];
xorlw 1; b0 ^= b3[Hynek];
andlw 1; W = parity[Hynek];
; Use the parity of crc_hi, ( input XOR crc_lo ), ;
; to complete the CRC calculation.;
xorwf Crc16 + 0, F; flip bit 0 of crc_lo;
rrf W, W; Carry - parity[Hynek];
rrf Crc16 + 1, F; shift parity into crc_hi;
movlw 0x40; [hynek];
btfsc STATUS, Carry; if shift out is one;
xorwf Crc16 + 0, F; flip bit 6 of crc_lo;
rlf Crc16 + 1, W; unshift crc_hi into W;
xorwf Crc16 + 1, F; combine them;
rrf Crc16 + 1, F; shift parity back into crc_hi;
movlw 0x80;
btfsc STATUS, Carry; if shift out is one;
xorwf Crc16 + 0, F; flip bit 7 of crc_lo;
+
| file: /Techref/microchip/crc16ca.htm, 12KB, , updated: 2021/7/6 08:58, local time: 2025/10/25 00:00,
216.73.216.188,10-3-157-36:LOG IN
|
| ©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://massmind.ecomorder.com/techref/microchip/crc16ca.htm"> PIC Microcontroller Bit Math Method - CRC</A> |
| Did you find what you needed? |
Welcome to ecomorder.com! |
Welcome to massmind.ecomorder.com! |
.