无法使用PINxn从Arduino Mega读取引脚值

时间:2017-09-27 05:56:49

标签: arduino embedded avr atmega

使用Arduino Mega 2560的注册表,我试图获取PORTA的信息。我已经提到了datasheet(第69-72页),并且我知道我必须使用PINxn(PINA)。但我得到的只是0作为输出。我已将引脚连接到LED。

代码和输出如下所述。

CODE

#define F_CPU 16000000
#include <avr/io.h>

int main(void) {
  DDRA = (1 << DDA0); // sets the pin OUTPUT
  __asm__("nop\n\t");
  PORTA = 0x01; // Sets it HIGH
  unsigned int i = PINA;
  Serial.println(i);
}

输出

0

提前感谢您的时间 - 如果我错过了任何内容,请在评论中过度强调或强调一个特定的要点。

2 个答案:

答案 0 :(得分:1)

如果您想回读之前写入输出的值,我建议您从写入的寄存器中读取它,即PORTA

然而根据提供的文件(由我粗体):

  

13.2.4 独立数据方向位DDxn的设置,可以通过PINxn寄存器位读取端口引脚

在写完另一个之后立即回读旧价值的可能解释可能是同一章中不久后续的部分:

  

PINxn寄存器位和前面的锁存器构成同步器。这是   如果物理引脚在内部时钟边缘附近改变值,则需要避免亚稳态,但它也会引入   延迟

所以你必须考虑到这个延迟 看看提供的计时功能,例如通过可用的库和可用的计时器硬件 但作为概念证明,我建议通过

进行演示
  • 在写入反转值
  • 之前打印PINA 的值
  • 将反转值写入PORTA(当然只反转相关位)
  • 多次阅读并打印PINA 的值(希望您的标题在此使用volatile)多次(比如1000)

我希望您会看到几个旧值,但接着是新值。

根据打印的方式(忙碌等待?),一次就足够了 您的NOP__asm__("nop\n\t");)可能会被设计为进行适当的等待。但我认为这是错误的(应该是在写完新值之后)而且可能太短了。如果它来自示例代码,那就足够了。移动它,也许两次,确保第一次尝试。这可能是有效的。

答案 1 :(得分:0)

你应该把&#34; nop&#34;在&#34; PORTA =&#34;之间任务和&#34; PINA&#34;读。由于写入PORTx寄存器的指令仅在时钟发生器的上升沿的系统时钟周期结束时更新输出引脚的状态,但从PINx寄存器读取将返回锁存在中间缓冲区中的信息。缓冲器锁存在上一个时钟周期的中间(即时钟发生器的下降沿)。

因此,从PINx读取总是延迟0.5到1.5个时钟周期。 如果逻辑电平在其中间(即时钟发生器的下降沿之前)的某个系统时钟中发生了变化,那么该值将立即被锁存,并且可通过在下一个系统读取PINx寄存器进行读取时钟周期。因此,延迟是0.5个周期 如果逻辑电平在锁存时刻之后发生改变,则它将仅在下一个周期中被锁存,并且在此之后的周期中可用于读取,从而引入1.5个周期的延迟

写入PORTx寄存器会在时钟周期结束时更新输出值,因此,它仅在下一个周期中锁存,并且仅在下一个周期后才能读取。

C编译器非常适合优化,所以,两个带有PORTA赋值和PINA读取的后续行被编译为只有两个结果 out PORTA,rxx in ryy,PINA 指令,导致该效果