Set, Clear, Toggle, and Check Bit Value in C
In the embedded system design, the system needs to check the input state and then send signals to other devices or change the state of the outputs. Since each GPIO pin is connected to a different device (some pins are input, and other pins may be output or other functions), it is impossible to check the pin state by comparing it with a constant value. The setting, clearing, and toggling pins also have the same situation: constant values can not be assigned directly to the port DATA register because each GPIO pin is associated with the corresponding bit in the port DATA register; a bitwise operation can be used to solve these issues.
Figure 1: Example of Embedded System
Bit Masks
Definition:
A bit mask is a binary number used to select or manipulate specific bits within another binary number. This is achieved through bit-wise operations such as AND, OR, and XOR. Each bit in the mask determines whether the operation will affect the corresponding bit in the target value.
- Mask 1:
- A bit mask where the bit of interest is set to 1 and all other bits are set to 0.
- Used to isolate, set, or toggle a specific bit.
- Example: To isolate bit 3, mask1 = 0b00001000, or mask1 = 0x08.
- Mask 0:
- A bit mask where the bit of interest is set to 0 and all other bits are set to 1.
- Used to clear a specific bit.
- Example: To clear bit 3, mask0 = 0b11110111, or mask0 = 0xF7.
- Converting Between Mask 1 and Mask 0 Values:
- To convert a Mask 1 value to a Mask 0 value, invert all the bits of the Mask 1 value. Conversely, to convert a Mask 0 value to a Mask 1 value, invert all the bits of the Mask 0 value
- Bit-wise NOT Operator (~):
- Convert Mask 1 to Mask 0:
- Convert Mask 0 to Mask 1:
- Convert Mask 1 to Mask 0:
Types of Masks:
- Single Bit Masks:
- Masks that target a single bit.
- Example:
- Multi-Bit Masks:
- Masks that target multiple bits.
- Example:
Summary:
A bit mask in embedded systems is a powerful tool for manipulating individual bits within a register or variable. Using bit-wise operations with carefully designed masks, programmers can set, clear, toggle, and check specific bits, enabling precise control over hardware behavior.
Bit-wise Operators in Embedded Programming
Bit-wise operators are crucial for manipulating individual bits within registers and variables in embedded programming. These operators allow precise control over hardware, enabling efficient and low-level operations.
Setting bits to 1
Clearing bits to 0
Toggling bit values
Set Multiple Bits Value
Checking bit value
Reading a bit value
Figure 2: Truth Table for Bitwise-OR
n:=0or1⇒{n|0=n→sameasnvaluen|1=1→alwaysbe1
To turn certain bits on, the bitwise-OR operation can be used, following the principle that n OR 1 = 1
and n OR 0 = n
. Therefore, to make sure a bit is on, OR
can be used with a 1
. To leave a bit unchanged, OR
is used with a 0
.
- A bit "mask 1" can be used to set specific bits to 1.
- This is commonly done using the bit-wise OR operation.
- Examples:
- Setting 1 on bits 5 and 3, the other bits are unchanged.
- To set the 3rd bit of an 8-bit register.
- To light on the lamp connected to PB2, bit 2 of the Port B DATA register needs to be set to 1.
The following expression shows how to set bit 2 to 1:
- Setting 1 on bits 5 and 3, the other bits are unchanged.
Figure 4: Truth Table for Bitwise-AND
n:0or1⇒{n&0=0alwaysbe0n&1=nsameasnvalue
From the above results, you can find that when a bit is AND
ed with a 0
, the result is always 0, i.e. n AND 0 = 0
. To leave the other bits as they were originally, they can be AND
ed with 1
, since n AND 1 = n
.
- A bit "mask 0" can be used to clear specific bits to 0.
- If a "mask 1" value is used, convert it to a "mask 0" value using the inverter operator (~).
- This is commonly done using the bit-wise AND operation with a "mask 0" value.
- Example:
- Clearing on bits 5 and 3, the other bits are unchanged.
- To clear the 3rd bit of an 8-bit register
- To turn off the lamp connected to PB2, bit 2 of the Port B DATA register needs to be clear to 0.
The following expression shows how to clear bit 2 to 0:
- Clearing on bits 5 and 3, the other bits are unchanged.
Figure 6: Truth Table for Bitwise-XOR
n:0or1⇒{n\^0=nsameasnvaluen\^1=ˉninverttednvalue
We discussed how to turn bits on and off, but not both at once. Sometimes, it does not know the current value, but it must be made the opposite of what it currently is. In other words, toggling means turning the bit on if it is off and turning it off if it is on. This can be implemented using the XOR
(exclusive or) operation. Therefore, inversion of the values of bits is done by XOR
ing them with a 1
. The other unchanged bits can be XOR
ed with 0
, because n OXR 0 = n
, just like an OR
.
- A bit "mask 1" can be used to toggle specific bits.
- This is commonly done using the bit-wise XOR operation.
- Example:
- Example: The other bits are unchanged, inverting on bits 5 and 3.
- To toggle the 3rd bit of an 8-bit register:
- To toggle the lamp connected to PB2, bit 2 of the Port B DATA register must be inverted.
The following expression shows how to invert bit 2:
- Example: The other bits are unchanged, inverting on bits 5 and 3.
To set specific bits in a register to arbitrary values, you can follow a two-step process:
- Clear the bits you want to modify.
- Set the desired bits to the new values.
Example: Set reg[4:2] to (010)2
- Clear bits 4, 3, and 2.
- Use a bit-wise AND operation with a "mask 0" value that has 0s in the positions of the bits to clear and 1s elsewhere.
- Set bits 4, 3, and 2 to the value (010)₂.
- Use a bit-wise OR operation to set the bits to the desired value.
Or, we can combine the two steps into one statement as below:
This method ensures that only the specified bits are modified while other bits in the reg remain unchanged.
So far, you have learned how to change bit values. However, suppose you want to determine whether the particular bit is set. The following test does not necessarily work:
This is because even if bit 2 in PORTB is set to 1, other bits might also be set to 1. The equality above is true only when bit 2 is the only bit set to 1.
The Bitwise-AND operator (&) can be used to check the bit state. First, use bitwise-AND to AND
PB with a bitmask value (The corresponding bit in bitmask must be set to 1, leaving other bits to 0). This produces a value that is 0 in all the other bit positions because 0 AND any value is 0
. Only the bits corresponding to the 1 is left unchanged because 1 AND any value is that value
. Therefore, if the result is zero, then the bit was off. But, if the result is any other value, then the bit was on. Figure 8 illustrates how this operation works.
Figure 8: How an & (and) Mask Works
The proper test is this:
For one-bit testing, programmers often simplify this test to the following:
For one-bit testing, programmers often simplify this test to the following:
For multiple-bit testing, you need to identify the correct value to compare with the result:
- Checking both PB0 & PB1 are 1
- Checking both PB0 & PB1 are 0
To read the current state of a pin into a variable, use the bit-wise AND operator to filter the corresponding bit. Since the pin state is a logic value, there are only two values, either logic 0 or logic 1, so the data type of the variable used to store the pin state can be set to a Boolean variable.
For example, the SW1 is connected to PB2. To read PB2 state into sw1 variable:
To check the sw1 state (connected on PB2):
Summary:
- Mask 1: Used for checking, setting, or toggling a bit.
- Mask 0: Used for clearing a bit.
- Bit-wise AND (&): Used for checking or clearing a bit.
- Bit-wise OR (|): Used for setting a bit.
- Bit-wise XOR (^): Used for toggling a bit.
Bit-wise operators are essential tools in embedded programming for manipulating individual bits within registers. They provide efficient and precise control over hardware, enabling tasks such as setting, clearing, checking, and toggling specific bits. You can write more efficient and maintainable embedded code by understanding and utilizing these operators.
Useful Pre-Definition Mask 1 Values
In embedded systems, it is common to define masks for specific bits to facilitate operations like setting, clearing, or checking bits. Below are some pre-defined mask 1 values for an 16-bit register, which you can use for various bit manipulation tasks. Write the following definitions in a header file, like MyDefines.h. Then, include the file in your project.
Example Usage:
- Setting a Bit:
- Clearing a Bit:
- Toggling a Bit:
- Checking a Bit:
Summary:
Pre-defined mask values are useful for simplifying bit manipulation tasks in embedded systems. By defining masks for individual bits, you can easily perform operations like setting, clearing, toggling, and checking specific bits within a register.
Bit Access Functions
Bit Access Functions
Using functions to get or set a particular bit in a variable can improve code readability and maintainability in embedded systems programming. Below are examples of such functions:
Set Any Bit to Either 0 or 1
SetBit() function sets a particular bit to either 0 or 1.
Function Definition:
Usage Example:
Get the Value of a Particular bit in an Integer Variable
GetBit() returns the value of a specific bit in a variable.
Function Definition:
Usage Example: