Sunteți pe pagina 1din 23

uss ca-.c.:.-. uss ca-.c.:.-. uss ca-.c.:.-. uss ca-.c.:.-.

.us|ng the nID C|ass


1he unlversal Serlal 8us [uS8] ls one of Lhe mosL common lnLerfaces ln consumer elecLronlcs producLs
and Lhls wrlLe up descrlbes wlLh pracLlcal lllusLraLlons, Lhe baslc prlnclples lnvolved ln Lhe use of Lhe uS8 for
slmple daLa LransacLlons beLween your embedded devlce and a C. 1he uS8 8us ls a complex proLocol and a
compleLe dlscusslon of lLs deslgn and use ls way beyond Lhe scope of Lhls wrlLe up.
1he uS8 ls a hlgh speed serlal lnLerface LhaL can provlde power Lo connecLed devlces, lL supporLs up Lo
127 devlces Lhrough lLs 8-blL addresslng sysLem [llmlLed by Lhe 7-blL address fleld slnce Lhe address 0 ls noL used
as lL has a speclal purpose] connecLed Lhrough a four-wlre serlal cable of up Lo flve meLers ln lengLh. uevlces
connecLed Lhrough hubs can go as far as slx Llers Lhereby llmlLlng by speclflcaLlon Lhe maxlmum dlsLance of a
devlce from lLs hosL Lo abouL LhlrLy meLers.
1he uS8 bus speclflcaLlon comes ln Lhree verslons: Lhe earller verslon, uS81.1, supporLs 11Mbps, Lhe
laLLer verslon, uS82.0, supporLs up Lo 480Mbps and Lhe laLesL verslon, uS83.0 whlch supporLs up Lo 3Cbps.
1he uS8 speclflcaLlon deflnes four daLa speeds:
Low speed - 1.3Mb/sec
lull speed -12Mb/sec
Plgh speed - 480Mb/sec
Super speed - 3Cb/sec
1he maxlmum power avallable Lo an exLernal devlce ls abouL 100mA aL 3volLs.
1he uS8 ls a four wlre lnLerface lmplemenLed uslng a four core shlelded cable. 1wo Lypes of connecLors
are speclfled ln Lhls wrlLe up: 1ype A and 1ype 8. 1he dlagrams along slde wlLh Lhelr color conflguraLlon are
shown below.
US8 connectors
|n out of US8 connectors
1wo of Lhe plns, u+ and u- , form a LwlsLed palr and carry dlfferenLlal daLa slgnals.

uS8 devlces aLLached Lo Lhe bus may be full cusLom devlces, requlrlng a full cusLom devlce drlver, or
Lhey may belong Lo a devlce class whlch enables Lhe same devlce drlver Lo be used for several devlces havlng
slmllar funcLlonallLles [e.g. uS8 mouse, prlnLers eLc.]. 1he mosL common devlce classes are shown below:

lor Lhe purpose of Lhls wrlLe up, Lhe Puman lnLerface uevlce [Plu] class wlll be used. 8elow are some common
uS8 Lerms:
Lndpo|nt: 1hls can elLher be a source or slnk of daLa. A slngle uS8 can only have slxLeen ln and Cu1 endpolnLs.
1ransact|on: 1ransfer of daLa on Lhe bus.
|pe: A loglcal daLa connecLlon beLween Lhe hosL C and an endpolnL.
ln Lhe uS8 communlcaLlon, Lhe hosL dlcLaLes Lhe use of Lhe uS8 bus. Whenever a new uS8 devlce ls
plugged ln, Lhe hosL uses Lhe address 0 Lo ask baslc lnformaLlon from Lhe devlce afLer whlch lL asslgns a unlque
address Lo Lhe devlce. AfLer Lhls, Lhe hosL asks for and recelves furLher lnformaLlon abouL Lhe devlce, such as Lhe
manufacLurer, devlce capablllLles, and producL lu, and Lhen Lwo way LransacLlons can begln [l.e. Lransmlsslon of
daLa packeLs]. uaLa can be Lransferred on a bus ln four ways:
8u|k transfer: 1hls ls deslgned Lo Lransfer bulk daLa where slow raLe of Lransfer ls no problem. lL can
supporL packeL slzes from 8 Lo 64 packeLs aL full speeds.
Interrupt transfer: 1hls ls used where daLa musL be Lransferred as qulckly as posslble wlLh no delay. lL
can supporL packeL slzes from 1 Lo 64 packeLs aL full speeds.
lsochronous Lransfer.
ConLrol Lransfer.
8aslcally, we'll be resLrlcLed Lo Lhe bulk and lnLerrupL Lransfers ln Lhls wrlLe up.
When a devlce ls plugged ln, lL becomes known Lo Lhe hosL Lhrough a process called enumerat|on. 1he
sLeps are sLaLed below:
When a devlce ls plugged ln, Lhe hosL becomes aware of lL because one of Lhe daLa llnes (u+ or u-)
becomes loglc hlgh.
When a devlce ls plugged ln, Lhe hosL becomes aware of lL because one of Lhe daLa llnes (u+ or u-)
becomes loglc hlgh.
1he hosL sends a uS8 reseL slgnal Lo Lhe devlce Lo place Lhe devlce ln a known sLaLe. 1he reseL devlce
responds Lo address 0.
1he hosL sends a requesL on address 0 Lo Lhe devlce Lo flnd ouL lLs maxlmum packeL slze uslng a CeL
uescrlpLor command.
1he devlce responds by sendlng a small porLlon of Lhe devlce descrlpLor.
1he hosL sends a uS8 reseL agaln.
1he hosL sends a 6et uevice uescriptor requesL Lo reLrleve Lhe compleLe devlce descrlpLor, gaLherlng
lnformaLlon such as monufocturer, Lype of devlce, and maxlmum conLrol packeL slze.
1he hosL sends a 6et confiqurotion uescriptors requesL Lo recelve Lhe devlce's conflguraLlon daLa, such
as power requlremenLs and Lhe Lypes and number of lnLerfaces supporLed.
1he hosL may requesL any addlLlonal descrlpLors from Lhe devlce.
noLe LhaL lnlLlal communlcaLlons beLween Lhe hosL and Lhe devlce ls carrled ouL uslng Lhe conLrol Lransfer Lype
of daLa flow.

All uS8 devlces have a hlerarchy of descrlpLors LhaL descrlbe varlous feaLures or Lhe devlce: Lhe
manufacLurer lu, Lhe verslon lf Lhe devlce, Lhe verslon of uS8 lL supporLs, whaL devlce lL ls, lLs power
requlremenLs, Lhe number and Lype of endpolnLs, eLc. 1he common ones are llsLed below:
uevlce descrlpLors.
ConflguraLlon descrlpLors.
lnLerface descrlpLors.
Plu descrlpLors.
LndpolnL descrlpLors.
We wlll noL be able Lo go ln-depLh lnLo Lhe aforemenLloned descrlpLors as Lhls wrlLe up employs a layman qulck
approach Lo Lhe sub[ecL.
now, Lo make Lhlngs clearer, we wlll embark on a pro[ecL, Lo deslgn an embedded devlce LhaL responds
Lo commands from Lhe C and also sends commands L Lhe C. We assume LhaL our reader can read and wrlLe
mlcroconLroller [mlcrochlp lC] sofLware ln CCS C.
1hls pro[ecL lllusLraLes Lhe deslgn of a uS8-based mlcroconLroller lnpuL and ouLpuL uslng Lhe lC18l4330
mlcroconLroller lnLerfaced Lo a C Lhrough a uS8 cable. A vlsual 8aslc program runs on Lhe C sends commands
Lo Lhe mlcroconLroller Lhrough Lhe uS8 bus, prompLlng Lhe mlcroconLroller Lo converL Lhe lnpuL daLa Lo Llme
lnLervals for bllnklng a LLu, mulLlplylng Lhe lnpuL daLa by 2 and Lhen sendlng lL back Lo Lhe C. 1he clrculL
dlagram ls shown below.

C|rcu|t d|agram of the above pro[ect

1he C Software:
1he vlsual 8aslc program ln Lhls pro[ecL uses a slngle form as shown below. 1he lnpuL daLa ls enLered ln
declmal ln LexL box, and Lhen Lhe command buLLon Send ls cllcked wlLh Lhe mouse. lor example, enLerlng Lhe
lnLeger 30 makes Lhe LLu connecLed Lo porL pln 880 Lo bllnk wlLh an lnLerval of 30ms whlle cllcklng kece|ve
prompLs Lhe mlcroconLroller Lo mulLlply Lhe lnLeger 30 by 2, bllnks Lhe Led s connecLed Lo porL lns 881 wlLh an
lnLerval of 100ms (l.e. 30*2) and flnally send Lhe resulL (l.e. 100) Lo Lhe recelve label. 1he program sends Lhe
enLered number Lo Lhe mlcroconLroller as a packeL conslsLlng of four characLers ln Lhe followlng formaL:

= n1

Where Lhe characLer " lndlcaLes Lhe sLarL of daLa, n" ls Lhe byLe Lo be senL Lo Lhe mlcroconLroller whlle 1 ls
Lhe LermlnaLor characLer (e.g. = 301). 1he boLLom parL of Lhe form lndlcaLes Lhe connecLlon sLaLus.


1he C V|sua| 8as|c form
1he vlsual 8aslc program used ln Lhls secLlon ls based on Lhe uS8 uLlllLy known as LasynID US8 W|zard,
developed by mecanlque (www.mecanlque.co.uk). LasyPlu ls deslgned Lo work wlLh uS8 2.0, and Lhere ls no
need Lo develop a drlver, as Lhe x operaLlng sysLem ls shlpped wlLh a Plu-based uS8 drlver.
1he sLeps lnvolved ln generaLlng a vlsual 8aslc code LemplaLe go Lhus:
lnsLall Lhe appllcaLlon and run lL.
LnLer your daLa ln Lhe flelds and cllck nexL.



LnLer your vendor lu (vlu) and roducL lu (lu) as shown below. vendor lus are unlque LhroughouL Lhe
world and are lssued by Lhe uS8 lmplemenLers (www.usb.org) aL a cosL. ln Lhls example, vlu x 4660 and
lu x 1 are selecLed for LesL purposes.

1he nexL form shows lmporLanL parameLers llke Lhe lnpuL and ouLpuL buffer slzes, whlch speclfy Lhe
number of byLes Lo be senL and recelved respecLlvely beLween Lhe C and Lhe mlcroconLroller durlng
uS8 LransacLlons. ln Lhls pro[ecL, 4 byLes are chosen for boLh flelds (our ouLpuL ls ln Lhe formaL = n1
whlch ls 4 byLes).
ln Lhe nexL form (see llgure 8.16), selecL a locaLlon for Lhe generaLed flles, choose Lhe mlcroconLroller
compller Lo be used (Lhls fleld ls noL lmporLanL, as we are only generaLlng code for vlsual 8aslc (l.e., Lhe
C end), choose Lhe mlcroconLroller Lype, and flnally selecL vlsual 8aslc as Lhe language Lo be used.

Cllcklng nexL> generaLes Lhe necessary flles (l.e. lormMaln.frm, uS8ro[ecL.vbp and mcPlulnLerface.8AS)
needed for Lhe vlsual 8aslc pro[ecL. 1hese have been modlfled for Lhe purpose of Lhls pro[ecL from a blank form
Lo dlsplay Lhe varlous conLrols used. 1he full source code for Lhe C sofLware end of Lhe pro[ecL ls glven below:




lormMoin.frm


' vendor and product IDs
Private Const VendorID = 4660 use 0x1234 for MCU software
Private Const ProductID = 1 use 0x0001 for MCU software

' read and write buffers
Private Const BufferInSize = 16
Private Const BufferOutSize = 16
Dim BufferIn(0 To BufferInSize) As Byte
Dim BufferOut(0 To BufferOutSize) As Byte

Private Sub cmdExit_Click()
DisconnectFromHID
End
End Sub

Private Sub cmdReceive_Click()
BufferOut(0) = 0 ' first byte is always the report ID
BufferOut(1) = Asc("P") ' first data item ("P")
BufferOut(2) = Asc("=") ' second data item ("=")
BufferOut(3) = Asc("?") ' third data item ("?")
BufferOut(4) = Asc("?") ' fourth data item ("?")
' write the data (don't forget, pass the whole array)...
hidWriteEx VendorID, ProductID, BufferOut(0)
lblStatus = "Data requested..."
End Sub

Private Sub cmdReset_Click()
BufferOut(1) = 0
BufferOut(2) = 0
BufferOut(3) = 0
BufferOut(4) = 0
txtSend = ""
lblReceive = ""
lblStatus = ""
End Sub

Private Sub cmdSend_Click()
BufferOut(0) = 0 ' first byte is always the report ID
BufferOut(1) = Asc("P") ' first data item (P)
BufferOut(2) = Asc("=") ' second data item (=)
BufferOut(3) = Val(txtSend) ' third data item (data)
BufferOut(4) = Asc("T") ' fourth data item (T)
' write the data (don't forget, pass the whole array)...
hidWriteEx VendorID, ProductID, BufferOut(0)
lblStatus = "Data sent..."
End Sub

' ****************************************************************
' when the form loads, connect to the HID controller - pass
' the form window handle so that you can receive notification
' events...
'*****************************************************************
Private Sub Form_Load()
' do not remove!
ConnectToHID (Me.hwnd)
lblStatus = "Connected to HID..."
End Sub

'*****************************************************************
' disconnect from the HID controller...
'*****************************************************************
Private Sub Form_Unload(Cancel As Integer)
DisconnectFromHID
End Sub

'*****************************************************************
' a HID device has been plugged in...
'*****************************************************************
Public Sub OnPlugged(ByVal pHandle As Long)
If hidGetVendorID(pHandle) = VendorID And hidGetProductID(pHandle)
= ProductID Then
lblStatus = "USB Plugged....."
End If
End Sub

'*****************************************************************
' a HID device has been unplugged...
'*****************************************************************
Public Sub OnUnplugged(ByVal pHandle As Long)
If hidGetVendorID(pHandle) = VendorID And hidGetProductID(pHandle)
= ProductID Then
lblStatus = "USB Unplugged....."
End If
End Sub

'*****************************************************************
' controller changed notification - called
' after ALL HID devices are plugged or unplugged
'*****************************************************************
Public Sub OnChanged()
Dim DeviceHandle As Long

' get the handle of the device we are interested in, then set
' its read notify flag to true - this ensures you get a read
' notification message when there is some data to read...
DeviceHandle = hidGetHandle(VendorID, ProductID)
hidSetReadNotify DeviceHandle, True
End Sub

'*****************************************************************
' on read event...
'*****************************************************************
Public Sub OnRead(ByVal pHandle As Long)

' read the data (don't forget, pass the whole array)...
If hidRead(pHandle, BufferIn(0)) Then
' The data is received in the format: P=nT where the first byte
' is the report ID. i.e. BufferIn(0)=reportID, BufferIn(0)="P" and so
on
' Check to make sure that received data is in correct format
If (BufferIn(1) = Asc("P") And BufferIn(2) = Asc("=") And BufferIn(4)
= Asc("T")) Then
lblReceive = Str$(BufferIn(3))
lblStatus = "Data received..."
End If
End If
End Sub

'*****************************************************************
' this is how you write some data...
'*****************************************************************
'Public Sub WriteSomeData()
' BufferOut(0) = 0 ' first by is always the report ID
' BufferOut(1) = 10 ' first data item, etc etc

' write the data (don't forget, pass the whole array)...
' hidWriteEx VendorID, ProductID, BufferOut(0)
'End Sub


mcnlulnterfoce.845

' this is the interface to the HID controller DLL - you should not
' normally need to change anything in this file.
'
' WinProc() calls your main form 'event' procedures - these are
currently
' set to..
'
' MainForm.OnPlugged(ByVal pHandle as long)
' MainForm.OnUnplugged(ByVal pHandle as long)
' MainForm.OnChanged()
' MainForm.OnRead(ByVal pHandle as long)

Option Explicit

' HID interface API declarations...
Declare Function hidConnect Lib "mcHID.dll" Alias "Connect" (ByVal
pHostWin As Long) As Boolean
Declare Function hidDisconnect Lib "mcHID.dll" Alias "Disconnect" ()
As Boolean
Declare Function hidGetItem Lib "mcHID.dll" Alias "GetItem" (ByVal
pIndex As Long) As Long
Declare Function hidGetItemCount Lib "mcHID.dll" Alias "GetItemCount"
() As Long
Declare Function hidRead Lib "mcHID.dll" Alias "Read" (ByVal pHandle
As Long, ByRef pData As Byte) As Boolean
Declare Function hidWrite Lib "mcHID.dll" Alias "Write" (ByVal pHandle
As Long, ByRef pData As Byte) As Boolean
Declare Function hidReadEx Lib "mcHID.dll" Alias "ReadEx" (ByVal
pVendorID As Long, ByVal pProductID As Long, ByRef pData As Byte) As
Boolean
Declare Function hidWriteEx Lib "mcHID.dll" Alias "WriteEx" (ByVal
pVendorID As Long, ByVal pProductID As Long, ByRef pData As Byte) As
Boolean
Declare Function hidGetHandle Lib "mcHID.dll" Alias "GetHandle" (ByVal
pVendoID As Long, ByVal pProductID As Long) As Long
Declare Function hidGetVendorID Lib "mcHID.dll" Alias "GetVendorID"
(ByVal pHandle As Long) As Long
Declare Function hidGetProductID Lib "mcHID.dll" Alias "GetProductID"
(ByVal pHandle As Long) As Long
Declare Function hidGetVersion Lib "mcHID.dll" Alias "GetVersion"
(ByVal pHandle As Long) As Long
Declare Function hidGetVendorName Lib "mcHID.dll" Alias
"GetVendorName" (ByVal pHandle As Long, ByVal pText As String, ByVal
pLen As Long) As Long
Declare Function hidGetProductName Lib "mcHID.dll" Alias
"GetProductName" (ByVal pHandle As Long, ByVal pText As String, ByVal
pLen As Long) As Long
Declare Function hidGetSerialNumber Lib "mcHID.dll" Alias
"GetSerialNumber" (ByVal pHandle As Long, ByVal pText As String, ByVal
pLen As Long) As Long
Declare Function hidGetInputReportLength Lib "mcHID.dll" Alias
"GetInputReportLength" (ByVal pHandle As Long) As Long
Declare Function hidGetOutputReportLength Lib "mcHID.dll" Alias
"GetOutputReportLength" (ByVal pHandle As Long) As Long
Declare Sub hidSetReadNotify Lib "mcHID.dll" Alias "SetReadNotify"
(ByVal pHandle As Long, ByVal pValue As Boolean)
Declare Function hidIsReadNotifyEnabled Lib "mcHID.dll" Alias
"IsReadNotifyEnabled" (ByVal pHandle As Long) As Boolean
Declare Function hidIsAvailable Lib "mcHID.dll" Alias "IsAvailable"
(ByVal pVendorID As Long, ByVal pProductID As Long) As Boolean

' windows API declarations - used to set up messaging...
Private Declare Function CallWindowProc Lib "user32" Alias
"CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long,
ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias
"SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal
dwNewLong As Long) As Long

' windows API Constants
Private Const WM_APP = 32768
Private Const GWL_WNDPROC = -4

' HID message constants
Private Const WM_HID_EVENT = WM_APP + 200
Private Const NOTIFY_PLUGGED = 1
Private Const NOTIFY_UNPLUGGED = 2
Private Const NOTIFY_CHANGED = 3
Private Const NOTIFY_READ = 4

' local variables
Private FPrevWinProc As Long ' Handle to previous window procedure
Private FWinHandle As Long ' Handle to message window

' Set up a windows hook to receive notification
' messages from the HID controller DLL - then connect
' to the controller
Public Function ConnectToHID(ByVal pHostWin As Long) As Boolean
FWinHandle = pHostWin
ConnectToHID = hidConnect(FWinHandle)
FPrevWinProc = SetWindowLong(FWinHandle, GWL_WNDPROC, AddressOf
WinProc)
End Function

' Unhook from the HID controller and disconnect...
Public Function DisconnectFromHID() As Boolean
DisconnectFromHID = hidDisconnect
SetWindowLong FWinHandle, GWL_WNDPROC, FPrevWinProc
End Function

' This is the procedure that intercepts the HID controller messages...
Private Function WinProc(ByVal pHWnd As Long, ByVal pMsg As Long,
ByVal wParam As Long, ByVal lParam As Long) As Long
If pMsg = WM_HID_EVENT Then
Select Case wParam

' HID device has been plugged message...
Case Is = NOTIFY_PLUGGED
MainForm.OnPlugged (lParam)

' HID device has been unplugged
Case Is = NOTIFY_UNPLUGGED
MainForm.OnUnplugged (lParam)

' controller has changed...
Case Is = NOTIFY_CHANGED
MainForm.OnChanged

' read event...
Case Is = NOTIFY_READ
MainForm.OnRead (lParam)
End Select

End If

' next...
WinProc = CallWindowProc(FPrevWinProc, pHWnd, pMsg, wParam, lParam)

End Function


1he M|crocontro||er Software:
When Lhe Send buLLon ls cllcked on mlcroconLroller recelves Lhe command = n1 from Lhe C and
bllnks Lhe LLu connecLed Lo porL pln 880 wlLh an lnLerval (n)ms. Slmllarly, when Lhe kece|ve buLLon ls cllcked on,
Lhe mlcroconLroller recelves Lhe command = ?? from Lhe C prompLlng lL Lo mulLlply Lhe lnLeger n" by 2,
bllnklng Lhe LLu connecLed Lo Lhe porL pln 881 wlLh an lnLerval (n*2)ms and Lhn flnally sendlng Lhe value back Lo
Lhe C ln Lhe formaL = (n*2)1.
ln conflgurlng Lhe mlcroconLroller sofLware, Lhe Lwo maln lmporLanL aspecLs are, edlLlng Lhe descrlpLor
flle, and wrlLlng Lhe maln code.

ditinq the descriptor fi/e:

8ecall LhaL Lhe CCS C Compller ls Lhe defaulL compller for Lhls pro[ecL. CCS by defaulL comes wlLh lLs own
preconflgured descrlpLor header flle (usb_desc_hld.h) whlch you wlll edlL Lo as shown below:

usb_desc_h|d.h

///////////////////////////////////////////////////////////////////////////
/// usb_desc_hid.h ////
//// ////
//// An example set of device / configuration descriptors for use with ////
//// CCS's HID Demo example (see ex_usb_hid.c) ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// ////
//// Version History: ////
//// ////
//// June 20th, 2005: ////
//// PIC18Fxx5x initial release ////
//// ////
//// March 21st, 2005: ////
//// EP 0x01 and EP 0x81 now use USB_EP1_TX_SIZE and USB_EP1_RX_SIZE ////
//// to define max packet size, to make it easier for dynamically ////
//// changed code. ////
//// EP 0x01 and EP 0x81 will now use 1ms polling interval if using ////
//// a full speed device. ////
//// ////
//// May 4th, 2004: Optimization and cleanup. ////
//// Some definitions may have changed. ////
//// ////
//// May 6th, 2003: Fixed non-HID descriptors pointing to faulty ////
//// strings ////
//// ////
//// August 2nd, 2002: Initial Public Release ////
//// ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2005 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
///////////////////////////////////////////////////////////////////////////

#IFNDEF __USB_DESCRIPTORS__
#DEFINE __USB_DESCRIPTORS__

#include <usb.h>

//////////////////////////////////////////////////////////////////
///
/// HID Report. Tells HID driver how to handle and deal with
/// received data. HID Reports can be extremely complex,
/// see HID specifcation for help on writing your own.
///
/// CCS example uses a vendor specified usage, that sends and
/// receives 2 absolute bytes ranging from 0 to 0xFF.
///
//////////////////////////////////////////////////////////////////
const char USB_CLASS_SPECIFIC_DESC[] =
{
6, 0, 255, // Usage Page = Vendor Defined
9, 1, // Usage = IO device
0xa1, 1, // Collection = Application
0x19, 1, // Usage minimum
0x29, 8, // Usage maximum

0x15, 0x00, // Logical minimum (0)
0x25, 0xFF, // Logical maximum (255)

0x75, 16, // Report size = 16 (bits)
0x95, 2, // Report count = 16 bits (2 bytes)
0x81, 2, // Input (Data, Var, Abs)
0x19, 1, // Usage minimum
0x29, 8, // Usage maximum
0x75, 16, // Report size = 16 (bits)
0x95, 2, // Report count = 16 bits (2 bytes)
0x91, 2, // Output (Data, Var, Abs)
0xc0 // End Collection
};

//if a class has an extra descriptor not part of the config descriptor,
// this lookup table defines where to look for it in the const
// USB_CLASS_SPECIFIC_DESC[] array.
//first element is the config number (if your device has more than one
//config)
//second element is which interface number
//set element to 0xFFFF if this config/interface combo doesn't exist

const int16 USB_CLASS_SPECIFIC_DESC_LOOKUP[USB_NUM_CONFIGURATIONS][1] =
{
//config 1
//interface 0
0
};

//if a class has an extra descriptor not part of the config descriptor,
// this lookup table defines the size of that descriptor.
//first element is the config number (if your device has more than one
//config)
//second element is which interface number
//set element to 0xFFFF if this config/interface combo doesn't exist

const int16 USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[USB_NUM_CONFIGURATIONS][1] =
{
//config 1
//interface 0
32
};

////////////////////////////////////////////////////////////////////////////
/// //
/// start config descriptor //
/// right now we only support one configuration descriptor. //
/// the config, interface, class, and endpoint goes into this array. //
/// //
///////////////////////////////////////////////////////////////////////////

#DEFINE USB_TOTAL_CONFIG_LEN 41 //config+interface+class+endpoint+endpoint
//(2 endpoints)

const char USB_CONFIG_DESC[] =
{
//IN ORDER TO COMPLY WITH WINDOWS HOSTS, THE ORDER OF THIS ARRAY MUST
//BE:
// config(s)
// interface(s)
// class(es)
// endpoint(s)

//config_descriptor for config index 1
USB_DESC_CONFIG_LEN, //length of descriptor size ==1
USB_DESC_CONFIG_TYPE, //constant CONFIGURATION (CONFIGURATION 0x02)
//==2
USB_TOTAL_CONFIG_LEN,0, //size of all data returned for this config
//==3,4
1, //number of interfaces this device supports ==5
0x01, //identifier for this configuration. (IF we had more than one
//configurations) ==6
0x00, //index of string descriptor for this configuration ==7
0xC0, //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we
//don't), bits 0-4 unused and bit7=1 ==8
0x32, //maximum bus power required (maximum milliamperes/2) (0x32 =
//100mA)

//interface descriptor 1
USB_DESC_INTERFACE_LEN, //length of descriptor =10
USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)
//=11
0x00, //number defining this interface (IF we had more than one
//interface) ==12
0x00, //alternate setting ==13
2, //number of endpoins, except 0 (pic167xx has 3, but we dont have to
//use all). ==14
0x03, //class code, 03 = HID ==15
0x00, //subclass code //boot ==16
0x00, //protocol code ==17
0x00, //index of string descriptor for interface ==18

//class descriptor 1 (HID)
USB_DESC_CLASS_LEN, //length of descriptor ==19
USB_DESC_CLASS_TYPE, //dscriptor type (0x21 == HID) ==20
0x00,0x01, //hid class release number (1.0) (try 1.10) ==21,22
0x00, //localized country code (0 = none) ==23
0x01, //number of hid class descrptors that follow (1) ==24
0x22, //report descriptor type (0x22 == HID) ==25
USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[0][0], 0x00, //length of report
//descriptor ==26,27

//endpoint descriptor
USB_DESC_ENDPOINT_LEN, //length of descriptor ==28
USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)
//==29
0x81, //endpoint number and direction (0x81 = EP1 IN) ==30
0x03, //transfer type supported (0x03 is interrupt) ==31
USB_EP1_TX_SIZE,0x00, //maximum packet size supported
//==32,33
250, //polling interval, in ms. (cant be smaller than 10) ==34

//endpoint descriptor
USB_DESC_ENDPOINT_LEN, //length of descriptor ==35
USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)
//==36
0x01, //endpoint number and direction (0x01 = EP1 OUT) ==37
0x03, //transfer type supported (0x03 is interrupt) ==38
USB_EP1_RX_SIZE,0x00, //maximum packet size supported
//==39,40
10 //polling interval, in ms. (cant be smaller than 10) ==41
};

//****** BEGIN CONFIG DESCRIPTOR LOOKUP TABLES ********
//since we can't make pointers to constants in certain pic16s, this is
//an offset table to find
// a specific descriptor in the above table.

//NOTE: DO TO A LIMITATION OF THE CCS CODE, ALL HID INTERFACES MUST
START AT 0 AND BE SEQUENTIAL
// FOR EXAMPLE, IF YOU HAVE 2 HID INTERFACES THEY MUST BE
//INTERFACE 0 AND INTERFACE 1
#define USB_NUM_HID_INTERFACES 1

//the maximum number of interfaces seen on any config
//for example, if config 1 has 1 interface and config 2 has 2
//interfaces you must define this as 2
#define USB_MAX_NUM_INTERFACES 1

//define how many interfaces there are per config. [0] is the first
//config, etc.
const char USB_NUM_INTERFACES[USB_NUM_CONFIGURATIONS]={1};

//define where to find class descriptors
//first dimension is the config number
//second dimension specifies which interface
//last dimension specifies which class in this interface to get, but
//most will only have 1 class per interface
//if a class descriptor is not valid, set the value to 0xFFFF

const int16 USB_CLASS_DESCRIPTORS[USB_NUM_CONFIGURATIONS][1][1]=
{
//config 1
//interface 0
//class 1
18
};

#if (sizeof(USB_CONFIG_DESC) != USB_TOTAL_CONFIG_LEN)
#error USB_TOTAL_CONFIG_LEN not defined correctly
#endif


//////////////////////////////////////////////////////////////////
///
/// start device descriptors
///
//////////////////////////////////////////////////////////////////

const char USB_DEVICE_DESC[USB_DESC_DEVICE_LEN] =
{
//starts of with device configuration. only one possible
USB_DESC_DEVICE_LEN, //the length of this report ==1
0x01, //the constant DEVICE (DEVICE 0x01) ==2
0x10,0x01, //usb version in bcd (pic167xx is 1.1) ==3,4
0x00, //class code ==5
0x00, //subclass code ==6
0x00, //protocol code ==7
USB_MAX_EP0_PACKET_LENGTH, //max packet size for endpoint 0. (SLOW
//SPEED SPECIFIES 8) ==8
0x34,0x12, //vendor id (use 4660decimal which is the same as
//1234hexadecimal- arrange in reverse as shown)
0x01,0x00, //product id (use 1decimal which is the same as
//0001hexadecimal- arrange in reverse as shown)
0x00,0x01, //device release number ==13,14
0x01, //index of string description of manufacturer. therefore we
//point to string_1 array (see below) ==15
0x02, //index of string descriptor of the product ==16
0x00, //index of string descriptor of serial number ==17
USB_NUM_CONFIGURATIONS //number of possible configurations ==18
};


//////////////////////////////////////////////////////////////////
///
/// start string descriptors
/// String 0 is a special language string, and must be defined. People in
/// U.S.A. can leave this alone.
///
/// You must define the length else get_next_string_character() will not
/// see the string
/// Current code only supports 10 strings (0 thru 9)
///
//////////////////////////////////////////////////////////////////

//the offset of the starting location of each string. offset[0] is the
start of string 0, offset[1] is the start of string 1, etc.
char USB_STRING_DESC_OFFSET[]={0,4,40};

char const USB_STRING_DESC[]=
{
//for this, //the string0 starts at 0. the next String index is 4
//xters long. the sting1 which is 34 xters+2 spaces to make 36 xters
//starts where string0 ends(i.e. 0 + 4).string2 which is 16 xters+2
//spaces make 18 xters starts where string1 ends(i.e. 0 + 4 + 36).

//string 0
4, //length of string index
USB_DESC_STRING_TYPE,//descriptor type 0x03 (STRING)
0x09,0x04, //Microsoft Defined for US-English
36, //length of string index
USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
'r',0,
'o',0,
'd',0,
'e',0,
'o',0,
'T',0,
'e',0,
'c',0,
'h',0,
'n',0,
'o',0,
'l',0,
'o',0,
'g',0,
'i',0,
'e',0,
's',0,
//string 2
18, //length of string index
USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
'r',0,
'o',0,
'd',0,
'e',0,
'o',0,
'U',0,
'S',0,
'B',0

};

#ENDIF






Ma|n.c


/////////////////////////////////////////////////////////////////////////
//// ////
//// HID_Template.c ////
//// ////
//// This simple template shows how to use the HID class to send ////
//// and receive custom data from the PC. Normally HID is used ////
//// with pre-defined classes, such as mice and keyboards, but ////
//// can be used for vendor specific classes. The example below ////
//// shows the basic template[i.e code structure] on how to use ////
//// Human Interfce Device[HID]. ////
//// For extra documentation on developing your own code, see the ////
//// header files and comments located in the other files of the ////
//// CCS PIC USB drivers. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// ABOUT HID: ////
//// ////
//// HID devices are useful because HID drivers are generally ////
//// installed and supplied with modern operating systems. ////
//// However, since HID is a general device with general drivers ////
//// there are limitations to what a HID device can do: ////
//// ////
//// - A report (message) can't be larger than 255 bytes. ////
//// (A report or message != A packet) ////
//// ////
//// - On slow speed devices the max packet size is 8. ////
//// On a full speed device the max packet size is 64. ////
//// ////
//// - Data is obtained on the host / PC through polling the HID ////
//// device (PC polls the PIC) ////
//// ////
//// - On a full speed device, max polling rate is 1 transaction ////
//// per 1ms. This is 64000 bytes per second (64 byte packets ////
//// every 1ms). ////
//// ////
//// - On a slow speed device, max polling rate is 1 transaction ////
//// per 10ms. This is 800 bytes per second (8 byte packets every ////
//// 10ms) ////
//// ////
//// - No guarantee that polls will happen at a guaranteed rate. ////
//// If you want guaranteed transfer rate you must use Isochronous ////
//// transfers, which HID is not. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// WINDOWS DRIVERS: ////
//// ////
//// USB HID drivers come included with all Windows, starting ////
//// with Windows 98 and up. Windows 95 does not include USB ////
//// support, unless you are running Windows 95 Gold (aka OSR2, or ////
//// Windows 95b). ////
//// ////
//// If you plug in the USB device, and it is working, a "Found new ////
//// device" window should pop-up. The Add Device wizard then will ////
//// install the HID drivers automatically. ////
//// ////
//// If you plug in the USB device and do not get this window then ////
//// the device is not working, or USB does not work on your ////
//// computer. Goto the Device Manager (Right Click on my Computer, ////
//// it is located under one of the Tabs. It is located under the ////
//// Hardware tab of Windows2000), and make sure that "Universal ////
//// Serial Bus controllers" is installed. Open "Universal Serial ////
//// Bus controllers" and you should see 1 or more "USB Root Hubs". ////
//// If you see these then that's a good indication that USB is ////
//// working on your computer. If you see a question mark and ////
//// an unkown USB device then this is quite possibly your USB ////
//// device that is not working. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// NOTES: ////
//// ////
//// *Although this application sends and receives only 4 bytes from ////
//// the PC, this demo defines USB_EP1_TX_SIZE and USB_EP1_RX_SIZE ////
//// to 16 to allocate 16bytes for these endpoint. These constants ////
//// are also used in the endpoint descriptor to specify the ////
//// endpoint max size. If you were conscious of RAM savings you ////
//// could redefine these to 2 (or even 1!), but you would lose ////
//// throughput. The reason for throughput loss is that if you send ////
//// a packet that is the same size as the max packet size then ////
//// you need to send a 0 len packet to specify end of message ////
//// marker. The routines usb_puts() and usb_gets() send and ////
//// receive multiple packet message, waiting for a 0 len packet ////
//// or a packet that is smaller than max-packet size. ////
//// *PIC is powered from the USB port ////
//// * ////
/////////////////////////////////////////////////////////////////////////

#include <18F4550.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL2,CPUDIV2,VREGEN
#use delay(clock=48000000)
// The 8MHz external crystal is pre-scaled by div 2 [PLL2] to 4MHz.
// PLL multiplies it by 16 to 96MHz. USBDIV post-scales with div by 2 to
//48MHz

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

//////////////////////////////////////////////////////////////////////////
// CCS Library dynamic defines: For dynamic configuration of the CCS //
// Library for your application, several defines need to be made. See the//
// comments at usb.h for more information //
////////////////////////////////////////////////////////////////////////////

//Tells the CCS PIC USB firmware to include HID handling code[i.e enables
//HID].
#DEFINE USB_HID_DEVICE TRUE

//the following defines needed for the CCS USB PIC driver to enable the
// Transmit[TX] endpoint 1[EP1] and allocate buffer space on the peripheral
#define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT //turn on EP1 for IN
//bulk/interrupt transfers
#define USB_EP1_TX_SIZE 16 //allocate 8 bytes in
//the hardware for transmission

//the following defines needed for the CCS USB PIC driver to enable the
//Receive[RX] endpoint 1 and allocate buffer space on the peripheral
#define USB_EP1_RX_ENABLE USB_ENABLE_INTERRUPT //turn on EP1 for OUT
//bulk/interrupt transfers
#define USB_EP1_RX_SIZE 16 //allocate 8 bytes in
//the hardware for reception

////////////////////////////////////////////////////////////////////////////
// //
// Include the CCS USB Libraries. See the comments at the top of these //
// files for more information //
// //
////////////////////////////////////////////////////////////////////////////

#include <pic18_usb.h> //Microchip 18Fxx5x hardware layer for usb.c
//[need not edit]
#include <usb_desc_hid.h> //USB Configuration and Device descriptors for
//this UBS device [to be edited as desired]
#include <usb.c> //Handles usb setup tokens and get descriptor
//reports[need not edit]


////////////////////////////////////////////////////////////////////////////
//// //
// usb_debug_task(): //
// //
// When called periodically, displays debugging information over serial //
// to display enumeration and connection states. Also lights LED1 based //
// upon //
// enumeration and status. //
// //
////////////////////////////////////////////////////////////////////////////

void usb_debug_task(void)
{
static int8 last_connected;
static int8 last_enumerated;
int8 new_connected;
int8 new_enumerated;

new_connected=usb_attached();
new_enumerated=usb_enumerated();

if (new_connected)
output_low(pin_b4);
else
output_high(pin_b4);

if (new_enumerated)
output_low(pin_b5);
else
output_high(pin_b5);

//The following Print Statements are to display debugging information on the
//USART terminal

if (new_connected && !last_connected)
printf("\r\n\nUSB connected, waiting for enumaration...");

if (!new_connected && last_connected)
printf("\r\n\nUSB disconnected, waiting for connection...");

if (new_enumerated && !last_enumerated)
printf("\r\n\nUSB enumerated by PC/HOST");

if (!new_enumerated && last_enumerated)
printf("\r\n\nUSBunenumerated by PC/HOST, waiting for
enumeration...")

last_connected=new_connected;
last_enumerated=new_enumerated;
}

void main()
{
////////////////////////////////////////////////////////////////////////////
// THIS IS WHERE YOUR CODE COMES IN: In this template, we'll be//
//illusatrating a simple example. The PC sends is data in this format //
// "P = nT", where "n" is the actual data to be transfered. "P" occupies//
//inData[0], "=" occupies inData[1], "T" occupies inData[3] while "n"//
//occupies inData[2]. Similarly, the PC prompts the PIC by sending a//
//message in this format "P = ??" after which the PIC multplies "n" by 2//
//and thn sends its value to the host PC. //
///////////////////////////////////////////////////////////////////////////
int8 data;
int8 inData[4];
int8 outData[4];
usb_init_cs();

while (TRUE)
{
usb_task();
usb_debug_task();
if (usb_enumerated())
{
if (usb_kbhit(1)) //affirms data reception from host PC
{
usb_get_packet(1, inData, 4); //gets data received and
//stores it in the buffer "inData"

if ((inData[0] == 'P' ) && (inData[1] == '=') &&
(inData[3] == 'T')) // verifes incoming data
{
printf("\r\n--> Received data: %c %c %d
%c",inData[0],inData[1], inData[2], inData[3]);
output_low(pin_B0); //LED blinks twice with an
//interval of "inData[2]"ms.
delay_ms(inData[2]);
output_high(pin_B0);
delay_ms(inData[2]);
output_low(pin_B0);
delay_ms(inData[2]);
output_high(pin_B0);
data = inData[2]*2;
printf("\r\n data= %d", data);
}
else if ((inData[0] == 'P' ) && (inData[1] == '=') &&
(inData[2] == '?') && (inData[3] == '?')) //verifes
//incoming data
{
outData[0] = 'P';
outData[1] = '=';
outData[2] = data;
outData[3] = 'T';
//usb_put_packet(1, outData, 4, USB_DTS_TOGGLE);
if(usb_put_packet(1, outData, 4, USB_DTS_TOGGLE))
//sends data to the host PC
printf("\r\n<-- Sending 4 bytes: %c %c %d %c",
outData[0], outData[1], outData[2], outData[3]);
output_low(pin_B1); //LED blinks twice with an
//interval of "inData[2] * 2"ms.
delay_ms(data);
output_high(pin_B1);
delay_ms(data);
output_low(pin_B1);
delay_ms(data);
output_high(pin_B1);
delay_ms(10);

}

}
delay_ms(10);
}
}
}
///////////////////////////////////////////////////////////////////////////
//PLEASE ENSURE THAT YOU THOROUGHLY GO THROUGH THE DOCUMENTATION/ COMMENTS//
//FRO THIS PROJECT AS TO HAVE A BETTER UNDERSTANDING OF IT. //
///////////////////////////////////////////////////////////////////////////


1est|ng the ro[ect
1esLlng Lhe pro[ecL ls relaLlvely easy. 1he sLeps are:
ConsLrucL Lhe hardware
Load Lhe program lnLo Lhe lC18l4330 mlcroconLroller
Copy or run Lhe C-based vlsual 8aslc program
When Lhe mlcroconLroller ls connecLed Lo one of Lhe uS8 porLs of Lhe C, a message should be vlslble aL Lhe
boLLom rlghL-hand corner of Lhe screen slmllar Lo Lhe one shown below. 1hls message shows LhaL Lhe new uS8
Plu devlce has been plugged ln and ls recognlzed by Lhe C.



ln addlLlon, Lhe devlce manager dlsplay should show an Plu-compllanL devlce and a uS8 human
lnLerface devlce as ln llgure 8.26. 1he properLles of Lhese drlvers can be dlsplayed Lo make sure Lhe vlu ls 1234
(4660 declmal) and Lhe lu ls 1 (1 declmal). LnLer daLa lnLo Lhe vlsual 8aslc form and cllck Lhe Send buLLon. 1he
correspondlng mlcroconLroller LLus should Lurn on. ln LesLlng your pro[ecL, lL ls advlsed LhaL you run lL ln Lhe
roLeus slmulaLor uslng lL lnbullL vlrLual uS8 funcLlonallLy.

lor furLher readlng, Lhese books can come ln handy:
AJvooceJ llc Mlctocoottollet ltojects lo c -uoqoo lbtoblm.
u58 complete j4
tb
Jltloo] -Ioo Axelsoo.




Pope you had a nlce Llme.

S-ar putea să vă placă și