Understanding port configuration

Go To Last Post
16 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I want to grok the logic behind I/O on Atmega128 and I am a newbie. I thought I understood it, but an recent assignment at school made me rethink my position. Let me lay out a easy example.
I want to configure PORTA as input and PORTB as output. Then all I have to do is this, right? (Assuming that I program in C atm ... )

DDRA = 0x00; (default)
DDRB = 0xFF;

Now if I a switch is plugged into bit0 on PORTA, and I want to read PORTA, then the value coming from PINA should be 0x01 right, if the switch is pressed?

If I am correct so far, the assignment says that If I read 0 from bit0, then it means that the switch is pressed. Now, how to I configure the PORTS according to that specification?

Thanks :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Switches usually use the internal 'pullups', so PINA will read 0xff. Switch pressed (contacts closed, voltage pulled down to zero) will read 0xfe. To turn on pullups, write to PORTA with DDRA set to input.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Pressing your switch must open, close or reconfigure some circuit. For example, you should have a resistor (say 10K) pulling PORTA.1 up and the button would short the same node to the ground. You can use an internal pull-up resistor (write 1 to PORTA), but having an external resistor kind of helps understanding the circuit better.

The Dark Boxes are coming.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

hen all I have to do is this, right?

Yes.
Quote:

and I want to read PORTA, then the value coming from PINA should be 0x01 right, if the switch is pressed?

No for many reasons. First how is the switched wired? When closed does it connect to Gnd or to Vcc? Does it have pull-up or pull-down resistors to hold it in the opposite state when open? Do you, perhaps, want to use the "free" pull-ups inside the AVR which would then mean that the switch would connect to Gnd when closed and would read "0" when closed and "1" when open. What's happening with the other 7 pins on port A? If just floating then there's no guarantee (assuming an active high switch) that you would ever read 0x01 - you cannot know what state the other 7 bits would be in.

Bottom line, because AVRs give you built in pull-ups (but no option for pull-down) the typical arrangement is to have a switch that connected to Gnd (not Vcc) when it is closed. Then in the software you do:

int main(void) {
  DDRA = 0x00; // set input (actually this is the default)
  PORTA = 0x01; // enable pull-up on bit 0
  while(1) {
    if (!(PINA & (1<<PA0))) {
      // switch pressed - do something
    }
  }
}

The DDR setting is the same as you had - but you still need to decide what you are doing with the other 7 bits - maybe you don't want all 8 bits of A as input in which case some of the bits would be set to 1 as output and the value here would not be 0x00.

The line:

PORTA = 0x01;

is new. When the DDR has been set to say that a particular bit is input then setting that same bit to be 1 in the PORT register says "switch on the internal pull up resistor for this bit position". That means that when nothing else is connected to bit 0 or PORTA the PIN register will read "1" for that position as it is being (gently) pulled up to Vcc level. But that pull-up only has a value of about 50KOhms so it is not strongly held at Vcc and any strong 0 signal will over-ride this and make it read 0.

To actually read the pin state the line is:

    if (!(PINA & (1<<PA0))) {

PINA will return the state of all 8 bits in the port - including the 7 that are "floating" and could randomly be reading 0 or 1. The "& (1<<PA0)" operation says "clear the other 7 bits to 0 - I'm only interested in the state of bit 0. Now we already established that when the switch is not pressed the pull up will make it read 1 and when the switch is closed and it connects to Gnd, this will over-ride the pull-up and make it read 0. Now C treats anything non zero as "true" and 0 as false. So this statement is effectively the "wrong way up". It could have been written as:

if (PINA & (1<<PA0)) {
  ; // nothing
} else {
  // button is pressed
}

but the ! operation means "turn false into true and true into false" so it inverts the sense of the logic and accounts for the fact that a closed switch reads 0 and an open one reads non-zero.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks everyone, and clawson, good explanation with depth and clarity, huge props!
I will now summarize my point of veiw, just so you can shoot me down if my reasoning is messed up.
This

DDRA = 0x00 (default, implicit)
PORTA = 0xFF

Will switch on internal pull-up resistor for all bits in PORTA. So if I try to read PINA when nothing is pushed, then PINA will read 0xFF. If I then push the switch connected to bit0, then PINA will read 0xFE. This means that if I want to do something when switch at bit0 is pushed, then I can write the following

if(!PINA & 0x01)
    ; // switch pressed, DO-SOMETING
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Once you feel comfortable with the above, the next chapter is entitled "Buttons bounce.".
http://www.ganssle.com/debouncin...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I will now summarize my point of veiw,

Sounds right. By the way you may also want to read this article in tutorial:

https://www.avrfreaks.net/index.p...

Clearly you understand the "& 0x01" thing but some programmers would use "& (1<<PA0)" to be even more explicit about what is going on.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Will switch on internal pull-up resistor for all bits in PORTA. So if I try to read PINA when nothing is pushed, then PINA will read 0xFF. If I then push the switch connected to bit0, then PINA will read 0xFE.
This is true assuming that the switch attached produces a low when pressed.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mushin wrote:
This means that if I want to do something when switch at bit0 is pushed, then I can write the following

if(!PINA & 0x01)
    ; // switch pressed, DO-SOMETING

Almost (missing brackets).

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Except for the really obvious cases, I don't always keep operator precedence in my head. Thus, to make sure that stuff is evaluated the way I intended, I insert parenthesis. Also makes readers of the code at another time sure what the original programmer intended (that is often "me" and "me" :D):

if(!(PINA & 0x01)) 
    ; // switch pressed, DO-SOMETING 

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
Once you feel comfortable with the above, the next chapter is entitled "Buttons bounce.".
http://www.ganssle.com/debouncin...

Is this related to waves in general? I have not read what you are referring to, just skimmed the intro. I am planning to study waves in physics this summer, mostly sound. Pressing the remote on the TV produces infrared waves? I will check it out, it's cool to transfer knowledge from one domain to another.

clawson wrote:
Quote:

I will now summarize my point of veiw,

Sounds right. By the way you may also want to read this article in tutorial:

https://www.avrfreaks.net/index.p...

Clearly you understand the "& 0x01" thing but some programmers would use "& (1<<PA0)" to be even more explicit about what is going on.

Thanks agian mate, I will check it out.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Is this related to waves in general?

No. "Buttons bounce." Read the article. Look at the pictures.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BTW as others have noted you are using '!' which is the logical NOT operator. While you can add parentheses to make it work:

if(!(PINA & 0x01)) 

another (I think prettier) solution would be:

if(~PINA & 0x01) 

which uses binary NOT instead. When the switch is pressed the (likely) 0xFE read from PINA will be inverted to 0x01 and then this is ANDed with 0x01 to make a non zero result which is considered "true".

If I'm honest I thought that was what you had written above - obviously I need my eyes tested!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yea, that was that I meant. I assumed that ! was eqivalent with ~.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I assumed that ! was eqivalent with ~

In programming never ASS-U-ME anything it only makes an ASS or U and ME.

For example;

uint8_t byte = 0xA5;
uint8_t logical, binary;

logical = !!byte;
binary  = ~~byte;

if (logical == binary) {
   printf("they do the same thing");
}
else {
   printf("no they don't");
}

Which do you think would be printed?

This is the code the above assignments generate:

	logical = !!byte;
  92:	80 91 60 00 	lds	r24, 0x0060
  96:	91 e0       	ldi	r25, 0x01	; 1
  98:	88 23       	and	r24, r24
  9a:	09 f4       	brne	.+2      	; 0x9e 
  9c:	90 e0       	ldi	r25, 0x00	; 0
  9e:	90 93 62 00 	sts	0x0062, r25
	binary  = ~~byte;
  a2:	80 93 63 00 	sts	0x0063, r24

(where 'byte' is held in location 0x0060).

BTW if you study what's happened here you'll also see that !! is a "clever" way to get any non-zero value to be 1 and 0 to be 0. It can be used in scenarios such as:

bool there_are_cats = !!number_of_cats;

Making a boolean out of something that is true if non-zero and false if 0.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Also makes readers of the code at another time sure what the original programmer intended (that is often "me" and "me" :D):

Ditto! :lol:

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius