USB and PIC Microprocessors 16C745 and 18F2455

From AlanMacek.com

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.

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.

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.

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.

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.

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).

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.

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.)

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.

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.

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.

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.

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).

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.

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