In this article we’re going to explore creating a simple sample for getting the PIC18F14K50 USB Breakout Board up and running as a USB HID device. Unlike last time, we’ll be using MikroElektronika’s mikroC PRO for PIC (version 126.96.36.199). In this example we won’t be using Microchip’s USB HID Bootloader, but rather programming the board directly with a programmer. I’ll be using the PICkit 3.
I like mikroC for a few reasons. The IDE itself is a pleasure to use, and I find many of the included libraries to be extremely helpful and very usable. Comparing this to other C compilers, I believe most people who are just getting started with microcontrollers and or C will find this compiler one of the easiest to use.
In this example, we’re using the USB library which will allow us to get our sample running in a very minimum number of lines of code which are also extremely easy to read. There are a few details along the way specific to the PIC18F14K50 so be sure to pay close attention.
Project files and code for this tutorial can be found on github: Click here
Our first step is to prepare our project.
Click “File” then “New” then “New Project…” This will display the New Project Wizard.
Step 5/6 allows us to choose whether we want to include all available libraries in the project. I typically choose to “Include None” and select them later – we’ll talk more about this in a bit. Click “Next“
Edit Project Settings
There are a few changes we need to make to the “Edit Project” screen in order to allow the code to operate on our board. This screen in particular sets the configuration bits for the device. If at the end of this article you’re having trouble getting your board to function – the most likely place to start looking for errors is here. If you miss this step, you can always access project settings by going to “Edit” and then “Edit Project Settings“.
Here are our changes:
- Make sure that Oscillator is set to “HS”
- 4 X PLL Enable bit should be set to “Oscillator Multiplied by 4” – This one is critical. Our board has a 12 MHz crystal, but we want the PIC to run at 48 MHz for compatibility with USB. This setting allows the PIC to run at this higher speed by using an internal PLL.
- Make sure that MCU Name is set to “PIC18F14K50”
- Make sure that Oscillator Frequency [MHz] is set to “48.000000”
- Click “OK”
One last step before we start coding – on a previous screen we had chosen not to include all libraries. Now we’ll go in and select the library we need for this project. On the right side of the IDE, you’ll see a tab called “Library Manager” – hover over this, and the list of available libraries should display. Scroll all the way to the bottom, and check the USB library.
Now it’s time to get started with the code. We will be using a modified version of MikroElektronika’s USB Library demo – with a few tweaks to make it operational on the PIC18F14K50.
Our code will be in two parts (or files in this case). We’ll have our main code file, in my project I call it USBHIDExample.c, and we’ll also have a file called USBdsc.c which is the code for our USB Descriptor. In short, every USB device needs to be able to identify itself, and its function or utility to the host on initialization. Our descriptor file contains the details which the library will use to send back to the host. In this case we’re creating an HID device, so the code will define this. USB Descriptor files can get fairly complicated – fortunately for HID device code, mikroC includes a utility called the “HID Terminal” which not only lets us test out our device (we’ll use this at the end of this article just for that), but also has a code generation capability geared towards creating a USB descriptor file for HID devices. So let’s create that file now.
Open the “HID Terminal” tool by clicking “Tools” and then “HID Terminal”
Click on the “Descriptor” tab, and enter the values shown in the screenshot. In summary, VID and PID are used to set the Vendor ID and Product ID for the USB device, which can be used later in code on your host to identify your device. Report Length specifies the number of bytes sent or received in a data transfer to or from your USB device. Vendor Name and Product Name are both strings that could be displayed on your host and further describe your device to the user.
Make sure “mikroC” is selected, click “Save descriptor”, navigate to your project’s root folder and save the descriptor file as USBdsc.c You can close the HID Terminal for now.
It is important to note that USB devices are licensed, and require a valid VID and PID in order to be sold. Each manufacturer must register for a Vendor ID, and then use Product ID’s under that Vendor ID. For our own testing however, we can use these “made up” values –just don’t plan to sell your new device using these! In the past, Microchip has offered the ability for users to register to use their VID with a specific Product ID for a limited number of devices, provided you’re using a Microchip Micro in your device. This could be a very cost effective option if you’re not looking to sell a bunch of devices. The last time I checked, this gave you permission to distribute up to 1000 devices with that Product ID. Check out Microchip’s web site for more details if you plan on using USB in a sellable design.
Now that we’ve generated the descriptor file, we need to add it to our project so that it is compiled. Click on the Project Manager tab on the right side of the IDE, then right click “Sources” and click “Add file to project…” navigate to the new USBdsc.c file and click “Open”.
Okay now back to the fun stuff, coding!
At the top of the file, in my case called “USBHIDExample.c” we’ll start by defining a few unsigned char variables which will act as our read and write buffers. These are unique in that we will be specifying where the compiler should place these in the PIC’s RAM by specifying an address with the absolute directive. The locations below are specific to the PIC18F14K50, and I find they work for this example.
You can see we’ve specified an address of 0×280 for the read buffer, and 0x2C0 for the write buffer. We’ve also defined a char variable called cnt – we’ll use this later.
Now, seeing we’ll be using an interrupt for USB servicing, we’ll need to include this in our code as follows:
This interrupt will fire periodically and execute the library function for USB servicing. This is critical, without it, your USB device will not function. Among several operations one of the most critical that are handled here are somewhat of a watchdog or keepalive type function that periodically contacts the host to keep the connection in place – otherwise your host would report your device as disconnected.
Now we’re ready for the main function.
One important takeaway from that portion of code is how we are looping through our 64 byte buffer, and then when we write our buffer to USB through HID_Write, note that we must send the entire 64 bytes, even if we’re only using a portion of them. This goes back to our descriptor where we specified the “Report Length” – our communication packets must always match this length.
So in total, our USBHIDExample.c file should now look like this:
That’s just 18 lines of code to get a simple example running, not bad at all!
Now that the code is done, it’s time to compile. Press CTRL+F9 or go to “Build” and click “Build”. You should see the compile process in the Messages window at the bottom of the screen, and hopefully the last message will start with “Finished successfully”. If there are any errors, go back and double check your code. Common mistakes are to forget to check off the USB library in the Library Manager, or to forget to include the USBdsc.c file in your project. Either will produce several errors.
It’s time to program the firmware into your PIC18F14K50 USB Breakout Board. I’m using a PICkit 3 to do this. It’s just a matter of going to MPLAB and importing the .hex file, or using the standalone PICkit 3 Programmer application. Be sure if using MPLAB that you leave the setting to use configuration bits from code.
Once programmed, disconnect your programmer form the breakout board. Now, make sure the power jumper is set to BUS, and disconnect any external power you may have been using. We’ll be using bus power for this example.
Now that the board has been programmed, we’re ready to test. Plug the board into your host PC via a USB cable. You’ll likely see a short delay while windows tries to find a driver for a generic HID device – once that is complete, your device should be connected. If there are any issues, you may see a popup regarding an unrecognized device. This is a pretty generic error but I find it is typically related to configuration bits not being set correctly which results in the board not being able to communicate with the host.
Now to test functionality. Back in the mikroC IDE, go to “Tools” and click on “HID Terminal”. Click on the “Terminal” tab. You should see your device listed in the HID Devices list, if you used the same product name as in the example above, it will show up as HID Test. To test, simply enter some text into the Communication’s section text box, and click “Send”. Your message will be sent to the breakout board, and you should see the message echoed in the bottom text box. If you change the format to HEX or DEC, you’ll see your message (in the corresponding format) as well as trailing filler data (either 0×00 or 0 depending on format).
Congratulations, you just finished your first USB device program with the PIC18F14K50 USB Breakout Board, and mikroC!
While this tutorial was pretty detailed and of significant length, now that you’ve gone through the process you can see the actual code required to get everything working is pretty minimal. From here you can add your own functions to start creating your own custom USB enabled device. It would be pretty simple to take this as a starting point, and create a USB device which communicates with an external peripheral over I2C – such as an accelerometer – and returns the data to the host PC. We’ll leave that for another post.
Project files and code for this tutorial can be found on github: Click here
Feedback is always welcome – if you enjoyed this tutorial, or have ideas for improvement or for another tutorial please feel free to leave a comment here or in our Forums. Thanks for reading!