In this tutorial, I will use the Atmel AVR ATMEGA8515 Microcontroller, on the STK500 starter kit. For beginners, I would recommend the STK500 if you have some spare cash, as it does the hard work for you. It even has a built in MAX232 to allow the Microcontroller to communicate with other Serial devices. I will be using AVR Studio 4.16SP1 on Windows as the programming environment, with WinAVR installed to add support for C. Before I start, I am sorry in advance for the lack of tabulations in the code. This is because the parser on this site rips them out.
Fire up AVR Studio, click New Project, give it a name and select AVR GCC, click Next, select AVR Simulator, then in the right hand pane, select the Microcontroller you are going to be writing your program for, then click Finish. Selecting the Microcontroller is a very important step that cost me many hours of blind fury. I used to simply give the project a name then click finish, which lead to the project not compiling with the serial routines. I felt very stupid after realising my mistake.
When that is all done, you should see the above. You are now ready to begin programming. Before we continue further, please ensure you know how to flash the program onto the Microcontroller. For the STK500, you have to connect the ISP header to the header corresponding to the socket the Microcontroller is sitting in, then in AVR Studio, click the 'AVR' button on the toolbar, choose the built binary file, and click Program. For other kits/programmers, please see the manual that came with your product.
Quick Introduction to C
If you already know C or C++, please skip this step, if not, read on. I assume you already know how to program in a different language.
// This is a comment, it can be placed on a new line, or after text on another line
/*
This is a comment box, it can contain multiple lines
Another line
You get the idea
*/
Comments are useful for putting, well, comments in your code.
#define A_DEFINITION 4
Definitions are useful to make code neater. You could imagine them as constants, but they never get compiled. The compilier simply replaces all instances of 'A_DEFINITION' with the number 4
#include <somefunctions.h>
Include/merge another file. We will definately be using this. AVR GCC Compilier has some pre-defined functions for the Microcontroller in .h files, which we will want to be using.
int myFunction(int incomingInt)
{
incomingInt = (incomingInt + 5) * 2;
return incomingInt;
}
As you have programmed before, you have seen functions. In C, functions MUST be declared before use (prototypes). To declare the function above, we would put the following before our main procedure
int myFunction(int incomingInt);
Functions are called in an assignment statement. Creating a procedure is very much like a function, except that we declare it to return void instead
void myProcedure(int incomingInt)
{
screamPlease();
}
Getting the AVR to do something
Now that we can use C, let's make a very simple program to change the output on PORTB (if you have the STK500, you will see an LED change).
#include <avr/io.h>
int main(void)
{
DDRB = 255; //Set PORTB for Output
PORTB = 1; //Send 1 to PORTB
}
Ok, now let's make a program to match the output at PORTB with the input at PORTD (STK500 users can push the buttons, and see the result on the LEDs)
#include <avr/io.h>
int main(void)
{
DDRB = 255; //Set PORTB for Output
while(1) //Infinite loop
{
PORTB = PIND; //Send PORTD to PORTB
}
}
As you can see now, the possibilities are endless with simple I/O. You can use If or Switch statements to branch depending on input.
if (PIND == 64)
{
// Do something
}
switch (PIND)
{
case 255:
//Do something
break;
case 64:
//Do something else
break;
}
Delays
This took me a while to find. To get delays, you must first find the F_CPU value from the datasheet provided with your Microcontroller. I'm using an ATMEGA8515, and my F_CPU value is 3680000UL. The following code shows a routine where the output goes 1 for 1 second, and 0 for 1 second forever.
#include <avr/io.h>
#define F_CPU 3680000UL
#include <util/delay.h>
int main(void)
{
while(1)
{
PORTB = 0;
_delay_ms(1000);
PORTB = 1;
_delay_ms(1000);
}
}
Internal Pull-Up resistors
Most AVRs have internal pull-up! Now we can simply connect our switches to the input and ground pins. No more messing around with resistors. To activate this feature, stick this into your code (preferably in an a procedure you would call before anything else, e.g. 'init_io()')
DDRx = 0;
PORTx = 255;
Just change the little x for the letter of the port being used, e.g. D for PORTD
Serial Programming
This will be held in a separate page, with Microcontroller and PC code. Coming soon
Page Comments
Please visit the
Forum. Here you may find more information related to the page you are on, and you too can contribute.
Sign up now! It won't take a minute
Other Pages