 
-------------CRC16_SX.ASM---------------------- ;By Charles Ader ;Translated to SX by Nikolai Golovchenko RESET start crc_hi DS 1 crc_lo DS 1 ;******************************************************************** ; CRC Test Program ;******************************************************************** org 1h start clr crc_hi clr crc_lo mov W, #080H ; crc_hi:crc_lo = 00 00 call CRC16 mov W, #075H ; crc_hi:crc_lo = A0 01 call CRC16 mov W, #08AH ; crc_hi:crc_lo = 27 A0 call CRC16 mov W, #00BH ; crc_hi:crc_lo = DF A6 call CRC16 mov W, #075H ; crc_hi:crc_lo = BD 1E call CRC16 mov W, #0C7H ; crc_hi:crc_lo = EF FC call CRC16 mov W, #0AAH ; crc_hi:crc_lo = D3 AE call CRC16 mov W, #075H ; crc_hi:crc_lo = C3 D2 call CRC16 mov W, #0C7H ; crc_hi:crc_lo = BA 82 call CRC16 mov W, #055H ; crc_hi:crc_lo = F3 7B call CRC16 mov W, #043H ; crc_hi:crc_lo = 1C 73 call CRC16 mov W, #01CH ; crc_hi:crc_lo = 14 1c call CRC16 mov W, #014H ; crc_hi:crc_lo = 00 14 call CRC16 jmp 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, 32 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 xor W, crc_lo ;W = input XOR old crc_lo xor W, crc_hi ;Swap old crc_hi with W xor crc_hi, W ; xor W, crc_hi ;new crc_hi = input XOR old crc_lo mov crc_lo, W ;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 INC STATUS to compliment ; carry. This is safe because the XOR ; will clear the zero flag if any of the ; inc instructions are going to execute. ; ; The inc can be executed a maximum of ; four times after the XOR before the ; bits to the left of zero in status will ; be affected. ; ; We use INC at most three time here. ; ; Note by NG: INC instruction doesn't work this way ; on SX chip. But INCSZ does! Since Z flag is ; set to zero if any INCSZ are going to execute, ; then STATUS will never reach zero after three ; INCSZ. Therefore skip is never executed. mov W, crc_hi ;Save crc_hi in W swap crc_hi ;Trade nibbles xor crc_hi, W ;XOR high half byte with low rr crc_hi ;Initialize Carry snb crc_hi.0 incsz STATUS ;Compliment carry snb crc_hi.1 incsz STATUS ;Compliment carry snb crc_hi.2 incsz STATUS ;Compliment carry mov crc_hi, W ;Restore crc_hi from W ; ; Use the parity of crc_hi, (input XOR crc_lo), ; to complete the CRC calculation. ; mov W, #001H snb C ; If carry xor crc_lo, W ; flip bit 0 of crc_lo mov W, #040H rr crc_hi ; shift parity into crc_hi snb C ; if shift out is one xor crc_lo, W ; flip bit 6 of crc_lo mov W, <<crc&hi ; unshift crc_hi into W xor crc_hi, W ; combine them rr crc_hi ; shift parity back into crc_hi mov W, #080H snb C ; if shift out is one xor crc_lo, W ; flip bit 7 of crc_lo retw 0 -------------End CRC16_SX.ASM------------------
-------------CRC16.ASM----------------------
;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  ---------------------
Questions:
Hello,+
I've tried the code shown above for the PIC micro (on a 16F877A and 16F84A targets). The simulation with the MPLAB software works fine but when I try to run this code on any of the target processors the results are quite different (don't work).
For example, at the initial stage I load crc_hi and crc_lo registers with 0xFF the buffer pattern is: 02-01-01-00-10-03 (all in HEX) and when I update the CRC calculation with all the bytes contained at the buffer including the last one, I xor the final result with 0xFF, so the result must be crc_hi=8F, crc_lo= FB. This works fine in MPLAB but, when I run this code in the PICmicro I found that the results given are crc_hi=8E, crc_lo=3B. The results are wrong!
Pseudo code for the above:
crc_hi = crc_lo = 0xFF;
update crc for all buffer bytes;
crc_hi = crc_hi XOR 0xFF;
crc_lo = crc_lo XOR 0xFF;
Even more, using the same target processors and a different buffer for the CRC calculation (01-04-01-01-10-03) the resulting CRC is: crc_hi=12, crc_lo=08. This works fine on the MPLAB IDE and when I run this code on the PIC micro runs OK too!! With this pattern the code works!
So, the question is, why the code runs fine on the MPLAB IDE for all tests made and for all patterns and why not on the PICmicro? any initial missconfiguration or something like that?
I hope anybody can help me solving this trouble!!
Regards,
Elkin.
| file: /Techref/scenix/lib/io/osi2/crc16ca_sx.htm, 20KB, , updated: 2013/7/22 18:15, local time: 2025/10/31 09:06, 
 
216.73.216.87,10-2-37-96: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://www.piclist.com/tecHREF/scenix/lib/io/osi2/crc16ca_sx.htm"> SX Specific Cyclic Redundancy Check </A> | 
| Did you find what you needed? | 
|  PICList 2025 contributors: o List host: MIT, Site host massmind.org, Top posters @none found - Page Editors: James Newton, David Cary, and YOU! * Roman Black of Black Robotics donates from sales of Linistep stepper controller kits. * Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters. * Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated! * Contributors: Richard Seriani, Sr. | 
| The Backwoods Guide to Computer Lingo | 
.