C 語(yǔ)言本身有較強(qiáng)的位處理功能。但在控制領(lǐng)域有時(shí)經(jīng)常需要控制某一個(gè)二進(jìn)制位為此在MCS-51 的C 語(yǔ)言中,如KEIL51 擴(kuò)充了兩個(gè)數(shù)據(jù)類型bit 和sbit。前者可以在MCS-51 的位尋址區(qū)進(jìn)行分配而后者只能定義為可位尋址的特殊功能寄存器SFR 中的某一位這兩個(gè)擴(kuò)充為MCS-51 應(yīng)用C 語(yǔ)言編程帶來(lái)很大的方便
相對(duì)于51系列單片機(jī),AVR單片機(jī)的位操作比較麻煩。在支持AVR的眾多C語(yǔ)言中,除了CodeVisionAVR C 可以像C51一樣直接使用位變量,其他語(yǔ)言如iccAVR,IAR icc90,avrgcc等均沒(méi)有定義。當(dāng)然也可以使用一定方法實(shí)現(xiàn),但在很多情況下它使編譯器產(chǎn)生繁復(fù)的代碼。
本文介紹如何用位域(BitField)來(lái)訪問(wèn)單片機(jī)寄存器的某一位,并且使產(chǎn)生的代碼相當(dāng)緊湊、高效。
請(qǐng)看下列代碼
/* 高效率的位操作,使用位域(BitFileds)。
在 IAR icc90 和avrgcc 下編譯通過(guò)。
張磊 浙江林學(xué)院163#
Zhang_lei@cnnb.net
USR.CN整理者注:這種寫(xiě)法不知最初出自誰(shuí)手,但是筆者最早看到是在傻孩子(Gorgon Meducer)的文章中。
*/
// 這是avrgcc;如是其它編譯器,請(qǐng)修改。
#include <avr/io.h>
// 定義一個(gè)寄存器(Register)或端口(Port)的八個(gè)位
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;
//定義一個(gè)宏,用來(lái)得到每一位的值
#define GET_BITFIELD(addr) (*((volatile bit_field *) (addr)))
//定義寄存器或端口的地址(一般已經(jīng)包含在頭文件中了,本步可不做
// #define PORTB 0x38
// #define PINB 0x36
//定義每一個(gè)位
#define LED GET_BITFIELD(PORTB).bit0
#define BUTTON GET_BITFIELD(PINB).bit7
//延時(shí)函數(shù)
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開(kāi)
delay(1000);
LED=1; //高電平,LED關(guān)
delay(1000);
}
else if( 1==BUTTON )
{
LED=1; //否則LED關(guān)
}
}
}