• AVR Freaks

Hot!Reaching individual bits of integer

Page: 1234 > Showing page 1 of 4
Author
GunkutA
Junior Member
  • Total Posts : 118
  • Reward points : 0
  • Joined: 2019/01/10 00:09:38
  • Location: 0
  • Status: offline
2019/05/16 06:47:04 (permalink)
0

Reaching individual bits of integer

I need to send some integer value that is between 0 and 100 to another PIC by using 8 bits of PIC18F26K83. The problem is pins are from different ports not from the same ports. So I cannot follow a way like: PORTA = integer number.
  1. bit should be sent to RC0.
  2. " "" " " " RC1.
  3. " "" " " " RC5.
  4. " "" " " " RC6.
  5. " "" " " " RC7.
  6. " "" " " " RA5.
  7. " "" " " " RA6.
  8. " "" " " " RA7.
I did something like this but it did not work:
 
LATC.B0 =avarage &0b00000001;
LATC.B1 =avarage &0b00000010;
LATC.B5 =avarage &0b00000100;
LATC.B6 =avarage &0b00001000;
LATC.B7 =avarage &0b00010000;
LATA.B5 =avarage &0b00100000;
LATA.B6 =avarage &0b01000000;
LATA.B7 =avarage &0b10000000;


 
Note: I use Micro C compiler.
#1

62 Replies Related Threads

    crosland
    Super Member
    • Total Posts : 1586
    • Reward points : 0
    • Joined: 2005/05/10 10:55:05
    • Location: Bucks, UK
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 07:15:05 (permalink)
    0 (2)
    GunkutA
    I did something like this but it did not work:
     

     
    So why don't you just go and do something else instead.
     
    Alternatively, give us a clue and tell us WHY it did not work.
     
    How did you test it?
     
    What were you expecting?
     
    What did you get?
     
     
    #2
    GunkutA
    Junior Member
    • Total Posts : 118
    • Reward points : 0
    • Joined: 2019/01/10 00:09:38
    • Location: 0
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 07:17:08 (permalink)
    0
    It works like this but it does not look like an efficient way : 
     
    void send_data(){
               if(avarage &0b00000001){
                LATC.B0=1;
               }
               else{
               LATC.B0=0;}
               
                if(avarage &0b00000010){
                LATC.B1=1;
               }
               else{
               LATC.B1=0;}
               
                if(avarage &0b00000100){
                LATC.B5=1;
               }
               else{
               LATC.B5=0;}
               
                if(avarage &0b00001000){
                LATC.B6=1;
               }
               else{
               LATC.B6=0;}
               
                if(avarage &0b00010000){
                LATC.B7=1;
               }
               else{
               LATC.B7=0;}
               
                if(avarage &0b00100000){
                LATA.B5=1;
               }
               else{
               LATA.B5=0;}
               
                if(avarage &0b01000000){
                LATA.B6=1;
               }
               else{
               LATA.B6=0;}
               
                if(avarage &0b10000000){
                LATA.B7=1;
               }
               else{
               LATA.B7=0;}
               
               }

    #3
    1and0
    Access is Denied
    • Total Posts : 9495
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 07:19:14 (permalink)
    +2 (2)
    Try && instead. ;)
     
    #4
    GunkutA
    Junior Member
    • Total Posts : 118
    • Reward points : 0
    • Joined: 2019/01/10 00:09:38
    • Location: 0
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 07:19:32 (permalink)
    0
    crosland
    GunkutA
    I did something like this but it did not work:
     

     
    So why don't you just go and do something else instead.
     
    Alternatively, give us a clue and tell us WHY it did not work.
     
    How did you test it?
     
    What were you expecting?
     
    What did you get?
     
     




    Yes, I changed it (see the post above) but I did not like it so asked if there might be a better way.
    I gave 255 to the avarage and then checked the GPIO pins.
     
    #5
    GunkutA
    Junior Member
    • Total Posts : 118
    • Reward points : 0
    • Joined: 2019/01/10 00:09:38
    • Location: 0
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 07:20:36 (permalink)
    0
    1and0
    Try && instead. ;)
     


    Thank you I will try it now :)
    Edit: It worked. Thanks again.
    post edited by GunkutA - 2019/05/16 07:23:00
    #6
    crosland
    Super Member
    • Total Posts : 1586
    • Reward points : 0
    • Joined: 2005/05/10 10:55:05
    • Location: Bucks, UK
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 07:24:07 (permalink)
    0
    So now think about what the result of 'average & 0b00000010' is.
     
    How many bits does it have?
     
    How many bits in a single LAT bit?
     
    Understand that and you will see why your first attempt does not work and your second one does.
     
     
    #7
    crosland
    Super Member
    • Total Posts : 1586
    • Reward points : 0
    • Joined: 2005/05/10 10:55:05
    • Location: Bucks, UK
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 07:25:17 (permalink)
    +1 (1)
    GunkutA
    1and0
    Try && instead. ;)
     


    Thank you I will try it now :)
    Edit: It worked. Thanks again.


    Are you sure?
     
    How many different values of average did you test it with?
     
    I think 1and0 is pulling your plonker.
    #8
    1and0
    Access is Denied
    • Total Posts : 9495
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 07:28:54 (permalink)
    0
    @OP, you need an expression that results in one bit value of 1 or 0.
    post edited by 1and0 - 2019/05/16 07:38:37
    #9
    1and0
    Access is Denied
    • Total Posts : 9495
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 07:29:47 (permalink)
    -1 (1)
    crosland
    I think 1and0 is pulling your plonker.

    Me.!? Haha ;) mr green: 
     
    My bad!
    post edited by 1and0 - 2019/05/16 07:36:47
    #10
    GunkutA
    Junior Member
    • Total Posts : 118
    • Reward points : 0
    • Joined: 2019/01/10 00:09:38
    • Location: 0
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 07:38:17 (permalink)
    0
    crosland
    GunkutA
    1and0
    Try && instead. ;)
     


    Thank you I will try it now :)
    Edit: It worked. Thanks again.


    Are you sure?
     
    How many different values of average did you test it with?
     
    I think 1and0 is pulling your plonker.


    Yes, it does not work hah. I wrote the reply after my first trial. My second post with the if and else loops work. I think I will use it.
     
    #11
    1and0
    Access is Denied
    • Total Posts : 9495
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 07:39:48 (permalink)
    0
    GunkutA
    Yes, it does not work hah. I wrote the reply after my first trial. My second post with the if and else loops work. I think I will use it.

    Got a brainfart moment. Anyway, you need an expression that results in a one bit value of 1 or 0.
    #12
    pcbbc
    Super Member
    • Total Posts : 1189
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 08:05:55 (permalink)
    +2 (2)
    There isn't really a efficient way.
    void send_data(unsigned char average) {
        LATC.B0 = (average & 0b00000001) != 0;
        LATC.B1 = (average & 0b00000010) != 0;
        LATC.B5 = (average & 0b00000100) != 0;
        LATC.B6 = (average & 0b00001000) != 0;
        LATC.B7 = (average & 0b00010000) != 0;
        LATA.B5 = (average & 0b00100000) != 0;
        LATA.B6 = (average & 0b01000000) != 0;
        LATA.B7 = (average & 0b10000000) != 0;
    }

     
    As some of the bits are consecutive and adjacent, you could handle then in groups an perhaps be slightly more efficient:
    bit0+bit1 => C0+C1
    bit2+bit3+bit4 => C5+C6+C7
    bit5+bit6+bit7 => A5+A6+A7
     
    Something like this (I don't guarantee it's 100% correct):
    LATC = (LATC & 0b00011100) | (average & 0b00000011) | ((average & 0b00011100) << 3);
    LATA = (LATA & 0b00011111) | (average & 0b11100000);

    #13
    1and0
    Access is Denied
    • Total Posts : 9495
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 08:36:09 (permalink)
    +1 (1)
    GunkutA
    It works like this but it does not look like an efficient way : 
     

    I think most here are not familiar with the MicroC compiler, so you will have to try different implementations and check the assembly it generated.  
     
    Based on pcbbc's observations, I can suggest something for the XC8 compiler, but that is not what you use.
     
    #14
    NorthGuy
    Super Member
    • Total Posts : 5544
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 14:05:51 (permalink)
    +2 (2)
    "if" and "else" is probably the most efficient on PIC18.
    #15
    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 15:44:09 (permalink)
    +1 (1)
    NorthGuy
    "if" and "else" is probably the most efficient on PIC18.

    Agreed. It looks like more C code, but in fact the generated assembly will be similar to the version in post#13.

    If you don't mind a small glitch at the start, the if/else version can be optimised to:
    void send_data(){ 
      LATC &= 0b00011100;    // clear B7 B6 B5 B1 B0
      LATA &= 0b00011111;    // clear B7 B6 B5
      if(avarage &0b00000001)
        LATC.B0=1;
              
      if(avarage &0b00000010)
        LATC.B1=1;
              
      if(avarage &0b00000100)
        LATC.B5=1;
              
      if(avarage &0b00001000)
        LATC.B6=1;
              
      if(avarage &0b00010000)
        LATC.B7=1;
              
      if(avarage &0b00100000)
        LATA.B5=1;
              
      if(avarage &0b01000000)
        LATA.B6=1;
              
      if(avarage &0b10000000)
        LATA.B7=1;
    }

     
    (n.b. is "avarage" meant to be "average" ? )

    Nearly there...
    #16
    pcbbc
    Super Member
    • Total Posts : 1189
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 16:21:43 (permalink)
    +1 (1)
    qhb
    NorthGuy
    "if" and "else" is probably the most efficient on PIC18.

    Agreed. It looks like more C code, but in fact the generated assembly will be similar to the version in post#13.

    I agree - my first version only looks more efficient if you only consider the C code.
    In reality the code the compiler (XC8 at least) produces will be much the same either way. That’s because there is no bit copy instruction, only bit set and clear.

    My second version produces less code (I checked) because it takes advantage of the juxtaposition of adjacent bits, and so copies more than one bit at a time.

    If you don't mind a small glitch at the start, the if/else version can be optimised to:
    void send_data(){ 
      LATC &= 0b00011100;    // clear B7 B6 B5 B1 B0
      LATA &= 0b00011111;    // clear B7 B6 B5
      if(avarage &0b00000001)
        LATC.B0=1;
              
      if(avarage &0b00000010)
        LATC.B1=1;
              
      if(avarage &0b00000100)
        LATC.B5=1;
              
      if(avarage &0b00001000)
        LATC.B6=1;
              
      if(avarage &0b00010000)
        LATC.B7=1;
              
      if(avarage &0b00100000)
        LATA.B5=1;
              
      if(avarage &0b01000000)
        LATA.B6=1;
              
      if(avarage &0b10000000)
        LATA.B7=1;
    }
     (n.b. is "avarage" meant to be "average" ? )

    Yep, that is likely even better. Around 20 instructions.
    I assumed average also, and so corrected it.
    #17
    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 16:39:47 (permalink)
    +1 (1)
    It would be a shame to ruin this nicely symmetrical post count ;)
     

    Attached Image(s)


    Nearly there...
    #18
    1and0
    Access is Denied
    • Total Posts : 9495
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/16 20:35:25 (permalink)
    0
    The following takes 15 instruction cycles
      WREG = average;
      WREG >>= 1;
      WREG = (WREG >> 4) | (WREG << 4);
      LATC ^= (LATC ^ WREG) & 0b11100000;
      LATC ^= (LATC ^ average) & 0b00000011;

      LATA ^= (LATA ^ average) & 0b11100000;

    which is only 2 more cycles than if it's in assembly.
    #19
    InvalidApple
    Super Member
    • Total Posts : 296
    • Reward points : 0
    • Joined: 2011/05/17 23:36:35
    • Location: Melbourne, Australia
    • Status: offline
    Re: Reaching individual bits of integer 2019/05/17 00:52:39 (permalink)
    0
    This sort of thing always looks neater with a ternary operator
     LATC.B0 = (avarage &0b00000001) ? 1 : 0;
    #20
    Page: 1234 > Showing page 1 of 4
    Jump to:
    © 2019 APG vNext Commercial Version 4.5