USB Communication Circuit Diagram

Figure 1: USB Communication Circuit Diagram

The CDC device class code is “0x02, this class defines various communications over USB.
The CDC class can be used to emulate the RS232 serial port (COM Port) and thus creating an easy solution to migrate the application from an old RS232 to the Universal Serial Bus (USB) interface without implementing many changes especially to the PC software. The device will create a virtual COM.

The current MikroC Pro for PIC version 6.0.0 does not have a built in USB CDC library in the compiler, but you can download the USB Device Library from LIBSTOCK. This library supports the USB HID Class, the USB CDC Class and the USB Mass Storage Device Class.

The file you are going to download has an .mpkg extension. You need the package manager to integrate this USB library into the MikroElekronika compilers. You can download the latest package manager from MikroElekronika website.

Once you have installed the package manager, Open the desired package file (*.mpkg) and it’s content will be displayed in Navigation and Information sections.

Click on File->Install option and the installation will begin. Installer will copy your package content into destination folders and update your definition files.

Figure 2: Installing a library into MikroC compiler

New installed library will appear in Library Manager of your compiler, and only for those chips that are compatible with installed library.

Figure 3: New installed library (USB_Device_PIC) in library manager

Below is a quick descriptions of the USB CDC Class library routines as described in the USB Device Library help file. This library works when PIC microcontroller with built-in USB are used (e.g., PIC18F4550), and port pins RC4 and RC5 are connected to the D+ and D- pins of the USB connector respectively.
USB buffers for sending and receiving data must be placed in the USB RAM.
You must also remember to set your clock configurations correctly as learned in USB Communication with PIC Microcontroller article.

To write a device class, certain function callbacks must be implemented in order to be used with library.
These functions must be in the user code:
USBDev_GetDescriptorHandler: Called when host requests descriptor.
USBDev_EventHandler:  This function is called when specific event happens, like device reset.
USBDev_SetupReqHandler: Called when there is a need to process non-standard requests.

USBDev_DataReceivedHandler: Called when data packet is received.
USBDev_DataSentHandler: Called when data packet is sent.

Some other Library Routines

USBDev_Init
This function initializes USB module in device mode.
This function returns no data.
Example:
USBDev_Init(); 

USBDev_IntHandler
This is a routine for servicing usb interrupts. This function should be called from USB interrupt routine.
Before using this function, the device should be initialized first and the USB interrupt should be enabled.
This function returns no data.
Example: 
// USB interrupt service routine
void interrupt()
{
 // Call library interrupt handler routine
USBDev_IntHandler();
}

USBDev_GetDeviceState
This function returns the current USB Device state.
Prototype: uint8_t USBDev_GetDeviceState(); 
Example:
// Wait until device is configured (enumeration is successfully finished) 
while(USBDev_GetDeviceState() != _USB_DEV_STATE_CONFIGURED) ; 

For more functions, please read the USB Device Library help file.

USB Device Library – CDC Class

USBDev_CDCInit
This function initializes the USB.
Before you can use any other functions, this  function should be called first.
This function returns no data.
Example:
void USBDev_CDCInit();  // Initialize CDC Class 
         
USBDev_CDCGetLineCoding
Prototype: TUSBCDCLineCoding* USBDev_CDCGetLineCoding(); 
Returns: Pointer to line coding structure.
Description: Returns pointer to line coding structure containing data rate, stop bits, parity and data bits.

USBDev_CDCSetLineCoding
Prototype: void USBDev_CDCSetLineCoding (uint32_t dwDTERate, uint8_t bCharFormat, uint8_t bParityType,
uint8_t bDataBits); 

This function returns no data.
Description: Sets line coding structure, data rate, stop bits, parity and data bits.
Parameters:
dwDTERate: data rate in bits per second.
bCharFormat: stop bits: 0 – 1 stop bit, 1 – 1.5 stop bits, 2 – 2 stop bits.
bParityType: parity: 0 – None, 1 – Odd, 2 – Even, 3 – Mark, 4 – Space.
bDataBits: data bits: 5, 6, 7, 8 or 16.

USBDev_CDCSendData
Prototype: void USBDev_CDCSendData(uint8_t* dataBuff, uint16_t dataLen); 
This function returns no data.
Description: This function sends data to the bulk data endpoint and requires two parameters:
dataBuff: pointer to the data (buffer to hold the data).
dataLen: length of the data (less or equal to the maximum packet size)
Example:
char buffer[64] absolute 0x500;    // Buffer of 64 bytes
uint16_t dataReceivedSize;           
//  length of the data

USBDev_CDCSendData(buffer, dataReceivedSize);  // Send data in buffer memory to the bulk data endpoint

USBDev_CDCSetReceiveBuffer
Prototype: void USBDev_CDCSetReceiveBuffer(uint8_t* dataBuff); 
This function returns no data.
Description: This function enables reception of one data packet on the data endpoint and it has one parameter:
dataBuff: pointer to the buffer where received packed will be stored.
The size of this reception buffer should be at least maximum packet size for that endpoint.

Example:
USBDev_CDCSetReceiveBuffer(buffer);  // Set receive buffer where received data is stored

USBDev_CDCDataReceived
Prototype: extern void USBDev_CDCDataReceived(uint16_t size);
This function returns no data.
Description: This function is going to be called when the packet is received on data endpoint and it
has one parameters: size: size of received data.

USBDev_CDCParamsChanged
Prototype: extern void USBDev_CDCParamsChanged();
This function returns no data.
Description:This function is going to be called when host issues Set Line Coding request.

                         Example

This project example (circuit on figure 1) shows the usage of USB CDC device that functions as a virtual COM port.

This example will send “This is USB CDC Example by studentcompanion.co.za” to terminal then send “Press any key…” after this any character pressed will be echoed back to the USART terminal.

When the device is connected to PC for the first time, Windows will detect a new hardware. Windows will ask you to install the device drivers. Tick on Install from a list or specific location (Advanced) radio box. Then click Next.

Browse for the device drivers then click Next, Windows will install the drivers for you. The project can be tested by connecting the output of the microcontroller to a USB port of a PC and then running the HyperTerminal terminal emulation software or any other serial terminal software

If you are using Microsoft windows XP, Go to Start, All Programs, Accessories, Communications and Hyper Terminal to open a windows free Hyper Terminal. 
Connect your Hyper Terminal to the correct COM Port (your USB virtual port).
To find out which COM Port has been assigned to your virtual Serial port, go to device manager (if you are using Windows XP, go to My Computer, at right hand side pane, click on View system information, click on Hardware tab then Device Manager) and expend the Ports (COM & LPT) to see all the COM ports on your PC.

Note: Your computer will automatically allocate a COM port number to your virtual Com Port, it does not have to be the same a the one illustrated here below on figure 4 (COM25) 

Figure 4: Virtual COM Port (COM25) in device manager

If your serial driver was installed correctly, you should see Mikroe Virtual Com Port and in bracket the COM number in the device manager as shown on figure 2 above.
Set the communications parameters to 9600 baud, 8 data bits, 1 stop bit, and no parity bit as shown on figure 5 below.

Figure 5: COM Port settings

Note: If you connect your device in another USB port, you will have to re-install the drivers again.

Here is the full project code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <stdint.h>
// Buffer of 64 bytes in USB RAM
char buffer[64] absolute 0x500 ;
// USB interrupt service routine
void interrupt(){
// Call library interrupt handler routine
  USBDev_IntHandler();
}
void USBDev_CDCParamsChanged(){
}
extern const uint8_t _USB_CDC_BULK_EP_IN;   // Data interface IN endpoint
extern const uint8_t _USB_CDC_BULK_EP_OUT;  // Data interface OUT endpoint
uint8_t dataReceived = 0;
uint16_t dataReceivedSize;
void USBDev_CDCDataReceived(uint16_t size){
  dataReceived = 1;
  dataReceivedSize = size;
}
//A function to send data to Uart when called
void Send_Data_To_Uart(char txt[64])
{
    int i;
    for(i = 0; i < strlen(txt); i++)
 {
    buffer[i] = txt[i];
 }
  USBDev_CDCSendData(buffer, strlen(txt));
}
void main(void){
  ADCON1 |= 0x0F;         // Configure all ports with analog function as digital
  CMCON  |= 7;            // Disable comparators
  // Initialize CDC Class
  USBDev_CDCInit();
  // Initialize USB device module
  USBDev_Init();
  // Enable USB device interrupt
  IPEN_bit = 1;
  USBIP_bit = 1;
  USBIE_bit = 1;
  GIEH_bit = 1;
  // Wait until device is configured (enumeration is successfully finished)
  while(USBDev_GetDeviceState() != _USB_DEV_STATE_CONFIGURED)
    ;
  // Set receive buffer where received data is stored
 USBDev_CDCSetReceiveBuffer(buffer);
delay_ms(5000); //5s delay
 //Send an Introduction text to Uart
 Send_Data_To_Uart("This is USB CDC Example by studentcompanion.co.zarn");
 delay_ms(500);
 Send_Data_To_Uart("Press any key...rn");
 
 // Infinite loop
while(1){
if(dataReceived == 1){
     dataReceived = 0;
       //Send back received packet
     USBDev_CDCSendData(buffer, dataReceivedSize);
    // Prepare receive buffer
      USBDev_CDCSetReceiveBuffer(buffer);
   }
  }
}

Figure 6 below shows data sent to terminal on a personal computer connected to the microcontroller via a USB port.. 

Figure 6: Computer Terminal

>> Read also on student companion: Creating a Serial Port Interface with C#

You can download the full project files (MikroC source code and Drivers) below here.

All the files are zipped, you will need to unzip them (Download a free version of the Winzip utility to unzip files).

Download: USB CDC Driver

Download: USB CDC Example