[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now


Decoding serial port data

Posted on 2006-03-27
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?
Question by:watersidedesigns
  • 3
  • 2
LVL 14

Accepted Solution

nayernaguib earned 2000 total points
ID: 16299708
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
LVL 14

Expert Comment

ID: 16299749
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

Author Comment

ID: 16300032
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 ?
LVL 14

Expert Comment

ID: 16300262
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

Author Comment

ID: 16301169
That's really helped.  Thanks Nayer

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In real business world data are crucial and sometimes data are shared among different information systems. Hence, an agreeable file transfer protocol need to be established.
If you are a mobile app developer and especially develop hybrid mobile apps then these 4 mistakes you must avoid for hybrid app development to be the more genuine app developer.
Loops Section Overview
Screencast - Getting to Know the Pipeline

868 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question