• AVR Freaks

Hot!BIT manipulation

Author
lewjoubert
New Member
  • Total Posts : 25
  • Reward points : 0
  • Joined: 2004/07/22 14:28:09
  • Location: Gold Coast Australia
  • Status: offline
2020/12/01 20:13:59 (permalink)
0

BIT manipulation

I have been programming in Pascal (Mikro Pascal) and Assembler for some time, and have decided to have a crack at C using XC8 in the hope of generating tighter more compact memory saving code than Pascal, and not as time consuming as Assembler.
The problem I have uncounted and hoping for some help/direction, is in bit setting and clearing.
ie: In Pascal "bitname.0 := 1;" will set bit zero of bitname, and "bitname.0 := 0;"  would clear the bit.
Reading a bit would be eg: "if bitname.0 = 1 then etc etc etc...."
I've have read explanations in various C publications that seem to indicate one has to AND or OR bits to perform the operation of setting and clearing bits.
I have attempted manipulating bits of a struct and integer without success either. (bit.bit0 = 1  or bit[0] = 1 ??)
Hope someone can point me in the correct direction and perhaps tell me where I am going wrong?
Many thanks. 
 

A monkey in silk is a monkey no less - Rodriguez.
#1

7 Replies Related Threads

    NKurzman
    A Guy on the Net
    • Total Posts : 19116
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: online
    Re: BIT manipulation 2020/12/01 20:59:16 (permalink)
    +2 (2)
    You have several choices.
    The first would be a “bit field“.
    Which is basically a special form of a struct.
    You could create a union of that and a byte variable if you want to access it both ways.
    You should be able to look that up easily on the Internet. Note that this is the method used to control the various registers from XC8.

    If you want to set One or more bits you could use bit wise OR. AVar |= 0x02; that would set the second to last bit. If you’re a beginner be sure you understand the difference between a bit wise 0R and a logical one.
    AND can be used to clear bits. And X0R to toggle them.
    #2
    Mysil
    Super Member
    • Total Posts : 4071
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: BIT manipulation 2020/12/02 03:08:02 (permalink)
    +3 (3)
    Hi,
    When using XC8 compiler,  there is a file available for each type of PIC microcontroller,
    with name for each register, field and bit, named as documented in the datasheet for the device,
     
    When PIC microcontroller type have been selected in MPLAB,
    then the 'device support file' is made available in your source code file by typing:
    #include  <xc.h>    

    in the source file.
     
    The "bit field" structs   have this form:  REGISTERbits.BIT   or REGISTERbits.FIELD, where you replace the uppercase names with actual register and bit names, as documented in the datasheet.
    Example:
        LATC = 0;                // Clear all bits of this register to zero. 
        LATCbits.LATC6 = 1;      // Set a single bit.
        ANSELC = 0;              // Enable Digital Inputs for all pins on port C, only for microcontrollers that have Analog features on this port.
        TRISCbits.TRISC3 = 1;    // Set tristate control bit to input for pin RC3.
        TRISCbits.TRISC4 = 1;    // Set tristate control bit to input for pin RC4.
        TRISCbits.TRISC6 = 0;    // Clear tristate control bit for output on pin RC6.  

     
    There are bit macro definitions that may be used in mask and shift operations:

        while ((SSPCON2 & ( _SSPCON2_SEN_MASK | _SSPCON2_RSEN_MASK | _SSPCON2_PEN_MASK | _SSPCON2_RCEN_MASK | _SSPCON2_ACKEN_MASK))
               || (SSPSTAT &  _SSPSTAT_R_nW_MASK))
            NOP;  

     
    There also are shorthand macro definitions available for many register bits.
    Some SFR bits are placed in different registers in different device families.
    It may be easier to type:
        SSP1IF = 0;    // Clear interrupt flag
        SSP1IE = 1;    // Enable interrupt
        BCL1IF = 0;
        BCL1IE = 1;  

     
    Instead of: 
    #if defined  _16F1718
        PIR1bits.SSP1IF = 0;    // Clear interrupt flag
        PIE1bits.SSP1IE = 1;    // Enable interrupt
        PIR2bits.BCL1IF = 0; 
        PIE2bits.BCL1IE = 1;
    #elif defined  _16F18875   // Different device have different register layout:
        PIR3bits.SSP1IF = 0;    // Clear interrupt flag
        PIE3bits.SSP1IE = 1;    // Enable interrupt
        PIR3bits.BCL1IF = 0; 
        PIE3bits.BCL1IE = 1;
    #endif   

     
    If such symbolic register and field names are used in a systematic way,
    and then use the code for a different device type,
    then the compiler will either adapt to differences if it can,
    or tell where attention is needed.
     
        Mysil
    #3
    Mysil
    Super Member
    • Total Posts : 4071
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: BIT manipulation 2020/12/02 03:56:16 (permalink)
    +1 (1)
    Hi again,
    Stuff I have tried to explain in message above,
    is also documented in XC8 C compiler user guide.
    It is installed in a /docs directory together with the compiler executables and all the supporting files,
    somewhere like: C:\Program Files (x86)\Microchip\xc8\v2.10\docs
    or:   C:\Program Files\Microchip\xc8\v2.20\docs
     
    There are separate user guide documents for C90 mode, and for C99 compiler mode.
    Also a separate user guide for using XC8 compiler with AVR devices.
     
    Device support files for each individual PIC device type is in: 
          C:\Program Files (x86)\Microchip\xc8\v2.10\pic\include
    or:   C:\Program Files\Microchip\xc8\v2.20\pic\include\proc\
    or somewhere similar, depending on compiler version, and operating system of your PC computer.
    It is Not recommended to include a device-specific hardware support file in source code,
    but when you have got somewhat familiar with how it may be used,
    it may be worth looking into the file for your device, to understand what is available.
     
        Mysil
     
    #4
    crosland
    Super Member
    • Total Posts : 2145
    • Reward points : 0
    • Joined: 2005/05/10 10:55:05
    • Location: Warks, UK
    • Status: offline
    Re: BIT manipulation 2020/12/02 05:30:18 (permalink)
    +1 (1)
    lewjoubert
    hope of generating tighter more compact memory saving code than Pascal, 



    As well as what other have said, don't forget to enable optimization :)
     
    To expand in the union idea, I use a typedef:
     

    typedef union {
    struct {
    unsigned fast_led:1;
    unsigned slow_led:1;
    unsigned can_stretch:1;
    unsigned :1;
    unsigned slot_timer:1;
    unsigned send_current:1;
    unsigned send_voltage:1;
    unsigned :1;
    } ;
    uint8_t byte;
    } timer_flags_t;
    extern volatile timer_flags_t timer_flags;

     
    then

    timer_flags.byte = 0; // clear all bits
    timer_flags.fast_led = 1; // set a bit

     
    Also you should prefer

    timer_flags.fast_led ^= 1; // toggle a bit

     
    over

    t imer_flags.fast_led = ~timer_flags.fast_led; // toggle a bit

     
    Look at the disassembly to see why!
    #5
    NorthGuy
    Super Member
    • Total Posts : 6471
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: BIT manipulation 2020/12/02 06:27:47 (permalink)
    +2 (2)
    You can also use logic operations.
     
    For example
     
    bit.3 := 1;
    bit.5 := 0;

     
    is the same as
     
    bit |= (1 << 3);
    bit &= ~(1 << 5);

     
    #6
    1and0
    Access is Denied
    • Total Posts : 11774
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: BIT manipulation 2020/12/02 06:39:32 (permalink)
    0 (2)
    NorthGuy
    You can also use logic operations.

    Turn them into macros:
    #define bitset(var, pos)  (var |= (1uL << pos))
    #define bitclr(var, pos)  (var &= (~(1uL << pos)))
    #define bitflip(var, pos) (var ^= (1uL << pos))

    post edited by 1and0 - 2020/12/02 06:42:24
    #7
    1and0
    Access is Denied
    • Total Posts : 11774
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: BIT manipulation 2020/12/02 07:10:59 (permalink)
    0
    Another method:
    typedef struct {
       unsigned b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
    } byte_t;

    uint8_t foo;
    #define foobits (*(byte_t *)&foo)

    foo = 42;          // access as a byte
    foobits.b3 = 1;    // set bit 3
    foobits.b5 = 0;    // clear bit 5

    #8
    Jump to:
    © 2021 APG vNext Commercial Version 4.5