查看原文
其他

串口数据传输中的共用体和结构体如何转换?

混说Linux 2022-11-19

点击左上方蓝色“混说Linux”,选择“设为星标

第一时间看干货文章 



 1

嵌入式系统的串口数据传输都是以字节为单位,但有些特殊的数据类型,比如浮点型float a = 231.5,在内存是如何表示的呢?


我们知道,浮点型float数据类型占用4个字节,实际上在内存当中a = 0x43678000,只是嵌入式芯片访问a时,知道a是浮点型数据,所以一次性读取4个字节,而且也按照浮点型的数据表示规定,将a转换为十进制的可读数据231.5。


如果我们从串口接收到4个字节数据{0x43,0x67,0x80,0x00},如何把这4个字节的数据转换为float型呢?


直接令float a = 0x43678000这是不行的(不信的读者可以自行验证),这就是串口通讯当中经常遇到的问题,如果数据传输中包括了浮点型数据,在这里我们可以通过共用体或者结构体来解决。


对于共用体:

typedef union
{
    float f;
    unsigned char s[4];
}Union_test;


f 的4个字节和s[4]的4个字节是共用一个区域,如果我们令f = 231.5,然后通过监视窗查看s[4]的数值,下面是测试程序:

#include <stdio.h>
//共用体
//float f;//4个字节
//char s[4];//4个字节
typedef union
{
    float f;
    unsigned char s[4];
}Union_test;

typedef struct st
{
    float f1;
}Struct_test;

void main(void)
{
    float a = 231.5;
    Union_test x;
    Struct_test z;
    x.f = a;
    z = *(Struct_test *)(&(x.s));
    printf("z=%.2f\r\n", (double)z.f1);
    printf("End of this programme\r\n");
}


监视结果如下所示:


我们同样适用结构体做了相同的实验,将数组s[4]={0x00,0x80,0x67,0x43}的首地址s[0]强制转换赋值给结构体z,最后打印输出的结果也是231.5这里我们看到原本应该是0x4367_8000的数据实际存储的时候变成了00H 80H 67H 43H,这是因为计算机系统使用了小端存储。


什么是小端存储呢?


我们都知道,对于一个超过一个字节的数据,其在计算机中的存储需要跨越字节。某些机器选择在存储器中按照从最低为有效字节到最高有效字节的顺序存储对象,而另一些机器则按照从最高为有效字节到到最低为有效字节的顺序存储,前一种存储方式被称为小端存储,后一种方式被称为大端存储。


举个例子,对于十六进制数0x01234567,其字节的存储顺序便依赖于机器,如下:

我们可以通过下面的函数测试是大端存储还是小端存储:

void test(void)
{
    int a = 1;
    unsigned char *start = &a;
    if(*start == 1)
        printf("小端存储");
    else if(*start == 0)
        printf("大端存储");
}


本文系网络转载,版权归原作者所有,如有侵权,请联系删除。





往期推荐

嵌入式软件工程师杂谈 —– 什么是BSP工程师?

图文并茂,详解TCP和UDP协议的原理和区别

详解C/C++堆栈的工作机制

嵌入式系统常用的7个技巧

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存