LENGUAJE C PARA MICROCONTROLADORES DIRECTIVAS DEL PREPROCESADOR

lenguaje c directivas 1

Cuando se realiza un programa en lenguaje C, se verá que al inicio del programa se tiene lo que se conoce  como directivas del preprocesador, estos se reconocen porque se inician  con la almohadilla esto es #, en la programación de microcontroladores se usa por ejemplo el #include, así como el #define, el #pragma, entre otros; las directivas no terminan en punto y coma.

Con las directivas lo que se hace es que se le indica al compilador del lenguaje C o también para el lenguaje C++ que realice algunas acciones antes de convertir el programa realizado a lenguaje máquina, esto es a código binario.

Se puede ver como que se le dice al compilador del lenguaje C o del lenguaje C++, oye compilador antes de compilar el programa que se te pide, toma en cuenta las directivas que se te han puesto ya que serán necesarias para que no tengas problemas  al compilar mi programa.

En este caso se comentará sobre las directivas #include y #define por ser las mas utilizadas al programar los microcontroladores, pero hay mas que se verán en futuras entradas, y también en los vídeos del canal de Youtube de MrElberni lo que nos interesa ahora  es comprender el porque se utilizan o porque aparecen al inicio de los programas que se realizan en el lenguaje C.

LENGUAJE C PARA MICROCONTROLADORES, LA DIRECTIVA INCLUDE

La directiva #include se le suele también llamar como archivo de cabecera, por ejemplo al programar los microcontroladores PIC con el XC8, este utiliza la directiva #include<xc.h>, aquí se le indica al compilador que incluya el archivo xc.h, ya que es donde encontrara lo que necesite sobre el microcontrolador PIC que se este programando.

Otro caso puede ser cuando se programan los microcontroladores AVR y se necesitan hacer pausas, se hace uso de la directiva #include <util/delay.h> aquí se le indica al compilador que tome en cuenta el archivo delay.h porque en el programa se  realizaran pausas, en este archivo se encontrarán las funciones necesarias para la realización de pausas.

En el Arduino por ejemplo que utiliza el lenguaje C++ si se quiere utilizar la pantalla lcd, se tendrá que utilizar la directiva #include<LiquidCrystal.h> para que el compilador del Arduino sepa donde encontrar lo referente a la pantalla lcd.

El XC8 también utiliza archivos de cabecera del lenguaje C o el lenguaje C++ que serán muy útiles a la hora de realizar los programas de los microcontroladores, uno de ellos es el stdio.h, que para usarlo se le indicará al compilador mediante la directiva #include <stdio.h>, este archivo de cabecera tiene muchas funciones, una de ellas es la función sprintf que se utilizara cuando se quieran convertir números a cadenas para poder verlos por ejemplo en las pantallas lcd. 

Los diversos archivos de cabecera que sean propios del lenguaje C o del compilador que se este utilizando, se irán viendo en próximas entradas, según se los vayan  necesitando.

También podemos crear nuestros propios archivos de cabecera, la forma de hacerlo  se muestra por ejemplo en las entradas publicadas sobre el uso de las pantallas lcd, tanto para el lcd microcontrolador PIC como para el lcd microcontrolador AVR, donde se crea el archivo de cabecera lcd.h, en estos casos la directiva será usada así #include "lcd.h", notar que cuando son creadas por nosotros se utilizan las comillas.

LENGUAJE C PARA MICROCONTROLADORES, LA DIRECTIVA DEFINE

La directiva del lenguaje C o del lenguaje C++ #define lo que se hace es crear constantes también llamados macros, que pueden ser numéricas o literales.

Por ejemplo tanto al programar los microcontroladores PIC o los microcontroladores AVR al programarlos con el compilador XC8, será necesario indicar de cuanto es el valor del oscilador utilizado, esto para que el microcontrolador pueda hacer los cálculos necesarios para su correcto funcionamiento.

Para indicar que se utilizará un oscilador de 20MHz para los microcontroladores AVR se realiza así 

#define F_CPU 20000000UL

mientras que en un microcontrolador PIC es así 

#define _XTAL_FREQ 20000000

Para el caso del microcontrolador PIC al programarlo con el XC8, lo que ocurre es que en algunas funciones que vienen dentro de los archivos que son utilizador por el XC8, se hace uso de la constante o macro _XTAL_FREQ, lo que ocurrirá será que en cada lugar  donde aparezca _XTAL_FREQ este será reemplazado por 20000000; si el cristal utilizado fuera de otra frecuencia, será el valor de esa frecuencia la que se use en el define y será por la que se reemplace para que el PIC funcione correctamente.

Lo mismo ocurrirá para el microcontrolador AVR, donde aparezca F_CPU el compilador lo reemplazará por 20000000 o por el valor de la frecuencia del cristal que se utilice.

También podemos crear nuestras propias macros para así hacer mas elegantes nuestros programas, un ejemplo puede ser darle un nombre al pin2 del puerto B que se este utilizando como salida digital al que se la ha conectado un led, para el caso cuando se quiera que el led este encendido o que este apagado.

Para el microcontrolador PIC o el microcontrolador AVR sería algo así

#define ledapagado PORTB&=~(1<<2); 

En este caso en el código del programa realizado en lenguaje C o lenguaje  C++, donde aparezca ledapagado, el compilador lo reemplazará por PORTB&=~(1<<2).

#define ledencendido PORTB|=(1<<2); 

En este caso en el código del programa realizado en lenguaje C o lenguaje  C++, donde aparezca ledencendido, el compilador lo reemplazará por PORTB|=(1<<2).

#define ledparpadea PORTB^=(1<<2); 

En este caso en el código del programa realizado en lenguaje C o lenguaje  C++, donde aparezca ledparpadea, el compilador lo reemplazará por PORTB^=(1<<2).

En el caso del Arduino por ejemplo para el Arduino Mega, si el pin 30 es utilizado como salida digital y se quiere que este parpadee, mediante la directiva  #define se puede declarar una macro así:

#define ledparpadea digitalWrite(30,!(digitalRead(30)));

En este caso el compilador del Arduido en el programa, donde aparezca ledparpadea, lo reemplazará por digitalWrite(30,!(digitalRead(30))).

LENGUAJE C PARA MICROCONTROLADORES, EJEMPLO USO DIRECTIVAS

En el siguiente ejemplo fijarse sobre todo en la utilización de las directivas, en ellas se ve que para elegir los bits de configuración se utiliza la directiva #pragma, también se utiliza la directiva #include par las característica del microcontrolador PIC a utilizar, en este caso es el PIC16F877A, también para incluir la librería lcd.h que se encuentra aquí, además se utiliza la directiva #define, los casos en los que se utilizan están comentados dentro del programa, observar que todo lo que va luego de // para el lenguaje C o el lenguaje C++ son comentarios que el compilador no toma en cuenta.

Lo que hará el programa será encender y apagar un led conectado en el pin  2 del puerto B, así como enviar un mensaje por una pantalla LCD y un número


//directivas para los bits de configuración
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#define _XTAL_FREQ 20000000 //directiva para frecuencia del cristal utilizado
#include <xc.h>//directiva para el microcontrolador utilizado

#include <stdio.h>  //directiva para poder convertir numero a cadenas
#include "lcd.h"    //directiva para el archivo de cabecera creado necesario

#define ledapagado PORTB&=~(1<<2); //directiva para apagar el led
#define ledencendido PORTB|=(1<<2); //directiva para encender el led
#define ledparpadea PORTB^=(1<<2);  //directiva para parpadear el led

char numcad[5]; //arreglo donde se guarda el numero entero convertido a cadena

unsigned char numero=0; //numero de 8 bits a ser visto en el LCD inicia a 0

void main(void) {
    TRISB&=~(1<<2);//pin RB2 como salida digital
    ledapagado;//pin RB2 inicia led apagado, aqui se usa una directiva #define
    
    lcd_inicia();//se inicializa la pantalla lcd PIC
    
    while (1) {//ciclo principal del programa
        lcd_ubicate(1,1);//ubica el cursor en la fila 1 columna 1
        lcd_mensaje("Directivas PIC");//mensaje primera fila
        sprintf(numcad,"numero = %d",numero); //guarda numero en numcad
        
        lcd_ubicate(2,1);//ubica el curso en la fila 2 columna 1
        lcd_mensaje(numcad);//mesaje segunda fila
        lcd_mensaje("                   ");//para borrar caracteres finales innecesarios
        
        ledparpadea;//pin RB2 cambia de estado, aqui se usa otra directiva #define
        
        numero++;//número aumenta en una unidad cada 200ms
        if(numero>255){//al llegar numero a 255
            numero=0;     //se reinicia a 0
        }
        __delay_ms(200);//para ver el parpadeo del led y 
                                    //el cambio de numero en el lcd
        
    }
    
    return;
}

La siguiente es la imagen del ejemplo realizado en el protoboard con el PIC16F877A, se observa que el programa funciona correctamente, tener en cuenta que en este caso lo importante es el uso de las directivas, lo demás se irá comentando en las siguiente entradas.

lenguaje c directivas 2

Esperamos de todo corazón haber podido ayudarles en este tema tan interesante del lenguaje C sobre las directivas del preprocesador, en cuanto a su uso con los microcontroladores.

ANTERIOR: Lenguaje C para microcontroladores

SIGUIENTE: Operaciones de bits

Publicar un comentario

Copyright © Electricidad y Electrónica. Designed by OddThemes