Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 7 of 7

Thread: Question about manipulating bits

  1. #1

    Question about manipulating bits

    Gentlemen,
    I have multiple questions... and I have searched the forums for a specific answer without any luck.
    I am trying to learn how to toggle multiple bits on and off without affecting other bits already set. I understand the bitshift part, but not quite have a grasp on the matter.

    I am currently setting 2 bits in the same register with two lines of code. It works!
    Code:
    GPIOD_PDOR |= (1<<6);      // HIGH
    GPIOD_PDOR |= (1<<5);      // HIGH
    However I want to acomplish the same by using only one line of code which compiles. Dont beat me up because I am not sure of the code below is correct.
    Code:
    GPIOD_PDOR |= ((1<<6) | (1<<5));
    Am I doing this right...

    Also if I want to set the same bits back to LOW, then is the code below correct?
    Code:
    GPIOD_PDOR &= ((1<<6) | (1<<5));

    Also, in the instance of the following where...
    Code:
    GPIOD_PDOR &= ~(1<<6);     // LOW
    GPIOD_PDOR |= (1<<5);        // HIGH
    How do I write a one liner to do the same...
    Thanks in advance

  2. #2
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    2,828
    Quote Originally Posted by BLMinTenn View Post
    Gentlemen,
    I have multiple questions... and I have searched the forums for a specific answer without any luck.
    I am trying to learn how to toggle multiple bits on and off without affecting other bits already set. I understand the bitshift part, but not quite have a grasp on the matter.

    I am currently setting 2 bits in the same register with two lines of code. It works!
    Code:
    GPIOD_PDOR |= (1<<6);      // HIGH
    GPIOD_PDOR |= (1<<5);      // HIGH
    However I want to acomplish the same by using only one line of code which compiles. Dont beat me up because I am not sure of the code below is correct.
    Code:
    GPIOD_PDOR |= ((1<<6) | (1<<5));
    Am I doing this right...
    Sure for setting the bits (providing the field you are referencing is a 32-bit int on a Teensy 3.x/LC, or 16-bit int on a Teensy 2.x). However generally you want to use names for each of the bits, rather than just using (1<<6) and (1<<5).

    Typewise, you probably want to use the same type as the GPIOD_PDOR definition, which in this case is uint32_t:

    Code:
    #define GPIOD_PDOR                (*(volatile uint32_t *)0x400FF0C0)  // Port Data Output Register
    I don't know the GPIOD structure, so I will just call the two fields ALPHA and BETA. You would define them like:

    Code:
    const uint32_t ALPHA = ((uint32_t)1) << 5;
    const uint32_t BETA = ((uint32_t)1) << 6;
    or if you prefer:

    Code:
    #define ALPHA (((uint32_t)1) << 5)
    #define BETA (((uint32_t)2) << 6)
    Casting the 1 to uint32_t insures that the resulting type after the shift is uin32_t. Otherwise, there might be issues if you use bit 31 due to int being signed. And if the type were a 64-bit type, you could get truncation if you go past 31.

    Quote Originally Posted by BLMinTenn View Post
    Also if I want to set the same bits back to LOW, then is the code below correct?
    Code:
    GPIOD_PDOR &= ((1<<6) | (1<<5));
    No, this is incorrect. You would clear all bits except (1<<5) and (1<<6), and those two bits would retain their value. What you are missing is the tilde ('~'), which reverses the bits values. To clear both bits (using my ALPHA and BETA from before):

    Code:
    GPIOD_PDOR &= ~(ALPHA | BETA);
    Quote Originally Posted by BLMinTenn View Post
    Also, in the instance of the following where...
    Code:
    GPIOD_PDOR &= ~(1<<6);     // LOW
    GPIOD_PDOR |= (1<<5);        // HIGH
    How do I write a one liner to do the same...
    Thanks in advance
    You would do something like:

    Code:
    GPIOD_PDOR  = (GPIOD_PDOR  & ~BETA) | ALPHA;
    The <op>= value operation is short hand for:

    Code:
    variable = variable <op> value;

  3. #3
    Michael,
    Thanks for the reply. To help you and the group understand, I am using a Teensy 3.2 and the GPIO_PDOR register to manipulate pins 20 & 21 high and low as as fast as possible.
    So to summarize....

    If I want to...
    Code:
    GPIOD_PDOR |= (1<<6);      // HIGH
    GPIOD_PDOR |= (1<<5);      // HIGH
    This works for single line application...
    Code:
    GPIOD_PDOR |= ((1<<6) | (1<<5));
    To do this...
    Code:
    GPIOD_PDOR &= ~(1<<6);     // LOW
    GPIOD_PDOR |= (1<<5);        // HIGH
    is the equivalent 1 liner...
    Code:
    GPIOD_PDOR = (GPIOD_PDOR & ~(1<<6)) | (1<<5);
    and last... this...
    Code:
    GPIOD_PDOR &= ~(1<<6);      // LOW
    GPIOD_PDOR &= ~(1<<5);      // LOW
    performs the same as...
    Code:
    GPIOD_PDOR &= ~((1<<6) | (1<<5));
    Do I have this correct?
    Thanks in Advance

  4. #4
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    2,828
    Quote Originally Posted by BLMinTenn View Post
    Do I have this correct?
    Thanks in Advance
    Yes that is correct.

  5. #5
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,774
    Your one-liner does a read, a and/or/eor and a write. So it is 3 operations (plus loading the adress).
    There are more specialized registers, for examplefor setting or clearing bits that don't need the read + and/or/eor operations.
    Open the reference manual and look for GPIOx_PSOR (set Bits), PCOR (clear Bits), PTOR (toggle Bits)
    Last edited by Frank B; 12-03-2018 at 11:05 PM. Reason: :-)

  6. #6
    All,
    Thanks for the response I understand the madness behind the bits. Just one more question.

    If I want to combine this...
    Code:
    if(GPIOD_PDIR & (1<<4) || GPIOD_PDIR & (1<<5)) {do something}
    is the below the same?
    Code:
    if(GPIOD_PDIR & ((1<<4) ^ (1<<5))  {do something}
    thanks in advance

  7. #7
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    2,828
    Quote Originally Posted by BLMinTenn View Post
    All,
    Thanks for the response I understand the madness behind the bits. Just one more question.

    If I want to combine this...
    Code:
    if(GPIOD_PDIR & (1<<4) || GPIOD_PDIR & (1<<5)) {do something}
    is the below the same?
    Code:
    if(GPIOD_PDIR & ((1<<4) ^ (1<<5))  {do something}
    thanks in advance
    No, you want inclusive-or, not exclusive-or, i.e.

    Code:
    if(GPIOD_PDIR & ((1<<4) | (1<<5))  {do something}
    would be the same as:

    Code:
    if((GPIOD_PDIR & (1<<4)) || (GPIOD_PDIR & (1<<5))) {...}
    If instead you wanted an '&&' replacement such as:
    Code:
    if((GPIOD_PDIR & (1<<4)) && (GPIOD_PDIR & (1<<5))) {...}
    you would code it as:
    Code:
    if ((GPIOD_PDIR & ((1<<4)|(1<<5))) == ((1<<4)|(1<<5))) {...}

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •