C语法/ AVR标头

时间:2012-09-03 23:56:38

标签: c bit-manipulation microcontroller avr

我想了解this代码

但我无法理解这部分代码。

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= -_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

sbicbi稍后在代码中用作

void system_sleep()
{
  sbi(MCUCR,PUD);                                  //Disables All Internal Pullup Resistors
  sbi(GIMSK,PCIE);                                   //Enable Pin Change Interrupts Interrups
  sbi(PCMSK,PCINT0);                              //Changes Interrupt to PIN1 (PCINT1) 
  cbi(ADCSRA,ADEN);                              //switch Analog to Digital Converter OFF
  cbi(MCUCR,SM0);                                  //Power Down Mode
  sbi(MCUCR,SM1);                                  //Power Down Mode
  sbi(MCUCR,SE);   //sleep Mode Power down enable (Sleep_enable(); should set this-- not tested yet)
  sleep_enable();                      //Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
  sleep_mode();                                       //sleep begins here
  sleep_disable();                                     //Coming out of sleep
  sbi(ADCSRA,ADEN);                             //switch Analog to Digital Converter ON
  cbi(MCUCR,PUD); //Enables Pullup Resistors Again 
 }

代码用于ATtiny85,我阅读了数据表,我发现所有这些都是MCCURADCSRA等都是寄存器。它还声明有两种说明SBICBI

我还阅读了一些关于使用C的微控制器编程的教程,并了解每个寄存器都有8位。可以使用针对不同功能的编程来设置这些位中的每一个。此外PUDPCIE是这些寄存器的不同位,这些寄存器在system_sleep函数中设置。所以我理解system_sleep函数正在做什么,它正在设置寄存器中的位。

我无法理解的唯一部分是

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= -_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

数据表中没有任何内容,例如_SFR_BYTE_BV。我查看了AVR / libc标题,在那里我发现_BV但不知道它在做什么。

3 个答案:

答案 0 :(得分:3)

宏的名称应该给你一些提示。 cbi代表Clear Bitsbi代表Set Bitcbi(sfr, bit)清除注册表bitsfr指示的位数。 sbi的类似解释。

如果您拥有整个项目,则可以搜索_SFR_BYTE_BV的定义。但在本质上他们粗略地转化为

#define  cbi(sfr, bit)   ((sfr) &= ~(1 << (bit)))

#define  sbi(sfr, bit)   ((sfr) |= (1 << (bit)))

详细了解bit-masking

答案 1 :(得分:1)

#define _BV(bit)       (1 << (bit))
#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr))

第一个_BV作为示例,您可以只编写1<<0而不是在代码中编写_BV(0)。 第二个_SFR_BYTE使用_MMIO_BYTE宏从寄存器sfr获取数据,该数据可以是MCUCR或ADCSRA或任何8位IO寄存器。

有关更多信息,请参阅avr/sfr_defs.h

答案 2 :(得分:0)

可以使用输入和输出指令读取/写入从0x00到0x1F的AVR ATMega寄存器,此外还有适用于这些寄存器的特定指令。也可以使用存储器指令读取这些寄存器。在这种情况下,那些寄存器地址必须采用0x20到0x3F的值。

宏__SFR_xxxx考虑到了这种行为。

以下是ATMega 2560“注册摘要”段落的注释:

  

-2。地址范围$ 00 - $ 1F内的I / O寄存器可使用SBI和CBI指令直接进行位访问。在这些reg-   通过使用SBIS和,可以检查单个位的值   SBIC指示。

     

-4。使用I / O特定命令IN和OUT时,必须使用$ 00 - $ 3F的I / O地址。将I / O寄存器作为数据空间进行寻址时   使用LD和ST指令,必须将20美元添加到这些地址。   ATmega640 / 1280/1281/2560/2561是一款复杂的微控制器   64个位置内可支持的外围设备数量更多   在操作码中保留IN和OUT指令。对于扩展   SRAM中的I / O空间从$ 60 - $ 1FF,只有ST / STS / STD和LD / LDS / LDD   可以使用说明。