We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you two Citrix podcasts. Learn about 2020 trends and get answers to your biggest Citrix questions!Listen Now


Decoding serial port data

Medium Priority
Last Modified: 2010-04-17
Dear sirs,
A bit of a tricky one this (for me anyway).

I am reading data from a weather station through the serial port which is arriving as a string of characters.

I need to be able to decode this data but have no idea where to start as there is no official instructions.  I managed to dig up some help but I have no idea what the heck they are talking about, hence my post.

Their instructions are:

Data is sent simplex from the weather station via an RS 232 interface to the PC

The frame format is as follows, the length being implied by the Code value:
Start Start Code Channel Data Checksum

Start 0xFF
Code 0x00 - 0x0F
Channel 0x00 in most cases, but with specific uses as follows:

The first hex digit indicates the battery status (where relevant). The second hex digit indicates the channel number (where relevant).

For the Clock Minute message this byte indicates the number of minutes.

Add all bytes arithmetically, including the Code byte but excluding the Start bytes and the Checksum byte. Subtract 2 and take the bottom 7 bits to get the correct checksum.

Number Formats
Numbers are represented in BCD, except for ambient pressure which is in binary. The digits come in a variety of orders. The topmost quartet is set to 0x8 for a negative number (temperature, wind chill). For example:

0x18 - 18 as an hour (6 PM)
0x1703 - 31.7 degrees as a temperature
0x3582 -23.5 degrees as a temperature
0x8015 -15 degrees as a wind chill.

Does anyone have any idea what they are talking about?
Watch Question

To decode the data, you need to do the following:

1. Locate the beginning of a frame by reading bytes until you encounter the bytes 0xFF 0xFF.
2. The next byte is the code byte, which can take values between 0x00 and 0x0F. I understand this represents the type of data sent in the frame, which also implies the frame length. You should have a list of frame types, and their corresponding lengths.
3. You read the channel byte (I don't know how you will be using it).
4. Read data byte(s) (I assume you already know the data length from the code byte).

Data should be parsed as follows:

All values (except for ambient pressure) are represented in BCD format. Converting BCD to decimal is quite easy; if the data is contained in a single byte (as in the case of the hour byte in the example you posted), each hexadecimal digit represents a corresponding decimal digit (values cannot exceed 9). For example:

0x18 is decoded to the decimal value 18

Values contained in two bytes as in temp. and wind chill are converted to decimal by first swapping the data bytes, and then converting the first digit to a sign (0 means +, while 8 means -). For example:

To convert 0x1703 to a temperature value, first swap the bytes. Now we have 0x0317. Next, remove the zero on the left (the value is positive), and place a decimal point where appropriate (I guess here you have only one decimal place). The value becomes 31.7 degrees :-)

To convert 0x3582, you again swap the bytes. Now you have 0x8235, which stands for -23.5.

Finally, to convert ambient pressure values, you simply read the data into an integer (or any numeric variable that will hold the value read), and then directly use it. Bytes read this way will be correctly converted to the corresponding decimal value.


  Nayer Naguib

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
Sorry, forgot about the checksum. You add the values of all frame bytes (excluding the two Start bytes and, *of course*, the checksum byte, which we are still calculating!) and store the sum in a variable. Next, you subtract 2 from the sum. Next, AND the result with 0x7F (to exclude the eighth bytes as instructed), and compare the value with the checksum byte received (to check the integrity of the data received). If both values match, then you have received the data correctly.
Now you are ready to read a new frame :-)


  Nayer Naguib


Thanks Nayer for your quick response.

Please forgive me as I am very very new to coms  :)

First I presume that to get the hex you can use hex(asc(character)) so when i am looking for a start of frame i am looking for two chr(255)'s together?

Is that right ?
Exactly! However, if you are reading characters, and you want to check for Start bytes using Chr(255), then you cannot compare this to the hexadecinal value returned by Hex(255), nor to the value returned by something like Hex(Asc(Chr(255))). You need to directly compare Chr(255) to the value of the character read from the input data stream.

Chr(x) returns the character corresponding to the number x from the ASCII table. However, Hex(x) returns the hexadecimal representation of number x.
Example: Chr(65)="A", while Hex(65)=41


  Nayer Naguib


That's really helped.  Thanks Nayer
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.