|
Palm J2ME
How to use the USB controller in PIC16C745/765
1. Generally about USB and PIC
Microchip has constructed several microcontrollers with built-in USB controller. The circuits used in this document, PIC16C745/765, are only usable for low speed communication up to 1.5 MBit/s. Low speed transfering allows only two kind of protocols, Control Transfer and Interrupt Transfer. Both are using big overheads and the highest speed of user data is very low. In our case Control Transfer is used in the period of enumerating, when the host (computer) receives information about the circuit (PIC microcontroller). Interrupt Transfer is used to send user data between the host and the microcontroller. The highest speed of user data becomes 800 bytes/s.
When enumerating the host receives information containing several descriptors from the microcontroller. The descriptors contain information about kind of device, how often the host should communicate, own strings etc. The source code introduced in this document is builded of routines from Microchip which are used to initiate, enumerate and transfer user data. The foremost things to learn are how the descriptors for our device shall be written and how to use the finnished routines from Microchip. You can use tools to reach appropriate descriptors and then write the result into the source code.
In our example the host interprets the microcontroller as a HID, Human Interface Device. HIDs can be mouses, keyboards etc. It's the information inside the descriptors which tell the host that the device is a HID and what kind of HID it is. The advantage to let the device be interpreted as a HID is that you can use Microsoft's HID drivers in Windows. You don't need to develop own USB drivers. Then Win32API can be used for communication.
Low speed controllers can only use three endpoints, EP0 - EP2. You can describe an endpoint as a channel where the host and the microcontroller can communicate. EP0 is allways using Control Transfer as protocol. That is the channel for enumerating. EP1 and EP2 are free to use for Interrupt Transfer to send data from and to the host. But you can also use EP0 with Control Transfer to send data to and from the device. Prefer Interrupt Transfer when much data are going to be transfered, it's a bit faster. In our example EP0 is used to enumerate and EP1 to send and receive data.
2. Source code for the microcontroller
The lowest layer of the source code for communication is supplied by Microchip. It contains a simple Put/Get interface to the programmer and most of the USB management is handled in the background throw an interrupt routine. Enumerating is managed automatically with help of own descriptors.
USB functions to use: InitUSB, PutEP1, PutEP2, GetEP1, GetEP2.
One macro to use: ConfiguredUSB.
InitUSB initiates the USB controller and gives the host the possibility to contact and enumerate the device.
PutEPn sends data to the host and GetEPn receives data which the host has sent to the microcontroller. The number of endpoint is represented by n. The program in this document is only using EP1 to transfer data and EP0 for enumerating.
ConfiguredUSB waits until the microcontroller is in the state configured, when the enumerating is finnished. It's appropriate to run ConfiguredUSB after InitUSB to let you know when the circuit is ready to transfer information. The time it takes to enumerate is only dependent of the host and how busy the USB bus is.
One extra function exists to handle sleepmode, Checksleep. However it's not used in the example.
The ISR (Interrupt Service Routine) used for communication is ServiceUSBInt and must be called when an USB interrupt occure. Interrupts must be activated throw the flag GIE in the INTCON register.
Functions for the USB management are located in three files: usb_ch9.asm, descript.asm and hidclass.asm. They must be linked into the project. To make it possible for a simple Put/Get interface you also need to include the file usb_defs.inc.
The file usb_ch9.asm contains interface and corefunctions to enumerate.
The file descript.asm contains all descriptors which should be changed dependent of device.
The file hidclass.asm contains specific HID functions. All functions aren't written yet, but can be implemented later. The functions above are written and full functional.
The file usb_defs.inc contains the functions PutEPn and GetEPn together with the ConfiguredUSB macro.
It's easy to communicate with help of the functions explained above. The following example is received from Microchip's manual, PICDEM USB User's Guide. It lets the host enumerate and then it sending back incomming data from the USB bus. To get a full functional system you need to implement some code to handle interrupts etc. Look at the source code of the USB I/O device to see a complete program. Sorry about the dots in the code, but I can't use tabs or several spaces.
; *****************************
Main
pagesel InitUSB
call InitUSB ; Set up everything so we can enumerate
pagesel Main
ConfiguredUSB ; Wait here until we have enumerated
CheckEP1 ; Check EP1 for an OUT transaction
bankisel BUFFER ; Point to lower banks
pagesel GetEP1
movlw BUFFER
movwf FSR ; Point FSR to our buffer
call GetEP1 ; If data is ready, it will be copied
pagesel CheckEP1
btfss STATUS,C ; Was there any data for us?
goto CheckEP1 ; Nope, check again
PutBuffer
bankisel BUFFER ; point to lower banks
pagesel PutEP1
movlw BUFFER
movwf FSR ; Point FSR to our buffer
movlw 0x08 : Send 8 bytes to endpoint 1
call PutEP1
pagesel PutBuffer
btfss STATUS,C ; Was it successful?
goto PutBuffer ; No: try again until successful
pagesel CheckEP1
goto CheckEP1 ; Yes: restart loop
; *****************************
To tell the host what kind of device it will communicate with you make use of descriptors. It's Device Descriptors, Configuration Descriptors, Interface Descriptors, Endpoint Descriptors, String Descriptors and Report Descriptors. Read an USB manual or the source code to know more about the different descriptors. The most interesting parts to change for a HID:
Device Descriptor - idVendor, idProduct. These two 16-bits words contain an address to the device. The host is using this address for communication to the right device.
Configuration Descriptor - bmAttributes, MaxPower. If the device takes it's power from the USB bus or not. Allowable current to use from the bus.
Interface Descriptor - Number of endpoints, 0x02 to use one input channel and one output channel.
Endpoint Descriptor - Information about the endpoints: input, output, number of bytes to send in one message, polling interval (how often the host will communicate with the microcontroller). For one output channel and one input channel you need two endpoint descriptors.
Report Descriptor - Everything here is interesting to change, dependent of HID. The information in this descriptor are needed for enumeration, it describes the type of device. Use tools to write a report descriptor.
String Descriptor - Name of the unit, showed by Windows.
Written by PerErik Klarenfjord
|