🚀 加载中...
侧边栏壁纸
博主头像
Fish's Embedded Study & Share

积跬步以至千里,积小流以成江河

  • 累计撰写 11 篇文章
  • 累计创建 14 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

double类型数据通过串口发送到上位机问题

玩不转C的鱼
2025-03-20 / 0 评论 / 0 点赞 / 87 阅读 / 0 字

一、问题引出

众所周知,串口发送数据一次是一个字节,那么如何将一个double类型数据(8字节)通过串口发送到上位机呢?

二、问题思考

首先考虑使用位运算的方式将8字节的数据逐一取出,然后逐一发送,但是没有想到**浮点型的数据是不可以位运算的**。

然后这个时候可以引出联合体了,已知联合体的特性:`各成员共享一段内存空间,一个联合变量的长度等于各成员中最长的长度`,那么联合体中变量内存空间共享了,那么给其中一个变量赋值,势必会造成其他变量的值的改变。(这里还需要了解小端存储概念

如下程序所示:

#include <stdio.h>

union

{

    unsigned int  var1;

    unsigned char var2[4];

}data;

int main(int argc, char const *argv[])

{

    data.var1 = 0x12345678;

    for (int i = 3; i >= 0; i--)

    {

        printf("%p : %x \n",&data.var2[i] , data.var2[i]);

    }

    return 0;

}

在上述程序中,定义了一个联合体,虽然我只将var1定义为0x12345678,但是由于联合体变量共用内存,由基于系统是小端存储,因此,连续四字节从低到高分别存储0x78、0x56、0x34、0x12。如下运行结果所示:

运行结果: 
gcc double.c -o double_test                                                                                  
root@DESKTOP-G52VFSH /m/c/U/Y/D/t/study#                                                                                                              
root@DESKTOP-G52VFSH /m/c/U/Y/D/t/study# ./double_test 
0x55cd189e0017 : 12 
0x55cd189e0016 : 34
0x55cd189e0015 : 56
0x55cd189e0014 : 78
root@DESKTOP-G52VFSH /m/c/U/Y/D/t/study#          

三、问题解决

基于上述的验证,我们在对不能位运算的浮点型数据有把它拆成一个字节一个字节需求时,可以使用联合体去处理,如下所示:

#include <stdio.h>

union

{

    double  var1;

    unsigned char var2[8];

}data;

int main(int argc, char const *argv[])

{

    data.var1 = 1.265341;

    for (int i = 7; i >= 0; i--)

        printf("%p : %#x \n",&data.var2[i] , data.var2[i]); 

    return 0;

}
运行结果:
root@DESKTOP-G52VFSH /m/c/U/Y/D/t/study# gcc double.c -o double_test                                                                                  
root@DESKTOP-G52VFSH /m/c/U/Y/D/t/study#                                                                                                              
root@DESKTOP-G52VFSH /m/c/U/Y/D/t/study#                                                                                                              
root@DESKTOP-G52VFSH /m/c/U/Y/D/t/study# ./double_test                                                                                                
0x555a9b1d501f : 0x3f 
0x555a9b1d501e : 0xf4
0x555a9b1d501d : 0x3e
0x555a9b1d501c : 0xd6
0x555a9b1d501b : 0x34
0x555a9b1d501a : 0x54
0x555a9b1d5019 : 0x9b
0x555a9b1d5018 : 0x63

如上所示,double型的1.265341在内存上的各个字节的分布

我们可以反过来验证一下,程序如下所示:

#include <stdio.h>

union

{

    double  var1;

    unsigned char var2[8];

}data;

int main(int argc, char const *argv[])

{

    /*实现将double数据转成拆开的单字节数据*/

    /*

    data.var1 = 1.265341;

    for (int i = 7; i >= 0; i--)

        printf("%p : %#x \n",&data.var2[i] , data.var2[i]); 

    */

   /*反向验证将拆开的字节数据放入联合体变量,是否会让double变量恢复*/

   data.var2[0] = 0x63;

   data.var2[1] = 0x9b;

   data.var2[2] = 0x54;

   data.var2[3] = 0x34;

   data.var2[4] = 0xd6; 

   data.var2[5] = 0x3e;

   data.var2[6] = 0xf4;

   data.var2[7] = 0x3f;

   printf("data.var1 = %lf \n",data.var1);

    return 0;

}

运行结果如下所示,说明该方法可行。

root@DESKTOP-G52VFSH /m/c/U/Y/D/t/study# gcc double.c -o double_test                                                                                  
root@DESKTOP-G52VFSH /m/c/U/Y/D/t/study#                                                                                                              
root@DESKTOP-G52VFSH /m/c/U/Y/D/t/study#                                                                                                              
root@DESKTOP-G52VFSH /m/c/U/Y/D/t/study# ./double_test                                                                                                
data.var1 = 1.265341 
root@DESKTOP-G52VFSH /m/c/U/Y/D/t/study#              

0

评论区