Up: Hands On AVR-GCC programming


Blink, A Hello World to AVRLIB

NOTE: Following code is for Wiring but it can be translated to /ardu with few changes.

Once you have all requirements for working with AVRLIB and AVR-GCC you should create a Wiring working directory on your home directory. On Linux and OS-X you can do this by typing on the command line on a terminal window:


 		 [host]  cd $HOME        
and then,


 		 [host] mkdir wiring        
Go to that directory and create another subdirectory called 'blink'.


 		 [host] cd wiring        
and then,


 		 [host] mkdir blink        
Go inside the 'blink' directory:


 		 [host] cd blink        

From now on, all work should be done in the blink directory. Use Emacs, Vi or your favorite editor to copy-and-paste contents of makefile.blink and global.h.blink, each them on a separate file. Save them separately as 'makefile' and 'global.h'. Your 'blink' directory should now contain these files.

Again, using Emacs, Vi or your favorite editor copy-and-paste the following code into a file and save it as 'blink.c'.


 		 
 
//------------------------------------------------------
//------------------------------------------------------
//   
//  AVRLIB-DEMO
//  For avrlib and Wiring development board.
//  
//
//  File:     blink.c
//  Author:   Juan Reyes    juanig-at-ccrma-stanford_edu
//  Date:     June 18, 2008
//
//  Notes:
//-----------------------------------------------------
//  USING THE WIRING DEVELOPMENT BOARD, BUILT-IN LED
//  IN PIN 48 PORT D SHOULD LIGHT.
//
//-----------------------------------------------------
//  More information about Wiring board:
//
//  http://wiring.org.co/hardware/index.html
//  
//-----------------------------------------------------
//  Information about functions used here and avrlib:
// 
//  ~/avrlib/examples/basic_io/basiciotest.c
//  
//  
//
//*********************************************************
//   Description:
//   ============
//
//   This program will cause Built-in LED to blink on/off 
//   every 500ms.
//
//*********************************************************


//compiler includes
#include <avr/io.h>
#include <avr/interrupt.h>

//avrlib includes
#include "global.h"
#include "timer.h"


int main(void)
{

	//  outb(register,byte) is a function that writes 
        //  a byte to a register.


        //  The DDRG register sets the direction of Port G.
        //  PORTG is labeled PORT6 on the Wiring Board.
  
	// a '1' makes the corresponding pin an OUTPUT.
        // a '0' makes the corresponding pin an INPUT.
	// Ports can only be set as INPUT or OUTPUT (0x00, 0xff).

        // 0xFF is hexadecimal for binary 11111111.
        // Therefore using ´outb'. all pins of PORTG 
        // are set to OUTPUT as follows:
        //
        outb(DDRG, 0xFF);
	//
	

        // Gnome calculator in Fedora can do bin-to-hex conversion.
    
        // The PORTG register can set the physical pins on port G high
        // or low when those pins are set to be outputs using DDRG. 
        // When pins are set to input, the PORTG register does something
        // else that will be discussed later.
        
        // To turn off the LEDs we want to pull the end connected to 
        // port A high (to 5V) so that there will be no voltage drop across
        // the LEDs. See the schematic.
        // So we "set" the low 4 bits HIGH (to 5V) of PORTG by writing 1's.
	// Remember 0xF0 is hexadecimal for binary 11110000
	
        outb(PORTG, 0xF0);
	

	// initialize the timer library
	timerInit();

	//loop forever
	while (1) {
	  //clear bit PG0 in the PORTG register - turn LED on
	  cbi(PORTG,PG0);
	  //PORTG = 0xFF;
          // pause for 500ms
	  timerPause(500);

	  //set bit PG0 in the PORTG register - turn LED off
	  sbi(PORTG,PG0);
	  // PORTG = 0x00;
          //pause for 500ms
	  timerPause(500);
	} 

	return 0;
}

You should now have the files 'makefile', 'global.h' and 'blink.c' in your 'blink' directory. You can make sure about this by issuing the 'ls' command on the terminal window:


 		 [host] ls -l        

Make sure you read and understand this code on 'blink.c'. Several points should be make here:

  1. This program causes Wiring built-in LED to blink on/off.

  2. A timer functions allows to blink every 500ms.

  3. Built-in LED is on Wiring 'pin-48'. By looking at the table in (§[*]) we can see that 'pin-48' is 'pin-0' of 'PORTG'.

  4. The function 'outb(DDRG, 0xFF)' sets PORTG as OUTPUT, and is equivalent to the portMode() function on the Wiring IDE.

  5. The function outb(PORTG, 0xF0) sets the low 4 bits HIGH of PORTG, thus the low pins of PORTG have 5 Volts. 'cbi(PORTG,PG0)', clears the bit on PORTG pin-0 to turn LED on. 'sbi(PORTG,PG0)' sets bit to turn LED off. 'sbi()' and 'cbi()' functions can be thought of like digitalWrite() function on Wiring .

  6. The line timerPause(500) from the timer library causes a delay of 500ms before the next blink.

Further information about this functions can be seen in the file: 'avrlib/examples/basic_io/basiciotest.c'. Also on the CCRMA's PID wiki: Anatomy of a C program for AVR.

To compile the 'blink.c' program, make sure you have AVR-GCC and all the AVR-tools install on your computer(see §2). Once ready and on the blink directory type:


 		 [host] make        
You should get output from AVR-GCC , and at the end if everything went fine:


 		 
 

avr-size blink.elf
   text    data     bss     dec     hex filename
   2094       0      28    2122     84a blink.elf
Errors: none
avr-objdump -S blink.elf > blink.ss 
rm /home/juanig/avrlib/timer.o

If you are not satisfied with a compilation or if you edit the '.c' file you can do a:


 		 [host] make clean       

After the compiler has generated a '.hex' file, it must be loaded onto the micro controller. There are a variety of ways of doing this, using different programming hardware and/or protocols for transmitting the data. In this case we are going to use again our 'makefile' also in theblink directory.

Connect a USB cord to the board and the other end to a USB port on your computer. Make sure the board gets powered and that it has communication through FTDI. On Fedora systems communication port device should be somenthing like: '/dev/ttyUSB0'. If it is not you might have to edit your 'makefile' on the 'UISP_PORT=/dev/ttyUSB0' line or on the 'AVRDUDE_PORT = /dev/ttyUSB0' line. If all is working! just press the '<reset>' button on the Wiring board, wait for three(3) seconds and on the command line type:


 		 [host] make load       

On this 'makefile', we are using UISP to load the '.hex' int the ATMega128. If communication is right you should see some progress output on the terminal window:


 		 
 
Firmware Version: 1.15
Atmel AVR ATmega128 is found.
Firmware Version: 1.15
Uploading: flash
##################################################################
(total 2094 bytes transferred in 0.61 s (3447 bytes/s)

Press the '<reset>' button again and wait for two(2) or three(3) seconds. The internal LED should blink now.

It is advisable to make changes to the 'blink.c' file, for instance change duration of blink or wait. If you do so, don't forget to recompile again: do a 'make clean', a 'make' and when you are ready to load again '<reset>' button and 'make load'. After the loading process is complete don't forget to press the '<reset>' button again. Read 'blink.c' to understand more about variables and hexadecimal values.


next up previous
Next: LEDs Traffic Light Up: Hands On AVR-GCC programming Previous: A note on DownloadersUploaDErs

© Copyright 2001-2008 CCRMA, Stanford University. All rights reserved.
Created and Mantained by Juan Reyes