After creating a software to count in binary, let's see how bit shifting works.
In this tutorial we are going to see how to turn on and off a single LED each time we will be using the left bit shifting.
But what is interesting, in this video example, it's that we will be manipulate GPIOs with P1OUT and P2OUT registers.
Let's get started.
In order to have exactly the same example as in the video, let's see which electronic stuff we need:
Before starting, I would like to tell you that the 22 kohm resistor is there only because the luminosity of my sixth green LED was to high with a 330 ohm one (I had only 5 same green LED).
This said, we can begin.
We would like to use the P1OUT and P2OUT registers to turn on and off a LED, successively, from P1.0 to P2.5.
Then only one LED will be turned at a time.
We start by P1OUT and we give it the value of BIT0.
Notice that BIT0 isn't equal to 0x000 but 0x001.
So the P1.0 pin will be set to high (1) and then the LED connected to this pin will be turned on.
We have then to turn off this first LED and turn on the second.
For that we will be use the left bit shift "<<" operator.
With it we will tell the P1OUT register to take the value on its right and multiply 2 exponant this value.
For example if we had this operation to understand:
P1OUT = 0x001 << 1
we could transform it by:
P1OUT = 0x001 x 2^1.
and then have as result:
P1OUT = 0x002
Now if we had:
P1OUT = 0x008 << 4
we could transform it by:
P1OUT = 0x008 x 2^4
and the result would be:
P1OUT = 0x080
Notice one important thing there is that each time we have a "x" in a number, this number is an hexadecimal number.
So starting from 0 to F:
Another important point is that 0x080 is then equal t0 128 in decimal.
Let's try to code a bit (OK nice pun!!).
#include <msp430.h> void delay_ms(unsigned int delay); #define TIME_START 7 /** * The main function. * Notice that we don't need a return value. * The function is thus of void type. */ void main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer P1DIR &= 0x00; // resetting the P1DIR registers P2DIR &= 0x00; // resetting the P2DIR registers P1DIR = 0xFF; // setting all the P1DIR registers to 1 (high) P2DIR = 0xFF; // setting all the P2DIR registers to 1 (high) P1OUT &= 0x00; // resetting the P1OUT registers P2OUT &= 0x00; // resetting the P2OUT registers P1OUT = BIT0; // setting the P1OUT registers to 0x0001 while (1337) { // infinite loop if (P1OUT == BIT7) { P1OUT = 0x00; P2OUT = BIT0; // setting the P2OUT registers to 0x0001 while (P2OUT != BIT5) { delay_ms(TIME_START); // delay P2OUT = P2OUT << 1; } delay_ms(TIME_START); // delay P2OUT = 0x00; P1OUT = BIT0; } P1OUT = P1OUT << 1; delay_ms(TIME_START); // delay } } /** * Takes a value in parameter in order to have a delay. * 16,000 is equal to 16,000,000 / 1,000. * -> 16,000,0000 = 16MHz (the CPU clock speed). */ void delay_ms(unsigned int delay) { while (delay--) { __delay_cycles(16000); } }
This kind of exercise is essential to understand hardware systems and learn how to manipulate them.
I recommend you changing data in the code in order to get subtleties.
Once again, great job, you've just made it.
Comments
Eric (not verified)
Sunday, November 13, 2016 - 12:15am
Permalink
Great exercise, this is just
Great exercise, this is just enough to get me started on my build, working with an outdoor display control for 120V strings. If I can get the code worked out then I can move up from the counter/ dividers and sensing parts to a point.
Jenny (not verified)
Sunday, January 29, 2017 - 3:12am
Permalink
This is great. The only thing
This is great. The only thing I don't understand from the code is where does the 1337 in the while loop come from.
Mi-K
Sunday, January 29, 2017 - 10:02pm
Permalink
Hello Jenny,
Hello Jenny,
In C language (and many others) when you are in a loop, if the variable you are testing becomes zero, then you go outside the loop.
In the code 1337 is like 1, -59, 34343, -9999, meaning that you can write the value you want except zero if you want to have an infinite loop.
So to be short, you can replace 1337 by 1.
Branson (not verified)
Wednesday, February 22, 2017 - 11:23pm
Permalink
Hello,
Hello,
I have a question about how to use P1OUT and P2OUT. If I'm using P1.5, and P2.0, they're both on the same side of the micro controller, would this constitute using P1OUT for both of those pins, or is P1.5 for P1OUT, and P2.0 used with P2OUT? I'm trying to figure out when to use certain port outputs based on certain pins being used...is it based off of the first number on the pin label, or the specific side of the micro controller?
Thanks for answering in advance!
Mi-K
Friday, February 24, 2017 - 9:52pm
Permalink
Hello Branson,
Hello Branson,
P1 and P2 are both ports.
But they are not linked, they are independant.
It means that if you want to play with the Port 1 (P1) and activate it only, you won't be able to use pins of Port 2.
To use pins of a port, you have to activate it.
They are on the same side because it was certainly easier for the board designers to create it.
Add new comment