打印
[AVR单片机]

位操作之C++版

[复制链接]
8198|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
John_Lee|  楼主 | 2007-8-20 13:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
倒塌......一下hotpower。:-)

以前看过hotpower的位定义https://bbs.21ic.com/club/bbs/showEssence.asp?id=5504&page=3,使用之后觉得有些不爽,不爽于位取反的低效。

例子:

#include <avr/io.h>
#define RELAY0    (*(volatile MCUBITBYTE *) (_SFR_ADDR (PORTA))).BIT.BIT01
#define RELAY1    (*(volatile MCUBITBYTE *) (_SFR_ADDR (PORTA))).BIT.BIT02
#define RELAY2    (*(volatile MCUBITBYTE *) (_SFR_ADDR (PORTA))).BIT.BIT03

void relay_example (void)
{
    RELAY0 = 1;     //  置1
    RELAY1 = 0;     //  置0
    RELAY2 ^= 1;    //  取反
}

生成的代码如下:

void relay_example (void)
{
    RELAY0 = 1;     //  置1
   0:   d9 9a           sbi     0x1b, 1 ; 27
    RELAY1 = 0;     //  置0
   2:   da 98           cbi     0x1b, 2 ; 27
    RELAY2 ^= 1;    //  取反
   4:   8b b3           in      r24, 0x1b       ; 27
   6:   86 95           lsr     r24
   8:   86 95           lsr     r24
   a:   86 95           lsr     r24
   c:   80 95           com     r24
   e:   81 70           andi    r24, 0x01       ; 1
  10:   88 0f           add     r24, r24
  12:   88 0f           add     r24, r24
  14:   88 0f           add     r24, r24
  16:   9b b3           in      r25, 0x1b       ; 27
  18:   97 7f           andi    r25, 0xF7       ; 247
  1a:   98 2b           or      r25, r24
  1c:   9b bb           out     0x1b, r25       ; 27
  1e:   08 95           ret
}

大家可以看到,单纯的赋值语句所生成的代码是最为简洁的,而读-修改-写语句的代码却非常低效(在其它编译器上是否也是如此?希望大家都来试验一下),用了13条指令。
最理想的代码应该是这样的:
in      reg1, 0x1b
ldi     reg2, 0x08
eor     reg1, reg2
out     0x1b, reg1

目前在C下,好像没有更好的办法让编译器编译出最优的代码,只能等待以后的编译器给出满意的结果了。

但是我们还有C++,它可以帮助我们得到最优的代码。

下面是用C++的模板实现的位模板定义:
template<uint8_t S, uint8_t W>
union _sbit_t
{
    struct {
        uint8_t                 :S;     //  无用的位
        volatile uint8_t sbit   :W;     //  有用的位
    };
    uint8_t byte;
    const _sbit_t<S, W> &operator = (uint8_t v) { sbit = v; return *this; }
    const _sbit_t<S, W> &operator ^= (uint8_t v) { byte ^= uint8_t ((v & ((1 << W) - 1)) << S); return *this; }
    operator uint8_t () { return sbit; }
};

再定义一个宏来使用上面的模板:
#define SFR(P, S, W)    (*(_sbit_t<S, W> *) (_SFR_ADDR (P)))
P:特殊功能寄存器
S:需操作的位在寄存器中的起始位置
W:位的宽度

好了,用上面同样的程序测试一下:
#define RELAY0    SFR (PORTA, 1, 1)
#define RELAY1    SFR (PORTA, 2, 1)
#define RELAY2    SFR (PORTA, 3, 1)

void relay_example (void)
{
    RELAY0 = 1;     //  置1
    RELAY1 = 0;     //  置0
    RELAY2 ^= 1;    //  取反
}

生成的代码:
void relay_example (void)
{
    RELAY0 = 1;     //  置1
   0:   d9 9a           sbi     0x1b, 1 ; 27
    RELAY1 = 0;     //  置0
   2:   da 98           cbi     0x1b, 2 ; 27
    RELAY2 ^= 1;    //  取反
   4:   8b b3           in      r24, 0x1b       ; 27
   6:   98 e0           ldi     r25, 0x08       ; 8
   8:   89 27           eor     r24, r25
   a:   8b bb           out     0x1b, r24       ; 27
   c:   08 95           ret
}

完美。

声明:任何媒体和个人以及法律所允许的可发表言论的任何媒体均不得转载和摘录,否则将承担由此产生的法律责任。

相关帖子

沙发
ayb_ice| | 2007-8-20 13:48 | 只看该作者

用C的位域不是很好吗...

使用特权

评论回复
板凳
hotpower| | 2007-8-20 23:06 | 只看该作者

冤枉呀~~~俺是反对低效的位域的~~~

哈哈~~~那是看张教主红宝书后的心得体会~~~


欢迎John_Lee教授参与讨论在MCU/ARM/DSP裸奔的C++框架结构.

先以GCCAVR/IAR AVR之C++开始~~~


谢谢!!!
相关链接:http://www.**/blog/hotpower/11714/message.aspx

使用特权

评论回复
地板
hotpower| | 2007-8-20 23:51 | 只看该作者

俺觉得IAR AVR的位域不错~~~老师您看如何???

使用特权

评论回复
5
hotpower| | 2007-8-20 23:59 | 只看该作者

哈哈~~~老师穿红裤头了~~~

不知帽子双龙给他带什么颜色~~~哈哈~~~

学习了~~~

使用特权

评论回复
6
hq_y| | 2007-8-21 06:04 | 只看该作者

著作权的意识大大提高了~~~~~~~~~~`

使用特权

评论回复
7
ayb_ice| | 2007-8-21 11:20 | 只看该作者

位域是否高效完全取决于编译器...

使用特权

评论回复
8
hotpower| | 2007-8-21 18:25 | 只看该作者

IAR的位芋还是挺聪明地~~~

使用特权

评论回复
9
hotpower| | 2010-7-27 19:54 | 只看该作者
说实话,John_Lee是AVR第一人,马潮教授也应该让三分~~~

使用特权

评论回复
10
testcode| | 2010-7-28 00:53 | 只看该作者
顶!

使用特权

评论回复
11
xuyiyi| | 2010-7-28 19:02 | 只看该作者
HOT大叔挖墓~~~

使用特权

评论回复
12
hotpower| | 2011-7-13 08:52 | 只看该作者
哈哈,继续

使用特权

评论回复
13
qin552011373| | 2011-8-22 14:19 | 只看该作者
不错  顶一个

使用特权

评论回复
14
dong_abc| | 2012-6-28 01:18 | 只看该作者
5年了才看到。

使用特权

评论回复
15
dong_abc| | 2012-6-28 01:19 | 只看该作者
好贴收藏。

使用特权

评论回复
16
kangxuebin| | 2012-10-19 22:03 | 只看该作者
不错

使用特权

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

本版积分规则

33

主题

1466

帖子

21

粉丝