Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Conversion of 4 bytes to single 3

Status
Not open for further replies.

SJA

Technical User
Nov 27, 2000
15
0
0
GB
I receive 4 seperate bytes from the comm port.
I need to create an IEEE754 single float out of them.
Presently I have 2 ways of doing this, non are very elegant.
1) Split all 4 bytes into a binary string (0s and 1s),
add them together, split them up using the IEEEE 754
rules, convert them back into a number by stepping
through and anding with powers of 2.
2) Open a file as binary, save the 4 bytes, close the file
open the file again and read the number back as a
single.
Can anyone suggest a better method, i.e. some way I could
save the 4 bytes to a specific memory location and then
read them back as a float.
 
Try using the CopyMemory API. Here's the declaration for it. Copy the location of the source to the destination. Be sure you save your project before you use this API call or it will most certianly crash. Be sure to use ByVal in the destination of your function call or you'll see Dr. Watson. One other thing to keep in mind is the order in which the bytes come in from the serial port. If they are low byte high byte, you should get the right answer. If they are the other way high byte, low byte, then you'll have to reverse them before you use the CopyMemory function.

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Good luck...
Snaggs
tribesaddict@swbell.net

 
Maybe the following piece of code could be helpfull, although I don't know if MS VB's Float (single or double) does conform to IEEE754. The language reference just states: variables are stored as IEEE 32-bit floating point numbers.

Here it goes:

Private Type typFourBytes
bytOne As Byte 'Low Order Byte
bytTwo As Byte
bytThree As Byte
bytFour As Byte 'High Order Byte
End Type

Private Type typFourLong
lngValue As Long
End Type

Public Sub main()

Dim typ_CommIn As typFourBytes
Dim typ_CommOut As typFourLong

Dim sngValue As Single

'Populate structure with some values
With typ_CommIn
.bytOne = 4 'Low order byte= 00000100 = 4
.bytTwo = 2 ' 00000010 = 512
.bytThree = 1 ' 00000001 = 65536
.bytFour = 0 'High order byte=00000000 = 0
End With 'SUM = 66052

LSet typ_CommOut = typ_CommIn
sngValue = CSng(typ_CommOut.lngValue)

Debug.Print sngValue, typ_CommOut.lngValue '66052

End Sub

-----
notes:
1. If the high order byte starts with "1" then the resulting number will be negative. (Why do you need float and not long?)

2. You'll have to find some method to pinch the incoming bytes from the comm port into the typ_CommIn structure. You'll probable have to use the Asc() or CByte() function to convert the incoming charactes to Byte Values.
 
Snaggs and RVBasic - thanks for your help.

Snaggs :-
I found reference to CopyMemory in MSDN and implemented it
as the following example :-

Byte_Array(0) = Val("&h" & Byte1T)
Byte_Array(1) = Val("&h" & Byte2T)
Byte_Array(2) = Val("&h" & Byte3T)
Byte_Array(3) = Val("&h" & Byte4T)
Call CopyMemory(Floater, Byte_Array(0), 4)
txt_float.Text = Floater

This works fine. In my real program the Byte_Array comes
from the comm port buffer.
---------------------------------------------------------
RVBasic :-
I didn't realise Lset could be used to force one type of
variable into another, I implemented this as follows :-

Private Type Typ_4Byte
Byte1 As Byte
Byte2 As Byte
Byte3 As Byte
Byte4 As Byte
End Type

Private Type Typ_Single
Byte_All As Single
End Type

Dim Four_Bytes As Typ_4Byte
Dim Floater1 As Typ_Single

Four_Bytes.Byte1 = Val("&h" & Byte1T)
Four_Bytes.Byte2 = Val("&h" & Byte2T)
Four_Bytes.Byte3 = Val("&h" & Byte3T)
Four_Bytes.Byte4 = Val("&h" & Byte4T)
LSet Floater1 = Four_Bytes
txt_float.Text = Floater1.Byte_All

Note I'm forcing four bytes into a floating point format,
not a long. This works fine as well.
I need floating point format because that is the format
that the individual bytes get sent to me (from an engine
management controller), and they are in IEEE 32 bit format.

Now the interesting bit, bearing in mind that my application
is basically a data logger sucking data from a controller
and displaying it as fast as possible.
Using my existing method 65535 conversions of 4 bytes to a
float takes 24.224 seconds on a 733 pentium III.
Using CopyMemory takes 41 mS.
Using LSet takes just 20 mS.

Thanks again & best regards
 
Excellent! You never know what you're gonna learn around this place.... Snaggs
tribesaddict@swbell.net
 
Glad I could offer some help. A last(?) remark: if you log as fast as possible, it could be advantageous to use a With ... End loop in stead of separate references.

With Four_Bytes
.Byte1 =
.Byte2 =
.Byte3 =
.Byte4 =
End With

In principle VB has to resolve the reference to Four_Bytes only once now. This should shave a couple of micro-(nano?)seconds off your process time. Although I didn't test this...
 
Ditto. I've used Lset for alignment but never for variable conversion. Thanks, SJA.
VCA.gif

Alt255@Vorpalcom.Intranets.com
 
The LSet statement for use with UDT's is not a well known technique. If you've read "Visual BASIC 6 Business Objects" from Wrox Publishing by Rockford Lhotka, he uses the heck out of them. Another fan of this technique is Deborah Kurata. She wrote "Doing Objects in Visual BASIC 6.0"

Here's the links to the two books respectivly:


and

Snaggs
tribesaddict@swbell.net
 
Argh.... Just we pass this information on to other programmers, Microsoft goes and takes it away! :-(

----------------

LSet
In Visual Basic 6.0, the LSet statement could be used to assign a variable of one user-defined type to another variable of a different user-defined type. This functionality is not supported in Visual Basic.NET.

Here's the link, it's at the bottom of the document.

Snaggs
tribesaddict@swbell.net
Experience is what you get when you didn't get what you wanted.
 
Those dirty dogs... I hope they provide work-arounds to help automate all the code conversions we'll be facing.
VCA.gif

Alt255@Vorpalcom.Intranets.com

"What this country needs is more free speech worth listening to."[tt]
Hansell B. Duckett[/tt]​
 
where shud i put this statement
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
thanx
 
You put it in a Module (.bas) file, or if you put it in a form or a class you have to change the word Public to Private.
Snaggs
tribesaddict@swbell.net
Life can only be understood backwards; but it must be lived forwards.
 
9 out of 10 programmers surveyed prefer to work in HEX when working with Bytes because it clearly shows which bits are set and which ones aren't. Example:

73 Decimal = 49 hex = 01001001 binary or 0100 1001 binary

The 4 is 0100 and the 9 is 1001.

Often when a number is used like this it's used to hold many on/off flags. When you look at the number 73 it's hard to tell what bits are set and what isn't. If you look at it hex, it's easy. Snaggs
tribesaddict@swbell.net
Life can only be understood backwards; but it must be lived forwards.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top