在嵌入式开发中,经常碰到因端序使用不当导致的错误,故决定决定将工作中常见的转序函数进行梳理,一是为了避免犯同样的错误,二是为了以后方便查询。本文分为四个部分: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)时,计算/使用时需要转序;