利用串口传输结构体数据

写在前面:

本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。


一、涉及到的知识点


二、应用

结构体是一种数据的归类方式,相比数组或变量更具有整体全面性,例如一个数组只可以放一些按照元素顺序存放的单元变量,即 buffer = {x, x, x, x, x…},i 有多大,数组内元素就有多少。那么我们这时候如果我们用这个数组来接收串口接收信息,信息的格式是: 数据头 ->数据长度 ->数据区 ->数据校验 ->数据尾

假设数据区为 <姓名-身高-体重-性别-年龄>

那么我们用数组接收时,提取数据的时候就需要计算出数据格式中每个单元所对应的位置,即数组中第 i 个元素对应的内容;这样显然是很麻烦的,效率低下,这就相当于先织了一个大网,捕捉到一网鱼,还得过下称,才能按照重量分类开来一样

若是使用结构体来作数据传输,那么只需要彼此约定俗成,注意一下事项就可以了

按照上面的,我们先来构建一下这个结构体

typedef struct
{
    uint8_t head;         // 数据头
    uint16_t datalen;     // 数据长度
    uint8_t name[10];	  // 姓名
    uint8_t height;       // 身高
    uint8_t weight;       // 体重
    uint32_t sex;         // 性别
    uint8_t age;          // 年龄
    uint8_t checksum;     // 校验和
    uint8_t endmark;      // 结束
} Profile_TypeDef;

1、发送

void Send_function(void)
{
    Profile_TypeDef test;
    
    test.head = 0x5A;
    ...
    ...
    test.endmark = 0xFF;
    
    USART_SendString((uint8_t *)&test, sizeof(test));
}

因为串口数据发送是以 Byte为单位,我们需要把结构体强制转换一下

2、接收

Profile_TypeDef Message;

void Recv_function( uint8_t *ReceiveBuf )
{
    Profile_TypeDef *receive = NULL;
    
    receive = (Profile_TypeDef *)ReceiveBuf;
    
    Message.head = receive->head;
    Message.datalen = receive->datalen;
    ...
    ...
}

你以为这样就结束了吗?错的,你还要注意一些东西


三、注意事项

1、大小端问题

假设你是用 STM32来通讯,那么它的数据存储方式是小端模式(这个看手册,各款有着不同的数据存储方式,具体以手册为准),即数据的高字节存储在内存地址的高字节,低字节存储在内存地址的低字节,如果串口接收到的数据是低字节在前,则拷贝来的数据就不用进行处理,如果接收的数据是高字节在前则需要对拷贝来的数据进行高低字节反转,这个知识看开篇的 “字节序部分”

2、数据对齐问题

结构体存放的数据是紧密的连在一起放在内存的,但是,各个硬件平台对存储空间的处理上有很大的不同;一些平台对某些特定类型的数据只能从某些特定地址开始存取,比如有些架构的 CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐;其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失

结构体的对齐以及数据大小计算可以看上面的 “C语言结构体大小及对齐问题”

一般来说,我们构建一个结构体,它的对齐方式是按照编译器的默认设置进行对齐的;然而,那么我们是不是可以改变编译器的这种默认对齐设置呢?这个是可以的,例如:

#pragma pack (2) /*指定按2字节对齐*/
struct C
{
  char b;
  int a;
  short c;
};
#pragma pack ()   /*取消指定对齐,恢复缺省对齐*/

#pragma pack (value)用于指定对齐值为 value值,当然,这是在 gcc编译器上的指定对齐操作,不同的编译器有着自己的操作指令

  • keil mdk中,可以要查看一下 __align()的用法;

  • iar ewarm中,则查看一下 #pragma data_alignment的用法


四、最后

参考:

http://www.stmcu.org.cn/module/forum/thread-615994-1-1.html

https://www.topbyte.cn/2010/09/c-byte-alignment/

https://www.amobbs.com/thread-5600177-1-1.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值