Go Down

Topic: Configuring Port A as digital Inputs on Mega 2560 - help pls (Read 6058 times) previous topic - next topic

three_jeeps

Nov 21, 2011, 10:23 pm Last Edit: Nov 21, 2011, 10:36 pm by three_jeeps Reason: 1
I am setting up PORT A as Inputs on the Mega 2560 and no matter how I change the inputs (0/1) I always get '0' when I read the port.  Please clarify:

Port A pins on the Mega board are pins 22 (PA0) - 29 (PA7) - Correct?
I connect pins 22,24,26,28 to +5 via a pullup, pins 23,35,27,29 to ground.
I set up Port A: DDRA = 0b00000000;
Declare and initialize a temp variable: byte var1 = 0;
In my loop I do the following:
var1 = PORTA;
Serial.print("\n var1 ");
Serial.print(var1, BIN);

the print output is: var1 0   which is incorrect because I tied even pins 22-28 high.
So, is Port A  NOT pins 22-29????  
Any insight/suggestions are appreciated...

-J


SurferTim

#1
Nov 21, 2011, 11:18 pm Last Edit: Nov 22, 2011, 01:03 am by SurferTim Reason: 1
I cheated. I didn't have a jumper handy, so I used the internal pullup resistors. This works for me.
Code: [Select]
void setup()
{
 Serial.begin(9600);
 DDRA = 0; // set PORTA to input
}

void loop()
{
 byte var1 = PINA; // get PORTA value
 Serial.println(var1,BIN);
 delay(1000);
}


Edit: This code reads the pins. My bad. It is PINA, not PORTA, that holds the input values.

nickgammon

PORTA is for writing, PINA is for reading, I believe.

Any objection to doing digitalRead?
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

SurferTim

#3
Nov 22, 2011, 01:10 am Last Edit: Nov 22, 2011, 01:15 am by SurferTim Reason: 1
@Nick: You are correct. PINA is the read, PORTA is the write. I was typing faster than I was thinking.

Edit: I can see why that would be handy. If you were looking for a specific pin setting combination rather than a single pin, this would be the quickest.

nickgammon

That's OK. I got caught by that a couple of times.

Your edit ninja'd my reply. :)
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

SurferTim

Sorry, Nick. I don't mean to ninja edit your replies. I did it again.  :smiley-red:

nickgammon

Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

three_jeeps


PORTA is for writing, PINA is for reading, I believe.

Any objection to doing digitalRead?


yes, reading pin by pin is inefficient and slow.  I want to read the entire byte at once.

TYVM for the PINA ..... I read that in the atmel data sheet but forgot completely about it...(port A r/w is a hold over from a processor I was working with previously)......speaking of that.....
Can either of you point me to the 'magic code' that underlies some of the arduino port and bit r/w libraries/macros?  There is way too much 'magic' being hidden at these high level port statements with no discussion about how to control pull ups/down, and how many instructions are actually used to do some of the actions.  As one who has programmed in assembly for 30+ years, all the vagueness of the higher level commands make me very uneasy....

Thanks
J


nickgammon


Can either of you point me to the 'magic code' that underlies some of the arduino port and bit r/w libraries/macros?  There is way too much 'magic' being hidden at these high level port statements with no discussion about how to control pull ups/down, and how many instructions are actually used to do some of the actions. 


I just use "find in files" in my favourite editor (Crimson Editor in my case) and search for something like digitalWrite in the appropriate sub-folders.

Some of the magic is used to make things work seamlessly on different platforms (like the Tiny, Mega etc.). As for the pull-ups etc. I would read the datasheet for the processor. I usually have that PDF file open.

Quote
reading pin by pin is inefficient and slow.


It depends on your application a bit. Someone has gone to the trouble of working out which bits belong to which ports, and it saves having to get all the bit positions right every time.

After all, most people use device drivers supplied with their printers, video cards etc., treating them as "black boxes" and don't try to work out exactly how to address them. Maybe it's slightly slower, but it tends to be more reliable and easier to maintain.

Another thing you can do is view the .elf files produced by the compiler to see what machine code is generated. I do that quite often if there is some doubt about whether code has been optimized away, or whether method A is better than method B.

Code: [Select]
avr-objdump -S <path-to>/foo.elf > mylisting.txt
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

three_jeeps



Can either of you point me to the 'magic code' that underlies some of the arduino port and bit r/w libraries/macros?  There is way too much 'magic' being hidden at these high level port statements with no discussion about how to control pull ups/down, and how many instructions are actually used to do some of the actions. 


I just use "find in files" in my favourite editor (Crimson Editor in my case) and search for something like digitalWrite in the appropriate sub-folders.


um, what exactly are you (or are you suggesting) editing? 


Some of the magic is used to make things work seamlessly on different platforms (like the Tiny, Mega etc.). As for the pull-ups etc. I would read the datasheet for the processor. I usually have that PDF file open.

If I were doing this in strictly assembly language, the data sheet is the *only* reference, however, it is not always clear what the mapping (code wise) is from the Atmel assembly to 'arduino-ese'...

Quote
reading pin by pin is inefficient and slow.


It depends on your application a bit. Someone has gone to the trouble of working out which bits belong to which ports, and it saves having to get all the bit positions right every time.

Yea, if one is dealing with a slow interface, then burn cycles with digitalReads, etc..... is as effective as var=PINx, however, from my pov, still inefficient.  If one never programmed before, perhaps this type of simplification is 'acceptable'...until one starts doing real work. 


After all, most people use device drivers supplied with their printers, video cards etc., treating them as "black boxes" and don't try to work out exactly how to address them. Maybe it's slightly slower, but it tends to be more reliable and easier to maintain.

Yes, for portability among many different platforms in a family, a perfectly acceptable abstraction.


Another thing you can do is view the .elf files produced by the compiler to see what machine code is generated. I do that quite often if there is some doubt about whether code has been optimized away, or whether method A is better than method B.


Code: [Select]
avr-objdump -S <path-to>/foo.elf > mylisting.txt

Would love to...what tool are you using to produce the .elf files?   Not the Arduino compliler?

nickgammon

Quote
Would love to...what tool are you using to produce the .elf files?   Not the Arduino compliler?


The compiler produces them anyway. To find out the pathname hold down Shift and click the Verify button (top left). Then copy and paste the file name.

Quote
... this type of simplification is 'acceptable'...until one starts doing real work.


You are implying that something like:

Code: [Select]

PORTD |= B10000000


... is somehow more real than:

Code: [Select]
digitalWrite (7, HIGH);

I submit that the latter is easier to maintain in the future, and personally I write with a view to re-using my code later on, and having other people understand it.

The digitalWrite version is "real" and would be acceptable in all cases but the extreme ones where you are hitting speed limitations of the hardware. Sometimes this happens, I admit. As an example, a RFID security system I developed is supposed to unlock a door reasonably promptly after you present the correct card. Microsecond speed improvements are not required. So my "simpler" solution is easier to maintain, and just as real.

I don't shy away from port manipulation when the library doesn't support something I want to do.

For example, on this page:

http://www.gammon.com.au/i2c

I have this line:

Code: [Select]
  TWAR = (MY_ADDRESS << 1) | 1;  // enable broadcasts to be received

and this one:

Code: [Select]
TWBR = 12;

That's because those functions were not supported by the library. But for the rest, using pinMode, and digitalWrite worked perfectly well, and were easier to follow later on.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

Go Up