[讨论] 假如串口通信上要用上浮点数,你是怎么处理的?

ywlzh   2017-3-24 10:30 楼主
     突然的头脑发热,闷声想出来的一个想法。而正是这种想法驱使着我一定要拿一个实验测试一下,平台肯定要在硬件上,如果用计算机直接去做,那就太没意思了。
     虽说现在大部分的项目中,尤其是在串口通信上,协议里大多数的情况下都不会去发送float,或者double数据,都是命令式的,带的数据都是整形的变量,假如要发送浮点数,怎么办?
     用ASCII码形式发送接收,哎呀,一下就想到问题的解决办法,的确,这个就能搞定,但这样,就得让整个通信协议都得做ASCII码,人嘛,总是会跟自己较真,要是用16进制呢? 于是,开始复习计算机理论基础,里面有提到过float,double型数据在内存是如何存储的,什么阶码,尾数,这里不做过多赘述。
     两个方法:用union 关键字,或者直接用unsigned char型指针。
     先看程序吧
  1. union Shared_float   //创造共用体
  2. {
  3.    float f;
  4.    unsigned char data[4];
  5. };

  6. union Shared_double
  7. {
  8.          double d;
  9.         unsigned char data[8];
  10. };

     
  1. void TestTask(void *p_arg)
  2. {
  3.         OS_ERR err;
  4.         union Shared_float numj;
  5.         union Shared_double numd;
  6.         u8 *p;
  7.         float te_fl;
  8.         double te_dou;
  9.         numj.f = 5.3f;
  10.         for(;;)
  11.         {
  12.                 if(USART_RX_STA&0x8000){ //串口接收到数据
  13.                         USART_RX_STA = 0;
  14.                         if(USART_RX_BUF[0] ==0x01){    //用共用体来存储float型数据
  15.                                 int i=0;
  16.                                 for(;i<4;i++){
  17.                                         numj.data[3-i] = USART_RX_BUF[i+1];
  18.                                 }
  19.                         }
  20.                         else if(USART_RX_BUF[0] ==0x02){   //用共用体来存储double型数据
  21.                                 int i=0;
  22.                                 for(;i<8;i++){
  23.                                         numd.data[7-i] = USART_RX_BUF[i+1];
  24.                                 }
  25.                         }
  26.                         else if(USART_RX_BUF[0] ==0x03){   //用指针来存储float型数据
  27.                                 int i=4;
  28.                                 p = (unsigned char *) &te_fl;
  29.                                 for(;i>0;i--){
  30.                                         *p = USART_RX_BUF[i];
  31.                                         p++;
  32.                                 }
  33.                         }
  34.                         else if(USART_RX_BUF[0] ==0x04){  ////用指针来存储double型数据
  35.                                 int i=8;
  36.                                 p = (unsigned char *) &te_dou;
  37.                                 for(;i>0;i--){
  38.                                         *p = USART_RX_BUF[i];
  39.                                         p++;
  40.                                 }
  41.                         }
  42.                 }
  43.                 OSTimeDlyHMSM(0,0,0,40,OS_OPT_TIME_HMSM_STRICT,&err);
  44.         }
  45. }

简单说下吧,硬件平台是stm32F1,软件框架是在ucosIII上添加了一个任务,串口采用的硬件中断接收,再加空闲中断,这样能处理不定长的数据,本来是想采用信号量的,省得麻烦,用USART_RX_STA这个变量的最高位来判断串口接收完数据没,数组USART_RX_BUF用来缓存串口接收的数据,第一个字节来判断是用共用体还是用指针
    0x01  就是用float的共用体
    0x02  就是用double的共用体
    0x03  就是用指针强制操作float数据
    0x04  就是用指针强制操作double数据
程序运行,是看不到结果的,在硬件仿真下才看的到结果,用串口调试助手和MDK的硬仿平台
QQ截图20170324100245.png
改变第一个字节的数据就OK.
QQ截图20170324095119.png
结果出来了,回到标题,你是怎么处理的呢?有没有更灵活的方式?
天地庄周马;江湖范蠡船。 个性签名还是放QQ号吧,2060347305,添加说明EEworld好友

回复评论 (4)

不用麻烦,单精度浮点数占用4个字节,直接传输这4个字节到上位机,上位机不做处理直接还原原数值 如果嫌4个字节太多就用两个字节传输,浮点数乘以10或者100转成整形数,上位机端除以10或者100得到原来的浮点数。 本帖最后由 汤权 于 2017-3-24 10:58 编辑
亚里士缺德
点赞  2017-3-24 10:57
引用: 汤权 发表于 2017-3-24 10:57
不用麻烦,单精度浮点数占用4个字节,直接传输这4个字节到上位机,上位机不做处理直接还原原数值
如果 ...

你想说出的是移位?

假如定义了一个float型数据 num_f
上位机接收的四个字节,在num_f里直接移位获取四个字节

等效之下,这的确也适应MCU,的确是个好办法
天地庄周马;江湖范蠡船。 个性签名还是放QQ号吧,2060347305,添加说明EEworld好友
点赞  2017-3-24 11:06
串口通讯跟数据的数制无关,至于怎么表示浮点数,用常规表示法或者你自己定义的方法都可以。而常规表示法之所以是“常规”,自然有其方便之处。关于这一点,计算机原理和编程语言的教材都有详细讲解。
上传了一些书籍资料,也许有你想要的:https://download.eeworld.com.cn/user/chunyang
点赞  2017-3-24 15:18
传float或者double的每个字节,接收方依次接收,然后按顺序解析。
作为一个菜逼,干货并没有多少。唯一会的就是水,所以回帖水分大。望见谅!
点赞  2017-3-24 15:24
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复