在嵌入式开发中,经常碰到因端序使用不当导致的错误,故决定决定将工作中常见的转序函数进行梳理,一是为了避免犯同样的错误,二是为了以后方便查询。本文分为四个部分:1、什么是大小端序;2、大小端序数据相互转换函数;3、应用场景;4、使用总结。
1、什么是大小端序
大端模式:是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。
小端模式:是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。
现在,以一个unsigned int整型数据0x12345678为例,其大端序、小端序的存储内容如图所示。
2、大小端序数据相互转换函数
a)将unsigned char数组转换成“大端序”整数;
/* * Function: ConverseArrayToBeUI * Description: 将无符号字符数组数据转换成“大端序”整数 * Parameter: srcArray --[in] 源数组数据 * desBeData --[out] 目标“大端序”整数 * Return 0 成功 * 非0 失败 * Note: * Other: */ int MULCONVERSE_CALL ConverseArrayToBeUI(unsigned char *srcArray,unsigned int *desBeData) { if (srcArray == NULL_POINT || desBeData == NULL_POINT) { return ERR_NULL_POINT; } *desBeData = (unsigned int)(srcArray[0]<<24) + (unsigned int)(srcArray[1]<<16) + (unsigned int)(srcArray[2]<<8) + (unsigned int)srcArray[3]; return _SUCCESS; }
b)将unsigned char数组转换成“小端序”整数;
/* * Function: ConverseArrayToLeUI * Description: 将无符号字符数组数据转换成“小端序”整数 * Parameter: srcArray --[in] 源数组数据 * desLeData --[out] 目标“小端序”整数 * Return 0 成功 * 非0 失败 * Note: * Other: */ int MULCONVERSE_CALL ConverseArrayToLeUI(unsigned char *srcArray,unsigned int *desLeData) { if (srcArray == NULL_POINT || desLeData == NULL_POINT) { return ERR_NULL_POINT; } *desLeData = (unsigned int)(srcArray[3]<<24) + (unsigned int)(srcArray[2]<<16) + (unsigned int)(srcArray[1]<<8) + (unsigned int)srcArray[0]; return _SUCCESS; }
c)将整数按照“大端序”格式存储在数组中;
/* * Function: ConverseUItoBeArray * Description: 将无符号整数转换成“大端序”存储的无符号字符数组 * Parameter: srcData --[in] 源整数 * desBeArray --[out] 目标“大端序”存储的数组数据 * Return 0 成功 * 非0 失败 * Note: * Other: */ int MULCONVERSE_CALL ConverseUItoBeArray(unsigned int srcData,unsigned char *desBeArray) { if (desBeArray == NULL_POINT) { return ERR_NULL_POINT; } desBeArray[0] = (unsigned char)(srcData>>24); desBeArray[1] = (unsigned char)(srcData>>16); desBeArray[2] = (unsigned char)(srcData>>8); desBeArray[3] = (unsigned char)srcData; return _SUCCESS; }
d)将整数按照“小端序”格式存储在数组中。
/* * Function: ConverseUItoLeArray * Description: 将无符号整数转换成“小端序”存储的无符号字符数组 * Parameter: srcData --[in] 源整数 * desLeArray --[out] 目标“小端序”存储的数组数据 * Return 0 成功 * 非0 失败 * Note: * Other: */ int MULCONVERSE_CALL ConverseUItoLeArray(unsigned int srcData,unsigned char *desLeArray) { if (desLeArray == NULL_POINT) { return ERR_NULL_POINT; } desLeArray[3] = (unsigned char)(srcData>>24); desLeArray[2] = (unsigned char)(srcData>>16); desLeArray[1] = (unsigned char)(srcData>>8); desLeArray[0] = (unsigned char)srcData; return _SUCCESS; }
3、应用场景
PC(小端序)向芯片(大端序)发送数据
假设PC产生一个整数数值0x00000001,经通信接口(比如串口)向芯片发送数据时,按照一次发一字节的方式传输数据,那么此时芯片就会收到4字节数据,其内容按照地址从低到高排序为0x01,0x00,0x00,0x00,那么芯片就会认为自己收到的整数数值为0x01000000。
此时,两个硬件平台就会因为大小端的不同造成数据收发错误,此时解决的方法有两种:1、PC发送数据之前,通过转换函数ConverseUItoBeArray,将整数数值0x00000001转换成[00,00,00,01]字符数组,然后经通信接口发给芯片;2、芯片接收到4字节数据之后,通过函数ConverseArrayToLeUI,将[01,00,00,00]转换成整数0x00000001。
4、使用总结
(1)不同的硬件平台如果采用同一种类型的端序,计算/使用时无需转序;
(2)不同的硬件平台如果采用不同类型的的端序,但传输的字符数组“无需”转换成多字节基本类型数据(如int,double,float)时,计算/使用时无需转序;
(3)不同的硬件平台如果采用不同类型的的端序,但传输的字符数组“需要”转换成多字节基本类型数据(如int,double,float)时,计算/使用时需要转序;