miércoles, 4 de enero de 2017

Tutorial MPLABX XC8 parte 3: Crear librerías–librería UART para PIC16F628A


Hola amigos, en este tutorial veremos cómo crear librerías para el manejo de módulos externos, específicamente para la comunicación serial asíncrona revisada en el tutorial anterior.

¿Qué es una librería?

Cuando realizamos varios proyectos con microcontroladores, nos damos cuenta que ciertas actividades son repetitivas.  Por ejemplo, al momento de enviar un dato por el USART siempre iniciamos el puerto, cargamos enviamos el ASCII y revisamos si la bandera de envío está activada (como se observó en el tutorial anterior); o cuando leemos el dato de un conversor analógico digital siempre se inicializa el conversor, se carga el valor en binario y se lo convierte a un tipo de dato que sea procesable o se pueda visualizar de mejor manera.  Así, una librería es una porción de código que puede reutilizarse en todo proyecto y permite realizar actividades repetitivas evitando que escribamos todo nuevamente.
De manera simple, una librería es código que se adiciona al proyecto.  En el caso del ejemplo de hoy todo será en un archivo de encabezado.




Librería usart.h

Vamos a programar una librería USART para enviar caracteres y cadenas de texto directamente, sin la necesidad de conocer el código ASCII de cada uno.
En el tutorial anterior se observó que para transmitir un dato por UART (modo asíncrono) se deben realizar los siguientes pasos:
  1. Declarar los puertos B1 y B2 como ingresos: TRISB<1> y TRISB<2> =1
  2. Inicializar el bit BRGH y el registro SBPRG con el baud rate requerido
  3. Activar el puerto asíncrono con SYNC=0 y SPEN=1
  4. Si se requiere que la transmisión sea por interrupción TXIE=1
  5. Si se requiere que la transmisión sea de 9 bits TX9=1
  6. Habilitar la transmisión con TXEN=1
  7. Si se seleccionó la transmisión de 9 bits, cargar el 9no bit en TX9D
  8. Cargar los bits de datos en el registro TXREG
Para diseñar la librería tomaremos en cuenta los siguientes parámetros:
La transmisión será asíncrona con 8 bits sin paridad y con 1 bit de parada pues es lo más común (UART 8N1).
  • El baudrate será elegido por el usuario.
  • Se utilizará siembre el modo de alta velocidad (BRGH=1)
  • La librería podrá leer y escribir el puerto
En el estricto sentido de la palabra, crearemos una clase más no una librería.  Pero esto es el principio de funcionamiento de las mismas, pues en una librería se agrega código más completo para soportar diferentes tipos de microcontroladores, diferentes condiciones iniciales, etc.

Init_UART()

Para iniciar la comunicación se debe declarar los puertos B1 y B2 como entradas


TRISBbits.TRISB1=1;
TRISBbits.TRISB2=1;



Utilizando la fórmula dada por el datasheet, debemos calcular SPBRG, para lo cual despejamos “X”.

image


unsigned int x;
x = (_XTAL_FREQ - baudrate*16)/(baudrate*16);

Con el cálculo de SPBRG ya no debemos preocuparnos de buscar el valor en la hoja de datos del dispositivo, únicamente debemos entregar al método el baudrate deseado.
Además, se requieren inicializar los bits de configuración del registro TXSTA y TCSTA


TXSTAbits.TX9=0; //transmisión 8 bits
TXSTAbits.TXEN=1; //transmisión habilitada
TXSTAbits.SYNC=0; // modo asíncrono
TXSTAbits.BRGH=1; // modo alta velocidad
TXSTAbits.TRMT=1; // borrar bandera de estado
RCSTAbits.SPEN=1; // habilitar puerto serial
RCSTAbits.RX9=0; //recepción en 8 bits
RCSTAbits.CREN=1; //habilitar recepción contínua
SPBRG = x; //cargar el valor para el baudrate



Write_UART()

Este método nos permite escribir un dato simple en el buffer de transmisión, siempre y cuando el mismo esté desocupado.  Recibe como variable un tipo “char”.


void Write_UART(char data)
{
  while(!TXIF); // escribir únicamente si el buffer no está ocupado
  TXREG = data;
}

Write_Text_UART()

Este método utiliza Write_UART() para enviar una cadena de texto, para lo cual hace uso de un bucle “for” el cual realiza el envío caracter por caracter hasta el fin de la cadena.  Recibe una cadena entre comillas de tipo texto.


void Write_Text_UART(char *text)
{
  int i;
  for(i=0;text[i]!='\0';i++) //escribir hasta que el final de la cadena
  {
      Write_UART(text[i]);
  }
}



Read_UART()

Método utilizado para leer un caracter del buffer.  Realiza la lectura cuando el buffer esté desocupado.


char Read_UART()
{
  while(!RCIF); //leer únicamente si el buffer no está ocupado
  return RCREG;
}

Read_Text_UART()

Por último, este método lee un conjunto de caracteres y devuelve una cadena de tamaño definido, es decir, el usuario debe ingresar la variable donde quiere que se guarde la lectura del puerto y el número de caracteres que quiere leer.


void Read_Text_UART(char *Output, unsigned int length)
{
    unsigned int i;
    for(int i=0;i<length;i++)
    {
        Output[i] = Read_UART();
    }
}



El código completo de la librería (clase) para manejo de uart quedaría de la siguiente manera:


void Init_UART(const long int baudrate)
{
    unsigned int x;
    
    x = (_XTAL_FREQ - baudrate*16)/(baudrate*16);
    
    TXSTAbits.TX9=0; //transmisión 8 bits
    TXSTAbits.TXEN=1; //transmisión habilitada
    TXSTAbits.SYNC=0; // modo asíncrono
    TXSTAbits.BRGH=1; // modo alta velocidad
    TXSTAbits.TRMT=1; // borrar bandera de estado
    RCSTAbits.SPEN=1; // habilitar puerto serial
    RCSTAbits.RX9=0; //recepción en 8 bits
    RCSTAbits.CREN=1; //habilitar recepción contínua
    SPBRG = x; //cargar el valor para el baudrate
}

char Read_UART()
{
  while(!RCIF); //leer únicamente si el buffer no está ocupado
  return RCREG;
}

void Read_Text_UART(char *Output, unsigned int length)
{
    unsigned int i;
    for(int i=0;i<length;i++)
    {
        Output[i] = Read_UART();
    }
}

void Write_UART(char data)
{
  while(!TXIF); // escribir únicamente si el buffer no está ocupado
  TXREG = data;
}

void Write_Text_UART(char *text)
{
  int i;
  for(i=0;text[i]!='\0';i++) //escribir hasta que el final de la cadena
  {
      Write_UART(text[i]);
  }
}

Utilizar la librería

Ahora, para poder utilizar la librería creada realizamos lo siguiente:
  1. Copiar el archivo de la librería (uart.h) en el proyecto, para lo cual hacemos click derecho sobre “Header Files” y seleccionamos “Add Existing Item…”
image
Seleccionamos el archivo uart.h el cual, debe estar dentro de la misma carpeta del proyecto

image

2. En nuestro programa principal incluimos el archivo uart.h y podemos utilizarlo para enviar un “Hola mundo”


#define _XTAL_FREQ 20000000 //declaración del cristal

#include <stdio.h>
#include <stdlib.h>
#include "confbits.h"
#include <xc.h>
#include "uart.h" //incluir la librería

int main(void)
{
    Init_UART(9600); //inicializar la librería uart a 9600 baudios
    while(1)
    {
        Write_Text_UART("Hola mundo \r\n");
    }
}


Con esto podemos cargar el archivo .hex a una simulación en Proteus y observaremos el funcionamiento de la librería.

image

Lectura y Escritura

Finalmente podemos utilizar 2 microcontroladores para probar tanto la escritura como lectura de datos.  Para esto se conecta el TX del microcontrolador que envía el dato al RX del que lo recibe.

image

El código para ambos microcontroladores es el siguiente:

Transmisor


#define _XTAL_FREQ 20000000 //declaración del cristal

#include <stdio.h>
#include <stdlib.h>
#include "confbits.h"
#include <xc.h>
#include "uart.h" //incluir la librería

int main(void)
{
    Init_UART(9600); //inicializar la librería uart a 9600 baudios
    while(1)
    {
        Write_Text_UART("Hola mundo \r\n");
        __delay_ms(1000);
    }
}

Receptor


#define _XTAL_FREQ 20000000 //declaración del cristal

#include <stdio.h>
#include <stdlib.h>
#include "confbits.h"
#include <xc.h>
#include "uart.h" //incluir la librería

int main(void)
{
    Init_UART(9600); //inicializar la librería uart a 9600 baudios
    unsigned char cadenarx[10];
    
    while(1)
    {
        if (RCIF==0){
            Read_Text_UART(cadenarx,10);
        }
        Write_Text_UART(cadenarx);
        __delay_ms(1000);
        
    }
}

La librería no es perfecta y puede completarse de muchas maneras.  Por ejemplo se puede adicionar un control de tráfico en el puerto, crear un buffer de lectura dinámico que cierre la variable cuando reciba un caracter especial, etc.  Sin embargo el propósito de este turorial es conocer cómo se realiza una librería básica para luego adaptarla a las necesidades de cada proyecto.  Además, Microchip en sus librerías (plib) tiene desarrollada una especial para el manejo de USART la cual puede ser utilizada en series 18.

El proyecto completo y la simulación en Proteus lo puedes descargar a continuación. Descarga ejemplo


Es todo por hoy, espero la información haya sido de ayuda.  Si te gustó por favor comparte la página, suscríbete y comenta.

Hasta una próxima entrega, adiós