miércoles, 8 de mayo de 2013

Protocolo RS232

Protocolo RS232


Aunque dejado de lado cada día mas siendo desplazado por el USB. El protocolo RS232 se niega a morir.
¿ Porque aun sigue siendo usado ? Quizás porque es fácil de implementar, de programar, aun la mayoría de las placa madres traen uno.

Por el lado técnico es un protocolo serial y asincronico. Solo 2 lineas de comunicación (mínimo para la comunicación, dejando de lado las señales CTS, DSR, RTS, etc. Presentes en la era en la que los modems se conectaban por RS232).

Cada trama a transmitir contiene los siguientes datos en ella:

1 bit de arranque.
7 u 8 bits de datos comenzando por el LSB.
1 bit de paridad.
1 o 2 bits de parada.



Dado que es un protocolo asincronico no posee una linea de reloj que habilite cada bit. Por eso el tiempo de cada bit es crucial ya que la lectura esta determinada por el tiempo.
Es por esto que existe el bit de arranque el cual le dice al receptor cuando comenzar a contar y calcular así cuando llegara un bit determinado.
El bit de paridad es opcional y puede indicar una paridad par o impar (cantidad par o impar de 1´s transmitidos). Si se nota raro el que los datos puedan ser de 7 bits es porque el 8vo es el de paridad. En la imagen se puede interpretar el dato como:

Dato: 01010101 con 1 bit de arranque 1 de parada, sin paridad y 8 bits de datos.

Como así también:

Dato: 1010101 con 1 bit de arranque 1 de parada, paridad impar y 7 bit de datos.

Es por eso que se debe prestar atención en que tanto el receptor como el transmisor estén configurados de la misma forma.

Si es una comunicación binaria ¿ para que usar un integrado como puede ser el MAX232 ? Es por el echo de que las tensiones establecidas en el protocolo son muy distintas a los 0v y 5V que puede manejar la mayoría de los microntroladores. Por el contrario el protocolo usa, para representar un 0 lógico, una tensión comprendida entre +5 y +15V (positivos) y un 1 lógico con una tensión entre -5V y -15V(negativa).

Ejemplo del programa en C para el Micro:

#define UnBit 416 // 416us = 2400 baudios
#define UnoyMedio 624 // 624us = 2400 baudios


Acá defino cuanto tarda cada bit y cuanto esperar para leer un bit. UnoyMedio indica el tiempo desde que la linea se hace baja (arranque), descontando el tiempo del bit de arranque (un bit) y esperando la mitad de la duración de un bit para hacer la lectura en el medio del bit a leer (yMedio).

*Baudios = bits/seg.
1/Baudio = UnBit. ==>  1/2400 = aprox 416us.


// Rutina que envía un dato por el puerto RS232
void Envia_232(unsigned char dato)
{
// 2400 - 8 bits - no paridad - 1 stop.

     unsigned char x;

     TX = 0;
     __delay_us(UnBit);

     for(x = 0; x < 8; x++) {
                                             TX = (dato & 1);
                                             __delay_us(UnBit);
                                            dato = dato >> 1;
                                         }
      TX = 1;
      __delay_us(UnBit);
}



Pongo la linea TX en 0 y espero 1 bit para crear el bit de arranque:

TX = 0;
__delay_us(UnBit);


Selecciono el bit a transmitir y lo pongo en la linea TX:

TX = (dato & 1);
__delay_us(UnBit);
// Duración del bit.

Roto a la derecha 1 posición para preparar el siguiente dato a enviar:

dato = dato >> 1;

Una vez enviados los 8 bit pongo la linea TX en alto y espero 1 bit de duración para crear el bit de stop:

TX = 1;
__delay_us(UnBit);



En el caso de la recepción por parte del microntrolador la función es:

// Rutina que recibe un dato por el puerto RS232
unsigned char Recive_232()
{
      unsigned char dato, x;

      dato = 0;

      while(RX == 1); // Espera a que la linea baje.
      __delay_us(UnoyMedio); // Espera 1 bit y medio.

       for(x = 0; x < 8; x++) { // Recibe los 8 bits
                                              dato = dato >> 1;
                                              dato = dato | (RX << 7); // LSB primero.
                                              __delay_us(UnBit);
                                           } 

      return dato;
}



Espero a que la linea RX se haga baja indicándome el inicio del bit de arranque. Una vez detectado espero 1 bit y medio para poder leer el primer bit:

while(RX == 1); // Espera a que la linea baje.
__delay_us(UnoyMedio); // Espera 1 bit y medio.


Una vez pasado el tiempo y situados en la mitad del bit lo leo y lo acomodo en el registro que guardara el dato recibido:

dato = dato >> 1;
dato = dato | (RX << 7); // LSB primero.
__delay_us(UnBit);



Obviamente que la recepción del dato se puede hacer (y daría mas flexibilidad al programa) con interrupciones.
Como se ve, incluso con un microcontrolador que no posea interrupciones ni un transmisor/receptor integrado RS232 no deja de ser muy fácil y rápido implementarlo por software.

Con el protocolo RS232 el máximo alcance del enlace es de 15metros, si necesitas mas alcance se puede convertir a RS485 con integrados especialmente diseñados para eso, aumentando el alance a 1200 metros.

Saludos.

No hay comentarios:

Publicar un comentario