Comunicación serial RS232 «envió de valores», Pic C Compiler

En esta sección aprenderás a realizar una comunicación serial RS232 con dos microcontroladores PIC. El objetivos es enviar cualquier valor por el puerto serial a un microcontroladores PIC para mostrarlo en una pantalla OLED.

Comunicación serial RS232

La comunicación RS232 es un protocolo de comunicación asíncrono que define cómo los dispositivos deben transmitir y recibir datos y señales de control. Establece normas para la transmisión de señales de control, como el inicio y el fin de los datos, y también define los parámetros de los cables y conectores utilizados para la conexión.

Además, la comunicación RS232 permite una amplia gama de velocidades de transmisión de datos, lo que la hace adecuada para una amplia variedad de aplicaciones. La velocidad de transmisión de datos se puede ajustar según sea necesario para adaptarse a las necesidades específicas de una aplicación.

A pesar de la popularidad de otros estándares más modernos, como USB y Ethernet, la comunicación RS232 sigue siendo una parte importante de la industria tecnológica. Se utiliza en una amplia variedad de aplicaciones, desde la conexión de dispositivos industriales hasta la conexión de dispositivos de almacenamiento y la transmisión de datos de sensores y controladores.

En resumen, la comunicación RS232 es un estándar de comunicación serie que ha resistido la prueba del tiempo y sigue siendo relevante en la industria tecnológica de hoy en día. Aunque ha sido superado por otros estándares en muchos casos, sigue siendo una parte importante de la tecnología y se utiliza en una amplia variedad de aplicaciones.

Circuito de conexión

Programación PIC de transmisión

Inicialmente se establecen los parámetros de la comunicación RS232.

  • baud = Velocidad de transmisión.
  • parity = Bit de paridad. 
  • xmit = Pin de transmisión.
  • rcv = Pin de recepción. 
  • bits = Datos de transmisión.
  • stream = identificación de transmisión.

#use rs232(baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8)

Se habilita la conversión analógica-digital para la entrada en los pines analógicos.


setup_adc(ADC_CLOCK_INTERNAL);

Para realizar la lectura en el pin analógico se define el pin donde se realizara la lectura, en este caso el pin AN0 o el pin AN1, una vez definido el pin se realiza la lectura y se guarda el valor en la variable.


 set_adc_channel (0);//lectura Vout del potenciometro en PIN AN0
 delay_us(10);
 POT1 = read_adc();// lectura del valor

 set_adc_channel (1);//lectura Vout del potenciometro en PIN AN1
 delay_us(10);
 POT2 = read_adc();// lectura del valor

Se realiza una sentencia donde preguntamos sí el valor pasado es diferente del valor actual, para que los datos se envíen por el puerto rs232 únicamente cuando el potenciometro cambie de valor.


if (pasPOT1 != POT1)
   {
      printf("POT1%lu\r",POT1);
      pasPOT1 = POT1;
   }

Se utiliza la misma lógica para las demás entrada analógicas.

Código completo PIC Transmisión 


#FUSES NOMCLR

#use rs232(baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8)

void main()
{
   setup_adc(ADC_CLOCK_INTERNAL);
   
   int16 POT1=0;     //variable para guardar el valor actual
   int16 pasPOT1=0; //variable para guardar el valor pasado

   int16 POT2=0;
   int16 pasPOT2=0;

   while(TRUE)
   {
   
       set_adc_channel (0);//lectura Vout del potenciometro en PIN AN0
       delay_us(10);
       POT1 = read_adc();// lectura del valor
       
       if (pasPOT1 != POT1)
       {
          printf("POT1%lu\r",POT1);
          pasPOT1 = POT1;
       }

         delay_ms(100);
         
       set_adc_channel (1);//lectura Vout del potenciometro en PIN AN1
       delay_us(10);
       POT2 = read_adc();// lectura del valor

       if (pasPOT2 != POT2)
       {
          printf("POT2%lu\r",POT2);
          pasPOT2 = POT2;
       }
      
        delay_ms(100);
      //TODO: User Code
   }

}

Programación PIC de recepción 

Inicialmente se definen los parámetros de la comunicación RS232.


#use rs232(baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8)

Se habilita la interrupción para la recepción de datos en el puerto rs232.


   enable_interrupts(int_rda);
   enable_interrupts(global);

Cuando se reciben datos en el pin de recepción RS232, se activara la interrupción y entrara a la subrutina «rda_isr()» donde recibirá la cadena de caracteres y se guardara en la variable recibido[].


#int_rda
void rda_isr()
{
   memset(recibido, 0, sizeof(recibido)); //limpia los registros de la varible
   int8 i=0;
   while(true)
   {
      recibido[i]=getc();//RECIBE EL CARACTER

      if(recibido[i]=='\r')//busca el salto de linea \r
      {
         recibido[i]='\0';//fin de la cadena = caracter nulo \0
         return;
      }
      i++;
   }
}

Cuando termine de recibir los datos, es necesario obtener el identificador del potenciometro y el valor del ADC. 

Utilizamos una sentencia «for()» para obtener los primeros 4 caracteres para identificar el potenciometro, si es «POT1» o «POT2».

Utilizamos otra sentencia «for()» para obtener los siguientes 4 caracteres que contienen el valor correspondiente al potenciometro «0 a 1023».


      for (int i=0; i<=3; ++i)
      {
         POT[i] = recibido[i]; //identifica el potennciometro
      }

      for (int i=0; i<=3; ++i)
      {
         num[i] = recibido[i+4]; //guarda el valor del potennciometro
      }

Se compara el identificador para saber si es «POT1» o «POT2».

Inicialmente si la variable «POT» contiene el identificador «POT1», resultado=0 y entra a la sentencia «if()» donde el valor que contiene la variable «num» en cadena de caracteres se convierte en un numero de 16 bits y se guarda en la variable «POT_1».


      result = strcmp(POT, POT1);//compara, si son iguales (0), no (+-1)

      if(result==0)
      {
         POT_1 = (int16)atol(num);  //convierte la cadena en un numero de 16bits
         return;
      }

Si la variable «POT» contiene el identificador «POT2», resultado=0 y entra a la sentencia «if()» donde el valor que contiene la variable «num» en cadena de caracteres se convierte en un numero de 16 bits y se guarda en la variable «POT_2».


      result = strcmp(POT, POT2);
      if(result==0)
      {
         POT_2 = (int16)atol(num);
         return;
      }

Finalmente se muestran el valor de cada potenciometro en la pantalla OLED.


   sprintf(texto,"POT1=%04lu",POT_1);
   OLED_DrawText(1,1,texto,1);

   sprintf(texto,"POT2=%04lu",POT_2);
   OLED_DrawText(1,10,texto,1);

   OLED_Display();//Muestra la información en pantalla;

Cuando termina de mostrar los datos en la pantalla oled, el programa se quedara esperando en la función «void main()» hasta que se reciban datos por el puerto RS232.

Código completo PIC recepción 


#include "string.h"
#include "stdlib.h"

#FUSES NOMCLR

#use i2c(Master,Fast, sda=PIN_B0, scl=PIN_B1,force_sw, stream=OLED_stream)//parametros I2C
#use rs232(baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8)


#define SH1106_128_64 //DEFINE EL MODELO DE LA PANTALLA OLED
//#define SSD1306_128_64

#include "OLED_I2C.c" //libreria oled I2C


char recibido[20];
int16 POT_1;
int16 POT_2;

void datos();
void mostrar();


#int_rda
void rda_isr()
{
   memset(recibido, 0, sizeof(recibido)); //limpia los registros de la varible
   int8 i=0;
   while(true)
   {
      recibido[i]=getc();//RECIBE EL CARACTER

      if(recibido[i]=='\r')//busca el salto de linea \r
      {
         recibido[i]='\0';//fin de la cadena = caracter nulo \0
         datos();
         mostrar();
         return;
      }
      i++;
   }
}


void datos()
{
   signed int8 result;

   char POT[10];
   char num[10];

   char POT1[10] = "POT1";
   char POT2[10] = "POT2";

   memset(POT, 0, sizeof(POT)); //limpia los registros de la varible POT
   memset(num, 0, sizeof(num)); //limpia los registros de la varible num

   while (true)
   {
       for (int i=0; i<=3; ++i)
      {
         POT[i] = recibido[i]; //identifica el potennciometro
      }

      for (int i=0; i<=3; ++i)
      {
         num[i] = recibido[i+4]; //guarda el valor del potennciometro
      }

      result = strcmp(POT, POT1);//compara, si son iguales (0), no (+-1)

      if(result==0)
      {
         POT_1 = (int16)atol(num);  //convierte la cadena en un numero de 16bits
         return;
      }

      result = strcmp(POT, POT2);

      if(result==0)
      {
         POT_2 = (int16)atol(num); //convierte la cadena en un numero de 16bits
         return;
      }

      return;
   }
}


void mostrar()
{
   char texto[20];

   sprintf(texto,"POT1=%04lu",POT_1);
   OLED_DrawText(1,1,texto,1);

   sprintf(texto,"POT2=%04lu",POT_2);
   OLED_DrawText(1,10,texto,1);

   OLED_Display();//Muestra la información en pantalla;
}


void main()
{
   enable_interrupts(int_rda);
   enable_interrupts(global);

   OLED_Begin();
   OLED_ClearDisplay();

   while(TRUE)
   {


      //TODO: User Code
   }
   
}
Scroll al inicio