Archivo del sitio

Programación de microcontroladores de la familia AVR en GNU/Linux (Debian/Ubuntu) Parte II

Nivel: Básico

¿Qué tengo que saber para este post?

—————————————

Como les prometí, en esta segunda parte les mostraré cómo hacer un primer programa. Voy a arrancar con el que tiene menos vueltas.

Programando con Code::Blocks

La interfaz

Bueno, teniendo todo instalado, lo único que necesitamos hacer es ejecutar el Code::Blocks, sí es la primera vez que lo utilizamos, aparecerá una venta notificando los compiladores que detectó automaticamente y el AVR GCC debe estar en esa lista como detectado.

Compiladores detectados

Compiladores detectados

Luego entramos a la pantalla principal, donde tendremos nuestra área de administración de proyectos a la izquierda, el editor a la derecha (ocupando la mayor parte del espacio), abajo el área de mensajes y las barras de tareas arriba (que son muchas, si lo pueden notar…).

Interfaz Code::Blocks

Interfaz Code::Blocks

Creando un proyecto nuevo

Para crear un proyecto nuevo, debemos hacer click en la carpeta azul que tenemos al centro de la pantalla y dice “Create a new project” (elemental, mi querdio Watson). Y en la ventana emergente debemos seleccionar “AVR project” y hacer clic en “Go”.

AVR Project

AVR Project

Ahora nos saltará la ventana emergente del wizard para hacer un proyecto, la primer ventana es siempre la que explica que nos va a guiar para generar un nuevo proyecto, yo siempre la tildo para que no aparezca la próxima vez e ir directamente a la selección de una carpeta para nuestro proyecto. Cuando decidamos un path, recuerden que por cada proyecto se genera una carpeta, es decir, conviene tener una carpeta llamada “~/proyectos” o “~/proyectos avr” y utilizar siempre ese mismo path. Porque cuando pongamos un nombre al proyecto, por ejemplo “ejemplo1” se creará una carpeta llamada “~/proyecto/ejemplo1/” donde estarán todos los archivos relacionados a nuestro proyecto. Si no entendieron, vean la imagen, que dice más que mil palabras:

Skip

Skip

ejemplo1

ejemplo1

Algo que es importante es que el nombre de su proyecto no puede contener espacios, porque al momento de compilar no funciona, así que si tienen ganas de poner espacios utilicen el guión bajo. Y recuerden de poner el path completo, yo puse “~/”, pero deberían poner “/home/usuario/”.

La siguiente ventana nos pregunta los “targets” a compilar. Yo nunca use, y nunca encontré la necesidad de compilar, la configuración de “Debug” y sólo tildo la de “Release”, pero si la quieren dejar, no hay problema. Pero tengan en cuenta que la que deben grabar en el micro es la versión “Release”, sino las cosas no van a funcionar del todo bien (sobre todo los delays). Y por último, la selección del micro que van a utilizar, el cristal y otras opciones. En general, salvo que ustedes deseen hacer algo especifico, pueden solamente seleccionar el micro y velocidad del oscilador. Yo voy a elegir el ATmega328P y como lo voy a usar con el oscilador interno que viene de fábrica fijado en 1Mhz, el valor de frecuencia de oscilador que voy a poner es “1000000UL”. Y para finalizar, hacer clic en el botón de “Finish”.

Target select

Target select

Chip select

Chip select

Escribiendo el programa

El Code::Blocks nos incluye dos archivos a nuestro proyecto, el “main.c” y el fuse.c. Ambos son templates, que tienen lo básico de cualquier programa, el header (cabecera necesaria) que agrega los registros necesarios para utilizar el micro seleccionado. El “fuse.c” tiene la configuración por defecto de los fuses del micro que estemos utilizando, para mi ejemplo, los voy a dejar como vienen. En caso de que este archivo no fuera generado automáticamente, les recomiendo que lo creen. Van a “File->New->File…” y eligen archivo “C/C++ source” y siguen los pasos para crear el archivo “fuse.c”, que por defecto contiene esto:

#include <avr/io.h>

FUSES = {
    .low = LFUSE_DEFAULT,
    .high = HFUSE_DEFAULT,
    .extended = EFUSE_DEFAULT
};

Como pueden ver, tiene todos los parámetros de fábrica. Oscilador interno de 8Mhz con un divisor por 8 (en el caso del ATmega328p, es decir 1Mhz de frecuencia de CPU (1000000UL). Esto es un define, que se utiliza, sobre todo, para la librería que nos provee los delays (“util/delay.h”). Si quieren saber sobre los defines para modificar los fuses, busquen acá, está en inglés pero bueno, tampoco es tan imposible de entender.

El template del “main.c” es muy básico:

/*
 */

#include <avr/io.h>

int main(void)
{

    // Insert code

    while(1)
    ;

    return 0;
}

Noten que, a pesar de que no hay un sistema operativo (supongo que es por alguna cuestión del gcc), la función main retorna un valor. Esto no tiene ningún sentido en la programación de microcontroladores, pero si no lo ponemos el gcc nos dará un warning. Y tampoco influye en mucho. Recuerden que todo programa con micros debe tener un loop infinito, para frenar al PC (o IP), y el dispositivo no tenga un comportamiento errático. Escribamos un código simple donde hagamos titilar un led, es decir cambiar el estado de algún pin de un puerto. Para ello, debemos conocer un poco de la familia AVR. En algún momento haré algún post sobre eso, pero ahora voy a asumir que tienen algún conocimiento básico y simplemente escribir el código. Noten que a la izquierda tienen  los archivos que pertenecen a su proyecto.

/*
 * Ejemplo1 AVR en GNU/Linux
 */

#include <avr/io.h>
#include <util/delay.h>

/*
    Inicialización del dispositivo:
*/
void InitDevice(void)
{
    DDRB=0x01;  // Declaro el PIN0 del PORTB como Salida
}

int main(void)
{
    // Inicializo el dispositivo
    InitDevice();

    // Bucle infinito
    while(1)
    {
        PORTB^=0x01;    // Alterno el valor del PIN0 del PORTB con una XOR
        _delay_ms(500); // Hago una demora de medio segundo
    }

    return 0;
}

Una vez que tenemos nuestro código, lo que resta es compilarlo, que lo haremos con el icono de la tuerca dorada que está en la barra de “compilación” y dice “Build”:

Compilando

Compilando

Si les salta el siguiente error de “/usr/include/features.h 323 fatal error: bits/predefs.h: No existe el fichero o el directorio”, no se asusten, es que hubo un pequeño cambio en Debian y es fácil de solucionar. Tienen que ir a “Settings->Compiler…”, allí seleccionar “GNU AVR GCC Compiler” e ir a la solapa que dice “Search directories” y más abajo a la solapa “Compiler” y borrar el ítem “/usr/include” haciendo clic y luego en el botón “Delete”. Lugo ir a la solapa que está al lado, la que dice “Linker” y borrar de la misma manera la que dice “/usr/lib” y confirmen las dos veces:

Corregir editando opciones del compilador

Corregir editando opciones del compilador

Borrar /usr/include

Borrar /usr/include

Borrar /usr/lib

Borrar /usr/lib

Clicqueamos Le damos clic al botón “Aceptar” más abajo y listo. Intentamos compilar de nuevo y si tuvimos éxito, debería verse algo así:

Éxito al compilar =)

Éxito al compilar =)

Simulación y debugging ( no hay… =( )

Ahora, debemos abarcar una pequeña cuestión, que desde mi punto de vista, es crucial. No encontré, ni encuentro aún, una herramienta que funcione bien y sea amigable para simular los microcontroladores de la familia AVR que sea GPL y/o gratuita. Así que, debemos volver a la edad de piedra, donde teníamos que grabar el firmware y verificar si todo funciona según lo planeado y crear diferentes estrategias, como prender un led cuando pasó por cierto punto del programa. Para eso diseñé una placa de desarrollo, pero sólo para micros de 28 pines de la familia AVR. Claro que pueden probarlo sobre un protoboard también, no hay que hacer tanto escándalo para prender un led.

Grabando el firmware al microcontrolador

Llego el momento de la verdad, como el Code::Blocks, a diferencia del plug-in del eclipse, no tiene un botón que invoque al avrdude, ni una configuración gráfica para éste, debemos hacerlo a mano. Hay dando vueltas por ahí algunas interfaces gráficas para el avrdude, pero ninguna que me convenza realmente, ni tan cómoda de instalar en GNU/Linux. Por eso iremos a configurar nuestra herramienta personalizada, para subir el firmware al microcontrolador. Yo les voy a dejar dos configuraciones muy simples (una con el dasa y la otro con el USBasp), que graban el firmware y los fuses high y low del micro, y evité a proposito el de lock y el extendido. El extendido porque no todos lo tienen y el de lock para evitar que dejen su micro inservible, porque asumo que recién están empezando con estos micros (como yo).

Vayamos al menú “Tools->Configure tools…” y le hacemos clic en “Add”. En mi caso le puse el nombre “Update w/dasa” y “Update w/USBasp” para diferenciar el programador que estoy utilizando. pero básicamente es igual, es copiar y pegar los códigos que aparecen abajo de los screenshots:

Añadir el llamado al avrdude

Añadir el llamado al avrdude

Llenamos los campos con los comandos que aparecen abajo

Llenamos los campos con los comandos que aparecen abajo

Para el programador dasa:

Update w/dasa
/usr/bin/avrdude
-c dasa -P /dev/ttyS0 -p $(MCU) -u -U flash:w:${TARGET_OUTPUT_BASENAME}.hex -U eeprom:w:${TARGET_OUTPUT_BASENAME}.eep -U lfuse:w:${TARGET_OUTPUT_BASENAME}.lfs -U hfuse:w:${TARGET_OUTPUT_BASENAME}.hfs
${PROJECT_DIR}/${TARGET_OUTPUT_DIR}

Para el programador USBasp:

Update w/USBasp
/usr/bin/avrdude
-c usbasp -P usb -p $(MCU) -u -U flash:w:${TARGET_OUTPUT_BASENAME}.hex -U eeprom:w:${TARGET_OUTPUT_BASENAME}.eep -U lfuse:w:${TARGET_OUTPUT_BASENAME}.lfs -U hfuse:w:${TARGET_OUTPUT_BASENAME}.hfs
${PROJECT_DIR}/${TARGET_OUTPUT_DIR}
Debería quedar así

Debería quedar así

Por último, llamamos al comando desde el menú “Tools->Update w/dasa” o el programador que tengan y grabamos el firmware al microcontrolador. Si todo salió bien deberíamos tener un retorno exitoso :).

Tools->Update w/dasa

Tools->Update w/dasa

¡Éxito! =)

¡Éxito! =)

Si quieren saber más sobre los parámetros que puede recibir el avrdude, hay muchos tutoriales dando vueltas por ahí. Recuerden que también pueden hacer desde una terminal:

man avrdude

Y así ver toda la documentación disponible y mucho más. Bueno, ya está todo configurado como para arrancar a programar y probar cosas. Y les dejo un vídeo del programa funcionando, de pésima calidad, tomado con la webcam (perdón, me da vergüenza mostrarlo), para que vean que sí funciona todo. Utilicé mi placa de desarrollo y el módulo de E/S, que consta de 8 leds y 8 pulsadores. Luego subiré ese diseño y los otros módulos también.

Cualquier duda que surja, o consejo que me quieran dar, será bienvenido. En el próximo post les mostraré como configurar y usar el plug-in de eclipse, para que elijan cual es su mejor opción. Saludos y hasta la próxima.