CRC -16 calculations back to ascii

Discussion in 'C-Touch/HomeGate/SchedulePlus/PICED Software' started by Merlin, Mar 12, 2006.

  1. Merlin

    Merlin

    Joined:
    Aug 3, 2004
    Messages:
    6
    Likes Received:
    0
    I am writing a interface using RS232 and PAC. The protocol requires a 2 Byte CRC value to be used on all coms

    I am using the following Procedure to calculate the CRC value

    procedure Update_CRC(Data: integer);
    const
    Poly = $A001;
    var
    I: Integer;
    Flag: Boolean;
    begin
    CRC := CRC xor Data;
    for I := 1 to 8 do
    begin
    Flag := (CRC and 1) <> 0;
    CRC := CRC shr 1;
    if Flag then CRC := CRC xor Poly;
    end;
    end;

    I use this procedure to pass each byte of the sent/recived commands through to transmit or validate the sting.

    Example

    command to Send

    #01#84

    When each byte is passed throgh the crc procedure the result returned is

    is the decimal value of 33793. This equates to 8401 hex.

    my question is in two parts. i am looking for the easyist way to convert the decimal result to its hexidecimal value and then to the the hex to its ascii equivalent as a string that i can apped to the command strig to be trasmitted out the serial port.

    their has to be an easy way for this but it is just not apparant to me.
     
    Merlin, Mar 12, 2006
    #1
  2. Merlin

    mattyb

    Joined:
    Jul 29, 2005
    Messages:
    78
    Likes Received:
    0
    Location:
    Sydney, Australia
    G'day

    I've had to do similar things with calculating checksums and there's probably an easier way but...

    You can use the chr(x) function to get the ascii character you need to spit out from the result you've calculated eg.

    Code:
    ascii_string:=chr(CRC);
    The slight problem is splitting the big decimal number into 2 hex numbers. This is where they may be an easier way but you can use the mod and div operands to get the two CRC bytes.

    CRC mod 256 will give you the LSB (33793 mod 256 = $01)

    and

    CRC div 256 will give you the MSB (33793 div 256 = $84)

    So, at the end of your CRC routine you might have something like:

    Code:
    CRC_MSB := CRC div 256;
    CRC_LSB := CRC mod 256;
    It's then just a matter of how you are putting together the 'packet' you want to spit out.

    I tend you use an array, so I have some code like this:

    Code:
    ControlByte[1]:=$53; {Some Data}
    ....
    ControlByte[7]:=CRC_LSB;
    ControlByte[8]:=CRC_MSB;
    Then you can either spit each element of the array out in turn:

    Code:
    for i := 1 to 8 do
       begin
          WriteSerial(1,chr(ControlByte[i]));
       end;
    or I've been creating a single 'packet' and sending it all at once:

    Code:
    for i := 1 to 8 do
       begin
          append(Packet,chr(ControlByte[i])); {'Packet' is a string}
       end;
    
    WriteSerial(1,Packet);

    Anyway, hope that makes some sense...I've confused myself a bit during the course of typing that out!

    Cheers

    Matt
     
    mattyb, Mar 13, 2006
    #2
  3. Merlin

    Merlin

    Joined:
    Aug 3, 2004
    Messages:
    6
    Likes Received:
    0
    Thanks Mattb

    The chr is the way i found to do it.
    another way to handle the 16bit value is to use shift right shr 8 this will result in an 8 bit number being the msb. multiply this answer by 256 and take it way fron the origional number will leave you with the lsb

    thanks for your help
     
    Merlin, Mar 21, 2006
    #3
  4. Merlin

    mattyb

    Joined:
    Jul 29, 2005
    Messages:
    78
    Likes Received:
    0
    Location:
    Sydney, Australia
    Cool, no worries. And thanks for the tip!

    Cheers

    Matt
     
    mattyb, Mar 22, 2006
    #4
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.