Go Down

Topic: Port registers on the uno (Read 8463 times) previous topic - next topic

waynewayne

Well, the thing is that digitalRead(PIND) is not merely a simple assignment.  "PIND" is itself a "C" macro which (as I understand it, not having used it) used as an argument, reads the value of that register into a byte - which is apparently what you really intend to do.  "digitalRead" however, is a function especially designed to take an index to an Arduino "pin number", figure out which port is being referenced, read from that port and select the corresponding bit and return the value of that bit only as a numeric value.

digitalWrite(PORTB, x) would perform a similar action, interpreting "x" as a Boolean value (either zero or non-zero) and writing it to a single port bit which it has determined from the value read from PORTB.  By no means the same as a simple assignment to PORTB as in
Code: [Select]
PORTB = x;
.

Paul__B,

Are you suggesting I cannot simply use digitalRead(PIND)? I guess I assumed maybe I could write digitalWrite(PORTB, PIND) as a very direct way of reading it. Wouldn't the logic of these suggest that it takes an index of that port (which includes all the pin numbers), and returns the value of those bits (as in HIGH or LOW) to its destination? I guess the question here is, the value of these bits, isn't that considered as a numeric value (0,1's)?

Thanks!
Wayne

larryd

#16
May 05, 2015, 06:43 am Last Edit: May 05, 2015, 06:53 am by LarryD
#1
Let's take this one step at a time.
Read this page about inputs.   http://www.thebox.myzen.co.uk/Tutorial/Inputs.html
Once you read it, do you understand what a PULLUP resistor does?

.
No technical PMs.
If you are asked a question, please respond with an answer.
If you are asked for more information, please supply it.
If you need clarification, ask for help.

larryd

#17
May 05, 2015, 06:50 am Last Edit: May 05, 2015, 06:53 am by LarryD
#2
Read the section
Bitwise AND (&)
http://www.arduino.cc/en/Reference/BitwiseAnd

Do you understand what & does?

.
No technical PMs.
If you are asked a question, please respond with an answer.
If you are asked for more information, please supply it.
If you need clarification, ask for help.

larryd

#18
May 05, 2015, 06:52 am Last Edit: May 05, 2015, 06:53 am by LarryD
#3
Read the section on >>
http://www.arduino.cc/en/Reference/Bitshift

Do you understand what >> does?

.
No technical PMs.
If you are asked a question, please respond with an answer.
If you are asked for more information, please supply it.
If you need clarification, ask for help.

larryd

#19
May 05, 2015, 07:00 am Last Edit: May 05, 2015, 07:42 am by LarryD
Think of it this way:

digitalRead() and digitalWrite() handle single bits in a port.

PIN_ and PORT_ handle 8 bits, which compose a byte, which is the number of bits in a port.

No technical PMs.
If you are asked a question, please respond with an answer.
If you are asked for more information, please supply it.
If you need clarification, ask for help.

westfw

#20
May 05, 2015, 09:05 am Last Edit: May 05, 2015, 09:07 am by westfw
Quote
I cannot simply use digitalRead(PIND)?
Correct - you can not!  "digitalRead()" is an arduino-specific function that takes an "Arduino Pin Number" as an argument.
"PIND" is NOT an "arduino Pin Number" (it's an "AVR Port Name")

"digitalWrite()" has similar restrictions, and so the code sequence:
Code: [Select]
x = digitalRead(PIND); //PIND reads PORT D pins
digitalWrite(PORTB, x);

is completely incorrect "nonsense code" (and the comment does not describe what is happening.)

The correct sequence would be:
Code: [Select]
x = PIND;  // PortRead(PIND), sort of
PORTB = x;  // PortWrite(PORTB, x)


You might think that a modern computer language would detect this sort of error, and give you a message like "attempt to use a PortName where a PinNumber was expected", and in fact that MIGHT be possible.  Except that both PortNames and PinNumbers are not actually implemented as "types" that the compiler understands; they both just look like integers.  (and some of that is because it's inherited from the C-level code rather than C++, and C is in no way a "modern computer language.")


Paul__B

Except that both PortNames and PinNumbers are not actually implemented as "types" that the compiler understands; they both just look like integers.
Umm, no they don't!

Pin Numbers are indeed numbers.  "PORTD" and "DDRD" are however not numbers at all, they are a macro which translates into assembler instructions to either read or write to the given I/O register in the chip, according to usage.

And that being the case, just what happens when someone writes
Code: [Select]
y = PORTB = x;
is a fascinating question!

westfw

#22
May 06, 2015, 07:45 am Last Edit: May 06, 2015, 07:46 am by westfw
Quote
"PORTD" and "DDRD" are however not numbers at all, they are a macro which translates into assembler instructions to either read or write to the given I/O register in the chip
Yes and no.   "I/O registers" on an AVR appear in the same memory space and map as RAM, so the the PORTD and DDRD and so on in fact resolve to dereferences of pointers to bytes, so, "x = PORTB"; becomes approximately:

Quote
x = * ((volatile byte *)(0x25))
Which is VERY close to being "just an integer (byte)" (much closer than would be the case on some other chips.  In particular, it's ALL done at C level without any pure assembler at all.  (C really likes having IO registers in the memory space!))

Code: [Select]
#define PORTB _SFR_IO8(0x05)   // iom328p.h
#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET) // sfr_defs.h
#define __SFR_OFFSET 0x20  // sfr_defs.h



(now, there's some magic in the compiler optimizer to use special instructions that exist for accessing the IO registers more efficiently than as "pure memory" (IN/OUT/SBI/CBI/etc instructions), but that's done inside the compiler rather than in the macros that define PORTB/etc.)


nickgammon

Quote
I need to get it so I can read 16 pin inputs, but read it really fast.
You need to read some DIP switches really fast? Whoa. What is going to be pressing them? Some hyper-active robot?

This thread is veering off into the bizarre quite fast. You don't need to read DIP switches really fast. Full stop.
Please post technical questions on the forum, not by personal message. Thanks!

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

nickgammon

Quote
If all 4 of the dip switches are on HIGH, all 4 Heathkit LEDs are HIGH (on). However, if I turn any number of the dip switches to the LOW position, all of the LEDs go LOW (off).
You are combining different ideas. That is the only reason it isn't working. Forget PORTD, PIND, etc. You just don't need them for this.
Please post technical questions on the forum, not by personal message. Thanks!

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

Paul__B

Yes and no.   "I/O registers" on an AVR appear in the same memory space and map as RAM, so the the PORTD and DDRD and so on in fact resolve to dereferences of pointers to bytes
Ah well, must have my head back in 8080 land! :smiley-eek:

Go Up