昨晚我和朋友遇到了一个我们试图理解的异常,但不能.当我们使用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); }
上面的代码是正确的,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); }
现在上面的代码确实偶尔会起作用.它不是每隔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的设置方式,我只是想了解它为什么会这样做.
您遇到了ATmega系列经常被忽略的功能:在PINx寄存器中设置一个位可以切换PORTx中的相应位.
从ATmega328P数据表中的第77页开始:
14.2.2切换销钉
向PINxn写入逻辑1会切换PORTxn的值,与DDRxn的值无关.请注意,SBI指令可用于在端口中切换一个位.