stm32自设指令协议中,大小端问题的处理

大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;

小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

data0

Data1

Data2

Data3

Data4

Data5

Data6

Data7

Data8

Data9

帧头

指令

参数

CRC校验码

0xaabb

0x0001

0x01

0x02

0x1234

 

如上指令协议,我在解读时会按照大端模式理解,

即数据发送的顺序为:aabb 0001 0102 1234 crc

为了处理方便,构建如下结构体:

typedef struct
{
    u16 frame_head;
    u16 module_cmd;
    u8 cmd_data4;
    u8 cmd_data5;
    u16 cmd_data67;
    u16 crc_data;
}ProtocolType;

但我用的stm32f4系列为小端模式,这么构建结构体会带来一些问题:

问题1: 不能使用memcpy函数向结构体中复制数据,如果直接复制,frame_head中存储的数据为0xbbaa,这是大小端模式导致的。

问题2:crc码的计算,正如问题1所述,若要为计算crc16建立一个u16的数组,需要将源数据按字节取出,按照小端模式组合,再赋值到数组中:    

for(;word_len < (len>>1) ;word_len++)
    {
        rec_cmd_buff[word_len] = ((u16)p_data[(word_len<<1)]<<8)+p_data[(word_len<<1)+1];

    }

问题3:按照问题2的处理方法,我们可以很容易计算数据的crc码,并校验,而且还可以直接把这个数组复制到问题1设想的结构体中,但又会出现新的问题:结构体中的cmd_data4并非是0x01,而是0x02,这是因为单字节数据本身不受大小端存储方式的影响,但在问题2中,我们强行把cmd_data4,cmd_data5合并为了u16类型数据,导致两个数据颠倒了位置,所以要想正常使用ProtocolType结构体,可以把cmd_data4,cmd_data5的定义颠倒一下,或者干脆也定义成u16类型数据,高低字节分别取用就是了。

至于为什么非要定义成一个结构体呢,为了维护方便,提高可读性。。。

 

你可能感兴趣的:(stm32编程技巧)