单片机数据存储大小端模式及避免数据结构接收出错问题

背景

    首先讲一下为什么有兴趣写这篇文章,是因为最近在工作中进行两个节点串口通讯数据收发,发现接收
数据的高字节和低字节出现了交换位置的现象。

举例

单片机数据存储大小端模式及避免数据结构接收出错问题_第1张图片
以上为博主定义的一个接收结构体,在不考虑字节对齐的情况下(实际上是以单字节对齐的方式)。我用这个结构体去接收来自串口发来的一组数据。假设串口端发来的数据是0X01,0X02,0X03,0X04,0X05,0X06,0X07,0X08,0X09,0X10,0X11,0X12,0X13,0X14,0X15,0X16,0X17这十七个字节数据。我当时理想状态是结构体中short类型的CRC16_Value值为0X1516。但仿真看数据发现CRC16_Value值为0X1615,高低字节发生了转换。经分析故引出大小端存储问题,对于以上这个问题在不改变数据结构的情况下保证数据接收正确的方法我将在下方进行说明。

大小端存储

小端:较高的有效字节存储在较高的存储器地址,较低的有效字节存储在较低的存储器地址。
大端:较高的有效字节存储在较低的存储器地址,较低的有效字节存储在较高的存储器地址。

STM32 属于小端模式,简单地说:比如:int temp=0X12345678;假设temp的地址为:0X4000 2000
那么,在内存里面,其存储就变成了:
小端模式:
地址 数值
0X4000 2000 0X78
0X4000 2001 0X56
0X4000 2002 0X34
0X4000 2003 0X12

大端模式:
地址 数值
0X4000 2000 0X12
0X4000 2001 0X34
0X4000 2002 0X56
0X4000 2003 0X78

原因说明如下:

为何会出现大小端之分:
这是因为在计算机系统中,我们是以字节为单位的,
每个地址单元都对应着一个字节,一个字节为8bit。
但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),
另外,对于位数大于8位的处理器,例如16位或者32位的处理器,
由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。
因此就导致了大端存储模式和小端存储模式。
例如一个16bit的short型x,在内存中的地址为0x0011,x的值为0x2233,
那么0x22为高字节,0x33为低字节。对于大端模式,就将0x22放在低地址中,即0x0011中,
0x33放在高地址中,即0x0012中。小端模式,刚好相反。
我们常用的X86结构是小端模式,而KEIL C51则为大端模式。
很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

大小端存储数据转化

针对上面抛出的问题,如果想让结构体中定义的超过1字节的数据顺利正确接收的话,应该让发送方按低字节先
发的方式,这样数据就可以按照定义的数据结构正常接收啦。

你可能感兴趣的:(数据结构,大小端存储,单片机,数据结构,嵌入式硬件)