Tuesday, September 13, 2016

PIC18F4550 USB HID Example using CCS PIC C

PIC18F4550 microcontroller has 1 USB (Universal Serial Bus) communication module. This topic shows how to use PIC18F4550 as a USB HID (Human Interface Device) to send and receive data from the PC.
The USB HID device doesn't need any additional driver because it's already installed in most of modern operating systems.
PIC18F4550 USB HID example hardware circuit:
The following figure shows our example basic circuit schematic.
PIC18F4550 USB HID example circuit CCS PIC C
The USB power supply pin (5V) can be used in this project.
To send/receive data to/from the microcontroller using USB communication a software named HID Terminal from MikroElektronika is used. The main interface of this software is shown below:
USB HID Terminal data receive and transmit
HID Terminal can be downloaded from the following link:
HID Terminal
About Example:
After plugging the USB cable which comes from the microcontroller, the device will appear in the HID devices list which named USB HID Example. If we want to send data to the microcontroller just tape the text and click on Send.
The LCD is used to display the data received by the microcontroller and after 1 second the microcontroller sends the same data back to the PC which will appear in the HID terminal software.
PIC18F4550 USB HID Example CCS C code:
In this project the an external oscillator (8MHz) is used to run the microcontroller as well as the USB module. PIC18F4550 microcontroller always needs an external oscillator to run its USB module.
The fuses used in this project are:
HSPLL : high speed oscillator is used with PLL enabled
PLL2 : Divide by 2  (8MHz oscillator input)
CPUDIV1 : No system clock postscaler
USBDIV : USB clock source comes from PLL divide by 2
VREGEN : USB voltage regulator enabled
NOMCLR : Master Clear pin used for I/O (MCLR pin function disabled)
The program can send and receive a maximum of 16 bytes. The sizes can be changed with the following two lines:
#define USB_CONFIG_HID_TX_SIZE 16                // Transmit packet size (bytes)
#define USB_CONFIG_HID_RX_SIZE 16                // Receive packet size (bytes)

The following two lines for product ID and vendor ID numbers. This numbers can be changed:
#define USB_CONFIG_PID 1                         //Chnage Product Id
#define USB_CONFIG_VID 1234                      //Chnage Vendor Id

Other lines are described in the code.
// PIC18F4550 USB HID Examlpe CCS C code
// http://ccspicc.blogspot.com/
// electronnote@gmail.com
// Use at your own risk

//LCD module connections
#define LCD_RS_PIN PIN_D0
#define LCD_RW_PIN PIN_D1
#define LCD_DATA4 PIN_D3
#define LCD_DATA5 PIN_D4
#define LCD_DATA6 PIN_D5
#define LCD_DATA7 PIN_D6
//End LCD module connections

#define USB_CONFIG_HID_TX_SIZE 16                // Transmit packet size (bytes)
#define USB_CONFIG_HID_RX_SIZE 16                // Receive packet size (bytes)
#define USB_CONFIG_PID 1                         //Chnage Product Id
#define USB_CONFIG_VID 1234                      //Chnage Vendor Id

#include <18F4550.h>
#use delay(clock = 48000000)
#include <lcd.c>
#define USB_STRING(x)  (sizeof(_unicode(x))+2), 3, _unicode(x)
rom char USB_STRING_DESC[]={
    //string 0 (must always provide this string)
    //4(length of string index),3(desciptor type is string),9&4(Microsoft Defined for US-English)
    4, 3, 9, 4,  
    //string 1 - vendor (this is optional, but we specified it's use in the device descriptor)
    //string 2 - product (this is optional, but we specified it's use in the device descriptor)
    USB_STRING("USB HID Example"),
    //string 3 - serial number (this is optional, but we specified it's use in the device descriptor)
#include <usb_desc_hid.h>

char data[16];
void main(){
  lcd_init();                                    // Initialize LCD module
  lcd_putc('\f');                                // LCD clear
  lcd_gotoxy(1, 1);
  lcd_putc("USB HID Example");
  usb_init_cs();                                 // Initialize USB hardware
    if(usb_enumerated()){                // If the device has been enumerated by the PC
      if(usb_kbhit(1)){                  // If endpoint1 has data in it's receive buffer
        lcd_gotoxy(1, 2);
        lcd_putc("                ");            // Clear 2nd line
        // Read up to 16 bytes from endpoint1 buffer and save it to variable data
        usb_get_packet(1, data, 16);
        lcd_gotoxy(1, 2);
        printf(lcd_putc, data);                  // Display the received bytes on LCD
        delay_ms(1000);                          // Wait 1 second
        // Return the received bytes back
        usb_put_packet(1, data, 16, USB_DTS_TOGGLE);

PIC18F4550 USB HID Example Videos:
The following video shows our example in protoboard circuit.

And the following video shows example Proteus simulation.