ComunicaciĆ³n USB, 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 comandos al microcontrolador para encender y/o apagar los LEDs 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();

En la subrutina recibe(), se recibe la cadena de caracteres o el comando, utilizando la funciĆ³n Ā«usb_cdc_getc()Ā» y en la sentencia Ā«if()Ā» espera el carĆ”cter Ā«\r\nĀ» para saber cuando terminara de recibir los 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 Ā«leds()Ā» inicialmente se colocan los comandos que se pueden recibir para despuĆ©s hacer la comparaciĆ³n con los comandos recibidos.


void leds()
{
   signed int8 result;

   char LED1_ON[8] = "LED1_ON";
   char LED1_OFF[9] = "LED1_OFF";

   char LED2_ON[8] = "LED2_ON";
   char LED2_OFF[9] = "LED2_OFF";

   char LED3_ON[8] = "LED3_ON";
   char LED3_OFF[9] = "LED3_OFF";
   .
   .
   .

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()Ā» paraĀ  encender o apagar el LED correspondiente al comando recibido.


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

      if(result==0)
      {
         OUTPUT_BIT(LED1,1);
         return;
      }//enciende el led1

      result = strcmp(recibido, LED1_OFF);

      if(result==0)
      {
         OUTPUT_BIT(LED1,0);
         return;
      }
      .
      .
      .

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


#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"

#define LED1   PIN_D0
#define LED2   PIN_D1
#define LED3   PIN_D2

char recibido[15];

void leds();

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++;
   }
}


void leds()
{
   signed int8 result;

   char LED1_ON[8] = "LED1_ON";
   char LED1_OFF[9] = "LED1_OFF";

   char LED2_ON[8] = "LED2_ON";
   char LED2_OFF[9] = "LED2_OFF";

   char LED3_ON[8] = "LED3_ON";
   char LED3_OFF[9] = "LED3_OFF";

   while (true)
   {
      result = strcmp(recibido, LED1_ON);//compara, si son iguales (0), no (+-1)

      if(result==0)
      {
         OUTPUT_BIT(LED1,1);
         return;
      }//enciende el led1

      result = strcmp(recibido, LED1_OFF);

      if(result==0)
      {
         OUTPUT_BIT(LED1,0);
         return;
      }

      result = strcmp(recibido, LED2_ON);

      if(result==0)
      {
         OUTPUT_BIT(LED2,1);
         return;
      }

      result = strcmp(recibido, LED2_OFF);

      if(result==0)
      {
         OUTPUT_BIT(LED2,0);
         return;
      }

      result = strcmp(recibido, LED3_ON);

      if(result==0)
      {
         OUTPUT_BIT(LED3,1);
         return;
      }

      result = strcmp(recibido, LED3_OFF);

      if(result==0)
      {
         OUTPUT_BIT(LED3,0);
         return;
      }
      return;
   }
}


void main()
{
   usb_init();
   while(TRUE)
   {


      //TODO: User Code
   }

}
Scroll al inicio