Mega2560 PINK (Digital) Read Question

Hi,

I have a question about reading the PINK pins of MEGA2560. I use external interrupt service routine (ISR) for PORTK of Mega2560. PORTK pins are the A8 - A15 pins on MEGA2560. When I read the whole PINK pins, I can display which pin is disturbed (0 or 1) but I could not read the pins separately. I used the following code for reading but this did not work properly.

byte pinVal1 = PINK & 1<<PK1
byte pinVal2 = PINK & 1<<PK2
.
.
.
byte pinVal8 = PINK & 1<<PK8

For example; assume that I read 11010111 for PINK. I was supposed to read 1 for pinVal1 and 0 for pinVal4. The code returns different values.

I will appreciate if someone help me.

King Regards,
zafer

 I used the following code for reading but this did not work properly.

byte pinVal1 = PINK & 1<<PK1
byte pinVal2 = PINK & 1<<PK2

Well, that’s not actually code (no semicolons.) Depending on where those statements are, it could behave differently. Could you actually post a cut&pasted complete example?

I’d be a lot more comfortable with pinVal1 = PINK & (1<<PK2), because you’re in the realm where order of operations isn’t immediately obvious. But as I read the spec, you shouldn’t actually NEED the parens…

Hi Westfw,

You can find the code below. If you run it, you will se the PINK readings and the (hopefully) the pin values. When I apply a change (0 to 1 or 1 to 0) for one bit I see the corresponding PINK bit is changing. There is also a change in corresponding pinValx but these are not matching.

For example the third pin of PINK goest 1 to 0 at time t; pinVal3 is changeing but in a different times than PINK.

Actually this is very hard to describe by writing. If you run the code you will see what I mean.

best regards,
zafer

unsigned int pinVal1, pinVal2, pinVal3, pinVal4, pinVal5, pinVal6, pinVal7, pinVal8;
//byte Pins = A8; //{A8, A9, A10, A11, A12, A13, A14, A15};

void setup(){
  cli();
  Serial.begin(115200);
  Serial.print("\n");


// Starting interrupt procedure // 
  DDRK = 0b00000000;
  PORTK = 0b11111111;

  PCICR |= (1 << PCIE2); 
  PCMSK2 |= 0b11111111;
  sei();
}

void loop(){
  Serial.print("PINK: ");Serial.print(PINK, BIN);
  Serial.print("\t pinVal1: ");Serial.print(pinVal1);
  Serial.print("\t pinVal2: ");Serial.print(pinVal2);
  Serial.print("\t pinVal3: ");Serial.print(pinVal3);
  Serial.print("\t pinVal4: ");Serial.print(pinVal4);
  Serial.print("\t pinVal5: ");Serial.print(pinVal5);
  Serial.print("\t pinVal6: ");Serial.print(pinVal6);
  Serial.print("\t pinVal7: ");Serial.print(pinVal7);
  Serial.print("\t pinVal8: ");Serial.print(pinVal8);
  Serial.print("\n "); 
}

ISR(PCINT2_vect) 
{
  pinVal1 = (PINK & 1 << PK0);
  pinVal2 = (PINK & 1 << PK1);
  pinVal3 = (PINK & 1 << PK2);
  pinVal4 = (PINK & 1 << PK3);
  pinVal5 = (PINK & 1 << PK4);
  pinVal6 = (PINK & 1 << PK5);
  pinVal7 = (PINK & 1 << PK6);
  pinVal8 = (PINK & 1 << PK7);
}

volatile unsigned int pinVal1, pinVal2, pinVal3, pinVal4, pinVal5, pinVal6, pinVal7, pinVal8;

Perhaps? It's needed for correctness, anyway.

Are you sure you don't just have a debouncing problem?

In addition to potential bounce issues, the current code does not ensure that the readings are synchronized atomically nor does it ensure that values printed represent the same point in time.

The combination of both has the potential to create some misleading values printed.

For example, In the ISR, the bits in the PINK register are examined through time rather than all at the same time. If you want the pinValx variables to represent a the same point in time you will need to read the PINK value and put it into a temporary variable and test against the temporary.

This also applies to the values you print in the foreground loop as the values printed don't represent values from the same point in time.

For example, you print PINK and then the pinValx values. Since interrupts are enabled, those values could change at any time and so there is no guarantee that values represent the state at the same point in time since time passes while each of the values is printing.

Also keep in mind that when using the Serial device that while there is a small buffer (16 or 64 bytes depending on processor) on the transmitter, that if you send enough data fast enough you will fill the s/w output buffer and then be throttled (blocked) by having to wait for the characters to drain out the physical serial port. This adds to the span of time that separates the printed pin readings in your loop() code. Give your current code, this is definitely happening. At 115200, since you are printing 12 characters that means you are blocked for about 1ms each time you print the pinValx value as you wait for space in the tx buffer for the 12 characters. So there is at least 8ms between printing pinVal1 and pinVal8

If you want a single snapshot of the values in loop() you will need to mask interrupts, and move all the values into temporary locals, then print the temporary locals after you re-enable interrupts.

You might want to change the code to avoid the constant printing by only printing when something changes.

Just a small nit but I'd use pinVal0 to pinVal7 vs pinVal1 to pinVal8 so that there is no confusion over bit names vs bit position. It doesn't affect the code just seems to be clearer (at least to me).

--- bill

Hi Westfw and Bill,

I would like to thank you both for your helps. Especially Bill, I appreciate that you spend time for the exellent description. Actually I am a newbie about MCUs and your exlanations give me a good understanding how the timing is important. (I hope that is what you mean :) )

Actually I was tried to find the duty cycle duration of PWM signals coming separately to the A8-A15 pins on MEGA. While I was working on it (and couldn't find the correct values), I faced the PINK problem and thought that this is the reason of the problem.

Eventually, while I was orginizing the code for post, I reilezed that I had a mistake in a for loop. I fixed it and now it works fine.

By the way I really apreciate for your helps. However, the PINK question is still exist and I will try your explanations to look deeply, I solved my major problem :)

King regards, zafer

I should add that PORK should usually be cooked until it isn’t PINK any more.
:slight_smile: