AVR笔记9:AVR的两种位操作的比较

发布者:Haifeeng最新更新时间:2015-09-16 来源: eefocus关键字:AVR笔记  位操作 手机看文章 扫描二维码
随时随地手机看文章
AVR的两种位操作的比较(wjc3k发于21ic)(位域与C位操作的比较)

AVR的两种位操作的比较(位域方式和移位宏方式)

测试环境如下:
硬件:AT90S2313
软件:    WiinAVR gcc3.3   -Os级优化(最小size)。


说明:
    由于AVR不支持位操作,所以必须通过软件来实现。下面对我所知道的两种方法进行一个简单的比较。
    1、位域方式。先定义一个位域,
            typedef struct _bit_struct
            {
                unsigned char bit0 ;
                unsigned char bit1 ;
                unsigned char bit2 ;
                unsigned char bit3 ;
                unsigned char bit4 ;
                unsigned char bit5 ;
                unsigned char bit6 : ;
                unsigned char bit7 ;
            }bit_field;
        再用一个宏    ,来指向要操作的位。
             #define LED             GET_BITFIELD(PORTB).bit0
             #define BUTTON      GET_BITFIELD(PINB).bit7
        使用时只需要直接赋值即可:如LED     ,LED 1,  或者直接判断 LED==0       LED ==1.
        这种方法类似C51中的位操作。直接。
    2、位移宏方式。主要有三个.
                #define Set_Bit(val, bitn)    (val |=(1<<(bitn)))
                #define Clr_Bit(val, bitn)     (val&=~(1<<(bitn)))
                #define Get_Bit(val, bitn)    (val &(1<<(bitn)) )
         三个分别用来设置某一位,清除某一位,取某一位的值.
           使用方法为.Set_Bit(PORTA,3);   Clr_Bit(PORTB,2);   Get_Bit(val,5);
    3、测试程序.
           说明,假设PORTB.7接按纽,PORTB.0 接LED
           测试程序完成如下操作。
                   当BUTTON == 0时 ,LED输出1 否则输出0,
                   这样的目的是即测试了输入,又测试了输出1和输出0,相对全面一点。  C代码如下.

                // testled.c     测试AVR的位操作.
                // 这是gcc;如是其它编译器,请修改。
                #i nclude 

                // 定义一个寄存器(Register)或端口(Port)的八个位
                typedef struct _bit_struct
                {
                    unsigned char bit0 ;
                    unsigned char bit1 ;
                    unsigned char bit2 ;
                    unsigned char bit3 ;
                    unsigned char bit4 ;
                    unsigned char bit5 ;
                    unsigned char bit7 ;
                    unsigned char bit6 ;
                }bit_field;

                  //定义一个宏,用来得到每一位的值
                #define GET_BITFIELD(addr) (*((volatile  bit_field *) (addr)))

                //定义每一个位
                #define LED             GET_BITFIELD(PORTB).bit0
                #define BUTTON      GET_BITFIELD(PINB).bit7


                #define Set_Bit(val, bitn)    (val |=(1<<(bitn)))
                #define Clr_Bit(val, bitn)     (val&=~(1<<(bitn)))
                #define Get_Bit(val, bitn)    (val &(1<<(bitn)) )

                int main( void )
                {
                    DDRB 0x41;   //配置PB0为输出,PB7为输入
                    if BUTTON==0     LED 1; else LED 0;
                    //if(!Get_Bit(PINB,7)  Set_Bit(PORTB,0);    else Clr_Bit(PORTB,0);
                    while(1);
                }
                //     ----------------------        end         -----------------------------
    4、测试过程。
       a.先使用位域方式。
       主程序中使用 if BUTTON==0     LED 1; else LED 0;
       结果如下:
                     int main( void )
                    {
                      4a:    cf ed           ldi    r28, 0xDF    223
                      4c:    d0 e0           ldi    r29, 0x00    0
                      4e:    de bf           out    0x3e, r29    62
                      50:    cd bf           out    0x3d, r28    61
                        DDRB 0x41;      //配置PB0为输出,PB7为输入
                      52:    81 e4           ldi    r24, 0x41    65
                      54:    87 bb           out    0x17, r24    23
                        if BUTTON==0     LED 1; else LED 0;
                      56:    86 b3           in    r24, 0x16    22
                      58:    e8 2f           mov    r30, r24
                      5a:    ff 27           eor    r31, r31
                      5c:    80 81           ld    r24, Z
                      5e:    86 fd           sbrc    r24, 6
                      60:    07 c0           rjmp    .+14         0x70
                      62:    88 b3           in    r24, 0x18    24
                      64:    e8 2f           mov    r30, r24
                      66:    ff 27           eor    r31, r31
                      68:    80 81           ld    r24, Z
                      6a:    81 60           ori    r24, 0x01    1
                      6c:    80 83           st    Z, r24
                      6e:    06 c0           rjmp    .+12         0x7c
                      70:    88 b3           in    r24, 0x18    24
                      72:    e8 2f           mov    r30, r24
                      74:    ff 27           eor    r31, r31
                      76:    80 81           ld    r24, Z
                      78:    8e 7f           andi    r24, 0xFE    254
                      7a:    80 83           st    Z, r24
                        while(1);
                      7c:    ff cf           rjmp    .-2          0x7c

         main函数共52Bytes.其中,从lst文件看得出:main函数的初始化用了4条指令,8Bytes. 最后一句while(1);用了1条指令2Bytes.( for循环和do-while也是)
         DDRB=0x41用了2条指令4Bytes. 计算一下:52-8-4-2=38Bytes,即if BUTTON==0     LED 1; else LED 0; 这句用了19条指令38Bytes. (居然运用了3个寄存器白r24,r30,r31,和一个Z,代码真是苦涩,,我看不懂,准备以后作代码加密用:).  )
       b.使用移位宏方式。
       将 if BUTTON==0     LED 1; else LED 0;  换为等效的     if(!Get_Bit(PINB,7)  Set_Bit(PORTB,0);    else Clr_Bit(PORTB,0);

       结果,main函数仅24Bytes.其它代码一样,略去. 所以,上面这句代码仅用了24-14=10Bytes ,5条指令。生成的代码如下:
              56:    b7 99           sbic    0x16,    22
              58:    02 c0           rjmp    .+4          0x5e
              5a:    c0 9a           sbi    0x18,    24
              5c:    01 c0           rjmp    .+2          0x60
              5e:    c0 98           cbi    0x18,    24
    5. 菜论:鱼和熊掌。
      由于AVR可以对I/O脚进行sbic,sbi,cbi,这样的位操作,所以使用I/O脚操作时,移位宏可以产生高效的代码。
      例如,要实现上面的几个简单的指令,为了实现LED=1这样的类似C51的sbit的效果,我必须多付出(38-10=28Bytes)的代价。

    6......
        对于I/O脚,可以产生这样高效的代码,是因为有sbi和cbi这样的指令,那么对于一般的变量,又如何呢?................

关键字:AVR笔记  位操作 引用地址:AVR笔记9:AVR的两种位操作的比较

上一篇:太阳能路灯联网监控节能系统方案
下一篇:AVR笔记8:mega16再次锁死

推荐阅读最新更新时间:2024-03-16 14:31

基于ARM9的32高端嵌入式微处理器和嵌入式操作系统内核研
本文研究的是基于ARM9的32位高端嵌入式微处理器和嵌入式操作系统内核,设计新型数据采集系统平台,是得到重庆大学创新实验室资助的研发项目。开发软件在uclinux操作系统下进行,本文详细介绍了uclinux开发环境的建立及编译运行、RS232串口模块和以太网模块的软件设计。      本文是基于嵌入式系统ARM9平台的设计,并得到了重庆大学创新实验室的资助,其系统设计及网络软件编程均经过实践检验,具有较强的通用性,部分功能的改变只需添加或删除相关的代码,不必对整个系统进行大改动,提供的实验步骤具有可操作性。本文是研发小组在研发过程中进行的软件部分总结而编写的。 1 嵌入式数据采集平台整体设计    一个完
[单片机]
STM32F429--操作
一、位带操作的原理 51单片机可以直接对某一位IO进行读写操作,而STM32则通过位带操作来控制一个单独的IO口。 概念 位带区:支持位带操作的地址区。 位带别名区:对别名地址的访问最终作用到位带区的访问上。位带别名区对位带区的访问有个地址映射过程。 目的 对位带区的比特位进行独立的读写操作,即单独操作一个位 ,它是通过对位带别名区的操作来实现。 具体过程: 对位带别名区进行读写访问,位带别名区通过地址映射关系映射到相应的位带区,对位带区进行原始比特的读写操作。 地址映射 对位带别名区进行读且操作 ---------------------- 对位带区进行读且操作(目的) 下面是位带操作的一些说明
[单片机]
STM32F429--<font color='red'>位</font>带<font color='red'>操作</font>
STM32操作-详解-计算过程
位带操作 位带操作的概念其实很多年前就有了,那还是 8051 单片机开创的先河。如今,CM3 将此能力进化,这里的位带操作是 8051 位寻址区的威力大幅加强版。 官方解释 先来看一下Cortex-M3权威指南中描述的位带操作: 支持了位带操作后,可以使用普通的加载/存储指令来对单一的比特进行读写操作。在CM3中,有两个区中实现了位带。其中一个是 SRAM 区的最低1MB 范围,第二个则是片内外设区的最低 1MB 范围。这两个区中的地址除了可以像普通的 RAM 一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个 32 位的字。当你通过位带别名区访问这些字时,就可以达到访问原始比特的目的。 正点原子库
[单片机]
STM32<font color='red'>位</font>带<font color='red'>操作</font>-详解-计算过程
avr复习笔记--iic读写多个24cxxx
实际上还是仅仅备份些代码,加些注释,因为这本身就很容易,没啥多说的。。。 先定义些东西 #define PORT_IIC PORTC #define DDR_IIC DDRC #define BIT_SCL 0 #define BIT_SDA 1 #define TW_START 0X08 #define TW_REP_START 0X10 #define TW_MT_SLA_ACK 0X18 下面切入正题 iic总线初始化 void iic_init(void) { TWSR=0; TWBR=32;//这点要注意下,不要设的速度太高,否则 //proteus仿真可能读不到数据 T
[单片机]
<font color='red'>avr</font>复习<font color='red'>笔记</font>--iic读写多个24cxxx
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved