Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I'm in charge with a project which main characteristic is to receive s +ome data by serial port comunication. The layout of the Data Block is: |STX|STATUS1|STATUS2|DATA1|DATA2|ETX|CRC| where: STX = 1 byte - binary(02h) STATUS1 = 1 byte - binary STATUS2 = 1 byte - binary DATA1 = 5 bytes - ASCII DATA2 = 5 bytes - ASCII ETX = 1 byte - binary(03h) CRC = 1 byte Sample Data Received: ÇÇ0229700000¤ The application will comunicate with the serial port by the Win32::Ser +ialComm module. After to receive the block I'll must do a Checksum (XOR from STX up to + ETX inclusive) and compare it to CRC to verify the data integrity. My questions is: How can I do it? Thanks in Advance. Eustaquio.

Replies are listed 'Best First'.
Re: CRC and Serial Port
by broquaint (Abbot) on Dec 05, 2001 at 01:18 UTC
    The ever cryptic pack() and unpack() functions will be perfect for this sort of binary data munging
    my ($stx,$status1,$status2,$data1,$data2,$etx,$crc) = unpack("CCCa5a5CC", $data_received);
    My example may not fit your data structure exactly (I make no pretense to my pack()ing skills ;o), but I think it's something along the lines of what you want.
    HTH

    broquaint

    Update: as Albannach kindly pointed out the template should be a5 and not 5a.

Re: CRC and Serial Port
by twerq (Deacon) on Dec 05, 2001 at 01:47 UTC
    about the checksum -- you obvously know more than I do about the other end that's sending you the data, but i've always done checksums on the whole record after zeroing the checksum, so you might end up having to pack it back up using the same unpack template...

    ...but for calculating the checksum itself, you might end up using unpack a third time

    from perldoc -f unpack:
    For example, the following computes the same number as the System V sum program: $checksum = do { local $/; # slurp! unpack("%32C*",<>) % 65535; };

    --twerq

      If you want to process data one block at a time, set $/ to your field length. That will save you from waiting to slurp the entire "file" before processing it.

        true, you can pass a value reference to $/ which translates into a record length, but as far as I know, there's no way to tell it to read 12 "lines", where a line can be variable length.

        --twerq