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

Mad*_*vad 2 assembly avr arduino

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

我注意到他的代码中有一个错误,他将LED设置为高(后来为低)PINB,6.我告诉他使用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);  
}
Run Code Online (Sandbox Code Playgroud)

上面的代码是正确的,led每500ms切换一次

void setup(){
  DDRB=0xFF;
}

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

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

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

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

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

void loop(){
  PINB |= 1<<5;    // turns on the LED
  delay(500);
}
Run Code Online (Sandbox Code Playgroud)

LED TOGGLES!每500ms.尝试清除OUTPUT不起作用,只设置它.

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

sky*_*ift 5

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

ATmega328P数据表中的第77页开始:

14.2.2切换销钉

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