on_the_road

博客园 首页 新随笔 联系 订阅 管理

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

posted on 2015-04-25 10:41  on_the_road  阅读(18940)  评论(1编辑  收藏  举报