打印

急!!avr程序向51程序移植时发现字节顺序不同,该如何解解

[复制链接]
2373|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
21ele|  楼主 | 2007-3-15 00:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
hotpower| | 2007-3-15 00:43 | 只看该作者

大端和小端即存储顺序相反~~~移植时细心便是~~~

使用特权

评论回复
板凳
21ele|  楼主 | 2007-3-15 01:17 | 只看该作者

谢谢!!


一直再用avr,类似(u08)( *((u16*)data_ptr) >> (StartAdr%8) )的用法一直在用,感觉字节和字指针强制类型转换非常有用。

我是在作modbus程序,在avr上调试通过了,到51上发现这个问题,如果不用指针类型强制转换,感觉实现起来会不太方便。

//*****************************************************************************************************//
// 01: 读线圈状态处理
//*****************************************************************************************************//
u08 MB_Read_Coli_Status(void)
{
    u08 i;
    u08 ByteCount;
    u08* data_ptr;
    u16 StartAdr, NumPoints;

    // 取起始地址
    StartAdr     = (mb_adu[2]<<8)+mb_adu[3];

    // 取数量
    NumPoints = (mb_adu[4]<<8)+mb_adu[5];
    
    //----------------------------------------------------------------------------//
    // 确认线圈地址及数量有效
    //----------------------------------------------------------------------------//
    data_ptr = MB_Is_M(StartAdr, StartAdr+NumPoints);
    if ( !data_ptr )
    {
        return MB_ILLEGAL_DATA_ADDRESS;
    }
    
    //----------------------------------------------------------------------------//
    // 生成响应PDU  数据:  字节数+   线圈状态数据
    //----------------------------------------------------------------------------//
    // 计算线圈数据字节数
    ByteCount = ((NumPoints-1)/8+1);
    mb_adu[2] = ByteCount;
        
    // 填充读出数据
    for (i=0;  i<ByteCount; i++ )
    {
        mb_adu[i+3] = (u08)( *((u16*)data_ptr) >> (StartAdr%8) );
        data_ptr++;
    }

        mb_adu[ByteCount+2] &= (0xFF>>(8-NumPoints%8)%8);

    // 计算请求长度
    mb_adu_len = 1+1+1+ ByteCount+1;

    //----------------------------------------------------------------------------//
    // 确认操作有效
    //----------------------------------------------------------------------------//
    return MB_REQUEST_OK;
    
}
 
mb_adu[i+3] = (u08)( *((u16*)data_ptr) >> (StartAdr%8) );8位
mb_adu[ByteCount+2] &= (0xFF>>(8-NumPoints%8)%8);
这两句是关键,是为了实现从data_ptr指针指向的位数据,从任意位地址开始取任意位数据,按字节保存,不足8位0补齐。
现在51里,字节顺序反了,数组里的低位是字里的高位,全乱了。

使用特权

评论回复
地板
21ele|  楼主 | 2007-3-15 08:49 | 只看该作者

问题解决了,写一个函数替代就好了!

//*****************************************************************************************************//
// 51 RAM 字节地址按字读入
//*****************************************************************************************************//
u16 Read_Word_51( u08* byte_ptr )
{
    u16 word_data;

    word_data  = (u16)*byte_ptr;            //读入低位字节
    word_data |= ((u16)*(byte_ptr+1))<<8;    //读入高位字节

    return word_data;
}



//*****************************************************************************************************//
// 01: 读线圈状态处理
//*****************************************************************************************************//
u08 MB_Read_Coli_Status(void)
{
    u08 i;
    u08 ByteCount;
    u08* data_ptr;
    u16 StartAdr, NumPoints;

    // 取起始地址
    StartAdr     = (mb_adu[2]<<8)+mb_adu[3];

    // 取数量
    NumPoints = (mb_adu[4]<<8)+mb_adu[5];
    
    //----------------------------------------------------------------------------//
    // 确认线圈地址及数量有效
    //----------------------------------------------------------------------------//
    data_ptr = MB_Is_M(StartAdr, StartAdr+NumPoints);
    if ( !data_ptr )
    {
        return MB_ILLEGAL_DATA_ADDRESS;
    }
    
    //----------------------------------------------------------------------------//
    // 生成响应PDU  数据:  字节数+   线圈状态数据
    //----------------------------------------------------------------------------//
    // 计算线圈数据字节数
    ByteCount = ((NumPoints-1)/8+1);
    mb_adu[2] = ByteCount;
        
    // 填充读出数据
    for (i=0;  i<ByteCount; i++ )
    {
        //mb_adu[i+3] = (u08)( *((u16*)data_ptr) >> (StartAdr%8) );            //AVR

        mb_adu[i+3] = (u08)( Read_Word_51(data_ptr)>>(StartAdr%8) );        //51
        data_ptr++;
    }

        mb_adu[3+ByteCount-1] &= (0xFF>>(8-NumPoints%8)%8);    //最后字节补0处理

    // 计算请求长度
    mb_adu_len = 1+1+1+ ByteCount+1;

    //----------------------------------------------------------------------------//
    // 确认操作有效
    //----------------------------------------------------------------------------//
    return MB_REQUEST_OK;
    
}

使用特权

评论回复
5
IC1008| | 2007-3-15 08:58 | 只看该作者

用union 联合类型啊

长整形 + 4个单字节数组啊

使用特权

评论回复
6
ayb_ice| | 2007-3-15 11:44 | 只看该作者

随便说说

    如果程序一开始没有考虑移植的话那只能慢慢改了,以后可以先定义一宏如

#define END_MODE 0  // 0=小端模式, 1=大端模式

#if END_MODE > 0    // 大端模式
    #define U16_HIGH_BYTE   0
    #define U16_LOW_BYTE    1
#else
    #define U16_HIGH_BYTE   1
    #define U16_LOW_BYTE    0
#endif

    unsigned int temp;

    ((unsigned char*)&temp)[U16_HIGH_BYTE] = 0x55;
    ((unsigned char*)&temp)[U16_LOW_BYTE]  = 0xAA;

    这样就具备可移植性了,在KEIL里只须定义END_MODE=1,在小端的编译器里
定义END_MODE=0即可.

使用特权

评论回复
7
21ele|  楼主 | 2007-3-15 12:30 | 只看该作者

联合解决不了问题,指针强制类型转换实现的就是联合的思

void main(void)
{

volatile unsigned  char tmp[4]={0x12,0x34,0x56,0x78};
volatile unsigned  char* data_ptr = tmp; 
   
volatile unsigned short a= *data_ptr;
volatile unsigned short b=  *(( unsigned short*)data_ptr);
union wd_be
{
  unsigned short wd;  //字  
  unsigned char be[2];  //字节数组
};
union wd_be* data_ptr1 = (union wd_be*)tmp;
volatile unsigned short c= (*data_ptr1).wd;
volatile unsigned short d= ( unsigned short )(*data_ptr1).be[0];
volatile unsigned short e= ( unsigned short )(*data_ptr1).be[1];

while(1)
{
  
}
}

使用特权

评论回复
8
21ele|  楼主 | 2007-3-15 12:34 | 只看该作者

ayb_ice的办法不错,谢谢分享!!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

21

主题

191

帖子

1

粉丝