From ProjectPages
Jump to: navigation, search

Installing and Using WinAVR


WinAVR™ (pronounced "whenever") is a suite of executable, open source software development tools for the Atmel AVR series of RISC microprocessors hosted on the Windows platform. It includes the GNU GCC compiler for C and C++.

First you need to download WinAVR™. In my case this was WinAVR-20100110-install.exe.

Step 1 - Choose your installation language and click 'OK'.
Step 2 - Click 'Next' to continue with the install.
Step 3 - Click 'I Agree' to accept the licence agreement.
Step 4 - The default destination for the files is the root of the C drive. So I just used that. Click 'Next'
Step 5 - I just left all the boxes ticked. Obviously, you want to install the files. You should add the filepath to the Windows PATH environment variable so that you can run the executables from any directory. Install programmers notepad unless you already have a favourite editor or IDE you want to use. Click 'Install'.
Step 6 - Now you will see the files being installed.
Step 7 - When the install has finished a browser will launch showing your local installation of the WinAVR User Manual.


Now we are going to check that things installed properly.

Go to Start->Run and type in 'cmd' and hit enter

Open a command window

The type 'path' and hit enter. You should see two entries added to the start of the path string, C:\WinAVR-20100110\bin;C:\WinAVR-20100110\utils\bin;.

The PATH environment variable

First, go to Start->All Programs and you should see a new entry like 'WinAVR-20100110'. It may be slightly different if there has been a release since this tutorial was written. Click on the entry and you should see something similar to the picture below:

Start menu entries

Guided Tour

AVR Insight

AVR Insight is a GUI (Graphical User Interface) to the GDB command-line debugger.

avr-libc Manual

A C manual for the particular variation of the C language used to program AVR Micros.

GNU Manuals Online

See GNU on WikiPedia


An automatic makefile generator for AVR GCC(GNU Compiler Collection). A makefile is a text file that lists and controls how something is made. It is most often used to control how software is made. We are going to use this.

Programmers Notepad

The Programmer's Notepad is a free IDE that can be used to write C programs (as well as other languages). We are going to use this also.

See my Programmer's Notepad tutorial

Uninstall WinAVR

Well, I hope you understand what this does!

WinAVR User Manual

Describes, in more detail, the packages that are included in the install. You should read this sometime!

First Project

The Code

Full Code

<syntaxhighlight line> /* Title: blinkled.c Author: Tony Norman Date Created: 30/10/2012 Last Modified: 30/10/2012 Purpose: This is a while loop that blinks an LED on PORTB PIN 5

  • /

//these are the include files. They are outside the project folder

  1. include <avr/io.h>
  2. include <util/delay.h>

int main (void) { //Set PB5 to output DDRB = 0x20; //create an infinite loop while(1) { //turns B5 HIGH - LED off PORTB |=(1<<5); //PAUSE 1 second _delay_ms(1000);

//turns B5 LOW - LED on PORTB &= ~(1 << 5); //PAUSE 1 second _delay_ms(1000); }

       return 0;

} </syntaxhighlight>


Let's go throught the code step by step. The #include lines tell the compiler it can use definitions and code from those files. The io.h file defines the names of the pins and registers for the particular device (e. g. PORTB and DDRB) The delay.h file gives us some standard delay routines (e. g. _delay_ms) based on the clock speed of the device (defined in the Make File). We don't have to write these, WinAVR makes them available to any project.

<syntaxhighlight line start=9> //these are the include files. They are outside the project folder

  1. include <avr/io.h>
  2. include <util/delay.h>


Main Routine

The highlighted lines define the main routine. The routine is called main and the curly brackets define the start and end of the routine. The int means the routine returns and integer. Academic in this case since the routine never exits, but we'll get to that in a minute. The (void) means that no parameters are passed to the routine. <syntaxhighlight line start=14 highlight=1,2,18> int main (void) { //Set PB5 to output DDRB = 0x20; //create an infinite loop while(1) { //turns B5 HIGH - LED off PORTB |=(1<<5); //PAUSE 1 second _delay_ms(1000);

//turns B5 LOW - LED on PORTB &= ~(1 << 5); //PAUSE 1 second _delay_ms(1000); }

       return 0;

} </syntaxhighlight>

Set Up

Now we start to run the code. The first thing to do is to set the Data Direction Register(DDR) for PORT B. We are going to use Pin 5 of PORT B. Now you need to get used to the fact that PIN numbers start from 0 and not 1. So Pin 5 is actually the sixth pin! DDRB = 0x20; means write the hexadecimal value 20 into the DDR for Port B. At power up, the chip sets its DDRs to zero, which means all the ports are set for input. We want our pin set to output so we can turn on the LED. Hexadecimal 20 is the same as the binary value 00100000. You count from the Least Significant Bit(LSB) and so you see the sixth bit is a 1. This sets the sixth pin of Port B(bit 5) to output. <syntaxhighlight line start=16 highlight=2> //Set PB5 to output DDRB = 0x20; </syntaxhighlight>

Switching The LED

We'll get to the loop part in a minute, first we are going to look at how we turn the LED on and off. First the turning off. Our LED is between Vcc and Pin 5, so Pin 5 must go low to turn it on. First the (1<<5). This means take the value 1, or 00000001 to make it easier, and shift it left 5 times. The result is 00100000.

We start with:

7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 1

Shift left 5 gives us:

7 6 5 4 3 2 1 0
0 0 1 0 0 0 0 0

Now |= means OR the right hand side of the expression with the left. So, we OR 00100000 with PORT B. This is a common technique. If you OR a bit with 0 the bit will remain unchanged (1 OR 0=1, 0 OR 0=0). So, if we OR PORT B with 00100000 it is the same as setting bit 5 to 1. Out LED will be turned OFF.

<syntaxhighlight line start=20 highlight=2> //turns B5 HIGH - LED off PORTB |=(1<<5); </syntaxhighlight>

In a similar way, (1<<5) evaluates to 00100000. However adding the tilde (~) means the complement, o inverse, of. So, 00100000 becomes 11011111.

Now, &= means AND the right hand side of the expression with the left. So we AND PORT B with 11011111. Another common technique.

If you AND a bit with 1 it will remain unchanged. If you AND a bit with 0 it will be set to 0 (1 AND 0=0, 0 AND 0=0). So, if we AND PORT B with 11011111, we will set bit 5 to 0 and leave the rest unchanged. Our LED will turn on!

<syntaxhighlight line start=25 highlight=2> //turns B5 LOW - LED on PORTB &= ~(1 << 5); </syntaxhighlight> So why are we so bothered about masking these bits so that we only change the one bit we are concerned about? Well, in this case, we aren't, but, if we had other functions using other pins on Port B, we'd be trampling all over whatever they'd been set to. So, if we do it right now, we won't have any funny bugs when we come to add other functions later.

The Delay

This bit is fairly straightforward. In our delay.h file that we included is a function called _delay_ms(1000). No surprises, it holds everything up for the number of milliseconds we put inside the brackets. So, in this case, 1000 milliseconds, or one second. <syntaxhighlight line start=22 highlight=2> //PAUSE 1 second _delay_ms(1000); </syntaxhighlight>

The Loop

As you can see the while loop encompasses the cycle of turning off and tuning on the LED. The while statement means while the thing in brackets is true, go round the loop. In this case, the thing in brackets is '1', and that is always true so this is a never-ending loop. That's why I said earlier that the return statement didn't really matter. It's because the program will never get to execute it. <syntaxhighlight line start=14 highlight=6,16> int main (void) { //Set PB5 to output DDRB = 0x20; //create an infinite loop while(1) { //turns B5 HIGH - LED off PORTB |=(1<<5); //PAUSE 1 second _delay_ms(1000);

//turns B5 LOW - LED on PORTB &= ~(1 << 5); //PAUSE 1 second _delay_ms(1000); }

       return 0;

} </syntaxhighlight> Hopefully, that's all clear. Although, you will just be able to copy the code into the editor in the next section and come back to this later if you want!

Programmer's Notepad

Making Folders

The 'Make' File