LOW-LEVEL ARDUINO PROGRAMMING(ASSEMBLER): BITWISE OPERATORS

LOW-LEVEL ARDUINO PROGRAMMING(ASSEMBLER): BITWISE OPERATORS-Uncategorized

INTRODUCTION

In the second tutorial about low-level Arduino programming, we will use Port D, i.e. digital pins 0-7. Port D’s pins 0 and 1 are used for serial communication and most people do not want to use them for anything else. Things can get weird if you play with them. So the usual practice is not to touch 0 and 1 bits of the DDRD and PORTD registry. In order to do this right, we need some foreknowledge about bits mathematics.

After a brief introduction about bits, we will program the push button and LED. If you have skipped the first lesson, return here.

BINARY SYSTEM

You already know that the binary system consists of stacks of 0s and 1s, along with the fact that 1 byte has 8 bits. If we are talking about registers of 8bit microcontrollers, each registry has 8 bits numerated from 0 to 7, from right to left. When we talked about registers controlling GPIO pins, we mentioned how we can change their state in different number systems. Before we proceed, let’s repeat the conversion.

Binarny to decimal

We convert to decimal system so that the base, number 2, is potentiated by the bit’s position. Bit 0 is 2 on 0, bit 1 is 2 on 1, bit 3 is 2 on 2, etc. In the example from the previous tutorial:

bin 2 dec

When we add the results, we get 32, which is equivalent to binary number B00100000.

Binary to hexadecimal

Hexadecimal system is most commonly used when changing states of registers in microcontrollers. We will divide the 8bit binary number into two 4bit, in bits 7-4 and 3-0, each will be separately potentiated with numbers 1,2,4 and 8, from left to right. Here is how it looks like in our example:

1

2

Sum of the 7-4 registry’s results is 2, while 3-0’s sum is equal to 0. We write the result down in a way that we write the first number next to the second one, i.e. 20. In order to recognize it as hexadecimal, we will write it as 0x20 in Arduino.

Let’s see what happens when the result of 4 bits is greater than 9, in an example:

3

The total is 8+4+1 which equals 13, i.e. “D”. So the binary number B1101 from the example is equivalent to hexadecimal number 0xD.

BITWISE OPERATORS

Let’s process the bitwise operators which are necessary for this tutorial and in general when using bits.

Bitwise AND, “&”

RULE: only if both bits are true(1), the result is true(1)

0 & 0 == 0
0 & 1 == 0
1 & 0 == 0
1 & 1 == 1

Therefore:

and

Bitwise OR, “|”

RULE: if one of the bits is true(1), the result is true(1) 

0 | 0 == 0
0 | 1 == 1
1 | 0 == 1
1 | 1 == 1

Therefore:

or

Bitwise XOR, “^”

RULE: the result is true(1) only if both bits are equal, both 1 or both 0 

0 ^ 0 == 1
0 ^ 1 == 0
1 ^ 0 == 0
1 ^ 1 == 1

Therefore:

xor

ARDUINO CODE

Port D’s registers look like this:

Connect the push button and LED according to the Fritzing scheme:

We have connected the LED to D7, the push button to D2 of Dasduino. Let’s set the D7 pin as output, and D2 as input without changing states of D0 and D1 pins we use for serial communication. We will turn on an internal pull-up resistor to pin D2, in order to avoid floating of the pin. Insert the code below to Arduino IDE and try it out:

void setup()
{
  // first, let's set the digital pin7 (D7) as output
  // this pin's bit for direction is located on the position 7 of DDRD registry
  // deafult state of the DDRD registry is B00000000
  DDRD = DDRD | B10000000;
  // "|" means logical OR
  // now we are sure that 7 bit == 1
  // and we know we have not changed bits 0 and 1
  // however, we do not know the state of bit 2 which we use for the push button
  // let's set them to 0 first, without changing the states of bits 0,1 i 7
  DDRD = DDRD & B10000011;
  // using logical AND, we are sure that the registry is: B100000000
  // that is how we have set what we wanted
  // set up the PORTD registry now
  // set all bits to 0, without changing D0 and D1
  PORTD = PORTD & B00000011;
  // we still have to set bit 2(D2) to HIGH state- turn on the internal pull-up
  // along the way, make sure we do not change the state of any other bit
  PORTD = PORTD | B00000100;
}
void loop()
{
  // reading the state of digital pin 2
  int tipkalo = PIND;
  // we save the whole registry to variable "tipkalo"
  // however, all we want to know is the state of bit 2 in this registry
  // since we are using an internal pull-up resistor
  // when the push button is inactive, the state of bit2 will be 1
  // and when it is pressed, the state will be 0 (we physically connect the pin to gnd)
  tipkalo = tipkalo & B00000100;
  // now, the registry looks like this:
  // when the push button is active: B00000000, in decimal system == 0
  // when the push button is inactive: B00000100, in decimal system == 2^2 = 4.
  // let's write the condition which will turn the LED on when the push button is activated
  if( tipkalo == 0)
  {
    // we turn the LED on D7 on by putting 7mi bit to state "1"
    // again, not changing the state of any other bit
    PORTD = PORTD | B10000000;
  }
  // all we have left to do is shut the LED down when the push button is no longer active
  PORTD = PORTD & B00000111;
  // the last command will set all bits to 0
  // except for the last 3 which will remain unchanged
}

In the following tutorial we will see how to write our own delay() function and test the speed of program’s performance using Arduino library and the way we are doing it at the moment.

Since void setup() is performed just once, we can make it easier for us by using Arduino pin mode() function for this part. Just a reminder how this looks like:

void setup()
{
  pinMode(7, OUTPUT);
  pinMode(2, INPUT_PULLUP);
}