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这样的指令,那么关于一般的变量,又怎么呢?…………….
声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/xitong/257340.html