C 语言本身有较强的位处理功能。但在控制领域有时经常需要控制某一个二进制位为此在MCS-51 的C 语言中,如KEIL51 扩充了两个数据类型bit 和sbit。前者可以在MCS-51 的位寻址区进行分配而后者只能定义为可位寻址的特殊功能寄存器SFR 中的某一位这两个扩充为MCS-51 应用C 语言编程带来很大的方便
相对于51系列单片机,AVR单片机的位操作比较麻烦。在支持AVR的众多C语言中,除了CodeVisionAVR C 可以像C51一样直接使用位变量,其他语言如iccAVR,IAR icc90,avrgcc等均没有定义。当然也可以使用一定方法实现,但在很多情况下它使编译器产生繁复的代码。
本文介绍如何用位域(BitField)来访问单片机寄存器的某一位,并且使产生的代码相当紧凑、高效。
请看下列代码
/* 高效率的位操作,使用位域(BitFileds)。
在 IAR icc90 和avrgcc 下编译通过。
张磊 浙江林学院163#
Zhang_lei@cnnb.net
USR.CN整理者注:这种写法不知最初出自谁手,但是笔者最早看到是在傻孩子(Gorgon Meducer)的文章中。
*/
// 这是avrgcc;如是其它编译器,请修改。
#include <avr/io.h>
// 定义一个寄存器(Register)或端口(Port)的八个位
typedef struct _bit_struct
{
unsigned char bit0 : 1 ;
unsigned char bit1 : 1 ;
unsigned char bit2 : 1 ;
unsigned char bit3 : 1 ;
unsigned char bit4 : 1 ;
unsigned char bit5 : 1 ;
unsigned char bit6 : 1 ;
unsigned char bit7 : 1 ;
}bit_field;
//定义一个宏,用来得到每一位的值
#define GET_BITFIELD(addr) (*((volatile bit_field *) (addr)))
//定义寄存器或端口的地址(一般已经包含在头文件中了,本步可不做
// #define PORTB 0x38
// #define PINB 0x36
//定义每一个位
#define LED GET_BITFIELD(PORTB).bit0
#define BUTTON GET_BITFIELD(PINB).bit7
//延时函数
void delay(unsigned int x)
{
unsigned char i;
unsigned int j;
for (i=0; i<255; i++)
for(j=0; j }
int main( void )
{
//配置PB0为输出,PB7为输入
outp(0x41,DDRB);
while(1) // 闪烁PB0
{
if( 0 == BUTTON )
(
LED=0; //低电平,LED开
delay(1000);
LED=1; //高电平,LED关
delay(1000);
}
else if( 1==BUTTON )
{
LED=1; //否则LED关
}
}
}