Can I read an entire port rather than just a pin?
I want to read all of the pins of a port at the same time. Can I do this?
What is the command?
It seems that most examples deal with setting and reading individual pins rather that the entire port.
Can I read an entire port rather than just a pin?
I want to read all of the pins of a port at the same time. Can I do this?
What is the command?
It seems that most examples deal with setting and reading individual pins rather that the entire port.
Yes you can.
Google "Arduino direct port manipulation" - it's not like you're the first person to ask.
Or take a look at the AVR processor datasheet for your Arduino.
Yes in fact an arduino must read the whole port if it does a digitalRead. Check the source code of digitalRead() for the details.
from - Arduino Reference - Arduino Reference
PORTB (digital pin 8 to 13)
PORTC (analog input pins)
PORTD (digital pins 0 to 7)
DDRD - The Port D Data Direction Register - read/write
PORTD - The Port D Data Register - read/write
PIND - The Port D Input Pins Register - read only
Assuming you do not want to use serial which is pin 0 and 1 you could state (e.g. 8 leds)
setup()
{
DDRD = B11111111; // all outputs
}
loop()
{
PORTD = random(256);
}
DigitalRead only reads a specific pin, according to the Arduino documentation. This is not what I want.
However, the statement x = PINA; will read the entire 8 bit port. This is what I want.
It seems that this is not mentioned in the documentation very clearly.
Which processor are you using?
I am using the Arduino Mega 2560. Does it matter?
barryjo:
I am using the Arduino Mega 2560. Does it matter?
Yes it does matter if you want your code to be portable.
Controllers may use different ports for pin configuration.
barryjo:
I am using the Arduino Mega 2560. Does it matter?
Yes, not all arduinos have PORT A
Can I read an entire port rather than just a pin?
Why?
Larryd,
I want to read the state of 8 momentary push butons switches. If I can read the entire port, 8 bits, then I can look for a change by comparing the port value now with a previous value and not having to query individual pins. It seems more efficient to me.
Reasonable.
However, efficient is a relative term.
Speed requirements would have to be explained why it is necessary.
It's quite easy to set up an array and read all the inputs in a for loop.
When the loop is finished, you can do your operations.
.
Yes but it is easy to merely say..
x = PINA;
if (PINA != x) {one of the pins has changed}
What could be simpler? This is not exactly correct but you get the idea.
but why do you need the speed ?
barryjo:
Yes but it is easy to merely say..x = PINA;
if (PINA != x) {one of the pins has changed}
What could be simpler? This is not exactly correct but you get the idea.
The test that some pin has changed is simpler indeed, but how do you detect which pin has changed?
you still have to loop over, or check, the individual pins one way or the other.
That part of the code might be more complex than needed, and possibly less maintainable.
Robtillart,
I could XOR the before and after values and then do a case statement on the result.
barryjo:
Robtillart,I could XOR the before and after values and then do a case statement on the result.
Take into consideration when two or more inputs have 'changed' too, which makes things messy with switch case.
barryjo:
DigitalRead only reads a specific pin, according to the Arduino documentation. This is not what I want.However, the statement x = PINA; will read the entire 8 bit port. This is what I want.
It seems that this is not mentioned in the documentation very clearly.
The reason it is not mentioned is it is outside Arduino.
The Arduino core API provides an API that abstracts the h/w so that it is portable across all implementations.
i.e. it works on all "duino" boards and all processors.
Using things like AVR specific registers and macros/functions from the AVR io header files and AVAR libC, which is what the code above is doing, is outside the Arduino APIs and goes against what Arduino is about, so Arduino documentation is unlikely to document/describe it.
While it does work, and can even be faster and more efficient for some operations, it is not portable since it is very specific to the AVR chips, the specific AVR chip, AND the specific Arduino core variant which is controlled by the board selected in the Arduino IDE.
Also, by doing that type of i/o, given the way the Arduino API and the Arduino cores define their pin mappings, it quickly gets very difficult and complicated to map arduino pin #s to the raw AVR port information.
i.e. you can't easily go from arduino pin number 6 to the corresponding AVR port and bit number.
(you can in some cores like the ESP8266, but not in most other cores and not in the AVR cores)
Yes there are macros & functions to do this, but there not functions to go the other way around.
i.e if you know AVR PORTD bit 2 is set, what Arduino pin number is that?
You kind of have to decide upfront if you are going to use Arduino API functions to talk to the h/w or bypass Arduino API functions and talk directly to the h/w. Mixing them is complicated and messy.
I would suggest that unless you have very specific performance requirements that need using this type of direct h/w i/o accesses that they be avoided since it locks the code into using a specific board and can be more difficult to maintain.
--- bill
bperrybap, you have given me a lot to think about, however, there is a big difference between the Arduino Uno and the Arduino Mega 2560 that I am using. I need the Mega to get more digital IO pins so I don't see how there can be a lot of portability here. Perhaps in the lower ports there is some commonality.
I am not sure I know what I am talking about.
barryjo:
Robtillart,I could XOR the before and after values and then do a case statement on the result.
double aa please,
As larry pointed out the switch can be quite complicated unless you are confident that only one button is pressed at the time. You know the requirements and the end users of the system
barryjo:
Yes but it is easy to merely say..x = PINA;
if (PINA != x) {one of the pins has changed}
What could be simpler? This is not exactly correct but you get the idea.
For this to work reliably, you would want to set all the other pins on that port to OUTPUT or to INPUT_PULLUP, or connect them to groud. If any of the are INPUT, they will float and could pick up noise from the environment.
Alternatively, mask off the pins you are not using. (PORTA & 0b01110100).
But as to "what could be simpler?" - the simplest thing is to use the API as intended and as everyone else uses it. Simpler in the long run. Especially if you are only interested in one pin.
"interested in one pin." I am interested in all 8 pins. I want to have 8 momentary push button switches, and 8 LEDs. When I push a button the LED above the push button lights. When I then push another button, the first LED goes off and the second goes ON. This is done in the loop area of the sketch. I have just about got it figured out but not programmed and tested.