Tutorial de CodeVision AVR

El Compilador CodeVisionAVR

CodeVisionAVR es un compilador desarrollado por Pavel Haiduc para los AVR de 8 bits, desde los ATtiny hasta los Xmega. Su principal ventaja es que provee librerías integradas para controlar sus recursos internos y también dispositivos externos como LCDs, GLCDs, RTCs, sensores de temperatura, etc. En este sentido se le podría comparar con los compiladores C de CCS o Mikroe para los PICmicro. Como lo comprobaremos enseguida, CodeVision es el compilador C para los AVR más fácil de usar, sin embargo, no llega a igualar la eficacia de los compiladores IAR AVR o AVR GCC. También podremos comprobar algo de esta diferencia en la siguiente práctica.

La versión de evaluación de CodeVisionAVR permite usarlo en casi toda su funcionalidad para fines no comerciales. Tiene ciertas limitaciones con algunas de sus librerías (casi ni se nota) y no compila programas que superen los 4 kbytes de código ejecutable. Para la presente práctica nos bastará esta versión, así que la puedes descargar desde www.hpinfotech.ro/html/download.htm o haciendo clic aquí. Si al final te convences de su performance puedes descargar la versión comercial y tendrás que comprar la clave de activación.

Instalación de CodeVisionAVR

Su instalación no requiere ninguna salvedad. Es el clásico procedimiento de Next, Next,…

Instalación de CodeVisionAVR.

Instalación de CodeVisionAVR.

Entorno de desarrollo IDE de CodeVisionAVR.

Creación de un Proyecto

Al iniciar CodeVisionAVR por primera vez nos aparece un ide como el de la siguiente figura.

Entorno de desarrollo IDE de CodeVisionAVR.

Entorno de desarrollo IDE de CodeVisionAVR.

Muchos de los paneles mostrados pueden ser útiles para los principiantes. Nosotros las cerramos luego. De momento las dejaremos como están y empezaremos sin más por crear nuestro proyecto.

Vamos al menú File > New y escogemos la opción Project.

CodeVision

Luego nos surge una ventanita si queremos usar el asistente de creación de proyectos CodeWizardAVR. Personalmente me aburre usar este asistente, aunque al inicio a todos nos intriga saber qué cosas nos ofrece. Así que esta vez lo tomaremos haciendo clic en Yes. Luego podrás recorrer por tu cuenta el camino al que lleva la opción No.

CodeVision

Naturalmente tomamos la opción de los ATmega.

CodeVision

A continuación nos aparece la ventana donde podemos configurar los recursos del microcontrolador. Empezamos por la pestaña Chip para seleccionar el AVR y establecer su frecuencia de operación en Clock, tal como se indica en la siguiente figura.

CodeVision

La opción Crystal Oscillator Divider generará el código para que el prescaler del reloj del sistema lo divida entre alguno de los valores allí indicados (desde 1 hasta 256). Por ahora no nos interesa porque de todos modos borraremos dicho código, ya que nosotros configuramos ese prescaler con el fuse CKDIV8.
Si está activada la opción Check Reset source el asistente generará el código que comprueba el origen de cada reset del AVR. De momento tampoco nos interesa esto.

La opción Program Type debe quedar en Application, a menos que estemos desarrollando un programa con Boot Loader.

Ahora pasamos a la pestaña USART0 ya que vamos a utilizar el puerto serie. Allí activamos las casillas para habilitar los módulos del Transmisor y Receptor porque los mensajes serán de ida y vuelta. No utilizaremos las interrupciones del USART. Las demás opciones las dejamos con su valor por defecto, como ve en la siguiente figura. Si deseas saber lo que significan estos parámetros puedes revisar el estándar RS232.

CodeVision

El USART es el único periférico de comunicación que utilizaremos en esta práctica, así que ya podemos terminar con esta etapa y presionamos el botón Generate program, save and exit, como se indica abajo.

CodeVision

Enseguida se nos presentan tres ventanas para nombrar los archivos del proyecto. Al archivo de código fuente principal yo siempre le llamo main.c. Previamente debemos ubicar una carpeta para estos archivos.

CodeVision

Los otros archivos corresponden al proyecto y al asistente que estamos usando. Este proyecto se llama ledflasher3 así que le puse ese nombre a ambos archivos (no tiene que ser iguales).

CodeVision

CodeVision

Por fin llegamos a entorno para editar el código en el editor que apenas se vislumbra. Por eso vamos a cerrar los paneles indicados en la siguiente figura. Si luego te interesa utilizarlos, podrás encontrarlos en el menú View.

CodeVision

Ahora tenemos al frente al editor mostrándonos el código que generó el asistente. La mayor parte es “código basura” con inicialización redundante de los periféricos del AVR. Lo único que vamos a rescatar de este código es elfragmento que configura el USART0, que se muestra abajo, y para que el programa luzca lo más parecido posible al código original escrito para IAR C o AVR GCC lo empaquetaremos en una función llamada usart_init.

CodeVision

Después de realizar lo descrito y de borrar el resto del contenido debemos completar nuestro código que como dije anteriormente corresponde a la práctica ledflasher3 y cuyo listado para CodeVisionAVR se muestra a continuación.

/******************************************************************************
 * FileName:   main.c
 * Purpose:    LED Flasher 3. Secuenciador de 3 efectos seleccionables vía USART
 * Processor:  ATmega164P
 * Compiler:   CodeVision AVR
 * Author:     Shawn Johnson. http://www.cursomicros.com.
 *             Basado en el led flasher 2 de Seiichi Inoue localizado en
 *             http://hobby_elec.piclist.com/index.htm.
 *
 * Copyright (C) 2008 - 2012 Shawn Johnson. All rights reserved.
 *
 * License:    Se permiten el uso y la redistribución de este código con 
 *             modificaciones o sin ellas, siempre que se mantengan esta 
 *             licencia y la nota de autor de arriba.
 *****************************************************************************/

#include <io.h>.
#include <stdio.h>
#include <delay.h>

#define  kbhit()     (UCSR0A & (1<<RXC0))

void usart_init(void);

/******************************************************************************
 Patrón que contiene el patrón de efecto del secuencial
    led1    111111111111111111111111111111...    Prendido 6 de 6 partes
    led2    100100100100100100100100100100...    Prendido 2 de 6 partes
    led3    100000100000100000100000100000...    Prendido 1 de 6 partes
 - Cada bloque tiene 6 items
 - Cada bloque se repite 100 veces
 - Hay una pausa de 150 µs entre los ítems
 - Hay 12/11 bloques en total
 -> Cada barrido dura  6 * 100 * 150 * 12 = 1.08 segundos aprox.
******************************************************************************/

__flash char Pattern[] =
{
    // Efecto 1. 12 bloques de 6 items
    0x81,0x81,0x81,0x81,0x81,0x81, 0xc3,0x42,0x42,0xc3,0x42,0x42,
    0xe7,0x24,0x24,0x66,0x24,0x24, 0x7e,0x18,0x18,0x3c,0x18,0x18,
    0x3c,0x18,0x18,0x18,0x18,0x18, 0x18,0x18,0x18,0x18,0x18,0x18,
    0x3c,0x24,0x24,0x3c,0x24,0x24, 0x7e,0x42,0x42,0x66,0x42,0x42,
    0xe7,0x81,0x81,0xc3,0x81,0x81, 0xc3,0x00,0x00,0x81,0x00,0x00,
    0x81,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,
    // Efecto 2. 11 bloques de 6 items
    0x80,0x80,0x80,0x80,0x80,0x80, 0xc0,0x40,0x40,0xc0,0x40,0x40,
    0xe0,0x20,0x20,0x60,0x20,0x20, 0x70,0x10,0x10,0x30,0x10,0x10,
    0x38,0x08,0x08,0x18,0x08,0x08, 0x1c,0x04,0x04,0x0c,0x04,0x04,
    0x0e,0x02,0x02,0x06,0x02,0x02, 0x07,0x01,0x01,0x03,0x01,0x01,
    0x03,0x00,0x00,0x01,0x00,0x00, 0x01,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,
    // Efecto 3. 11 bloques de 6 items
    0x01,0x01,0x01,0x01,0x01,0x01, 0x03,0x02,0x02,0x03,0x02,0x02,
    0x07,0x04,0x04,0x06,0x04,0x04, 0x0e,0x08,0x08,0x0c,0x08,0x08,
    0x1c,0x10,0x10,0x18,0x10,0x10, 0x38,0x20,0x20,0x30,0x20,0x20,    
    0x70,0x40,0x40,0x30,0x40,0x40, 0xe0,0x80,0x80,0xc0,0x80,0x80,
    0xc0,0x00,0x00,0x80,0x00,0x00, 0x80,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00
};

/*****************************************************************************
 * Main function
 ****************************************************************************/
void main(void)
{
    unsigned int i, j, k, b, bi, ba;
    char c, Effect;
    
    DDRB = 0xFF;                    // Setup PORTB for output
    
    usart_init();                   // Initialize USART @ 9600 N 1

    puts("\n\r Escoja un efecto  ");
    puts("\n\r (1) Barrido simétrico");
    puts("\n\r (2) Barrido a la derecha");
    puts("\n\r (3) Barrido a la izquierda");

    Effect = '1';        // Por defecto iniciar con efecto 1

    while(1)
    {    
        start:
        /* Establecer parámetros de barrido del efecto actual */
        switch(Effect)
        {
            case '1': ba = 0; b=12; break;
            case '2': ba = 6*12; b=11; break;
            case '3': ba = 6*(12+11); b=11; break;
        }                    

        /* Iniciar barrido del efecto actual */
        for(i=0; i<b; i++)              // Para barrer b bloques
        {
            for(j=0; j<100; j++)        // Cada bloque se repite 100 veces
            {
                bi = ba + 6*i;
                for(k=0; k<6; k++)      // Cada bloque tiene 6 items
                {
                    PORTB = Pattern[bi+k];
                    //PORTB = pgm_read_byte(&(Pattern[bi+k]));  
                    
                     /* Este bloque sondea el puerto serie esperando recibir una
                     * opción válida para cambiar de efecto  
                     */
                    if(kbhit())                   // Si hay datos en el USART,..
                    {
                        c = getchar();            // Leer dato
                        if((c<='3') && (c>='1'))  // Si es una opción válida,...
                        {
                            Effect = c;           // Tomar opción            
                            goto start;           //  y reiniciar
                        }                        
                    }
                    delay_us(150);
                }
            }
        }
    }
}

void usart_init(void)
{
    // USART0 initialization
    // Communication Parameters: 8 Data, 1 Stop, No Parity
    // USART0 Receiver: On
    // USART0 Transmitter: On
    // USART0 Mode: Asynchronous
    // USART0 Baud Rate: 9600 (Double Speed Mode)
    UCSR0A=0x02;
    UCSR0B=0x18;
    UCSR0C=0x06;
    UBRR0H=0x00;
    UBRR0L=0x67;
}
      

Copia todo este código y pégalo en el editor de CodeVisionAVR.

codevision

Construir el Proyecto

Los botones de las barras de herramientas de CodeVisionAVR no me parecen nada intuitivos porque después de tantos años apenas si logro distinguirlos. Para construir el proyecto yo prefiero utilizar el menú Proyect > Build All, como se ve abajo.

CodeVisionAVR

Después de construir el proyecto (esto es compilar, enlazar, ensamblar y generar los archivos de salida), tendremos la ventana que reporta los resultados del proceso. Si la construcción fue exitosa esta ventana tendrá adicionalmente la pestaña Assembler con la información de memoria utilizada, como se aprecia en la siguiente figura.

CodeVisionAVR

También el panel Code Navigator puede dar cuenta de la creación de los archivos de salida como resultado de una construcción exitosa. De todos modos podemos examinar la carpeta del proyecto para comprobar la existencia de los archivos de salida, como el archivo HEX para grabar el AVR o el archivo COFF para las simulaciones en programas como Proteus o Studio 5. El archivo HEX se encuentra dentro de la carpeta Exe.

CodeVisionAVR

Si quieres que los archivos de salida no se “desparramen” entre tantas carpetas (Exe, Linker, List y Obj) y que más bien vayan todos a una carpeta Debug como en AVR CGG o IAR C, que es como se acostumbra en los programas de cursomicros.com, puedes hacer la reconfiguración en el menú Project > Configure >File > Output directories. Escribes Debug en los campos respectivos como se ve en la siguiente captura, aceptas con OK y luego podrás borrar las otras carpetas.

CodeVisionAVR

Simulación del Programa

CodeVisionAVR no tiene un simulador integrado. Si queremos simular nuestro programa tendremos que recurrir a un simulador externo como Proteus VSM o Studio 5.

Para simular en Proteus creamos el diseño respectivo y cargamos el archivo HEX, o COFF si queremos trabajar con una depuración paso a paso. Obviamente, ahora no voy a entrar en detalles. Para eso puedes revisar el tema dedicado a simulaciones con Proteus.

proteus y CodeVisionAVR

Quienes no tengan el privilegio de contar con Proteus, puedes utilizar el simulador del Studio 5. Ahora el traspase del programa ya no es tan flexible como lo era en el Studio 4 pero todavía es posible mediante el archivo COFF.

Así que abrimos el Studio 5 y vamos al menú File > Open > Open Object File for Debugging como se indica en la siguiente toma.

studio 5 y CodeVisionAVR

En la siguiente ventana debemos ubicar el archivo COFF a simular. También dice que AVR Studio creará un proyecto para la simulación, así que debemos darle un nombre y especificar una carpeta donde se guardará el proyecto. El nombre no es relevante pero igual le puse ledflasher3. Es preferible que la carpeta sea la misma que contiene el proyecto de CodeVisionAVR.

CodeVisionAVR

Luego seleccionamos el microcontrolador del proyecto.

CodeVisionAVR

Ahora podremos apreciar que el panel Solution Explorer del Studio 5 muestra los archivos de depuración COFF y de código fuente main.c. Sin más inicia la simulación presionando el botón indicado.

CodeVisionAVR

Aquí seleccionamos AVR simulador. Se habla con más amplitud de esto aquí.

codevision

Lo que sigue es historia conocida para quienes conocen las simulaciones con el Studio 5. Si aún no eres de ellos, puedes revisar la sección simulación del programa. Observa que el archivo COFF puede mostrar las variables ubicadas en los registros de trabajo, a diferencia de la depuración con el archivo ELF.