Instalando programas iniciales
La intención de este tutorial es mostrar mediante ejemplos simples, la operación del AVR-MT utilizando un microcontrolador ATtiny 2313. Se asume que el lector posee conocimientos básicos de C (sobretodo manipulación de bits).

Para comenzar a trabajar con un microcontrolador AVR utilizando el lenguaje de programación C, es necesario obtener un compilador de C para la arquitectura.
Si bien existen varios compiladores para avr, en este tutorial utilizaremos el compilador avr-gcc, el cual es compatible con ANSI C, genera código suficientemente bueno, posee la librería avr-libc y adicionalmente es software libre.
El compilador y ensamblador de C puede ser descargado de la página AVR Freaks, la cual está dedicada al desarrollo utilizando microcontroladores AVR. Se recomienda su visita ante cualquier duda o si se quiere profundizar más en el tema.
En el caso de que se trabaje en windows, existe un paquete llamado WinAVR que incluye el compilador (avr-gcc), un programador (avrdude) y un debugger (avr-gdb).
También se instalará el entorno de desarrollo AVR Studio, con el cual podremos crear proyectos en C o en assembler. Una ventaja de esta aplicación es que se puede programar y depurar si se dispone de un J-TAG, y adicionalmente simular el código (si es que no se posee un debugger).
Al momento de escribir estas notas, la versión actual de AVR Studio es la 4, y es recomendable instalar el service pack 4 (el más reciente), que soluciona varios bugs de la aplicación.
En el caso que se utilice un programador como el AVR-PG1B, será necesario instalar el programador PonyProg2000 o utilizar el programador avrdude.
Las consideraciones generales que se debe tener al programar un microcontrolador AVR, es que en la documentación cada vez que se refieran a que un bit está programado, quiere decir que ese bit es 0. Si el bit no está programado entonces vale 1. Si bien al comienzo cuesta asimilar lo anterior, es sólo cuestión de costumbre.
Una vez instaladas las aplicaciones que utilizaremos para programar, procedemos a crear un nuevo proyecto en AVR Studio. En la primera pantalla, se nos da la opción de que el proyecto utilice AVR GCC. Escogemos esta opción y a continuación damos un nombre al proyecto. Luego hacemos click en next.

En la siguiente pantalla, se nos ofrece la opción de escoger el programador/depurador a utilizar. En nuestro caso, estamos utilizando el programador AVR-PG1B, por lo que no tenemos un debugger. Es por esto que simularemos nuestros programas (en caso de necesitar depurar alguno de ellos), seleccionando la opción AVR Simulator. Es nuestro caso particular, estamos utilizando un ATtiny 2313, por lo que seleccionamos ese modelo en la ventana de configuración. Si usted se encuentra usando un microcontrolador distinto al citado, por favor elija el modelo de la lista a la hora de crear el proyecto.

Una vez creado el proyecto, se nos presenta la ventana principal del entorno. En el editor, lo primero que haremos, será incluir la cabecera avr/io.h. Realizando esto, nos aseguramos que el preprocesador se encargue de incluir el archivo correcto con las definiciones necesarias para trabajar con el microcontrolador seleccionado. En nuestro caso (y viendo el archivo io.h), se incluye indirectamente el archivo iotn2313.h. Es una buena práctica no incluir directamente el archivo correspondiente a nuestro microcontrolador, sino siempre incluir io.h. Si incluimos directamente la cabecera de nuestro microcontrolador, podríamos perder definiciones importantes realizadas en io.h.
#include<avr/io.h>
En caso de duda siempre es bueno mirar el archivo de definiciones correspondiente al microcontrolador que se esté usando. Sobretodo cuando se tiene la duda de si un registro o puerto está definido o cúal es su nombre.
Una vez incluido avr/io.h, escribimos nuestra función main, el punto de partida de cualquier programa en C. La intención de un primer programa en C es ver si todo está funcionando como debiese. Es por eso que para probar que las herramientas de compilación se escribirá el siguiente programa,
#include<avr/io.h> int main(void) { for(;;) { } }
Para compilar en AVR Studio, se presiona la tecla F7 (que no solo compila, sino que construye el proyecto completo). El mismo resultado se puede obtener desde el menú Build, seleccionando la opción Build. Vale notar que a esta altura, AVR Studio ha creado un Makefile para el proyecto y que las opciones de compilación que cambiemos a lo largo del desarrollo se verán reflejadas en él. En el caso de proyectos de este tipo es sumamente recomendable construir un Makefile (en el caso que no se trabaje con una herramienta que lo haga automáticamente), pues entre presionar la tecla F7 (o escribir make en un terminal), y escribir una línea de comando como (para nuestro proyecto que nada hace),
avr-gcc.exe -mmcu=attiny2313 -Wall -gdwarf-2 -Os -fsigned-char -MD -MP -MT Nada.o -MF dep/Nada.o.d -c ../Nada.c
avr-gcc.exe -mmcu=attiny2313 Nada.o -o Nada.elf
avr-objcopy -O ihex -R .eeprom Nada.elf Nada.hex
Es mucho más conveniente la primera opción. Si nos fijamos, el modelo del microcontrolador se pasa al compilador por medio de la línea de comandos, así como también el nivel de optimización. El nivel de optimización es un ajuste que dependerá de la aplicación en desarrollo, pero en general se utiliza 0s, que minimiza el tamaño del código (que es casi siempre el recurso más escaso).
WinAVR incluye en su distribución la utilidad make, por lo que los usuarios de windows no deberían tener problemas
Recomendaciones
Una buena práctica es utilizar la optimización -Os ofrecida por avr-gcc, pues se logra una notoria disminución en el tamaño del código. Por el contrario, utilizar optimizaciones que reduzcan el tiempo de ejecución no se recomiendan, pues en muchos casos pueden expandir el código de los ciclos lo que trae una pérdida de espacio en la memoria de programa. Cuando se programa en microcontroladores en general demorar unos cuantos ciclos más de reloj no es un problema, pero sí lo es que el tamaño del programa sea extenso pues en la mayoría de los casos es ese el recurso limitado (por ejemplo el microcontrolador ATtiny 2313 tiene solamente 2KB de memoria).

Otro punto importante y relativo a las optimizaciones es que expresiones del tipo
a = 0; a = 1;
Muchas veces son reeemplazadas por la última de ellas, debido a que el compilador desestima la primera. Pero en general en el mundo de los microcontroladores una expresión de ese tipo puede tener algún sentido (también en un programa con varios hilos de ejecución). Se debe entonces tener especial cuidado de utilizar volatile en la declaración de variables sensibles a las optimizaciones (por ejemplo en alguna variable utilizada para leer desde un registro en una rutina de atención de interrupciones).
volatile unsigned char a;
Vale la pena mencionar que para configurar los pines de los puertos, existen los registros DDRx, donde x es la letra del puerto. Si un bit del registro DDRx es 1, quiere decir que el pin correspondiente a ese número de bit será considerado como una salida. Si el bit es 0, entonces se considera que el pin asociado es una entrada. Por ejemplo, si quisiéramos dejar como entrada al pin 5 de PORTB y como salida al pin 2, el código sería
//pin5esentrada DDRB &= ~(1 << 5); //pin2essalida DDRB |= (1 << 2);
También se debe tener en cuenta que la lectura de los pines de los puertos se realiza a través de los registros PINx, donde x es la letra del puerto. Además, si asignamos un valor a un pin en PORTx y luego lo leemos desde PINx, se debe esperar un ciclo para que PINx se sincronice, por ejemplo,
unsigned char val; PORTB = (1 << 3 | 1 << 5); //Esperamosuncicloparasincronización asm volatile("nop"); //Leemoslospines val = PINB;