上位机如何发送小数给下位机?

[复制链接]
 楼主| 万思博 发表于 2009-12-11 16:51 | 显示全部楼层 |阅读模式
本帖最后由 万思博 于 2009-12-11 17:02 编辑

思路:
上位机控制台程序:我用C++写的,输入个浮点数,想转换成32位二进制数,
然后通过串口发给DSPIC
下位机程序:接收到4个8位的数据后,在组合成一个浮点数。
问题:
A: 单精度浮点数-5.625对应存储的二进制码为C0B40000
    方法:对-5.625与0x000000ff按位与后,取最后8位给一个字节型的变量,然后依次取高8位的重复操作;
    出现的问题1:浮点数不能够移位?
    出现的问题2:怎么截取浮点数的最后8位?
B:前提:上位机如果转换成功的话,
   目标:下位机程序,将接收到的4个8位的数据组合成一个浮点数
   方法:将4个字节数组合成一个32位的常量,在赋值给一个浮点型的变量。
            目前没试过,这样做可以吗?总觉的很别扭!!
请问:如果上面的方法不可取,有什么别的方法可以“将小数发送下去,并接收”吗?
又想到的:
思路二:
比如:发送的小数范围是0.01——100.99
如果发送的是50.21,
float Input=50.02f;
int SendData;
SendData=(int)Input*128;
将SendData转换成两个字节数发出即可
下位机,组合后在除以128即可。
yewuyi 发表于 2009-12-11 17:05 | 显示全部楼层
实在搞不懂你难在哪里?!


更搞不懂你移位不移位的事情。。。

一个浮点数,根据精度不同,有可能是24BIT,也可能是32BIT,对应3个字节或者4个字节的2进制数字,实在搞不懂传送这几个字节数字有多难。。。


在下位机器中,使用结构和联合的方式,把浮点数字直接和4个字节并容到一个RAM空间内,PC把4字节数字传到MCU,MCU把收到的4个字节放到这个RAM空间内,剩下还有什么问题吗?
 楼主| 万思博 发表于 2009-12-11 17:11 | 显示全部楼层

怎么把abc转换成4个字节?

本帖最后由 万思博 于 2009-12-11 17:34 编辑

感谢2楼,下位机的处理方法!很好!
传送很简单!
不过,问题在C++编程,
怎么把abc转换成4个字节?
float abc=-5.625;
char  jieguo[4];

void zhuanhuan(float abc,char &jieguo);
这个函数怎么写呢?
dlw2i 发表于 2009-12-11 17:20 | 显示全部楼层
在C++中也可以使用联合+结构体的方式;
或使用指针+类型强制转换。
 楼主| 万思博 发表于 2009-12-11 17:28 | 显示全部楼层

void zhuanhuan(float abc,char &jieguo);怎么写呢

本帖最后由 万思博 于 2009-12-11 17:37 编辑

4楼能说的再具体些吗?
void zhuanhuan(float abc,char &jieguo);
怎么使用联合+结构体来写这个函数呢?
单精度浮点数,强制类型转换的话
(int)5.625 结果不成5了吗?这样的话没有意义了!

指针+强制类型转换和上面的例子有什么不同吗?
 楼主| 万思博 发表于 2009-12-11 18:35 | 显示全部楼层
关于思路二中:
输入量:abc=1.1
c++模拟数据的转换过程
程序:
        float abc=1.1f;
        float abd;
        int jieguo;
        jieguo=(int)(abc*128);
        printf("%d\n",jieguo);
        abd=(jieguo/128);
        printf("%f",abd);
输出的结果为1.000000。
问题在:jieguo=(int)(abc*128);
abc*128=140.8经过强制类型转换后成了140
如何才能提高运算的精度呢?
牛牛特工 发表于 2009-12-11 23:41 | 显示全部楼层
~~~ 俺也不晓得
首先浮点数的存储方式 其中一部分存储的是有效值 即浮点数的开头N位
另外一部分存储的则是小数点的位置 即指数位 故直接移位肯定是不行的~~
单精度正常 共32位  一个符号位 数值部分或叫尾数部分为23位  指数部分 8位
你按照顺序把那几位取出来就行了
还要注意指数部分为补码表示
我也是百度的
http://zhidao.baidu.com/question/37438761.html?si=2
貌似标准库函数里也有提供一些转换函数的吧
偶没怎么用过如果我自己做,肯定就是把 指数 尾数 分别取出来而已咯
lxyppc 发表于 2009-12-12 00:02 | 显示全部楼层
不用作类型转换,你只要把你想发的数据传出去即可
//C++
union{
  unsigned char data[sizeof(float)];
  float         fVal;
}MyFloat;

MyFloat.fVal = 14.6f;
Send(MyFloat.data,sizeof(float));

// DSPIC
Read(MyFloat.data,sizeof(float));
float result = MyFloat.fVal;
牛牛特工 发表于 2009-12-12 00:28 | 显示全部楼层
貌似光传输好像是不要转换哈
直接用指针发送也行的
headwolf_83 发表于 2009-12-12 10:15 | 显示全部楼层
1、搞清楚你的PC,浮点是不是32位,4个字节。2、在你的下位机,找到32位的浮点的表示类型,比如PICC,应该用DOUBLE而不是FLOAT。
3、所谓浮点,在PC内的存储不过是4个字节而已,用8楼的办法,用联合体结构体,对一个浮点给值,传输的时候直接用指针指向字节。
4、搞清楚你的上位机是小端点还是大端点,而下位机又是小端点还是大端点,别传下来后字节存储顺序反了。不过也很简单的,看看结果,不对反一遍就可以了。C++处理这个应该很简单吧。
mohanwei 发表于 2009-12-12 10:42 | 显示全部楼层
要求不高还可以转换成字符串来传输
上位机:sprintf(str,"%f",f);
            sendstr(buff);
下位机:f=atof(str);带格式复杂一点还有sscanf,strtof……
这样你就不用管平台之间的差异和浮点数格式的差异了,这是真正的跨平台代码
yxb0310 发表于 2009-12-12 12:41 | 显示全部楼层
协议
 楼主| 万思博 发表于 2009-12-12 13:45 | 显示全部楼层
本帖最后由 万思博 于 2009-12-12 13:54 编辑

小结:
指针法:
        float abc=1.1f;
        char *abd;
        abd=&abc;
        printf("%d\n",sizeof(abc));
        printf("%x,%x,%x,%x\n",*abd,*(abd+1),*(abd+2),*(abd+3));
输出结果:
        4
        ffffffcd,ffffffcc,ffffff8c,3f
思路二中方法改进(提高精度)
       输入参数:abc=1.1f
       float abc=1.1f;
       float abd;
       int jieguo;
       jieguo=(int)(abc*1024);
       printf("%d\n",jieguo);
       //注意:此处须先将jieguo转换成浮点数在运算
       abd=(float)jieguo/1024;
       printf("%f",abd);
输出结果:1.099609
 楼主| 万思博 发表于 2009-12-12 14:53 | 显示全部楼层
下位机:俺用的是DSPIC30
试验程序:
        struct{
                  unsigned char a;
                unsigned char b;
                unsigned char c;
                unsigned char d;
        }MyFloat;
        MyFloat.a=0xCD;
        MyFloat.b=0xcc;
        MyFloat.c=0x8c;
        MyFloat.d=0x3f;
        float *abd;
        abd=&MyFloat;
        float abc;
        abc=*abd;
输出结果:abc=1.100000
上位机将浮点数转换的方法中,牛牛特工曾提过
“肯定就是把 指数 尾数 分别取出来而已咯”
我也试了,但没成功,取尾数的思路如下:
拿0.1来解释:                              (下面的数是尾数)
0.1   <     0.5                                                  第1位是0
0.1   <     0.25                                                第2位是0     
0.1   <     0.125                                              第3位是0  
0.1   >    0.0625       0.1-0.0625=0.0375                第4位是1
0.0375>0.03125      0.0375- 0.03125 = 0.00625    第5位是1  
0.00625   < 0.015625                                             第2位是0   
...............
牛牛特工 发表于 2009-12-12 20:45 | 显示全部楼层
俄 你直接到Float存储里面去取就行了 不需要计算的
比如之前说的X86的单精度Float 读出其2进制值 然后把对应位取出来就OK
俺还是学习去了~~
e掾木 发表于 2009-12-13 11:52 | 显示全部楼层
here:
  typedef union  tagfloat {
        float f_data;
        char  ch_data[sizeof(float)];
}_data;
backupyan 发表于 2009-12-28 16:34 | 显示全部楼层
单片机处理浮点数会哭的!
xzhenggen 发表于 2009-12-30 13:07 | 显示全部楼层
C++做上位机太麻烦了,我不用这个C++。用LABVIEW轻松搞掂。
huangqi412 发表于 2009-12-30 13:33 | 显示全部楼层
神啊.
李冬发 发表于 2010-1-5 00:07 | 显示全部楼层
~~~ 俺也不晓得
首先浮点数的存储方式 其中一部分存储的是有效值 即浮点数的开头N位
另外一部分存储的则是小数点的位置 即指数位 故直接移位肯定是不行的~~
单精度正常 共32位  一个符号位 数值部分或叫尾数部分为2 ...
牛牛特工 发表于 2009-12-11 23:41

指数部分是偏移码,不是被码。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

10

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部