今天调试一台设备时,在交互的Modbus协议中,设定数值位用的是浮点数。
带过那么多学生,我竟然脑袋一空??!
Modbus用浮点型?
浮点型与U32互转?
于是硬着头皮,重新把这块的内容,复盘了一遍~~现在整理笔记,分享给大家。
明天可能会依据这个出个QT的demo,需要的可以一蹲!
一、浮点数与16进制的转化概念
对于一个32位的浮点数中,有以下三个部分组成:符号位、阶码和尾数。具体格式如下:
对各部分解释如下:
S:浮点数的符号位,1 位。0表示正数,1表示负数。
M:尾数,23位。用小数表示,小数点在尾数域前面。
E:阶码,采用移码方式来表示。
作用:移码方法对两个指数大小的比较和对阶操作都比较方便,因为阶码域值大者其指数值也大。
采用移码方法时,需要将浮点数的指数真值e变成阶码E,变换方法是将指数 e 加上一个固定的偏移值127(01111111),即 E=e+127
浮点数的真值x计算格式为:x = (-1)^s × (1.M) × 2^e
32位浮点数e=E-127;64位浮点数e = E-1023
简单举几个例子:
例题1. 若浮点数x的二进制存储格式为(41360000)16进制,求其32位浮点数的值。
将16进制数转换为2进制 0100 0001 0011 0110 0000 0000 0000 0000
则e = 10000010 - 01111111 = 3(十进制)
M = 01101100000000000000000
则x = (-1)^0 × 1.011011× 2^3 = 1011.011(2进制)
= 11.375(十进制)
例题2. 将十进制数20.59375转换成32位浮点数。
首先分别将整数和分数部分转换成二进制数:
20.59375=10100.10011
然后移动小数点,使其在第1,2位之间
10100.10011=1.010010011 × 2^4 e=4
于是得到:
S=0,E=4+127=131,M=010010011
最后得到32位浮点数的二进制存储格式为:
0100 0001 1010 0100 1100 0000 0000 0000
=41A4C000(16进制)
二、浮点数与16进制的转化概念
以QT编译器为例,C/C++针对float浮点型与16进制转换的实现如下:
#include <stdio.h>
float Hex_To_Decimal(unsigned char *Byte,int num)//十六进制到浮点数
{
// char cByte[4];//方法一
// for (int i=0;i<num;i++)
// {
// cByte[i] = Byte[i];
// }
// float pfValue=*(float*)&cByte;
//return pfValue;
return *((float*)Byte);//方法二
}
long FloatTohex(float f_tohex)//浮点数到十六进制转换1
{
return *( long *)&f_tohex;
}
void FloatToByte(float floatNum,unsigned char* byteArry)/*浮点数到十六进制转换2*/
{
char* pchar=(char*)&floatNum;
for(int i=0;i<sizeof(float);i++)
{
*byteArry=*pchar;
pchar++;
byteArry++;
}
}
int main(int argc, char *argv[])
{
unsigned char floatToHex[4];
uint32_t float_32;
uint8_t u8_f32[4];
unsigned char hexbyte[4]={0xcd,0xCC,0xCC,0x3D};//传输数据为3d cc cc cd
float Hdecimal=0.0;
float flh=2.0;
Hdecimal=Hex_To_Decimal(hexbyte,sizeof(hexbyte));//十六进制转换为浮点数
// printf("\n 浮点数为:\n %f\n",Hdecimal);
qDebug()<<QString(" 浮点数为:%1").arg(Hdecimal);
long hX=FloatTohex(Hdecimal);//浮点数转换为十六进制一
// printf("\n正序十六进制值:\n %f=%X \n",Hdecimal,hX);//正序显示
qDebug()<<QString(" 正序十六进制值:%1 => %2").arg(hX).arg(Hdecimal);
FloatToByte(Hdecimal,floatToHex);//浮点数转为十六进制二
// printf("\n倒序十六进制:\n%f=%x %x %x %x\n",Hdecimal,floatToHex[0],floatToHex[1],floatToHex[2],floatToHex[3] );//倒序显示
qDebug()<<QString(" 倒序十六进制:%1=%2 %3 %4 %5").arg(Hdecimal).arg(QString::number(floatToHex[0], 16).toUpper()).arg(QString::number(floatToHex[1], 16).toUpper()).arg(QString::number(floatToHex[2], 16).toUpper()).arg(QString::number(floatToHex[3], 16).toUpper());
FloatToByte(flh,floatToHex);//浮点数转为十六进制二
qDebug()<<QString(" 倒序十六进制:%1=%2 %3 %4 %5").arg(flh).arg(QString::number(floatToHex[0], 16).toUpper()).arg(QString::number(floatToHex[1], 16).toUpper()).arg(QString::number(floatToHex[2], 16).toUpper()).arg(QString::number(floatToHex[3], 16).toUpper());
qDebug()<<QString(" 正序十六进制:%1=%2 %3 %4 %5").arg(flh).arg(QString::number(floatToHex[3], 16).toUpper()).arg(QString::number(floatToHex[2], 16).toUpper()).arg(QString::number(floatToHex[1], 16).toUpper()).arg(QString::number(floatToHex[0], 16).toUpper());
}
PS:以上代码,只简单例举了浮点型与16进制的转换,那么浮点型和U32的转换,你能举一反三实现出来吗?
明天会发一个基于QT的demo进行揭晓哟!欢迎一蹲!