Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

using sprintf to print binary data collected from the serial port

by Bruce32903 (Scribe)
on May 22, 2008 at 22:29 UTC ( #688053=perlquestion: print w/replies, xml ) Need Help??
Bruce32903 has asked for the wisdom of the Perl Monks concerning the following question:

Greetings Monks

I'm trying to collect and process binary data collected from the serial port. The data can range from 0x00 to 0xff. I am using Device::SerialPort and I seem to be receiving the data with no problem. But, I am getting nowhere trying to use the data.

I seem to be getting the binary data into a variable $ibuf. In an attempt to see a byte or two of the data I use the following line of code hoping to display the hex-text representation of the data in a Tk window.

$ibuf_display = sprintf("%x ", substr($ibuf, 1, 1));

With this I get the following (or similar) error messages:

Argument "^C" isn't numeric in sprintf at (program_name) line (line_number)

As far as I know Perl should just have "data", so this looks like a "sprintf from C" issue. But I don't know what to do about it.

As I go downstream I will be interested in doing the following:

1) Display data in "human friendly" form. This would be 0x03 for the ^C that was in the error message above.

2) Use if ( ) conditionals to process the data.

Any suggestions would be appreciated. Somehow I haven't yet tripped accross this while Googling.


  • Comment on using sprintf to print binary data collected from the serial port

Replies are listed 'Best First'.
Re: using sprintf to print binary data collected from the serial port
by pc88mxer (Vicar) on May 22, 2008 at 22:45 UTC
    You need to use ord:
    $ibuf_display = sprintf("%x ", ord(substr($ibuf, 1, 1)));
    I often use unpack with a hex format to display binary data:
    (my $hex = unpack("H*", $buf)) =~ s/(..)/$1 /g; print $hex, "\n";
      Thank you to you and the others. The responses have been very helpful.

      I am still having trouble with the if() conditionals. Error messages such as "Argument "^C" isn't numeric in numeric eq(==) at (file_name) line (line_num)" suggest that I am both correctly receiving the serial data and that I am correctly "substr"-ing the data. But that leaves me a little confused and lost. As far as I know Perl does not have "int" and "char" data types like the C language. So, since I don't think data types exist (am I wrong?) I don't know of a way to convert data types.

      I could try "thinking strings" and use "eq" and hope to find escape sequences for all byte values from 0x00 to 0xff. This seems like a huge amount of work to create a huge failure.

      I could use "ord" to convert data to ASCII-HEX digits and do my comparisons to "A", "C", "F3", etc. This seems like it would probably work but it seems like using a bulldozer to move an ant hill.

      Any suggestions on both how to write the code and what is going on? My "this is impossible in Perl" response means that this is a good chance to learn something.


      P.S. Is there a proper term for items such as "F3" that I want to display? I called it ASCII-HEX and one of the kind people responding to my question called them ALPHA. I have had many discussions of this in the past (big number) years. It is not exactly "HEX" since the "F3" is actually 0x46 and 0x33. I sometimes refer to it as the "ASCII text representation of the hex number" but saying that over and over in a planning meeting (or argument) can get old very fast. Actually, it is not exactly representing a hex number since it is really representing a binary pattern of 11110011. ... Kind of trivial until you have to write a document or coordinate the work of several people.

Re: using sprintf to print binary data collected from the serial port
by Aim9b (Monk) on May 23, 2008 at 11:42 UTC
    Here are a couple of routines I used to convert some hex data fields...

    sub DecodeBCD { # Convert a string of hex digits such as "x\12x\34x\56" # into a string of ASCII characters such as "123456". my $str = shift; my $hex; $hex .= sprintf "%02x", ord for split //, $str; return $hex; } # End of Sub DecodeBCD sub DecodeBCA { # Convert a string of packed ALPHA digits such as "x\BDx\CCx\FF" # into a string of ASCII characters such as "BDCCFF". my $str = shift; my $hex; if (length($str) > 0) { $hex .= sprintf "%02x", ord for split //, $str; } else { $hex = 0; } return $hex; } # End of Sub DecodeBCD

    Bugs/Blames are mine, any credit goes to the Monestary.
    Too many monks to mention had a hand in this, it was my first perl program, & not so long ago. ;-)
Re: using sprintf to print binary data collected from the serial port
by andreas1234567 (Vicar) on May 23, 2008 at 12:02 UTC
    You can be inspired by one of the many implementations of hexdump in perl, e.g. this one (Note that is uses neither strict nor warnings, so a good exercise could be to improve it).
    No matter how great and destructive your problems may seem now, remember, you've probably only seen the tip of them. [1]

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://688053]
Approved by pc88mxer
[erix]: friction gives warmth!
LanX comes back ...
[LanX]: FIGHT?
LanX orders pop corn
[erix]: ha ha, you missed it

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2018-03-19 21:29 GMT
Find Nodes?
    Voting Booth?
    When I think of a mole I think of:

    Results (246 votes). Check out past polls.