0

Using the register of an Arduino Mega 2560, I am trying to grab the information of the PORTA. I have referred to the datasheet (pages 69-72) and understood that I've to use PINxn (PINA) for this. But all I am getting is 0 as output. I have connected the pin to a LED.

The code and the output are mentioned below.

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);
}

OUTPUT

0

Thanks in advance for your time – if I’ve missed out anything, over- or under-emphasised a specific point let me know in the comments.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
Nithin Varghese
  • 893
  • 1
  • 6
  • 28
  • 1
    You are using the pin as an input, at least that is what I assume the `DDRA = (1 << DDA0);` does. What do you expect to achieve by `PORTA = 0x01;` ? I would not be surprised by the value of `PINA` reflecting the volatage level applied from extern to that pin, without influence by what you write into that bit before. So please explain in detail each of your code lines, i.e. what you think it does and what the documentation says it does. – Yunnosch Sep 27 '17 at 06:09
  • And describe what you do to the physical pin. Apply ground, leave free floating, apply voltage, connect some kind of peripheral. What is the voltage you measure with a multimeter? – Yunnosch Sep 27 '17 at 06:10
  • How is `DDA0` supposed to be used? Is it a bit position, value 0? That seems to match your code. But could it be a bit mask, value 1? That could lead to your code setting bit position 1 for reading and whatever level the pin sees, does not make it into PINA. – Yunnosch Sep 27 '17 at 06:13
  • I have made the necessary changes and have added comments in the code.Thanks for pointing out the same @Yunnosch – Nithin Varghese Sep 27 '17 at 06:27
  • So you set the pin to output (I was guessing wrong). What do you expect to read from the input bit for an output-configured pin? What does the docu say? What do you read from PORTA, which is where I would attempt to read back the output value I just wrote. – Yunnosch Sep 27 '17 at 06:29
  • The expected output is 1 since the value is HIGH in portA0(0000 0001) according to doc. – Nithin Varghese Sep 27 '17 at 06:49
  • According to 13.2.4 of documentation, there is a delay for reading pin levels. Please print the value read before writing `PORTA = 0x01;` and, lets say, a thousand times afterwards. (Maybe that is what your NOP is for, but I consider it in the wrong place and potentially too short.) – Yunnosch Sep 27 '17 at 06:59
  • I found the reason, the PINx only can be used for the input pins. So that is why its returning 0. Thank u so much for the help.@Yunnosch – Nithin Varghese Sep 27 '17 at 07:04
  • We could make this a useful Q/A if you would provide a quote from documentation, with chapter or page, to back that up. Feel free to make your own answer, edit mine to add a reference, or to comment here so that I edit mine (quicker than you doing it). – Yunnosch Sep 27 '17 at 07:14
  • I found this in your docu, please clarify what seems to be a contrast to your statement that PINx can only be used for input pins. "Independent of the setting of Data Direction bit DDxn, the port pin can be read through the PINxn Register bit." – Yunnosch Sep 27 '17 at 07:20

2 Answers2

1

If you want to read back the value previously written to output, I recommend to read it from the register you wrote to, i.e. PORTA.

However according to provided docu (bold by me):

13.2.4 Independent of the setting of Data Direction bit DDxn, the port pin can be read through the PINxn Register bit.

A possible explanation for reading back the old value, immediatly after writing a different one, is probably the shortly following part in the same chapter:

PINxn Register bit and the preceding latch constitute a synchronizer. This is needed to avoid metastability if the physical pin changes value near the edge of the internal clock, but it also introduces a delay.

So you will have to account for that delay.
Have a look at timing features provided e.g. by available libraries and at available timer hardware.
But as a proof of concept, I propose to demonstrate by

  • print the value of PINA before writing the inverted value
  • write the inverted value to PORTA (inverting only the relevant bit of course)
  • read and print the value of PINA afterwards (hoping that your header uses volatile here) many times (say 1000)

I expect that you will see several old values, but then the new value.

Depending on how the printing is done (busy waiting?), once might be sufficient.
Your NOP (__asm__("nop\n\t");) might be designed to do the appropriate waiting. But I think it is misplaced (should be after writing new value) and it might be too short. If it is from example code, it should be sufficient. Move it, and maybe do it twice, to be sure for first try. That is likely to be effective.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
0

You should put the "nop" in between the "PORTA = " assignment and "PINA" read. Because the instruction of writing to the PORTx register updates the status of the output pins just at the end of the system clock cycle at the rising edge of the clock generator, but reading from the PINx register returns information which is latched in an intermediate buffer. The buffer latches at the middle (i.e. at the falling edge of the clock generator) of the previous clock cycle.

So, reading from the PINx is always delayed for from 0.5 to 1.5 clock cycles. If the logic level changed in some system clock just before it's middle (i.e. before the falling edge of the clock generator), then this value will be immediately latched, and available for read thru reading the PINx register at the next system clock cycle. Thus, the delay is 0.5 cycles If the logic level changed just after that latching moment, then, it will be latched only in the next cycle, and will be available for reading in the cycle next after that, thus introducing the delay of 1.5 cycles

The writing to PORTx register updates the output value at the end of the clock cycle, so, it only latched in the next cycle, and will be available for reading only in next cycle after that.

The C compiler is pretty good for optimizaion, so, two consequent lines with PORTA assignment and PINA reading were compiled to just two consequent out PORTA, rxx and in ryy, PINA instructions, which cause that effect

AterLux
  • 4,566
  • 2
  • 10
  • 13