一、stm32程序
通过查找网络资料,决定采用函数转换的方式,实现float数转换成char数,再送入modbus寄存器。
首先,在头文件.h中定义:
void float_char(float f,u8 *s);
其次,在源文件.c中增加float_char子函数:
void float_char(float f,u8 *s)
{
u8 *p;
p=(u8*)&f;
*s=*p;
*(s+1)=*(p+1);
*(s+2)=*(p+2);
*(s+3)=*(p+3);
}
最后,在modbus收发处理函数里增加:
u8 *Att_0;
float Att;
float_char(Att,Att_0);//将Float数据Att,转换成Att_0的字符数组
Modbus_HoldReg[192]=(int)Att_0[3]*256+(int)Att_0[2];
Modbus_HoldReg[193]=(int)Att_0[1]*256+(int)Att_0[0];
说明:Att=4.8414259,在单片机里面为0X409AECF6,正确的是:Att_0[0]=0xF6,Att_0[1]=0xEC,Att_0[2]=0x9A,Att_0[3]=0x40;但是调用 float_char子函数后,发现Att_0[0]=0X60,Att_0[0]=0X12,Att_0[0]=0X00,Att_0[0]=0X20,
通过单独调式发现R2寄存器里面的数据变成了0X409AECF6,可是Att_0就是不正确。
难道是float_char子函数不对吗?在VS2013里面,将程序拷贝进去,cout << uu[0] << endl;的情况下,输出的uu[0]为符号,将uu[0]转换成int,输出的结果的确是0xF6,其他三个字节也是完全正确的。
再通过单片机程序调试发现,Att_0[4],Att_0[5],...Att_0[9]这些变量里面都有值,但是和Att的32位浮点数却不一致。感觉在单片机程序里面,程序在执行时,似乎Att的字节未按照顺序传入Att[0]--Att[3],决定修改程序如下:
u8 Att_p[4]={0,0,0,0};
float_char(Att,&Att_p[0]);
Modbus_HoldReg[192]=Att_p[3]*256+Att_p[2];
Modbus_HoldReg[193]=Att_p[1]*256+Att_p[0];
直接用数组的方式,将第一个数组的地址送入子函数的形参中。通过监视串口发送的数据,发现完全正确,问题得到解决,浮点数按照先高后低的方式存入modbus寄存器中。
二、C++程序
在C++中需要将单片机中发送过来的以4个字节形式的浮点数数据进行转换处理,送入float变量。具体程序如下:
float Heading = 0.0;//浮点数变量
char Heading_0[4] = { 0, 0, 0, 0 };
//Modbus接收的数据处理
Heading_0[0] = mySerialPort.RevData[8];//注意接收字节顺序要反过来
Heading_0[1] = mySerialPort.RevData[7];
Heading_0[2] = mySerialPort.RevData[6];
Heading_0[3] = mySerialPort.RevData[5];
memcpy(&Heading, Heading_0, sizeof(Heading_0));
//Heading = ((float *)Heading_0)[0]; //也可行
//Heading = *((float*)Heading_0); //也可行
cout << "浮点数据:" << Heading << endl;
需要注意的是,字节形式浮点数转换过程中,先从低字节处理开始,需要将Modbus接收的最低位先送入Heading_0[0]进行转换处理。