Tuesday, May 20, 2008

First step into EMBEDDED world....Blinking a LED using ATMEGA8



We are on the game...
The above circuit diagram represents the burning circuit for Atmega8.As you see there is a LED at pin 15 in the programmer schematic.This circuit is only used for testing the programmer(here the programmer software is uisp.But we can use any programmer software that supports DAPA-'Direct AVR Parallel Access) with the following simple program-avrledtest.c

As soon as you've connected your programmer to the parallel port and switched on power, you can test the hardware with:

# uisp -dprog=dapa
Atmel AVR ATmega8 is found.


avrledtest.c

#include

void delay_ms(unsigned short ms)
/* delay for a minimum of */
/* with a 4Mhz crystal, the resolution is 1 ms */
{
unsigned short outer1, outer2;
outer1 = 200;

while (outer1) {
outer2 = 1000;
while (outer2) {
while ( ms ) ms--;
outer2--;
}
outer1--;
}
}

int main(void)
{
/* enable PB0 as output */
PORTB=0xff;
sbi(DDRB,PB0);
while (1) {
/* led on, pin=0 */
cbi(PORTB,PB0);
delay_ms(500);
/* set output to 5V, LED off */
sbi(PORTB,PB0);
delay_ms(500);
}
return 0;
}

The above program switch the LED between on and off state with the help of a delay function.Some registers and built in functions are used in the program that are strangers to a beginner.A brief idea is given below:



The DDRx Register

The DDRD register sets the direction of Port D. Each bit of the DDRD register sets the corresponding Port D pin to be either an input or an output. A 1 makes the corresponding pin an output, and a 0 makes the corresponding pin an input. To set the first pin of Port D to be an output pin, you could use the sbi(reg,bit) function, which sets a bit (makes it high or binary 1) in a register:

sbi(DDRD, 0); //these two statements are equivalent
sbi(DDRD, PD0); //both set the first pin of port D to be an input
//by setting the 0 bit of the DDRD register.

To set the second pin to be an input, you could use the cbi(reg,bit) function which clears a bit (makes it low or binary 0) in a register:

cbi(DDRD, 1); //these two statements are equivalent
cbi(DDRD, PD1); //both set the second pin of port D to be an output
//by setting the 1 bit of the DDRD register.

You can also set the value of all the bits in the DDRx register (or any register) using the outb(reg,byte) command. It writes a byte (8 bits) to a register. For example, if you wanted to set pins 1-4 of port B to output and pins 5-8 to input, you could use:

outb(DDRB, 0x0F); //Set the low 4 pins of Port B to output
//and the high 4 pins to input

An alternate way to write a value to a register is using the same syntax as a C assignment:

DDRB = 0x0F; //Set the low 4 pins of Port B to output
//and the high 4 pins to input


The PORTx Register


The PORTx register functions differently depending on whether a pin is set to input or output. The simpler case is if a pin is set to output. Then, the PORTC register, for example, controls the value at the physical IO pins on Port C. For example, we can set all the port C pins to output and then make 4 of them high (binary 1) and 4 of them low (binary 0):

DDRC = 0xFF; //Set all Port C pins to output
PORTC = 0xF0; //Set first 4 pins of Port C low and next 4 pins high

When a pin is set to be an input, PORTx register DOES NOT contain the logic values applied to the pins. We use the PINx register for that. If a pin is an ouput, a 1 in the PORTx register sets a pull-up resistor. This is helpful for a variety of circuits.

DDRC = 0x00; //Set all Port C pins to input
PORTC = 0xFF; //Set pull-up resistors on Port C



The PINx Register

When a pin is set to input, the PINx register contains the value applied to the pin. The pins have an electrical threshold of around 2.5 volts. If a voltage above this level is applied to an input pin, the corresponding bit of the PINx register will be a 1. Below this voltage, the bit will be a zero.To read the value of an input port, you can use the inb(reg) function or a direct assignment. It returns an 8-bit number that is the value of the 8 bits in the specified register.

u08 foo; // declare an 8-bit variable

DDRD = 0x00; // set port D pins to input
PORTD = 0xFF; // set pull-ups on port D

foo = PIND; // read the value of the port D pins
// and store in the variable foo



Compilation can be done using avr-gcc by creating a makefile as follows:

MCU=atmega8
CC=avr-gcc
OBJCOPY=avr-objcopy
# optimize for size:
CFLAGS=-g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues

all: avrledtest.hex
avrledtest.hex : a.out
$(OBJCOPY) -R .eeprom -O ihex a.out avrledtest.hex
a.out : avrledtest.o
$(CC) $(CFLAGS) -o a.out -Wl,-Map,avrledtest.map avrledtest.o
avrledtest.o : avrledtest.c
$(CC) $(CFLAGS) -Os -c avrledtest.c

# erase the AVR before it is programmed
load: avrledtest.hex
uisp -dlpt=/dev/parport0 --erase -dprog=dapa
uisp -dlpt=/dev/parport0 --upload if=avrledtest.hex -dprog=dapa -v=3 --hash=32

clean:
rm -f *.o *.map *.out

Store this makefile in your current working directory using a vim or emac editor.Issue "make" to compile the program and "make load" to program the microcontroller with uisp.When you give the "make" command,"make" will search for file named makefile in the current directory and execute the commands in the file."make" command is highly specific about indentation.So,be sure that you give the separators and indentations as given above(do copy-paste). Any change in any part will lead to error messages while compiling.

As soon as the programming cycle is finished,LED starts to flash...
HURRAY!!!We have successfully entered to our dream world of embedded system....

No comments: