含16进制IEEE754数据的字符串转换为十进制浮点数-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 11867|回复: 14

[未解决] 含16进制IEEE754数据的字符串转换为十进制浮点数

[复制链接]
发表于 2019-5-28 23:26 | 显示全部楼层 |阅读模式
本帖最后由 jiangshh 于 2019-5-28 23:27 编辑

  最近接触到一个角度传感器,采用串口读取数据,MCU发送数据请求指令后,传感器的应答数据是遵从IEEE754标准的单精度浮点数,我需要提取出字符串中有效数据,并将16进制表示的字符串转换为浮点型数据,下图是传感器的实用手册。

传感器使用手册

传感器使用手册

自己的NANO板烧了,也没法测试,但是通过网上的String类函数写了一下,不知道呢能否实现功能,或者各位大神有没有更好的写法,我是感觉自己写的有些问题。
下面的我写的程序。


[pre]/*
选用传感器的命令格式:
发送读取数据指令后,传感器会应答。
应答的字符例如“01030443870148F18A”
其中43870148是IEEE754标准的单精度浮点数
本程序将16进制IEEE754标准的数据表示为十进制的浮点数
*/

#include <stdlib.h>
String angle = ""; //用于储存串口读取的字符串
String angle_read = ""; //用于储存提取有效数据后的字符串
const char *angle_date; //用于储存 string类字符串转换为const char类型
float angle_val;//用于储存换算后的浮点数


void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
}

void loop()
{
    Serial.print("01030001000295CB");//给传感器发送的命令
    delay(10);
   
    while (Serial.available() > 0)  //将串口收到的字符储存入angle
    {
        angle += char(Serial.read());
        delay(2);
    }
   
    if (angle.length() > 0)
    {
        angle_read = angle.substring(6,13);//提取angle的含有效数据字符串
        angle_read.trim();//去除字符串前后的空格
        angle_date = angle_read.c_str();//将string类字符串转换为const char类型
        angle_val = atof(angle_date);//将字符串转换为双精度浮点数
        Serial.print(angle_val,2);//串口打印,保留两位小数点
        angle = "";
        angle_read = "";
    }
   
}[/pre]
 楼主| 发表于 2019-5-30 09:11 | 显示全部楼层
本帖最后由 jiangshh 于 2019-5-30 09:14 编辑

这是我修改后的代码,功能已完善,供大家参考试用。

[pre]String angle = ""; //用于储存串口读取的字符串
String angle_read = ""; //用于储存提取有效数据后的字符串
String angle_date = ""; //将储存0x与有效字符合并的字符
float angle_val;//用于储存换算后的浮点数

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
}

void loop()
{
    //Serial.println("01030001000295CB");//给传感器发送的命令
    //delay(10);

    while (Serial.available() > 0)  //将串口收到的字符储存入angle
    {
        angle += char(Serial.read());
        delay(2);
    }
   
    if (angle.length() > 0)
    {
        angle_read = angle.substring(6,14);//提取angle的含有效数据字符串
        angle_date = "0x"+angle_read; //将有效字符串前加0x
        char* date = (char*)angle_date.c_str();//将string字符串转换为char*型
        long val = strtol(date,NULL,16);//将char*字符串转化为长整型
        float angle_val = *(float*)&val;//16进制IEEE754标准转化十进制浮点数
        Serial.println(angle_val,2);//串口打印,保留两位小数点
        angle = "";
        angle_read = "";
        angle_date = "";
    }
}[/pre]
发表于 2019-5-29 15:44 | 显示全部楼层
本帖最后由 t3486784401 于 2019-5-29 15:47 编辑

用 MFC 写了个,LZ 试试看(IEEE754转DEC): F32TODEC.rar (96.24 KB, 下载次数: 53)

运行如下:

2019-05-29_154654.png

 楼主| 发表于 2019-5-30 09:10 | 显示全部楼层
t3486784401 发表于 2019-5-29 15:44
用 MFC 写了个,LZ 试试看(IEEE754转DEC):

运行如下:

非常感谢你,我是做本科毕业设计,用到这一款传感器,我要用2560多串口采集数据并发送出去,读这款传感器实用手册时上面写道是应答命令用IEEE754标准的浮点数储存方式,所以要写一段程序来转换,经过各种资料查找,今早刚刚写好,我现在发出来供大家以后参考用。还是非常感谢您。
发表于 2019-7-11 19:22 | 显示全部楼层
请问如何将float类型转换成IEEE标准的16进制字符串呢,我的需求正好相反,卡了半天了,请教各位大佬
发表于 2019-7-11 20:17 | 显示全部楼层
lucas_卢 发表于 2019-7-11 19:22
请问如何将float类型转换成IEEE标准的16进制字符串呢,我的需求正好相反,卡了半天了,请教各位大佬 ...

内存里存储的就是 IEEE754 格式的,直接取地址就能访问了
发表于 2020-4-5 19:32 | 显示全部楼层
正好需要,看看这个能不能用
发表于 2021-7-5 16:49 | 显示全部楼层
本帖最后由 我是新新新新手 于 2021-7-5 16:51 编辑
t3486784401 发表于 2019-5-29 15:44
用 MFC 写了个,LZ 试试看(IEEE754转DEC):

运行如下:

你好,我是用arduino的,跟楼主一样接收回来是4字节字符,需要转换成10进制浮点数,但找了好久没找到可转换代入的公式。楼主的代码也试过,编译不了,看了你写了个转换的软件,想讨教下你公式,我想转换成10进制后打印出来
本人在这里换算过是OK的 https://www.23bei.com/tool-23.html#

  1. //功率表发送01 03 00 2A 00 02 E5 C3回应01 03 04 40 20 31 27 BB B3,40203127为有效浮点数,右高字节
  2. unsigned char data2[8] = {0x01,0x03,0x00,0x2a,0x00,0x02,0xE5,0xC3}; //功率表指令
  3. String comdata2 = "";
  4. float gonglv;

  5. void setup() {

  6.     Serial.begin(9600); //设置串口波特率9600
  7.     Serial2.begin(9600); //设置串口波特率9600   功率表

  8. void loop() {
  9.     gonglvbiao();

  10. void gonglvbiao() { //功率表
  11.    
  12.     delay(20);
  13.     for (int j = 0; j < 8; j++)
  14.     {
  15.     Serial2.write(data2[j]);//向串口2发送信息
  16.     }
  17.     delay(20);

  18.     while (Serial2.available() > 0)
  19.     {
  20.     comdata2 += char(Serial2.read());  //每次读一个char字符,并相加  字符串
  21.     delay(2);     
  22.     }
  23.    
  24.     if (comdata2.length() > 0){
  25.     float data5=comdata2[3];
  26.    float data6=comdata2[4];
  27.     float data7=comdata2[5];
  28.    float data8=comdata2[6];

  29.     delay(20);
  30.     Serial.print(comdata2);
  31.     delay(200);
  32.     Serial.print(data7);
  33.     delay(200);
  34. //    comdata2 = "";//清空数据,等待下一次接收
  35.     }
复制代码
发表于 2021-7-6 01:46 | 显示全部楼层
我是新新新新手 发表于 2021-7-5 16:49
你好,我是用arduino的,跟楼主一样接收回来是4字节字符,需要转换成10进制浮点数,但找了好久没找到可转 ...

请不要使用 String 格式处理这种 RAW 格式的数据,但凡遇到个 00H 整个字串都乱了。
随便写个 uint8_t 数组,再用个变量记录写进去的长度即可。

最后说明一句,只要内存了存储了 LE 格式的 4 字节数据,就可以直接拿 float * 指针指过去的,
然后指针取值就有了 float 数据。

至于转十进制,在 print 函数之前,浮点、整形都是以二进制形式存储的,所以转成什么格式都只是个名头;
只有在 print 之时才会以不同的格式对待,并最终显示成需要的十进制格式。
发表于 2021-7-14 21:26 | 显示全部楼层
t3486784401 发表于 2019-7-11 20:17
内存里存储的就是 IEEE754 格式的,直接取地址就能访问了

请问如何访问?我也是需要把float类型转换成IEEE标准的16进制字符串
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 07:43 , Processed in 0.109367 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表