Comunicación USB «recepción», Pic C Compiler

En esta sección aprenderás a realizar una comunicación USB mediante la computadora y el microcontrolador PIC, el objetivo es enviar valores al microcontrolador para controlar el ciclo de trabajo de dos señales PWM utilizando un monitor serial en la computadora.

Comunicación USB

La comunicación USB (Universal Serial Bus) funciona mediante un protocolo estandarizado que permite la transferencia de datos y la conexión de dispositivos electrónicos. El protocolo USB se basa en la estructura de «maestro-esclavo», donde un dispositivo actúa como el maestro (anfitrión) y controla uno o más dispositivos esclavos (dispositivos USB).

Microchip ofrece una variedad de microcontroladores PIC con capacidades USB integradas, lo que permite que estos dispositivos se comuniquen con una computadora o funcionen como dispositivos USB en sí mismos.

Monitor serial

Para realizar la comunicación entre el microcontrolador y la computadora, se utiliza un monitor serial para enviar, recibir y graficar los datos.

Descarga en un archivo .zip, lo extraes en la computadora y abres la aplicación QTseralMonitor.

Circuito de conexión

Procedimiento

Inicialmente en el archivo .h se define el oscilador del microcontrolador, y se habilita la velocidad de la comunicación USB.


#use delay(clock=48MHz,crystal=20MHz,USB_FULL)

Se establece la corriente de funcionamiento necesaria para que el microcontrolador se conecte mediante USB.


#define USB_CONFIG_BUS_POWER 500 //500ma corriente de entrada

Para la comunicación USB se utiliza la siguiente librería.


#include "usb_cdc.h"

Se inicializa la comunicación USB.


   usb_init();

Cuando se reciben datos por el puerto USB en la subrutina «recibe()» se obtiene la cadena de caracteres con la función «usb_cdc_getc()» y se guardan en la variable de caracteres «recibido[]», cuando se recibe el carácter «\n» se termina la recepción de datos, después se borran los caracteres especiales «\r y \n» para conservar solo el comando recibido, finalmente el programa se dirige a la subrutina «datos()».


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

      if(recibido[i] == '\n')//busca el salto de linea \r\n
      {
         recibido[i-1] = '\0';  //  \r = \0 (caracter nulo)
         recibido[i] = '\0';   //  \n = \0 (caracter nulo)

         leds();
         return;
      }
      i++;
   }
}

En la subrutina «datos()» se identificara el comando y el valor correspondiente, para ello se declaran dos variables para separa el comando del valor.


   char ID_val[6];
   char num[4];

   char val01[6] = "val01";
   char val02[6] = "val02";

La variable «recibido[]» contendrá el comando y el valor recibido, por lo que, en el primer ciclo «for()» se obtienen los primeros 5 caracteres correspondientes al comando, sea «val01» o «val02» y se guarda en la variable «ID_val[]», en el segundo ciclo «for()» se obtienen los tres caracteres siguientes correspondientes al valor y se guarda en la variable «num[]».


       for (int i=0; i<=4; ++i)
      {
         ID_val[i] = recibido[i]; //identifica la variable
      }

      for (int i=0; i<=2; ++i)
      {
         num[i] = recibido[i+5]; //guarda el valor de la variable
      }

Los siguiente es utilizar la función «strcmp()» para comparar el comando recibido con los diferentes comandos declarados, cuando la comparación resulta igual, la función devuelve «0» y entrara a la sentencia «if()» donde se utiliza la función «atoi» para convertir el valor en «num» que es una variable de caracteres a una variable de 8 bits, finalmente el valor se guarda en la variable correspondiente al comando sea «val01_num» o «val02_num».


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

      if(result==0)
      {
         val01_num = (int8)atoi(num);  //convierte la cadena en un numero de 8bits
         return;
      }

      result = strcmp(ID_val, val02);

      if(result==0)
      {
         val02_num = (int8)atoi(num); //convierte la cadena en un numero de 8bits
         return;
      }

En este ejemplo se utilizara el valor recibido para controlar el ciclo de trabajo de dos señales PWM de salida en los pines CCP1 y CCP2.

Se habilita el timer2 para generar la señal de salida.


   setup_timer_2(T2_DIV_BY_16,63,1);

   setup_ccp1(CCP_PWM);//habilita el pin ccp1
   setup_ccp2(CCP_PWM);//habilita el pin ccp2

Se colocan las variables en las funciones para controlar el ciclo de trabajo.


      set_pwm1_duty((int16)val01_num);//100% duty clicle = numero 255
      set_pwm2_duty((int16)val02_num);

Finalmente antes de colocar la librería «usb_cdc.h», se define la interrupción por recepción de datos USB, colocando la subrutina en este caso «recibe()» y después de definirla se declara la subrutina «void recibe();»


#define USB_CDC_ISR() recibe() //Interrupcion por recepcion de datos

void recibe();//Subrutina de la interrupcion

Código completo


#include "stdlib.h"

#FUSES NOMCLR

#define USB_CDC_ISR() recibe() //Interrupcion por recepcion de datos

void recibe();//Subrutina de la interrupcion

#define USB_CONFIG_BUS_POWER 500 //500ma corriente de entrada

#include "usb_cdc.h"

char recibido[15];

int8 val01_num = 0;
int8 val02_num = 0;

void datos();

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

      if(recibido[i] == '\n')//busca el salto de linea \r
      {
         recibido[i-1] = '\0';  //  \r = \0 (caracter nulo)
         recibido[i] = '\0';   //  \n = \0 (caracter nulo)

         datos();
         return;
      }
      i++;
   }
}

void datos()
{
   signed int8 result;

   char ID_val[6];
   char num[4];

   char val01[6] = "val01";
   char val02[6] = "val02";

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

       for (int i=0; i<=4; ++i)
      {
         ID_val[i] = recibido[i]; //identifica la variable
      }

      for (int i=0; i<=2; ++i)
      {
         num[i] = recibido[i+5]; //guarda el valor de la variable
      }

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

      if(result==0)
      {
         val01_num = (int8)atoi(num);  //convierte la cadena en un numero de 8bits
         return;
      }

      result = strcmp(ID_val, val02);

      if(result==0)
      {
         val02_num = (int8)atoi(num); //convierte la cadena en un numero de 8bits
         return;
      }
}

void main()
{
   usb_init(); 
   
   setup_timer_2(T2_DIV_BY_16,63,1);

   setup_ccp1(CCP_PWM);//habilita el pin ccp1
   setup_ccp2(CCP_PWM);//habilita el pin ccp2
   
   while(TRUE)
   {
      set_pwm1_duty((int16)val01_num);//100% duty clicle = numero 255
      set_pwm2_duty((int16)val02_num);

      //TODO: User Code
   }

}
Scroll al inicio