¿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:
Declarar los puertos B1 y B2 como ingresos: TRISB<1> y TRISB<2> =1
Inicializar el bit BRGH y el registro SBPRG con el baud rate requerido
Activar el puerto asíncrono con SYNC=0 y SPEN=1
Si se requiere que la transmisión sea por interrupción TXIE=1
Si se requiere que la transmisión sea de 9 bits TX9=1
Habilitar la transmisión con TXEN=1
Si se seleccionó la transmisión de 9 bits, cargar el 9no bit en TX9D
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 puertoEn 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.
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:
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…
Seleccionamos el archivo uart.h el cual, debe estar dentro de la misma carpeta del proyecto
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.
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.
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