I
know that you are ready to write the first program. You have been through a lot
so far! While we are on the subject, let's recap the events. You went out and
purchased the AVR Atmel
Microcontroller of your choice. I chose the ATMega32 for my uses. You
were introduced to the concept
of microcontrollers how they work; and were also introduced to the
programmer, the device that helps transfer the program into the microcontroller.
You built
a convenient interface that is used to connect the SPI pins to the
correct pins of the microcontroller. You verified that the programmer
(USBTinyISP) drivers were installed correctly for the 32-bit and
64-bit versions of Windows (XP, 7 and Vista). You also installed the
programming environment installed
the "Programming Environment" called WinAVR so that you can
have an environment in which to write your program, and then transfer it into
the microcontroller. And to make sure that everything functions correctly, you
used avrdude totested
the programmer while plugged into the computer and the
microcontroller. Recall that this program is the program transfer utility to
move our compiled program into the memory on the microcontroller. Finally, you
built the first circuit so that we could have something to write a program for.
Whew... that was a lot! But since you jumped through all of those hurdles, the
hard work is over and it's smooth sailing from here on. Hopefully you were able
to get through the previous steps without any problems--so now let's get on
with our first program.
For
the sake of simplification, let's categorize the function of the microcontroller
into three categories: Control, sensing and communication. We'll leave the
details of how to develop each of these functions, and delve into these details
as we write the various programs. Note that there are many ways to program
these functions. For the first program, we'll make the microcontroller
"control" something. And as you know from the previous post, we'll be
using an LED for this purpose. Basically, we will turn the LED on. Yes I
know... boring, right? Well I need to start somewhere! As I take you through
the experience of programming, I will add more complexity a little at a time so
you are easily able to wrap your head around these important concepts.
So
at this point you're probably asking...how do we make a program to control an
LED? Well, it's really easy: We will simply tell Pin0 on PORTB to output 5
volts. Remember that this is the pin to which the positive lead (anode) is
connected. The first key in this scenario is "output, " and the next
is "5 volts." There is a way we can tell a particular pin to be set
to be an output from the MCU. Once a pin has been set to provide output, you
will then be able to control that pin and make it either high (5 volts) or make
it low (zero voltage). And since there are only two states for this pin in the
output mode (5v or 0v), and only two states for the mode itself (input or
output), you only need to set the value to either logical 1 or a 0. Note that
this must be accomplished for each pin we wish to use in our circuit. But
before we get to plugging in a 1 or 0, let's talk about input versus output.
When a pin is in input mode, it is listening for a voltage. When the pin is in
output mode, the it can be charged at 5v, or not charged at 0v. That's it!
There
are many ways to do this. This is not to confuse you, but rather to make things
simpler. I will be introducing you to one of the many ways to accomplish this
task, and later I will explain some other methods while writing other programs.
Note however that while this first method is great for introducing the concept,
it's probably not as good in practice. Therefore you will see other methods in
future programs that will leave contextual pins (those pins on either side of
the pin of interest) unaffected, as they may very well have been previously set
in the program. But since we're writing a simple program, we won't worry about
this complexity at this time.
To
pick the output mode for a pin, you will use the Data Direction Register (DDR).
Oh man! What is a register?!? Don't let this worry you. A register is simply a
memory location that makes the microcontroller react in some way. We use a
register to set a state for the microcontroller, or make the microcontroller do
something. It's like reflexes, or tickles. When a person tickles another person,
it invokes laughter. We can make the MCU do something by setting a specific
value in a register. That's all you need to know at the moment.
So
when you use the DDR register, you are able to set the pin to either output
data, or accept data input. But we said input or output, now you're saying data
also. The term "data" used here simply just adds another dimension to
this idea in the form of "time." If you make a pin 5 volts, then zero
volts, and then 5 volts again...you are actually sending 1s and 0s. To the pin,
this is nothing more than a high (5 volts) state, and then a low (zero volts)
state: The MCU sees this high/low logic. And you can also receive data in the
same way.
There
are several ways to set pin0 for port B to output. One way to do this is to
write:
DDRB
= 0b00000001;
Let
me explain. "DDRB" refers to the Data Direction Register for port B;
"0b" is to tell the compiler that what follows is the binary
expression of a number; and the "1" on the end denotes the pin 0
position (the first pin in port B). Recall that there are 8 pins for port B;
pins 0 though 7. There are also 8 digits in our line of code. So each digit
represents a pin on the port, and we can use the individual digits to
specifically refer to any one of the pins in port B. So the '1' at the end of
our code statement refers to the first pin in port B, which in this case is pin
0. (Recall that C and C++ are zero-based languages, so the first index of a
data structure refers to is the zero'th element; the second index refers to the
first element, etc.) We really don't need to get any more complex at this
point, as this will be covered in much more detail in future tutorials. However
if you would like to know more about the binary system, check here.
Now
we need to apply 5v to the pin. This works just like the DDR code statement we
used above. We will use a binary number to put 5v on that pin (pin 0) using
this statement:
PORTB
= 0b00000001;
The
only difference between this and the previous statement is that we are now
using the PORT register. This register knows the pins of that specific port,
and gives us access to specify the actual data value (logical 0 or 1) for these
pins.
Now
we need to talk a bit about the overall structure of our program. All programs
need a specified place to start the execution. It's like giving someone a set
of instructions on how to make a cake without telling them which step to start
on. The "main" function is the place where all C/C++ programs start
execution. So we will create a main function.
int main(void)
{
}
{
}
In
order for the program to understand the DDR and PORT register information and
how these work within the microcontroller, an include statement must be added
that contains all of the information about the AVR microcontrollers. This
include statement will probably be in all of your programs.
#include
<avr/io.h>
int main(void)
{
}
int main(void)
{
}
When
the compilation process starts, the pre-processor portion of the compiler looks
in the "avr" directory for the "io.h" file. The
".h" extension here indicates that this is a header file, and (as its
name implies) the code within that file will be inserted at the beginning
(head) of the source file you are creating. Now we can insert the DDR and PORT
statements into our code, since the inclusion of the io.h header file has
informed the compiler about them.
#include
<avr/io.h>
int main(void)
{
int main(void)
{
DDRB = 0b00000001; //Data
Direction Register setting pin0 to output and the remaining pins as input
PORTB = 0b00000001; //Set
pin0 to 5 volts
}
Now
the direction of the pin0 is set to output, with a value set at 5v. But we are
still not finished. We need to keep the microcontroller running indefinitely,
so we need a routine to do this. This is called an endless (or infinite) loop.
The infinite loop makes sure that the microcontroller does not stop performing
its operations. I will explain this in more detail when we have stuff to do
within this loop. There are several types of loops we can use for this purpose,
but for this demonstration I will use the while loop. It means the same in
English as it does in code: For instance, "while" I have my hand up,
you should keep clapping.
#include
<avr/io.h>
int main(void)
{
int main(void)
{
DDRB = 0b00000001; //Data
Direction Register setting pin0 to output and the remaining pins as input
PORTB = 0b00000001; //Set pin0 to 5 volts
while(1)
{
PORTB = 0b00000001; //Set pin0 to 5 volts
while(1)
{
//Code
would be in here if it needed to execute over and over and over ... endlessly
}
}
Note
that we use a '1' as the argument to the while loop, because anything other
than '0' is a logical true. Therefore the while loop condition will never be
anything other than logically true, and the program will continue to execute
indefinitely (i.e.; I keep my hand raised).
So,
here is the fruit of our labor. It was a long ride so far, but I promise,
everything from here on will be gratifying and far less time consuming. In the
next video and instruction, we will make the LED blink. We will investigate how
to create a delay so the LED does not blink so fast that it looks like it's not
blinking.
Reference:
newbiehack.com
No comments:
Post a Comment