打印

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

[复制链接]
7807|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
万思博|  楼主 | 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++中也可以使用联合+结构体的方式;
或使用指针+类型强制转换。

使用特权

评论回复
5
万思博|  楼主 | 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了吗?这样的话没有意义了!

指针+强制类型转换和上面的例子有什么不同吗?

使用特权

评论回复
6
万思博|  楼主 | 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
如何才能提高运算的精度呢?

使用特权

评论回复
7
牛牛特工| | 2009-12-11 23:41 | 只看该作者
~~~ 俺也不晓得
首先浮点数的存储方式 其中一部分存储的是有效值 即浮点数的开头N位
另外一部分存储的则是小数点的位置 即指数位 故直接移位肯定是不行的~~
单精度正常 共32位  一个符号位 数值部分或叫尾数部分为23位  指数部分 8位
你按照顺序把那几位取出来就行了
还要注意指数部分为补码表示
我也是百度的
http://zhidao.baidu.com/question/37438761.html?si=2
貌似标准库函数里也有提供一些转换函数的吧
偶没怎么用过如果我自己做,肯定就是把 指数 尾数 分别取出来而已咯

使用特权

评论回复
8
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;

使用特权

评论回复
9
牛牛特工| | 2009-12-12 00:28 | 只看该作者
貌似光传输好像是不要转换哈
直接用指针发送也行的

使用特权

评论回复
10
headwolf_83| | 2009-12-12 10:15 | 只看该作者
1、搞清楚你的PC,浮点是不是32位,4个字节。2、在你的下位机,找到32位的浮点的表示类型,比如PICC,应该用DOUBLE而不是FLOAT。
3、所谓浮点,在PC内的存储不过是4个字节而已,用8楼的办法,用联合体结构体,对一个浮点给值,传输的时候直接用指针指向字节。
4、搞清楚你的上位机是小端点还是大端点,而下位机又是小端点还是大端点,别传下来后字节存储顺序反了。不过也很简单的,看看结果,不对反一遍就可以了。C++处理这个应该很简单吧。

使用特权

评论回复
11
mohanwei| | 2009-12-12 10:42 | 只看该作者
要求不高还可以转换成字符串来传输
上位机:sprintf(str,"%f",f);
            sendstr(buff);
下位机:f=atof(str);带格式复杂一点还有sscanf,strtof……
这样你就不用管平台之间的差异和浮点数格式的差异了,这是真正的跨平台代码

使用特权

评论回复
12
yxb0310| | 2009-12-12 12:41 | 只看该作者
协议

使用特权

评论回复
13
万思博|  楼主 | 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

使用特权

评论回复
14
万思博|  楼主 | 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   
...............

使用特权

评论回复
15
牛牛特工| | 2009-12-12 20:45 | 只看该作者
俄 你直接到Float存储里面去取就行了 不需要计算的
比如之前说的X86的单精度Float 读出其2进制值 然后把对应位取出来就OK
俺还是学习去了~~

使用特权

评论回复
16
e掾木| | 2009-12-13 11:52 | 只看该作者
here:
  typedef union  tagfloat {
        float f_data;
        char  ch_data[sizeof(float)];
}_data;

使用特权

评论回复
17
backupyan| | 2009-12-28 16:34 | 只看该作者
单片机处理浮点数会哭的!

使用特权

评论回复
18
xzhenggen| | 2009-12-30 13:07 | 只看该作者
C++做上位机太麻烦了,我不用这个C++。用LABVIEW轻松搞掂。

使用特权

评论回复
19
huangqi412| | 2009-12-30 13:33 | 只看该作者
神啊.

使用特权

评论回复
20
李冬发| | 2010-1-5 00:07 | 只看该作者
~~~ 俺也不晓得
首先浮点数的存储方式 其中一部分存储的是有效值 即浮点数的开头N位
另外一部分存储的则是小数点的位置 即指数位 故直接移位肯定是不行的~~
单精度正常 共32位  一个符号位 数值部分或叫尾数部分为2 ...
牛牛特工 发表于 2009-12-11 23:41

指数部分是偏移码,不是被码。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

10

帖子

0

粉丝