setting one bit and leaving others the same.

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

I've got a C program for a Tiny84.
I have 2 ports PB0 and PB1 that I've set as outputs in the DDR.

I can set control the state of each port using the following...

PORTB = 0b0000010; // sets PB1 high, all others low.

or

PORTB = _BV(PORTB1);

But how would I set PB1 to logic 1 and leave the others in their previous state.
What about setting the PB1 to 0 (zero) and leave the other bits alone.

I'm sure this question must have been asked before, but I'm not entirely sure what to search for.
Thanks, all.[/code]

Jim M., Rank amateur AVR guy.

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

Sorry to reply to myself. But...
I've come up with something scavended from another post.
This sets B0 to 1 and leaves everything else the same.

PORTB &= 0b11111110; // Retains all values except PORTB0
PORTB |= (0b00000001 & 0b00000001); // Sets PORTB0 to 1

This sets B0 to 0 and leaves everything else the same...

PORTB &= 0b11111110; // Retains all values except PORTB0
PORTB |= (0b00000000 & 0b00000001); // Sets PORTB0 to 0

Is there a better way to do this?

Jim M., Rank amateur AVR guy.

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

JimmyM wrote:
Sorry to reply to myself. But...
I've come up with something scavended from another post.
This sets B0 to 1 and leaves everything else the same.

PORTB &= 0b11111110; // Retains all values except PORTB0
PORTB |= (0b00000001 & 0b00000001); // Sets PORTB0 to 1

This sets B0 to 0 and leaves everything else the same...

PORTB &= 0b11111110; // Retains all values except PORTB0
PORTB |= (0b00000000 & 0b00000001); // Sets PORTB0 to 0

Is there a better way to do this?

Yes. Delete the unnecessary statements. For the first objective, "setting B0 to 1, leaving all else unchanged", just
    PORTB |= 1; 

will do. For the second, "clearing B0 to 0, leaving all else",

    PORTB &= ~1;

is all you need.

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

I'm not a fan of using hard coded values when they have special meaning especially when there are already existing defines available.
So for a bit more clarity and portability, I'd use:

    PORTB |= _BV(PORTB1); /* set only PORTB1 */

    PORTB &= ~_BV(PORTB1); /* clear only PORTB1 */
 

And to allow the bits/pins to be changed easily in the future, I also like to have my own local defines so that I can easily move things around if I want/need to.

So something like this:

#define MYPORT PORTB
#define MYPORTBIT PORTB1

    MYPORT |= _BV(MYPORTBIT); /* set only MYPORTBIT */

    MYPORT &= ~_BV(MYPORTBIT); /* clear only MYPORTBIT */
 

Or if you want to get rid of the _BV macro references:

#define MYPORT PORTB
#define MYPORTBITVAL _BV(PORTB1)

    MYPORT |= MYPORTBITVAL; /* set only MYPORTBIT */

    MYPORT &= ~MYPORTBITVAL; /* clear only MYPORTBIT */
 

That way if you want/need to change ports or bits you simply change your defines and presto magico all your code will be updated to the new port and bit values.
If you use hard coded values, it is a much more difficult task.

--- bill

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

You need a trip to the "Programming 101" thread in the tutorials forum.

Regards,
Steve A.

The Board helps those that help themselves.

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

Thanks, Levenkay and bperrybap for the great answers. I knew there had to be a better way.

Jim M., Rank amateur AVR guy.

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

What Steve was hinting at was the "Bit manipulation" tutorial. It is here: https://www.avrfreaks.net/index.p... . Obligatory reading if you ask me.

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

JohanEkdahl wrote:
What Steve was hinting at was the "Bit manipulation" tutorial. It is here: https://www.avrfreaks.net/index.p... . Obligatory reading if you ask me.

Thanks, Johan. That's what I was looking for. I just didn't know exactly what to call it.

Jim M., Rank amateur AVR guy.

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

bperrybap wrote:
I'm not a fan of using hard coded values when they have special meaning especially when there are already existing defines available.
Quote:

#define MYPORT PORTB
#define MYPORTBITVAL _BV(PORTB1)

    MYPORT |= MYPORTBITVAL; /* set only MYPORTBIT */

    MYPORT &= ~MYPORTBITVAL; /* clear only MYPORTBIT */
 

When I do that sort of thing,
my macro names usually end in _MASK.
The macros like PB1 always seemed a bit silly to me.
Quote:
That way if you want/need to change ports or bits you simply change your defines and presto magico all your code will be updated to the new port and bit values.
If you use hard coded values, it is a much more difficult task.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

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

Macros cause profanity a year after they are written. The author, much less others, have to spend too much time with a captain Midnight decoder sheet.

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

stevech wrote:
Macros cause profanity a year after they are written. The author, much less others, have to spend too much time with a captain Midnight decoder sheet.
The decoder sheet is rather the point.
When the hardware guys decide that LED 4 should be
controlled by pin 3 of port D instead of pin 2 of port C,
the change can be made in one place.
If done right, or just not poorly,
one will usually not need to know the values of LED4_PORT or LED4_MASK.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles