Issue with direct port reading (PINC) on ATMega328

If i upload the following code to a board that has an ATMega168 (decimilia) it acts exactly as i intend it to. It reads the state of the ports and outputs it.
If i upload it to a board that has an ATMega328 (duemilanove) it does not compile.

void setup() 
{
  Serial.begin(9600);
  DDRC = 0b00000000;
}
void loop() 
{
  char pincState = 0;
  pincState = PINC;
  Serial.println("PINC state:");
  Serial.println(pincState);
  Serial.println("PC0 state:");
  Serial.println(PINC & (0<<PC0));
  Serial.println("PC1 state:");
  Serial.println(PINC & (1<<PC1));
  Serial.println("PC2 state:");
  Serial.println(PINC & (2<<PC2));
  Serial.println("PC3 state:");
  Serial.println(PINC & (3<<PC3));
  Serial.println("PC4 state:");
  Serial.println(PINC & (4<<PC4));
  Serial.println("PC5 state:");
  Serial.println(PINC & (5<<PC5));
  delay(5000);
}

It’s the same if i just do a Verify. It verifies fine on the 168

Done Compiling:

Binary sketch size: 2458 bytes (of a 14336 byte maximum)

If i do a verify on the 328, it gives this:

'PC0' was not declared in this scope

PINB_Read_1_0.cpp: In function 'void loop()':
PINB_read_1_0:12: error: 'PC0' was not declared in this scope
PINB_read_1_0:14: error: 'PC1' was not declared in this scope
PINB_read_1_0:16: error: 'PC2' was not declared in this scope
PINB_read_1_0:18: error: 'PC3' was not declared in this scope
PINB_read_1_0:20: error: 'PC4' was not declared in this scope
PINB_read_1_0:22: error: 'PC5' was not declared in this scope

Of course i found a link that i believe answers my question just as soon as i submitted it (i promise i searched the forum before posting). Is this the answer to make it work?: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1260222792

I don't have the board with me so i'll test it out later when i can get it. I'm just curious why they would have dropped support for PC0..7 and kept PINC0...7 (if that's the case)

Also... what does the number that it return refer to? It's a digital read, but the different ports return a different number (when compiled on 128 with PC0...7 and i assume with the new code as well). It does not vary with the amount of voltage supplied (fed it 5v and 3.3v, both across a 38ohm resistor when testing). I have seen that number it returns change, but i don't know what causes it to change

tempmj: Is this the answer to make it work?

Yes.

I'm just curious why they would have dropped support for PC0..7 and kept PINC0...7

Very likely the person responsible for the 328 header files missed those constants.

Also... what does the number that it return refer to?

I don't understand the question.

what does the number that it return refer to? It's a digital read, but the different ports return a different number

Reading PINC returns the state of the input pins. If you have a bare arduino, these will not be connected to anything, and will "float" at a value that is dependent on the the amounts of stray electrons that the pins have picked up from ... wherever. Use the internal (or external) pullups (or pulldowns) to force unconnected pins into a known state.

It is generally bad form in electronics to leave digital input pins not connected to anything, although this is pretty common for arduino sketches. In addition to the randomness of values you might read from the pins, they can also end up with voltages that are not "legal" for digital pins (halfway between the power rails), which can lead to excess power consumption and perhaps other problems. It would be better to set unused pins to be outputs. (They default to inputs because that's "safer" if they're connected to another power/voltage source.)

westfw:

what does the number that it return refer to? It's a digital read, but the different ports return a different number

Reading PINC returns the state of the input pins. If you have a bare arduino, these will not be connected to anything, and will "float" at a value that is dependent on the the amounts of stray electrons that the pins have picked up from ... wherever. Use the internal (or external) pullups (or pulldowns) to force unconnected pins into a known state.

It is generally bad form in electronics to leave digital input pins not connected to anything, although this is pretty common for arduino sketches. In addition to the randomness of values you might read from the pins, they can also end up with voltages that are not "legal" for digital pins (halfway between the power rails), which can lead to excess power consumption and perhaps other problems. It would be better to set unused pins to be outputs. (They default to inputs because that's "safer" if they're connected to another power/voltage source.)

I can give a better example tomorrow when i return to the office and can test, but i know when i connected from +5vdc to a pin i'm reading using a 38ohm resistor it returns a value of "32". I think on a different pin it returned a different value, but i don't recall 100%. Does the value 32 mean HIGH?

can give a better example tomorrow when i return to the office and can test, but i know when i connected from +5vdc to a pin i'm reading using a 38ohm resistor it returns a value of "32". I think on a different pin it returned a different value, but i don't recall 100%. Does the value 32 mean HIGH?

You would have to prove that one to me. A digital input pin can only return a value of 0 or 1. Now a analog input pin can return a variable value of 0-1023, but not with +5vdc wired to it. So show your code where a pin reads back a 32 when wired to +5vdc.

Lefty

@tempmj: You need to correct some bugs in your Sketch…

void loop()
{
char pincState = 0;
pincState = PINC;
Serial.println(“PINC state:”);
Serial.println(pincState);
Serial.println(“PC0 state:”);
Serial.println(PINC & (1<<PC0));
Serial.println(“PC1 state:”);
Serial.println(PINC & (1<<PC1));
Serial.println(“PC2 state:”);
Serial.println(PINC & (1<<PC2));
Serial.println(“PC3 state:”);
Serial.println(PINC & (1<<PC3));
Serial.println(“PC4 state:”);
Serial.println(PINC & (1<<PC4));
Serial.println(“PC5 state:”);
Serial.println(PINC & (1<<PC5));
delay(5000);
}

You’re isolating single bits, but you aren’t converting to 0/1 values.
So if you read 8 bits from PINC and get 01110010 (PC5 set, and a bunch of others), then (PINC & (1<<PC5)) will be 00100000, which is … 32. If you want 0 or 1, you can add additional logic (if statement) or something like ((PINC>>PC5) & 1) (which is probably icky-slow.)

I probably just made that mistake quickly putting the post together. I had it right in my code.

westfw:
You’re isolating single bits, but you aren’t converting to 0/1 values.
So if you read 8 bits from PINC and get 01110010 (PC5 set, and a bunch of others), then (PINC & (1<<PC5)) will be 00100000, which is … 32. If you want 0 or 1, you can add additional logic (if statement) or something like ((PINC>>PC5) & 1) (which is probably icky-slow.)

That makes more sense… i’ll experiment and see if that’s what i’m seeing. Thanks for the heads up.

something like ((PINC>>PC5) & 1) (which is probably icky-slow.)

I vaguely recall that the compiler recognizes that as a bit test and generates fairly efficient code.

something like ((PINC>>PC5) & 1) (which is probably icky-slow.)

I vaguely recall that the compiler recognizes that as a bit test and generates fairly efficient code.

No such luck.

  Serial.print((PINC>>PORTC5) & 1) ;
 118:   66 b1           in      r22, 0x06       ; 6
 11a:   70 e0           ldi     r23, 0x00       ; 0
 11c:   85 e0           ldi     r24, 0x05       ; 5
 11e:   75 95           asr     r23
 120:   67 95           ror     r22
 122:   8a 95           dec     r24
 124:   e1 f7           brne    .-8             ; 0x11e <loop+0x6>
 126:   61 70           andi    r22, 0x01       ; 1
 128:   70 70           andi    r23, 0x00       ; 0
 12a:   8f e9           ldi     r24, 0x9F       ; 159
 12c:   91 e0           ldi     r25, 0x01       ; 1
 12e:   4a e0           ldi     r20, 0x0A       ; 10
 130:   50 e0           ldi     r21, 0x00       ; 0
 132:   0e 94 f6 03     call    0x7ec   ; 0x7ec <_ZN5Print5printEii>

I does do this for an IF statement:

  if ((PINC>>PORTC5) & 1) {
 118:   35 9b           sbis    0x06, 5 ; 6
 11a:   06 c0           rjmp    .+12            ; 0x128 <loop+0x10>

No such luck.

How very odd. My memory isn’t usually THAT bad. Let me check something … Ah ha! “if” is a special case…

  if ( ((PINC>>PC5) & 1) )
  d2:	35 9b       	sbis	0x06, 5	; 6
  d4:	05 c0       	rjmp	.+10     	; 0xe0 <loop+0x2a>
  {

I’m NOT losing my mind! I DID see that structure result in nice tidy code.

Actually using the value (e.g. Serial.println or assignment to a boolean variable) generates the nasty code. It gets even stranger…

  Flag = ((PINC>>PC5) & 1) ? true : false;

…nasty code.

  if ( ((PINC>>PC5) & 1) ) { Flag = true; } else { Flag = false; }

…good code.

That pesky optimizer never ceases to baffle me. westfw, thank you for taking the time to test this!