新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > AVR筆記9:AVR的兩種位操作的比較

        AVR筆記9:AVR的兩種位操作的比較

        作者: 時間:2016-11-27 來源:網絡 收藏
        AVR的兩種位操作的比較(wjc3k發于21ic)(位域與C位操作的比較)

        AVR的兩種位操作的比較(位域方式和移位宏方式)

        測試環境如下:
        硬件:AT90S2313
        軟件:WiinAVRgcc3.3-Os級優化(最小size)。


        說明:
        由于AVR不支持位操作,所以必須通過軟件來實現。下面對我所知道的兩種方法進行一個簡單的比較。
        1、位域方式。先定義一個位域,
        typedefstruct_bit_struct
        {
        unsignedcharbit0:1;
        unsignedcharbit1:1;
        unsignedcharbit2:1;
        unsignedcharbit3:1;
        unsignedcharbit4:1;
        unsignedcharbit5:1;
        unsignedcharbit6 :1;
        unsignedcharbit7:1;
        }bit_field;
        再用一個宏,來指向要操作的位。
        #defineLEDGET_BITFIELD(PORTB).bit0
        #defineBUTTONGET_BITFIELD(PINB).bit7
        使用時只需要直接賦值即可:如LED=0,LED=1,或者直接判斷LED==0,LED==1.
        這種方法類似C51中的位操作。直接。
        2、位移宏方式。主要有三個.
        #defineSet_Bit(val,bitn)(val|=(1<<(bitn)))
        #defineClr_Bit(val,bitn)(val&=~(1<<(bitn)))
        #defineGet_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<avr/io.h>

        //定義一個寄存器(Register)或端口(Port)的八個位
        typedefstruct_bit_struct
        {
        unsignedcharbit0:1;
        unsignedcharbit1:1;
        unsignedcharbit2:1;
        unsignedcharbit3:1;
        unsignedcharbit4:1;
        unsignedcharbit5:1;
        unsignedcharbit7:1;
        unsignedcharbit6:1;
        }bit_field;

        //定義一個宏,用來得到每一位的值
        #defineGET_BITFIELD(addr)(*((volatilebit_field*)(addr)))

        //定義每一個位
        #defineLEDGET_BITFIELD(PORTB).bit0
        #defineBUTTONGET_BITFIELD(PINB).bit7


        #defineSet_Bit(val,bitn)(val|=(1<<(bitn)))
        #defineClr_Bit(val,bitn)(val&=~(1<<(bitn)))
        #defineGet_Bit(val,bitn)(val&(1<<(bitn)))

        intmain(void)
        {
        DDRB=0x41;//配置PB0為輸出,PB7為輸入
        if(BUTTON==0)LED=1;elseLED=0;
        //if(!Get_Bit(PINB,7))Set_Bit(PORTB,0);elseClr_Bit(PORTB,0);
        while(1);
        }
        //----------------------end-----------------------------
        4、測試過程。
        a.先使用位域方式。
        主程序中使用if(BUTTON==0)LED=1;elseLED=0;
        結果如下:
        intmain(void)
        {
        4a:cfedldir28,0xDF;223
        4c:d0e0ldir29,0x00;0
        4e:debfout0x3e,r29;62
        50:cdbfout0x3d,r28;61
        DDRB=0x41;//配置PB0為輸出,PB7為輸入
        52:81e4ldir24,0x41;65
        54:87bbout0x17,r24;23
        if(BUTTON==0)LED=1;elseLED=0;
        56:86b3inr24,0x16;22
        58:e82fmovr30,r24
        5a:ff27eorr31,r31
        5c:8081ldr24,Z
        5e:86fdsbrcr24,6
        60:07c0rjmp.+14;0x70
        62:88b3inr24,0x18;24
        64:e82fmovr30,r24
        66:ff27eorr31,r31
        68:8081ldr24,Z
        6a:8160orir24,0x01;1
        6c:8083stZ,r24
        6e:06c0rjmp.+12;0x7c
        70:88b3inr24,0x18;24
        72:e82fmovr30,r24
        74:ff27eorr31,r31
        76:8081ldr24,Z
        78:8e7fandir24,0xFE;254
        7a:8083stZ,r24
        while(1);
        7c:ffcfrjmp.-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;elseLED=0;這句用了19條指令38Bytes.(居然運用了3個寄存器白r24,r30,r31,和一個Z,代碼真是苦澀,,我看不懂,準備以后作代碼加密用:).)
        b.使用移位宏方式。
        if(BUTTON==0)LED=1;elseLED=0;換為等效的if(!Get_Bit(PINB,7))Set_Bit(PORTB,0);elseClr_Bit(PORTB,0);

        結果,main函數僅24Bytes.其它代碼一樣,略去.所以,上面這句代碼僅用了24-14=10Bytes,5條指令。生成的代碼如下:
        56:b799sbic0x16,7;22
        58:02c0rjmp.+4;0x5e
        5a:c09asbi0x18,0;24
        5c:01c0rjmp.+2;0x60
        5e:c098cbi0x18,0;24
        5.菜論:魚和熊掌。
        由于AVR可以對I/O腳進行sbic,sbi,cbi,這樣的位操作,所以使用I/O腳操作時,移位宏可以產生高效的代碼。
        例如,要實現上面的幾個簡單的指令,為了實現LED=1這樣的類似C51的sbit的效果,我必須多付出(38-10=28Bytes)的代價。

        6......
        對于I/O腳,可以產生這樣高效的代碼,是因為有sbi和cbi這樣的指令,那么對于一般的變量,又如何呢?................

        本文引用地址:http://www.104case.com/article/201611/322371.htm


        關鍵詞: AVR筆記位操

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 古交市| 濮阳市| 确山县| 缙云县| 绥芬河市| 桑日县| 靖宇县| 随州市| 丰原市| 丰台区| 四子王旗| 江山市| 凌海市| 郎溪县| 垦利县| 枣庄市| 侯马市| 怀仁县| 嘉义县| 垫江县| 东台市| 木里| 屏山县| 三门县| 吉隆县| 平度市| 麟游县| 宣城市| 金沙县| 五常市| 边坝县| 双辽市| 孝感市| 普定县| 准格尔旗| 常山县| 安乡县| 德阳市| 东兴市| 噶尔县| 纳雍县|