-The OR operation is used between the variable that we want to change and a constant which is called a BIT MASK or simply the MASK. The mask is used to identify the bit that we want changed. #This time we will use hexadecimal for completion of the examples, instead of binary.
Imagine we have a variable by the name of state:
state = state | 0x01; */ we set bit 0 to 1 ( HIGH ) and store it back into state*/
PS- this can be made shorter in real programming practice
state |= 0x01;
-To clear a bit ( in this case bit 0), we have to use the AND operator and the NOT operator.
state = state & ~0x01;
PS-Again, this can be made shorter with
state &= ~0x01;
So with this in mind, lets translate it into some code, that we can use in Arduino board for example, and flash the led on pin 13 ( bit 5 on Port B)
#include <avr/io.h> #include <util/delay.h> int main(void){ DDRB = 0b00100000; /* set bit 5 of data direction register to output */
while (1) { PORTB |= (0x01 << 5); */ we set bit 5 to 1 ( HIGH ) and store it back into PORT register */ _delay_ms(100); */ delay 100 ms, acording to <util/delay.h> header file */
PORTB &= ~(0x01 << 5); */ we clear bit 5 and store it back into PORT register */
_delay_ms(100);
}
}
PORTB |= (0x01 << 5);
So this sets bit 5 (and only bit 5) to 1. This is because it translates into:
PORTB = PORTB | 0b00100000;
PORTB &= ~(0x01 << 5);
Translates into
PORTB &= ~ 0b00100000;
A mistake here would be
PORTB &= (0x01 << 5);as this would set all bits to 0 ( therefore, all pins), and not just bit 5.Translated would bePORTB &= 0b00000000;To add to this we still have the toggle a bit option, which can be useful if, in this case, the delay were to be the same for on and off states...#include <avr/io.h> #include <util/delay.h> int main(void) { DDRB = 0xFF; while(1) { PORTB ^= (1 << 7); _delay_ms(250); } }We can also change more than one of the bits, using the AND operator (" | "):
#include <avr/io.h> #include <util/delay.h> int main(void){ DDRB = 0b00100000; /* set bit 5 of data direction register to output */ while (1) { PORTB |= (0x01 << 5); PORTB &= ~( ( 1 << DDB3 ) | ( 1 << DDB4 ) ) ; /*this will only be used on the second loop, as at this time the register hasnt been set for these bits*/ _delay_ms(100); DDRB|= ( ( 1 << DDB3 ) | ( 1 << DDB4 ) ) ; /* pin 3 and 4 as outputs rest left in their original state */ PORTB |= ( ( 1 << DDB3 ) | ( 1 << DDB4 ) ) ; /* we set bit 3 and 4 to 1 ( HIGH ) and store it back into PORT register */ PORTB &= ~(0x01 << 5); /*clear the bit 5*/ _delay_ms(100); } }
I would advise, as a next step, to research about the _BV() Macro, in the, from the avr-libc .BV stands for Bit Value).
PS:New intro-tutorial about the _BV() http://dubworks.blogspot.co.uk/2012/07/introduction-to-c-language-bitwise_21.html
The _BV() macro is defined as:
#define _BV(x) (1 << x)
this allows:
PORTC |= _BV(0); // Set bit 0 only.
PORTC &= ~(_BV(1)); // Clear bit 1 only.
PORTC ^= _BV(7); // Toggle bit 7 only.
No comments:
Post a Comment
Feel free to contact me with any suggestions, doubts or requests.
Bless