打印

标志位及全局变量的处理问题

[复制链接]
4583|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zq1987731|  楼主 | 2008-11-27 22:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
51单片机中定义全局标志位相当方便,只要用bit关键字,然后就可以进行相关操作,相对效率挺高,但是在ARM7这样的32位RISC我就感觉比较麻烦了...
目前我用的方法:
1) uint32 Flag_XXX;      // 牺牲RAM空间换取执行速度
2) uint8  Flag_XXX;      // 执行时先要扩成32位才载入寄存器,也就是牺牲执行速度节省RAM
3) typedef struct
    {
        uint32 Bit_31 : 1;
        uint32 Bit_30 : 1;
        ......
        uint32 Bit_0  : 1;
    }Flag_Type;

    Flag_Type XXX;        // 最省RAM的方法了...速度好像...当然也慢不到哪去
======================================================
现在我的程序中所有局部变量全都是uint32,包括只用了1bit的局部变量也作为uint32,反正函数调用完就销毁,又不浪费速度又快,但是用在全局变量中我就很难取舍了...在此请问大家是如何处理的呢?




相关帖子

沙发
zq1987731|  楼主 | 2008-11-27 23:30 | 只看该作者

突发奇想看了看反汇编,没想到...

typedef struct
    {
        uint8 Bit_31 : 1;
        uint8 Bit_30 : 1;
        ......
        uint8 Bit_0  : 1;
    }Flag_Type;

// 占用4个字节,每个位都用uint8定义
    Flag_Type XXX; 
        
// 下面是反汇编结果,分别对其中2个位置1和清0    
    // XXX.Bit_31 = 1; 
    LDRB      R0,[R13]
    BIC       R0,R0,#0x00000001
    MOV       R1,#0x00000001
    AND       R1,R1,R1
    ORR       R0,R0,R1
    STRB      R0,[R13]

    // XXX.Bit_24 = 0; 
    LDRB      R0,[R13]
    BIC       R0,R0,#0x00000080
    MOV       R1,#0x00000080
    AND       R1,R1,R2,LSL #7
    ORR       R0,R0,R1
    STRB      R0,[R13]

==================================================================
typedef struct
    {
        uint32 Bit_31 : 1;
        uint32 Bit_30 : 1;
        ......
        uint32 Bit_0  : 1;
    }Flag_Type;

// 同样占用4个字节,每个位都用uint32定义
    Flag_Type XXX;         

// 下面是反汇编结果,分别对其中2个位置1和清0
    // XXX.Bit_31 = 1; 
    LDR       R0,[R13]
    ORR       R0,R0,#0x00000001
    STR       R0,[R13]

    // XXX.Bit_24 = 0; 
    LDR       R0,[R13]
    BIC       R0,R0,#0x00000080
    STR       R0,[R13]

==================================================================
    所用编译环境RealView MDK 3.24 ,编译器:RealView Compiler
    原来......即使同样大小的位段成员(1bit),同样大小的结构——4个uint8(unsigned char)组成的32位以及1个uint32(unsigned long int)组成的32位,操作起来也能有如此大的区别...看来要坚决把uint32用到底了...

使用特权

评论回复
板凳
ejack| | 2008-11-28 07:52 | 只看该作者

一定要记住,32位就是32位,按8位处理只会给自己找麻烦

使用特权

评论回复
地板
xwj| | 2008-11-28 08:32 | 只看该作者

当然是按处理器字长来操作最快

不要把51 的习惯带到其他的东西上哦~

使用特权

评论回复
5
zq1987731|  楼主 | 2008-11-28 18:02 | 只看该作者

这下明白了...

51用习惯了处处unsigned char然后造成了这种问题...

现在开始用下面的形式了:
typedef struct
    {
        uint32 Bit_31 : 1;
        uint32 Bit_30 : 1;
        ......
        uint32 Bit_0  : 1;
    }Flag_Type;

    Flag_Type X_State;

感觉这样用的话也挺方便的...比如存进SRAM只需要:
Write_Bytes( (uint8*)&X_State, sizeof(X_State) );
 

不过我今天硬件调试时从串口的反馈中看出了这样的问题所在:
我给X_State赋了初值:
X_State = { 0, 0, 0, 0, 1, 1, 1, 1,
            1, 1, 1, 1, 0, 0, 0, 0,
            1, 1, 0, 0, 1, 1, 0, 0,
            0, 0, 1, 1, 0, 0, 1, 0 };

然后从结构体第一个字节(Bit_31~Bit_24这8个位段)开始按顺序发送至串口,得出以下结果:
0xF0 -- (uint8*)(&X_State + 0)
0x0F -- (uint8*)(&X_State + 1)
0x33 -- (uint8*)(&X_State + 2)
0x4C -- (uint8*)(&X_State + 3)

也就是字节不变,字节内的数据前后颠倒...难道C语言编译器都是这样的么?还是RealView来个别出心裁?又难道是我地址引用错误?...
 

使用特权

评论回复
6
Swd21ic| | 2008-11-28 19:08 | 只看该作者

re

标志位当然是用UINT8,不用UINT32.
在ARM7中RAM资源是非常宝贵的. 最大的ARM7也只能做到128K的内部SRAM.(AT91SAM7X512)

使用特权

评论回复
7
zq1987731|  楼主 | 2008-11-28 20:56 | 只看该作者

To Mr.Swd21ic

我现在弄明白了...用uint8和uint32作为标志位其实都很浪费的...
现在正采用的标志位是结构体位段..
好处在于空间利用率最高,同时读写速度虽说没uint32那么快但至少比uint8快了,比如我在上面举过例子的两个位段,sizeof的结果都是4字节,同时它们都含有32个1bit的标志位,但是在执行时,用uint8定义的位段要先扩成uint32后才能进入寄存器,但是用uint32定义的位段直接就可以进入寄存器。
所以标志位段用uint32占用空间和uint8相同的情况下速度更快。这么看来要是有64位的单片机,uint64就要用得泛滥了..

使用特权

评论回复
8
ayb_ice| | 2008-11-28 23:11 | 只看该作者

这很简单因为ARM是32位机

使用特权

评论回复
9
xhtxzxw| | 2008-11-29 00:03 | 只看该作者

嘿嘿

ARM v7 就好了,没这个问题,比如STM32,就有"位别名"空间,位操作都是单周期的.

使用特权

评论回复
10
zq1987731|  楼主 | 2008-11-29 09:51 | 只看该作者

早知道就上STM32了...

我现在用的是ADuC7026,ADI的ARM7,超级冷门...
要不是有12路12位AD(这个到也没什么,好多主流的都有)和4路12位DA(这个是重点)我估计早换型了.....

使用特权

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

本版积分规则

95

主题

759

帖子

3

粉丝