Aunque, indirectamente ya he utilizado en el blog protocolos de comunicaciones, como en la entrada Proyectos USB (II), hasta ahora no os había hablado en profundidad de ninguno de ellos.
La mayoría de los sistemas formados por uno o varios microcontroladores necesitan que estos se comuniquen entre ellos, que se comuniquen con periféricos externos, como memorias, y en algunos casos, que se comuniquen también con un sistema superior como un PC. La forma en que los distintos dispositivos envían y reciben los datos, así como el medio físico por el que se transmiten se conoce como protocolo. Así pues existen 2 grandes grupos de distintos protocolos, los protocolos paralelo, los cuales presentan los datos de forma paralela y los protocolos serie. Ojo! cuando digo paralelo no significa que si tenemos que enviar 128 bits necesitemos 128 hilos, sino que enviamos cada 8 o 16 bits de forma conjunta, necesitando por tanto 8 o 16 hilos al menos. Las ventajas y desventajas de cada grupo de protocolos están claras, en las comunicaciones en paralelo su mayor ventaja es la velocidad, ya que para mandar 64 bits con un bus de 16 bits tan solo necesitamos enviar 4 datos, mientras que si lo enviamos en serie enviamos uno a uno. En cuanto a las comunicaciones en serie su mayor ventaja reside en que solo necesitamos un solo hilo para transmitir los datos. Debido a la gran velocidad que permiten las comunicaciones serie, llegando a MHz en algunos casos, la velocidad de transmisión no representa un problema, por lo que es el tipo de comunicación que más se utiliza.
Centrándonos en los protocolos serie existen otros dos grandes grupos, los síncronos, que utilizan una línea para enviar la señal de reloj, lo cual incluye un hilo más, y los asíncronos, los cuales los dos dispositivos se sincronizan sin necesidad de línea de reloj. De los protocolos síncronos los más utilizados son el SPI y el I2C, y en cuanto a los asíncronos tenemos el RS232 y RS485. En esta entrada voy a hablaros del más utilizado a nivel doméstico, el RS232.
Aunque poco a poco está siendo sustituido por el USB, todavía queda espacio para este protocolo con dispositivos como el MCP2200 o los chips FTDI, que transforman una comunicación USB en una simple RS232, y no solo podemos convertirlo en USB, sino que con la ayuda de módulos BLUETOOTH podemos crearnos una comunicación inalámbrica entre PC y microcontrolador. La mayor ventaja de
trabajar con este protocolo es que la mayoría de microcontroladores lo implementan por hardware, lo que hace muy fácil la programación, de hecho solo hacen falta 3 o 4 registros para tener el módulo funcionando, sin que intervengan librerías ni paquetes especiales. Los registros cambian según si utilizamos un PIC un DSPIC o un PIC32, por ejemplo, para un PIC18F2550 existen 4 registros de configuración: TXSTA, que controla la configuración de la transmisión a parte de características básicas de la comunicación, RCSTA que hace lo mismo con la recepción, BAUDCON que junto al registro BRG establece la velocidad de la comunicación, y luego los registros de envío y recepción que son el TXREG y el RCREG. Una configuración de estos registros podría ser la siguiente:
void main (void)
{
//configuracion eusart
BAUDCON=0x00; //modo 8 bits
TXSTA=0x24; //8 bits, transmision habilitada
RCSTA=0x90; //8 bits, canal eusart habilitado, recepcion habilitada
SPBRG=129; //velocidad real de comunicacion 9600 baudios 20MHz
//configuracion de interrupciones
INTCON=0xE0; //interrupciones habilitadas a nivel global, interrupcion de timer 0 habilitada
PIE1bits.RCIE=1; //habilitacion de la interrupcion por recepcion
while (1); // Bucle sin fin
}
En este código hemos incluido la habilitación de la interrupción de recepción para que cuando en el buffer de entrada haya un dato listo para ser leído salte la interrupción.
En el caso de PIC32, el nombre de los registros cambia, al igual que, evidentemente, su tamaño, así pues para PIC32 existen tan solo 2 registros de configuración, UxMODE, con el que se realiza la configuración básica del módulo, así como su comportamiento en los modos de reposo del microcontrolador, el UxSTA, mediante el cual realizamos la configuración de la comunicación, tanto del envío, como de la recepción, y luego tenemos el registro por el cual establecemos la velocidad de comunicación que es el UxBRG. La x de cada registro hace referencia a los distintos módulos de comunicaciones que dispone un PIC32, llegando hasta 5 módulos UART. Una configuración básica de estos registros podría ser la siguiente:
#define GetSystemClock() 80000000u
#define GetPeripheralClock() (GetSystemClock()/(1<<OSCCONbits.PBDIV)) //80MHz / 8 = 10MHz
#define BAUDRATE 9600
#define BRGDATA (GetPeripheralClock()/4/BAUDRATE-1)
#define U_ENABLE 0x8008 // enable,BREGH=1, 1 stop, no parity
#define U_TX 0x1400 // enable tx & rx, clear all flags
void main()
{
AD1PCFG = 0xFFFF; // Configuramos todos lo pines como digitales
LED1_TRIS = 0;
U2MODE = U_ENABLE; // initialize the UART module
U2STA = U_TX; // enable the Transmitter and Receiver
U2BRG = BRGDATA;
while(1);
}
El micro, en este caso está funcionando a 80MHz, y el bus de periféricos esta dividido entre 8, por lo que la frecuencia de los periféricos es de 10MHz, que es un valor mucho más manejable para generar retardos o velocidades de comunicación bajas. El valor del registro U2BRG viene dado por la ecuación siguiente:

Que es la que realizamos en el #define. Una vez inicializados correctamente los registros, solo nos queda leer el buffer de entrada y salida, que está formado por los registros UxRXREG y UxTXREG, de forma que un programa sencillo podría ser el siguiente:
#include <p32xxxx.h>
//#include <plib.h> //incluimos la libreria de periféricos
// Bits de configuración
#pragma config POSCMOD = XT, FNOSC = PRIPLL, FSOSCEN = ON
#pragma config FPLLIDIV = DIV_2, FPLLMUL = MUL_20, FPLLODIV = DIV_1, FPBDIV = DIV_8
#pragma config OSCIOFNC = ON, CP = OFF, BWP = OFF, PWP = OFF
#define LED1_IO _LATG6
#define LED2_IO _LATD6
#define LED1_TRIS _TRISG6
#define LED2_TRIS _TRISD6
#define GetSystemClock() 80000000u
#define GetPeripheralClock() (GetSystemClock()/(1<<OSCCONbits.PBDIV)) //80MHz / 8 = 10MHz
#define BAUDRATE 9600
#define BRGDATA (GetPeripheralClock()/4/BAUDRATE-1)
#define U_ENABLE 0x8008 // enable,BREGH=1, 1 stop, no parity
#define U_TX 0x1400 // enable tx & rx, clear all flags
void main()
{
AD1PCFG = 0xFFFF; // Configuramos todos lo pines como digitales
LED1_TRIS = 0;
U2MODE = U_ENABLE; // initialize the UART module
U2STA = U_TX; // enable the Transmitter and Receiver
U2BRG = BRGDATA;
while(1)
{
while (!U2STAbits.URXDA); //esperamos que llegue un dato nuevo
if(U2RXREG == 'e')
LED1_IO = 1;
else
LED1_IO = 0;
}
}
No hay comentarios:
Publicar un comentario