设置PINx时会发生什么?为什么它有时会起作用?

时间:2014-01-13 03:47:26

标签: assembly arduino avr

昨晚,我和一位朋友遇到了一个异常,我们正试图理解,但不能。当我们使用AVR组件玩ATTiny2313时,今天我在ATMega328P上复制了与Arduino完全相同的体验。

我注意到他的代码中有一个错误,他使用PINB,6将LED设置为高(后来为低)。我告诉他使用PORTB,6和(由于某些其他原因)根本不起作用。整个代码现在已经消失了,所以我在Ardunio C ++中复制了它并得到了意想不到的结果,正确分配时一切正常,但如果分配不正确,LED会以一半的速率闪烁。这似乎是一个阶段性的问题。

在我进入代码之前,我知道你不能通过PIN分配输出,问题是我们尝试(错误)并试图了解它是如何工作的。

void setup(){
  DDRB=0xFF;
}

void loop(){
  PORTB |= 1<<5;    // turns on the LED
  delay(500);
  PORTB &= ~(1<<5); // turns off the LED
  delay(500);  
}

上面的代码是正确的,并且每隔500毫秒就会切换一次

void setup(){
  DDRB=0xFF;
}

void loop(){
  PINB |= 1<<5;    // turns on the LED
  delay(500);
  PINB &= ~(1<<5); // turns off the LED
  delay(500);  
}

现在上面的代码实际上偶尔会起作用。它不是每隔500毫秒打开和关闭,而是每秒打开和关闭!

我已经检查了芯片的电路图(实际上是ATMEga128-因为我这里有PDF的硬拷贝),pp66,图30,通用数字I / O.

电路指示PINx是只读的,但你显然可以设置它,虽然它似乎需要每三个设置。

有趣的是,如果你只设置PINx(如下面的代码:):

void loop(){
  PINB |= 1<<5;    // turns on the LED
  delay(500);
}
LED TOGGLES!每500ms。尝试清除OUTPUT不起作用,只能设置它。

同样,我知道这不是OUTPUT的设置方式,我只是想了解它为什么会这样做。

1 个答案:

答案 0 :(得分:5)

您遇到了ATmega系列经常被忽略的功能:在PINx寄存器中设置一个位可切换PORTx中的相应位。

来自ATmega328P datasheet

的第77页
  

14.2.2切换Pin

     

向PINxn写入逻辑1可切换PORTxn的值,与DDRxn的值无关。请注意,SBI指令可用于在端口中切换一个位。