Sunday, April 17, 2011

USB and PIC Microprocessors 16C745 and 18F2455

http://www.alanmacek.com/usb/

Introduction

This page describes a project a colleague and I completed between September, 2000 and March, 2001 as part of the Engineering Physics degree program at the University of British Columbia.   In summary this project involved building a USB device using the PIC 16C745 microprocessor from Microchip.  The USB device consisted of a microphone, the microprocessor and other hardware and the device sent audio data to the host computer.
This page contains notes, links and code extracts from this project relating to USB, USB Human Interface Devices, the 16C745 microprocessor, and specifics of this project.  Hopefully this information will be helpful to your project.

Table of Contents


Result

We achieved our goal and built a working device.  This involved building the device hardware (microprocessor, microphone, and supporting electronics) and software (microprocessor code and host computer code).  Unfortunately, the relatively low sampling rate by the microprocessor in the analog-to-digital conversion process mangled the audio signal to make it indecipherable at the host computer, but loud/soft transitions were easily detected.
To top.

USB

USB (Universal Serial Bus) is a protocol that allows two way communication between peripheral devices and a host computer.  It is hot pluggable, allowing the device to be connected and/or removed while the computer is running.  There are lots of other features of USB.
The specifications for USB are available at www.usb.org.  Be warned that while this information is very thorough, it is not very practical for developing a device or software.  Technical documents are available at www.usb.org/developers/docs.html.
Here is a quick overview of what is involved in USB.
  • The Hardware:
    • A USB cable has four wires: power, ground, D+ and D-. The signal wires usually operate in differential mode (one is high while the other is low).
    • There are two types of USB devices: high speed and low speed. There are differences in the type, length and connectors that can be used with the two types. Generally the requirements are stricter for high speed devices. A high speed device can transfer data at a maximum of 12 Mbs while low speed is limited to 1.5 Mbs.  The PIC 16C745 can only operate at low speed standard.
    • The connector at the computer (A End) is a flattened rectangle while at the device (B end) the connector is square with two cut-off corners (necessary to be compliant with the high-speed standard but optional for low speed devices).
    • Each USB device is able to draw 100mA from the cable which allows a device to be bus powered. A device can negoiate up to 500mA once connected to the USB cable but this power may not be available.  If the power is unavailable the device must stay in a low power setting. Obviously devices can be powered externally as well.
  • The Software:
    • When a device is connected, the computer (or a hub) detects the device by a pullup resister (see circuit). A pullup resister on the D- wire signals a low speed device, while a high speed device has a pullup on the D+ wire. When detected a series of enumeration steps are started.
    • The enumeration process assigns an identifier number to the device (there can be a maximum of 127 devices on a network) and also tells the host computer what sort of capabilities a device has (input, ouput, etc). The device also informs the computer of its name (Vendor, Product, Version and Serial Number).
    • If the device identifies itself as a HID (Human Interface Device) then the device describes how the data should be interpreted. See the section on HID.
To top.

USB and Human Interface Devices (HID)

Human Interface Devices (HID) are a class of USB devices that give structure to the data that will transfered between the device and the host computer. During the enumeration process, the device describes the information that it can receive and send.  This allows a host computer to handle the data being received from the USB device without requiring a specially designed device driver.
The HID class is supposed to include devices such as a mouse, joystick, keyboard, etc. Because the host computer knows what the data means a device driver is not necessary for HID devices, the operating system can supply a generic HID driver. For instance, if you plug in a USB Mouse, it will immediately work because the OS knows how to interpret information received from a mouse.
Information on the HID class can be found at www.usb.org/developers/hidpage. You can see examples of HID descriptors starting on page 89 of the HID 1.1 spec from usb.org.

A very useful tool for designing HID class devices is the HID Descriptor Tool also available from usb.org. This tool allows you to put together the HID description and run it through the HID parser.

Some other useful tools are available from Intel University Press[1]. They include 'USB Single Step', 'USBView', 'HIDView' and the HID Descriptor Tool described above.

If you are using Visual C++, then the 'hview' sample program that comes with the Windows DDK is good for examining the HID descriptor and values. Unfortunately the program is more complicated than it needs to be and is not a good example of using the USB functions.
To top.

PIC 16C745

I used the PIC 16C745 from Microchip as the USB interface microcontroller. This chip belongs to a two chip family (along with the 16C765) called the 16c7xx.

The 16C745 is a 28 pin microprocessor operating at 24 Mhz. It has 8K of program memory, 256 bytes of RAM and 5 x 8bit analog inputs (the 16C765 has 40 pins and 8 analog inputs). The specifications are available from Microchip. The reference manual for the mid-range microprocessors is also useful.

Download the development environment from Microchip called MPLAB (freely available from Microchip's web site). Another necessary component is the USB firmware. The support files that I used seem to no longer exist on the Microchip web site being replaced by a more sophisticated USB example. The firmware includes the following pieces:
  • The 'Chapter 9' standard protocol support. The name comes from the set the messages being described in Chapter 9 of the USB specification. This is a file called usb_ch9.asm.
  • The HID interface support. This file handles requests for information relating to the HID specification. This is a file called hidclass.asm.
  • The device descriptor. This file contains the data that will be sent to the host during the enumerator process. Most of the values are fully specified by the USB spec but the vendor id, product id and version number all specified here. Importantly, the HID descriptor is stored in this file. This file is called descriptors.asm (also known as usb_mouse.asm). The version you download identifies the device as a mouse to the host.
  • The demo program. This program sets up the interrupts and initializes the USB code. It also runs through a loop that causes the cursor to move in a box shape on the screen. This program demonstrates how you use the USB specific functions to communicate with the host. This file is called main.asm (also known as usb_main.asm).
  • There is also a definitions include file called usb_defs.inc.
  • The entire project has an MPLAB project file (usbmic.pjt)
Warning: It has been a long time since I've worked on this project so I do not know if these files are complete or if they can be compiled directly.
Try to understand how the usb_main.asm file works. A couple of gotchas that you should watch out for are:
  • Triple check that the HID descriptor you are using matches the one you design in the HID Descriptor Tool. Even a single difference in a hex value will cause a failure in the enumeration process.
  • If you are using a HID descriptor, make sure that the number of bytes described in your descriptor is exactly the same as the number of bytes you are actually sending.
I used the PIC-Start programmer available from Microchip to program the 16C745.  Because this chip is not available in a flash version, a UV light is also required in order to erase the program before it can be reprogrammed.  If you are looking for a suitable third party programmer, look for those that have an external power supply of at least 12V.  Programmers that are powered from the USB or Serial port are NOT powerful enough for the non-flash microprocessors such as the 16C745.  I have used a programmer from http://www.kitsrus.com/ with success and they have programmers suitable for the 16C745.
To top.

Host Computer Code

Once a have is connect, you want to send and receive data from your applications. This document describes how you can do with using C in Visual C++. It is also possible to do this in Visual Basic (see below)

The following examples assume you are using Windows 2000. It should also work on Windows 98 but I'm not sure what the differences might be. Windows 95 did not fully support USB.  Linux also supports USB HID.
More information on these Windows API calls are available on the Microsoft web site. I used to have links directly to the appropriate page on the Microsoft MSDN website but Microsoft, in their wisdom, rearrange their website every 6 months or so, breaking all the links.  Compiling code to use these function calls requires that you install the Windows DDK (Device Development Kit) which used to be freely available from the Microsoft website (see below obtaining copies of the required dlls and header files.)
  • HidD_GetHidGuid (GUID *hidGUID)
  • HDEVINFO SetupDiGetClassDevs (GUID hidGUID, PSTR *filterString, hwndParent, DWORD flags)
  • BOOL SetupDiEnumDeviceInterfaces (infoset, infoData, interfaceClassGuid, index, deviceInterfaceData)
  • BOOL SetupDiGetDeviceInterfaceDetail (infoSet, deviceInterfaceData, interfaceDetail, interfaceDetailSize, requiredSize, infoData)
  • HANDLE CreateFile (name, access, sharemode, security, creation, flags, template)
  • BOOL HidD_GetAttributes (deviceHandle, &deviceAttributes))
See the example code below for details on using these methods.
To top.

Visual Basic Code

Even though Visual Basic does not allow direct access to the API calls, you can convert the API calls into visual basic functions. A good source of examples is at the web site for the book USB by Example[1]. The files HIDinterface.bas and OSinterface.bas available from the book's web site demonstrate using the API calls in Visual Basic.
To top.
-

Example Host Code

I have put together some library code which uses the above api's to connect to available HID USB devices.  The code returns a file handle to the USB device which allows a program to read and write data with the device just like with a regular file handle.  Note that this code is not a fully working program - it requires, at the minimum, a main function.
These file are known to compile under Visual C++ 5.0 on Windows 2000 with the Windows DDK installed. Make sure that the path to the file 'setupapi.h' is in your header file path (Project->Settings). You will also need to add 'setupapi.lib' and 'hid.lib' to list of libraries and ensure the path to these files is added to the library path for your project.
The code samples are:
You can either download the complete Windows DDK (which used to be available free from the Microsoft Website at http://www.microsoft.com/ddk/W2kDDK.htm or download just the few files actually needed for the sample code. These are from the Microsoft DDK which used to be freely available.
One person who found my code useful optimized my example code which removes some of the dependencies on the Windows DDK.  See Ross Bencina's P5 Glove Project for details.

A visitor to my site, Jim Koornneef, has provided a C++ class wrapper for my code that you can download from usb.h and usb.cpp.  This class encapsulates the functionality in my code but also provides read/write methods and automatic connect/disconnect functionality.
To top.

Project Hardware

This section describes the hardware specific to my project.  Please note that the focus of this page is on the USB aspects of the project.  My understanding is that the analog circuity for the microphone is not well designed.
The analog signal from the microphone was amplified using an op-amp and then digitized using the 16C745's analog-to-digital feature.  If you are reproducing this project, I would recommend putting in a filter to remove the frequencies higher than the microprocessor's sampling rate.  The digital data was buffered in the microprocessor and then set to the host computer over the USB connection.  Since 'interrupt' method of transfer only allows 8 bytes of data transfered every 10ms, this limited the amount of data that could be transfered.
The following circuit connects the PIC to the usb cable. It is designed to be powered off the USB cable. The 6 MHz clock controls the internal oscillator.

The 'reset' switch, causes a reset condition which should cause most of the special registers to clear and the program to start again.

The value of R1 is not critical since it is only used as a pull-up for the MCLR (master clear) pin. The R2 resister is required by the USB specification and should be 1.5 kOhms. The capacitor C3, is not critical and simply stabilizes the Vusb pin voltage. The values of the capacitors, C1 and C2 can be in a range specified in the 16C745 specification (15pf - 69 pf) and may depend on the crystal that you use.

Check that USB power and ground connections are correct before connecting the chip. It is easy to get turn around between the cable pinout and the socket pin out.
Circuit Diagram showing USB connections
The following circuit is used to power the electret microphone and then amplify the signal. The output signal is connected to one of the analog pins of the 16C745, we used pin 2, corresponding to AN0 (analog pin 0).
Microphone Powering Circuit

The components are
  • OP1 - a TLE2141 Op Amp. This comes in an 8 pin package with GND at pin 4, Power at pin 7, IN- at pin 2, IN+ at pin 3, and output at pin 6.
  • R1 - 1 kOhm resister
  • R2 - 3.2 kOhm resister
  • R3 - 1 kOhm resister
  • R4 - 500 kOhm resister
  • C1 - 0.005 uF capacitor
  • MIC1 - a electret microphone
The left side of the circuit is copied from http://www.hut.fi/Misc/Electronics/circuits/microphone_powering.html and the right side amplifies the signal 500 times (1 + R4/R3) using the op amp.
Update: a visitor to the site made the following suggestion to improve the circuit to allow the Op Amp to amplify the negative portion of the signal. 'Romano' said, "You should (if you want, of course), put a resistor between (+) of op-amp and Vcc, call it R2a, 6.8kohm will be good. R2 should be 6.8k again, so without mic signal you will have Vcc/2 at (+). Finally disconnect R3 from GND and put a capacitor (1uf or more) between R3 and GND. Without signal you will get Vcc/2 at the input of A/D."
Further update (06/09/27): Tito wrote me to suggest improvements to the amplifer. He made the following suggestion, "I noticed that your audio amplifier is not well polarized. I think it has big distortions because it only amplifies the positive part of the signal. I recommend using a negative amplifier configuration for the OPAMP. You just need to add a voltage divisor and a filter to polarize the OPAMP inputs."
To top.

Links

  • The book USB by Example by John Hyde. The companion web sites are at www.usb-by-example.com and http://www.intel-u-press.com/usb_dbe/ have lots of examples.
  • The book USB Complete by Jan Axelson. This book covers similar material as above but has more on the HID class. The companion web site has lots of example code and further references.

No comments:

Post a Comment