Proton BASIC Compiler - CCITT CRC16 [CRC-16] Routines


  • Pic® Basic


  • CCITT CRC16 [CRC-16] Routines

    I needed a stream CRC16 calculator for a project I was working on, I found a small example in C and ported it to Proton+, this code runs on a PIC® 18F46K22, but should work fine on any 16F too. I unwrapped a lot of the C code to compile smaller. The demo takes input from USART1, use a MAX232 or equivalent line translator in needed, I use a TTL level serial port. Connect at 9600 8-N-1, bytes will be echoed back with an ongoing byte-per-byte CRC calculation. Test vectors can be found in the source provided. Code compiles relatively small, 536 bytes including the demo code. There's a 32 byte lookup table stored in CData, this is included in the estimate. The CRC16 routines only consume 7 bytes of RAM, including the input and output variables.

    I hope this helps someone.

    Code:
    '*********************************************************************
    '*  Name    : CRC16.BAS                                [CCITT CRC16] *
    '*  Author  : Ashley Roll, Phil Ciebiera                             *
    '*  Notice  : Derived from works at:                                 *
    '*          : www.digitalnemesis.com/info/codesamples/embeddedcrc16/ * 
    '*          : Ported to Proton+ BASIC - www.protonbasic.co.uk/       *
    '*  Date    : 2/21/2011                                              *
    '*  Version : 1.0                                                    *
    '*  Notes   : Test Vector: 0x313233343536373839 : 0x29B1             *
    '*          : Test Vector: 0x393837363534333231 : 0x84DF             *
    '*          : Continuously calculates CRC16 CCITT on incoming USART1 *
    '*          : PIC®18F46K22 INTOSC 16x4PLL 64MHz - Connect 9600 8-N-1 *
    '*          : This code is shared under The MIT License              *
    '*********************************************************************
    
    
    '--- BEGIN: Microchip™ PIC® INITIALIZATION ---
    Device 18F46K22
    Xtal 16
    All_Digital True
    
    Config_Start
        FOSC = INTIO67  ' Internal oscillator block, port function on RA6 and RA7
        PLLCFG = On     ' Oscillator multiplied by 4  
        PRICLKEN = On   ' Primary clock is always enabled
        FCMEN = Off     ' Fail-Safe Clock Monitor disabled
        IESO = Off      ' Oscillator Switchover mode disabled
        PWRTEN = Off    ' Power up timer disabled
        BOREN = Off     ' Brown-out Reset disabled in hardware and software
        WDTEN = Off     ' Watch dog timer is always disabled. SWDTEN has no effect.
        'WDTPS = 1      ' 1:1
        CCP2MX = PORTB3 ' CCP2 input/output is multiplexed with RB3
        PBADEN = Off    ' PORTB<5:0> pins are configured as digital I/O on Reset 
        CCP3MX = PORTB5 ' P3A/CCP3 input/output is multiplexed with RB5  
        HFOFST = On     ' HFINTOSC output and ready status are not delayed by the oscillator stable status
        T3CMX = PORTC0  ' T3CKI is on RC0
        P2BMX = PORTD2  ' P2B is on RD2
        MCLRE = EXTMCLR ' RE3 input pin enabled; MCLR disabled
        STVREN = Off    ' Stack full/underflow will not cause Reset
        LVP = On        ' Single-Supply ICSP disabled
        XINST = Off     ' Instruction set extension and Indexed Addressing mode enabled
        Debug = Off     ' Disabled
        CP0 = Off       ' Block 0 (000800-003FFFh) not code-protected  
        CP1 = Off       ' Block 1 (004000-007FFFh) not code-protected
        CP2 = Off       ' Block 2 (008000-00BFFFh) not code-protected  
        CP3 = Off       ' Block 3 (00C000-00FFFFh) not code-protected
        CPB = Off       ' Boot block (000000-0007FFh) not code-protected
        CPD = Off       ' Data EEPROM not code-protected  
        WRT0 = Off      ' Block 0 (000800-003FFFh) not write-protected
        WRT1 = Off      ' Block 1 (004000-007FFFh) not write-protected  
        WRT2 = Off      ' Block 2 (008000-00BFFFh) not write-protected  
        WRT3 = Off      ' Block 3 (00C000-00FFFFh) not write-protected
        WRTC = Off      ' Configuration registers (300000-3000FFh) not write-protected  
        WRTB = Off      ' Boot Block (000000-0007FFh) not write-protected
        WRTD = Off      ' Data EEPROM not write-protected  
        EBTR0 = Off     ' Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
        EBTR1 = Off     ' Block 1 (004000-007FFFh) not protected from table reads executed in other blocks  
        EBTR2 = Off     ' Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks  
        EBTR3 = Off     ' Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks
        EBTRB = Off     ' Boot Block (000000-0007FFh) not protected from table reads executed in other blocks  
    Config_End 
    
    OSCCON.4 = 1 
    OSCCON.5 = 1 'FOR 16MHZ
    OSCCON.6 = 1 
    
    DelayMS 300
    '--- END: Microchip™ PIC® INITIALIZATION ---
    
    ' Jump over CRC16 Definitions to the Demo
    GoTo DemoStart
    
    ' --- BEGIN: CRC16 RELATED ---
    ' CRC16 Result Bytes
    Dim bCRC16_High As Byte
    Dim bCRC16_Low As Byte
    ' Internal Work Variables
    Dim bCRC16_Work1 As Byte
    Dim bCRC16_Work2 As Byte
    ' CRC16 I/O Bytes
    Dim bCRC16_Input As Byte
    Dim wCRC16_Output As Word
    
    ' Sets the initial CRC value
    CRC16_Initialize:
        bCRC16_High = $FF
        bCRC16_Low = $FF
    Return
    
    ' Processes the CRC16 from the byte at bCRC16_Input and updates the checksum at wCRC16_Output
    CRC16_ProcessInput:    
        ' process byte from CRC16_Input
        ' High Nibble
        bCRC16_Work2 = bCRC16_Input >> 4
        GoSub CRC16_ProcessNibble
        ' Low Nibble
        bCRC16_Work2 = bCRC16_Input & $0F
        GoSub CRC16_ProcessNibble
        ' Assemble output word
        wCRC16_Output.LowByte = bCRC16_Low
        wCRC16_Output.HighByte = bCRC16_High
    Return
    
    ' Actually computes a 4-bit CRC
    CRC16_ProcessNibble:
        ' Step one, extract the Most significant 4 bits of the CRC register
        bCRC16_Work1 = bCRC16_High >> 4
        ' XOR in the Message Data into the extracted bits
        bCRC16_Work1 = bCRC16_Work1 ^ bCRC16_Work2  
        ' Shift the CRC Register left 4 bits
        bCRC16_Work2 = bCRC16_Low >> 4
        bCRC16_High = bCRC16_High << 4
        bCRC16_High = bCRC16_High | bCRC16_Work2
        bCRC16_Low = bCRC16_Low << 4
        ' Do the table lookups and XOR the result into the CRC Tables
        ' High byte
        bCRC16_Work2 = CRead (CRC16_LookupTables + bCRC16_Work1)
        bCRC16_High = bCRC16_High ^ bCRC16_Work2
        ' Low byte
        bCRC16_Work2 = CRead (CRC16_LookupTables + 16 + bCRC16_Work1)
        bCRC16_Low = bCRC16_Low ^ bCRC16_Work2
    Return
    ' --- PAUSE: CRC16 RELATED ---
    
     
    ' --- BEGIN: DEMO RELATED ---
    DemoStart:
    ;Calculated Baudrate = 9592 @ Xtal 16MHz, Error = -0.08%
    RCSTA     = 144 ; Enable continuous receive
    TXSTA     = 36  ; Enable transmit, BRGH = 1
    SPBRG     = 160 ; Baud Rate Generator Low Byte Value
    SPBRGH    = 1   ; Baud Rate Generator High Byte Value
    BAUDCON.3 = 1   ; Enable the 16 bit Baud Rate Generator
    Declare Hserial_Clear On
    Dim ser_data As Byte
    GoSub CRC16_Initialize
    Demo:
        HSerIn 100, Demo, [ser_data]    ' Listen for a byte on the USART
        bCRC16_Input = ser_data         ' Assign the byte to the CRC16 routine input
        GoSub CRC16_ProcessInput        ' Process the CRC16 for the byte
        HSerOut [ser_data,": ",Hex4 wCRC16_Output,13,10] ' Output the formatted result
    GoTo Demo                           ' Loop
    ' --- END: DEMO RELATED ---
    
       
    ' --- RESUME: CRC16 RELATED ---
    ' CRC16 computational lookup tables
    CRC16_LookupTables:
    CData $00, $10, $20, $30, $40, $50, $60, $70, $81, $91, $A1, $B1, $C1, $D1, $E1, $F1    ' CRC16_Lookup High
    CData $00, $21, $42, $63, $84, $A5, $C6, $E7, $08, $29, $4A, $6B, $8C, $AD, $CE, $EF    ' CRC16_Lookup Low
    ' --- END: CRC16 RELATED ---
    This article was originally published in forum thread: CCITT CRC16 [CRC-16] Routines started by pciebiera View original post
  • Recent Activity

    rcurl-44

    PICKitPlus Forum

    Thread Starter: evan

    PICkitPlus PICkitPlus is a total replacement for the existing Microchip PICkit2™ and PICkit3™ Windows GUI software. The PICkitPlus software ...

    rcurl Today, 20:28 Go to last post
    towlerg-21522

    Request for Assistance - PIC16F15323

    Thread Starter: gdesantis

    After having successfully programmed various enhanced PIC16 MCUs, I plan to use a PIC16F15323 in a new application. As always, I first start with a...

    towlerg Today, 13:26 Go to last post