Advanced PIC18 Projects—USB Bus Projects:USB-Based Microcontroller Input/Output

PROJECT 8.2—USB-Based Microcontroller Input/Output

This project is very similar to Project 8.1, except that it includes two-way communication, while in Project 8.1 data to be output on PORTB was sent to the

microcontroller. In addition, PORTB data is received from the microcontroller and displayed on the PC.

The PC sends two commands to the microcontroller:

• Command P ¼ nT requests the microcontroller to send data byte n to PORTB.

• Command P ¼ ?? requests the microcontroller to read its PORTB data and send it as a byte to the PC. The PC then displays this data on the screen. The microcontroller sends its data in the familiar format P ¼ nT.

The hardware of this project is the same as the hardware for the previous project, shown in Figure 8.11, where eight LEDs are connected to PORTB of a PIC18F4550 microcontroller which is operated from a 8MHz crystal.

A single form is used in this project, and Figure 8.31 shows the format of this form. The upper part of the form is the same as in Project 8.1, i.e., sending data to PORTB of the microcontroller. A text box and a command button named CLICK TO RECEIVE are also placed on the form. When the button is pressed, the PC sends command P ¼ ?? to the microcontroller. The microcontroller reads its PORTB data and sends it in the format P ¼ nT to the PC where it is displayed in the text box.

Advanced PIC18 Projects—USB Bus Projects-0172

Figure 8.32 shows the mikroC program of the project. The program is named USB2.C and is very similar to the one for the previous project. But here, in addition, when the command P ¼ ?? is received from the PC, the microcontroller reads PORTB data and sends it to the PC in the format using the mikroC function Hid_Write.

The program checks the format of the received command. For P ¼ ?? type commands, PORTB is configured as inputs, PORTB data is read into Write_buffer[2], and Write_buffer is sent to the PC, where Write_buffer[0] ¼ “P,” Write_buffer[1] ¼ “¼”, and Write_buffer[3] ¼ “T” as follows:

Advanced PIC18 Projects—USB Bus Projects-0173

The microcontroller clock should be set as in Project 8.1 (i.e., both the CPU and the USB module should have 48MHz clocks). The other configurations bits should also be set as described in the previous problem.

Testing the Project

The project can be tested using one of the methods described in the previous project. If you are using the Visual Basic program, send data to the microcontroller and make sure the correct LEDs are turned on. Then connect some of the PORTB pins to logic 0 and click the CLICK TO RECEIVE button. The microcontroller will read its PORTB data and send it to the PC, where it will be displayed on the PC screen.

Advanced PIC18 Projects—USB Bus Projects-0174

Advanced PIC18 Projects—USB Bus Projects-0175

Advanced PIC18 Projects—USB Bus Projects-0176

The project can also be tested using the HID terminal of mikroC IDE. The steps are:

• Start the HID terminal.

• Send a command to the microcontroller to turn on the LEDs (e.g., P ¼ 1T ) and make sure the correct LEDs are turned on (in this case, LEDs 0, 4, and 5 should turn on, corresponding to the data pattern “0011 0001”).

• Connect bits 2 and 3 of PORTB to logic 1 and the other six bits to ground.

• Send command P ¼ ?? to the microcontroller.

• The PC will display the number 12, corresponding to bit pattern “0000 1100”. The Visual Basic program listing of the project is given in Figure 8.33. Only the main

program is given here, as the library declarations are the same as in Figure 8.19. The program jumps to subroutine OnRead when data arrives at the USB bus. The format of this data is checked to be in the format P ¼ nT, and if the format is correct, the received data byte is displayed in the text box.

An installable version of the Visual Basic PC program is available in folder USB2 on the CDROM included with this book.

Advanced PIC18 Projects—USB Bus Projects-0177Advanced PIC18 Projects—USB Bus Projects-0178Advanced PIC18 Projects—USB Bus Projects-0179

 

Advanced PIC18 Projects—USB Bus Projects:Descriptors

Descriptors

All USB devices have a hierarchy of descriptors that describe various features of the device: the manufacturer ID, the version of the device, the version of USB it supports, what the device is, its power requirements, the number and type of endpoints, and so forth.

The most common USB descriptors are:

• Device descriptors

• Configuration descriptors

• Interface descriptors

• HID descriptors

• Endpoint descriptors

The descriptors are in a hierarchical structure as shown in Figure 8.7. At the top of the hierarchy we have the device descriptor, then the configuration descriptors, followed by the interface descriptors, and finally the endpoint descriptors. The HID descriptor always follows the interface descriptor when the interface belongs to the HID class.

All descriptors have a common format. The first byte (bLength) specifies the length of the descriptor, while the second byte (bDescriptorType) indicates the descriptor type.

Device Descriptors

The device descriptor is the top-level set of information read from a device and the first item the host attempts to retrieve.

Advanced PIC18 Projects—USB Bus Projects-0134

A USB device has only one device descriptor, since the device descriptor represents the entire device. It provides general information such as manufacturer, serial number, product number, the class of the device, and the number of configurations.

Table 8.5 shows the format for a device descriptor with the meaning of each field.

bLength is the length of the device descriptor.

bDescriptorType is the descriptor type.

bcdUSB reports the highest version of USB the device supports in BCD format. The number is represented as 0xJJMN, where JJ is the major version number, M is the minor version number, and N is the subminor version number. For example, USB 1.1 is reported as 0x0110.

bDeviceClass, bDeviceSubClass, and bDeviceProtocol are assigned by the USB organization and are used by the system to find a class driver for the device.

bMaxPacketSize0 is the maximum input and output packet size for endpoint 0. idVendor is assigned by the USB organization and is the vendor’s ID. idProduct is assigned by the manufacturer and is the product ID.

bcdDevice is the device release number and has the same format as the bcdUSB.

Advanced PIC18 Projects—USB Bus Projects-0135

iManufacturer, iProduct, and iSerialNumber are details about the manufacturer and the product. These fields have no requirement and can be set to zero.

bNumConfigurations is the number of configurations the device supports.

Table 8.6 shows an example device descriptor for a mouse device. The length of the descriptor is 18 bytes (bLength ¼ 18), and the descriptor type is 0x01 (bDescriptorType

¼ 0x01). The device supports USB 1.1 (bcdUSB ¼ 0x0110). bDeviceClass, bDeviceSubClass, and bDeviceProtocol are set to zero to show that the class information is in the interface descriptor. bMaxPacketSize0 is set to 8 to show that the maximum input and output packet size for endpoint 0 is 8 bytes. The next three bytes identify the device by the vendor ID, product ID, and device version number. The next three items define indexes to strings about the manufacturer, product, and the serial number. Finally, we notice that the mouse device has just one configuration (bNumConfigurations ¼ 1).

Advanced PIC18 Projects—USB Bus Projects-0136

Configuration Descriptors

The configuration descriptor provides information about the power requirements of the device and how many different interfaces it supports. There may be more than one configuration for a device.

Table 8.7 shows the format of the configuration descriptor with the meaning of each field.

bLength is the length of the device descriptor.

bDescriptorType is the descriptor type.

wTotalLength is the total combined size of this set of descriptors (i.e., total of configuration descriptor þ interface descriptor þ HID descriptor þ endpoint descriptor). When the configuration descriptor is read by the host, it returns the entire configuration information, which includes all interface and endpoint descriptors.

Advanced PIC18 Projects—USB Bus Projects-0137

bNumInterfaces is the number of interfaces present for this configuration.

bConfigurationValue is used by the host (in command SetConfiguration) to select the configuration.

iConfiguration is an index to a string descriptor describing the configuration in readable format.

bmAttributes describes the power requirements of the device. If the device is USB bus-powered, then bit D7 is set. If it is self-powered, it sets bit D6. Bit D5 specifies the remote wakeup of the device. Bits D7 and D0–D4 are reserved.

bMaxPower defines the maximum power the device will draw from the bus in 2mA units.

Table 8.8 shows an example configuration descriptor for a mouse device. The length of the descriptor is 9 bytes (bLength ¼ 9), and the descriptor type is 0x02 (bDescriptorType ¼ 0x02). The total combined size of the descriptors is 34 (wTotalLength ¼ 34). The number of interfaces for the mouse device is 1 (bNumInterfaces ¼ 1). Host SetConfiguration command must use the value 1 as an argument in SetConfiguration() to select this configuration. There is no string to describe this configuration. bmAttributes is set to 0x40 to indicate that the device is self-powered. bMaxPower is set to 10 to specify that the maximum current drawn by the device is 20mA.

Advanced PIC18 Projects—USB Bus Projects-0138

bLength is the length of the device descriptor.

bDescriptorType is the descriptor type.

bInterfaceNumber indicates the index of the interface descriptor.

bAlternateSetting can be used to specify alternate interfaces that can be selected by the host using command Set Interface.

bNumEndpoints indicates the number of endpoints used by the interface. bInterfaceClass specifies the device class code (assigned by the USB organization). bInterfaceSubClass specifies the device subclass code (assigned by the USB organization).

bInterfaceProtocol specifies the device protocol code (assigned by the USB organization).

iInterface is an index to a string descriptor of the interface.

Table 8.10 shows an example interface descriptor for a mouse device. The descriptor length is 9 bytes (bLength ¼ 9) and the descriptor type is 0x04 (bDescriptorType ¼ 0x04). The interface number used to reference this interface is 1 (bInterfaceNumber ¼ 1).

Advanced PIC18 Projects—USB Bus Projects-0139

bAlternateSetting is set to 0 (i.e., no alternate interfaces). The number of endpoints used by this interface is 1 (excluding endpoint 0), and this is the endpoint used for the mouse to send its data. The device class code is 0x03 (bInterfaceClass ¼ 0x03). This is an HID (human interface device) type class. The interface subclass is set to 0x02. The device protocol is 0x02 (mouse). There is no string to describe this interface (iInterface ¼ 0).

HID Descriptors

An HID descriptor always follows an interface descriptor when the interface belongs to the HID class. Table 8.11 shows the format of the HID descriptor.

bLength is the length of the device descriptor. bDescriptorType is the descriptor type. bcdHID is the HID class specification.

bCountryCode specifies any special local changes.

bNumDescriptors specifes if there are any additional descriptors associated with this class.

bDescriptorType is the type of the additional descriptor specified in

bNumDescriptors.

wDescriptorLength is the length of the additional descriptor in bytes.

Advanced PIC18 Projects—USB Bus Projects-0140

Table 8.12 shows an example HID descriptor for a mouse device. The length of the descriptor is 9 bytes (bLength ¼ 9), and the descriptor type is 0x21 (bDescriptorType

¼ 0x21). The HID class is set to 1.1 (bcdHID ¼ 0x0110). The country code is set to zero (bCountryCode ¼ 0), specifying that there is no special localization with this device. The number of descriptors is set to 1 (bNumDescriptors ¼ 1) which specifies that there is one additional descriptor associated with this class. The type of the additional descriptor is REPORT (bDescriptorType ¼ REPORT), and its length is 52 bytes (wDescriptorLength ¼ 52).

Advanced PIC18 Projects—USB Bus Projects-0141

Endpoint Descriptors

Table 8.13 shows the format of the endpoint descriptor. bLength is the length of the device descriptor. bDescriptorType is the descriptor type. bEndpointAddress is the address of the endpoint. bmAttributes specifies what type of endpoint it is. wMaxPacketSize is the maximum packet size.

bInterval specifies how often the endpoint should be polled (in ms).

Table 8.14 shows an example endpoint descriptor for a mouse device. The length of the descriptor is 7 bytes (bLength ¼ 7), and the descriptor type is 0x05 (bDescriptorType

Advanced PIC18 Projects—USB Bus Projects-0142

¼ 0x05). The endpoint address is 0x50 (bEndpointAddress ¼ 0x50). The endpoint is to be used as an interrupt endpoint (bmAttributes ¼ 0x03). The maximum packet size is set to 2 (wMaxPacketSize ¼ 0x02) to indicate that packets longer than 2 bytes will not be sent from the endpoint. The endpoint should be polled at least once every 20ms (bInterval ¼ 0x14).

 

Advanced PIC18 Projects—USB Bus Projects:mikroC Language USB Bus Library Functions

mikroC Language USB Bus Library Functions

The mikroC language supports a number of functions for USB HID-type communications. Each project based on the USB library should include a descriptor source file which contains vendor ID and name, product ID and name, report length, and other relevant information. To create a descriptor source file we can use mikroC’s integrated USB HID terminal tool (see Tools ! HID Terminal). The default name for descriptor file is USBdsc.c, but it can be renamed if required. The USBdsc.c file must be included in USB-based projects either via the mikroC IDE tool, or as an #include option in the program source file.

The mikroC language supports the following USB bus library functions when a PIC microcontroller with built-in USB is used (e.g., PIC18F4550), and port pins RC4 and RC5 are connected to the Dþ and D- pins of the USB connector respectively:

Hid_Enable: This function enables USB communication and requires two arguments: the read-buffer address and the write-buffer address. It must be called before any other functions of the USB library, and it returns no data.

Hid_Read: This function receives data from the USB bus and stores it in the receive- buffer. It has no arguments but returns the number of characters received.

Hid_Write: This function sends data from the write-buffer to the USB bus. The name of the buffer (the same buffer used in the initialization) and the length of the data to be sent must be specified as arguments to the function. The function does not return any data.

Hid_Disable: This function disables the USB data transfer. It has no arguments and returns no data.

The USB interface of a PIC18F4550 microcontroller is shown in Figure 8.9. As the figure shows, the interface is very simple. In addition to the power supply and ground pins, it requires just two pins to be connected to the USB connector. The microcontroller receives power from the USB port.

Advanced PIC18 Projects—USB Bus Projects-0144

 

Advanced PIC18 Projects—USB Bus Projects:PIC18 Microcontroller USB Bus Interface

PIC18 Microcontroller USB Bus Interface

Some of the PIC18 microcontrollers support USB interface directly. For example, the PIC18F4550 microcontroller contains a full-speed and low-speed compatible USB interface that allows communication between a host PC and the microcontroller. In the USB projects in this chapter we will use the PIC18F4550 microcontroller.

Figure 8.8 is an overview of the USB section of the PIC18F4550 microcontroller. PORTC pins RC4 (pin 23) and RC5 (pin 24) are used for USB interface. RC4 is the USB data D- pin, and RC5 is the USB data Dþ pin. Internal pull-up resistors are provided which can be disabled (setting UPUEN ¼ 0) if desired and external pull-up resistors can be used instead. For full-speed operation an internal or external resistor should be connected to data pin Dþ, and for low-speed operation an internal or external resistor should be connected to data pin D-.

Operation of the USB module is configured using three control registers, and a total of twenty-two registers are used to manage the actual USB transactions. Configuration

Advanced PIC18 Projects—USB Bus Projects-0143

of these registers is a highly complex task and is not covered in this book. Interested readers should refer to the PIC18F4550 data sheet and to books on USB internals.

In this chapter we are using the mikroC language USB library functions to implement USB transactions. The details of these functions are given in the next section.

 

Advanced PIC18 Projects—USB Bus Projects:USB Bus Communication

USB Bus Communication

USB is a host-centric connectivity system where the host dictates the use of the USB bus. Each device on the bus is assigned a unique USB address, and no slave device can assert a signal on the bus until the host asks for it. When a new USB device is plugged into a bus, the USB host uses address 0 to ask basic information from the device. Then the host assigns it a unique USB address. After the host asks for and receives further information about the device, such as the name of the manufacturer, device capabilities, and product ID, two-way transactions on the bus can begin.

Packets

Data is transmitted on a USB bus in packets. A packet starts with a sync pattern to allow the receiver clock to synchronize with the data. The data bytes of the packet follow, ending with an end of packet signal.

A packet identifier (PID) byte immediately follows the sync field of every USB packet. A PID itself is 4 bits long, and the 4 bits are repeated in a complemented form. There are seventeen different PID values, as shown in Table 8.4. These include one reserved value and one that is used twice, with two different meanings.

There are four packet formats, based on which PID is at the start of the packet: token packets, data packets, handshake packets, and special packets.

Figure 8.4 shows the format of a token packet, which is used for OUT, IN, SOF (start of frame), and SETUP. The packet contains a 7-bit address, a 4-bit ENDP (endpoint number), a 5-bit CRC checksum, and an EOP (end of packet).

Advanced PIC18 Projects—USB Bus Projects-0132

A data packet is used for DATA0, DATA1, DATA2, and MDATA data transactions. The packet format is shown in Figure 8.5 and consists of the PID, 0–1024 bytes of data, a 2-byte CRC checksum, and an EOP.

Advanced PIC18 Projects—USB Bus Projects-0133

Figure 8.6 shows the format of a handshake packet, which is used for ACK, NAK, STALL, and NYET. ACK is used when a receiver acknowledges that it has received an error-free data packet. NAK is used when the receiving device cannot accept the packet. STALL indicates when the endpoint is halted, and NYET is used when there is no response from the receiver.

Data Flow Types

Data can be transferred on a USB bus in four ways: bulk transfer, interrupt transfer, isochronous transfer, and control transfer.

Bulk transfers are designed to transfer large amounts of data with error-free delivery and no guarantee of bandwidth. If an OUT endpoint is defined as using bulk transfers, then the host will transfer data to it using OUT transactions. Similarly, if an IN endpoint is defined as using bulk transfers, then the host will transfer data from it using IN transactions. In general, bulk transfers are used where a slow rate of transfer is not a problem. The maximum packet size in a bulk transfer is 8 to 64 packets at full speed, and 512 packets at high speed (bulk transfers are not allowed at low speeds).

Interrupt transfers are used to transfer small amounts of data with a high bandwidth where the data must be transferred as quickly as possible with no delay. Note that interrupt transfers have nothing to do with interrupts in computer systems. Interrupt packets can range in size from 1 to 8 bytes at low speed, from 1 to 64 bytes at full speed, and up to 1024 bytes at high speed.

Isochronous transfers have a guaranteed bandwidth, but error-free delivery is not guaranteed. This type of transfer is generally used in applications, such as audio data

transfer, where speed is important but the loss or corruption of some data is not. An isochronous packet may contain 1023 bytes at full speed or up to 1024 bytes at high speed (isochronous transfers are not allowed at low speeds).

A control transfer is a bidirectional data transfer, using both IN and OUT endpoints. Control transfers are generally used for initial configuration of a device by the host. The maximum packet size is 8 bytes at low speed, 8 to 64 bytes at full speed, and 64 bytes at high speed. A control transfer is carried out in three stages: SETUP, DATA, and STATUS.

Enumeration

When a device is plugged into a USB bus, it becomes known to the host through a process called enumeration. The steps of enumeration are:

• When a device is plugged in, the host becomes aware of it because one of the data lines (Dþ or D-) becomes logic high.

• The host sends a USB reset signal to the device to place the device in a known state. The reset device responds to address 0.

• The host sends a request on address 0 to the device to find out its maximum packet size using a Get Descriptor command.

• The device responds by sending a small portion of the device descriptor.

• The host sends a USB reset again.

• The host assigns a unique address to the device and sends a Set Address request to the device. After the request is completed, the device assumes the new address. At this point the host is free to reset any other newly plugged-in devices on the bus.

• The host sends a Get Device Descriptor request to retrieve the complete device descriptor, gathering information such as manufacturer, type of device, and maximum control packet size.

• The host sends a Get Configuration Descriptors request to receive the device’s configuration data, such as power requirements and the types and number of interfaces supported.

• The host may request any additional descriptors from the device.

The initial communication between the host and the device is carried out using the control transfer type of data flow.

Initially, the device is addressed, but it is in an unconfigured state. After the host gathers enough information about the device, it loads a suitable device driver which configures the device by sending it a Set Configuration request. At this point the device has been configured, and it is ready to respond to device-specific requests (i.e., it can receive data from and send data to the host).

 

Advanced PIC18 Projects—USB Bus Projects:USB States

USB States

Some of the USB bus states are:

Idle: The bus is in idle state when the pulled-up line is high and the other line is low. This is the state of the lines before and after a packet transmission.

Detached: When no device is connected to the bus, the host sees both lines as low.

Attached: When a device is connected to the bus, the host sees either Dþ or D- go to logic high, which means a device has been plugged in.

J state: The same as idle state.

K state: The opposite of J state.

SE0: The single ended zero state, where both lines on the bus are pulled low.

SE1: The single ended one state, where both lines on the bus are high. SE1 is an illegal condition on the bus; it must never be in this state.

Reset: When the host wants to communicate with a device on the bus, it first sends a “reset” condition by pulling low both data lines (SE0 state) for at least 10ms.

EOP: The end of packet state, which is basically an SE0 state for 2 bit times, followed by a J state for 1 bit time.

Keep alive: The state achieved by EOP. Keep alive is sent at least once every millisecond to keep the device from suspending.

Suspend: Used to save power, suspend is implemented by not sending anything to a device for 3ms. A suspended device draws less than 0.5mA from the bus and must recognize reset and resume signals.

Resume: A suspended device is woken up by reversing the polarity of the signal on the data lines for at least 20ms, followed by a low-speed EOP signal.

 

Advanced PIC18 Projects—USB Bus Projects:Speed Identification on the Bus

The Universal Serial Bus (USB) is one of the most common interfaces used in electronic consumer products today, including PCs, cameras, GPS devices, MP3 players, modems, printers, and scanners, to name a few.

The USB was originally developed by Compaq, Microsoft, Intel, and NEC, and later by Hewlett-Packard, Lucent, and Philips as well. These companies eventually formed the nonprofit corporation USB Implementers Forum Inc. to organize the development and publication of USB specifications.

This chapter describes the basic principles of the USB bus and shows how to use USB-based applications with PIC microcontrollers. The USB bus is a complex protocol. A complete discussion of its design and use is beyond the scope of this chapter. Only the basic principles, enough to be able to use the USB bus, are outlined here. On the other hand, the functions offered by the mikroC language that simplify the design of USB-based microcontroller projects are described in some detail.

The USB is a high-speed serial interface that can also provide power to devices connected to it. A USB bus supports up to 127 devices (limited by the 7-bit address field—note that address 0 is not used as it has a special purpose) connected through a four-wire serial cable of up to three or even five meters in length. Many USB devices can be connected to the same bus with hubs, which can have 4, 8, or even 16 ports.

A device can be plugged into a hub which is plugged into another hub, and so on. The maximum number of tiers permitted is six. According to the specification, the maximum distance of a device from its host is about thirty meters, accomplished by using five hubs. For longer-distance bus communications, other methods such as use of Ethernet are recommended.

The USB bus specification comes in two versions: the earlier version, USB1.1, supports 11Mbps, while the new version, USB 2.0, supports up to 480Mbps. The USB specification defines three data speeds:

• Low speed—1.5Mb/sec

• Full speed—12Mb/sec

• High speed— 480Mb/sec

The maximum power available to an external device is limited to about 100mA at 5.0V.

USB is a four-wire interface implemented using a four-core shielded cable. Two types of connectors are specified and used: Type A and Type B. Figure 8.1 shows typical USB connectors. Figure 8.2 shows the pin-out of the USB connectors.

The signal wire colors are specified. The pins and wire colors of a Type A or Type B connector are given in Table 8.1.

Advanced PIC18 Projects—USB Bus Projects-0127

Advanced PIC18 Projects—USB Bus Projects-0128

The specification also defines a mini-B connector, mainly used in smaller portable electronic devices such as cameras and other handheld devices. This connector has a fifth pin called ID, though this pin is not used. The pin assignment and wire colors of a mini-B connector are given in Table 8.2.

Two of the pins, Dataþ and Data-, form a twisted pair and carry differential data signals and some single-ended data states.

Advanced PIC18 Projects—USB Bus Projects-0129

USB signals are bi-phase, and signals are sent from the host computer using the NRZI (non-return to zero inverted) data encoding technique. In this technique, the signal level is inverted for each change to a logic 0. The signal level for a logic 1 is not changed. A 0 bit is “stuffed” after every six consecutive ones in the data stream to make the data dynamic (this is called bit stuffing because the extra bit lengthens the data stream). Figure 8.3 shows how the NRZI is implemented.

Advanced PIC18 Projects—USB Bus Projects-0130

A packet of data transmitted by the host is sent to every device connected to the bus, traveling downward through the chain of hubs. All the devices receive the signal, but only one of them, the addressed one, accepts the data. Conversely, only one device at any time can transmit to the host, and the data travels upward through the chain of hubs until it reaches the host.

USB devices attached to the bus may be full-custom devices, requiring a full-custom device driver, or they may belong to a device class. Device classes enable the same device driver to be used for several devices having similar functionalities. For example, a printer device has the device class 0x07, and most printers use drivers of this type.

The most common device classes are given in Table 8.3. The USB human interface device (HID) class is of particular interest, as it is used in the projects in this chapter.

Some common USB terms are:

Endpoint: An endpoint is either a source or a sink of data. A single USB device can have a number of endpoints, the limit being sixteen IN and sixteen OUT endpoints.

Transaction: A transaction is a transfer of data on the bus.

Pipe: A pipe is a logical data connection between the host and an endpoint.

Advanced PIC18 Projects—USB Bus Projects-0131

Speed Identification on the Bus

At the device end of the bus, a 1.5K pull-up resistor is connected from the Dþ or D- line to 3.3V. On a full-speed bus, the resistor is connected from the Dþ line to 3.3V, and on a low-speed bus the resistor is from D- line to 3.3V. When no device is plugged in, the host will see both data lines as low. Connecting a device to the bus will pull either the Dþ or the D- line to logic high, and the host will know that a device is plugged into the bus. The speed of the device is determined by observing which line is pulled high.

 

Advanced PIC18 Projects—SD Card Projects:Temperature Logger

PROJECT 7.4—Temperature Logger

This project shows the design of a temperature data logger system. The ambient temperature is read every ten seconds and stored in a file on an SD card. The program is menu-based, and the user is given the option of:

• Sending the saved file contents to a PC

• Saving the temperature readings to a new file on an SD card

• Appending the temperature readings to an existing file on an SD card The hardware of this project is similar to the one for Project 7.1 (i.e., as shown in Figure 7.8), but here, in addition, the serial input port pin (RC7) is connected to the RS232 connector so data can be received from the PC keyboard. In addition, a LM35DZ-type analog temperature sensor is connected to the microcontroller’s analog input AN0 (pin 2). The new circuit diagram is shown in Figure 7.14.

Advanced PIC18 Projects—SD Card Projects-0118

The LM35 DZ is a three-pin analog temperature sensor that can measure with 1oC accuracy temperatures between 0oC and þ100oC. One pin of the device is connected to the supply (þ5V), another pin to the ground, and the third to the analog output. The output voltage of the sensor is directly proportional to the temperature (i.e., Vo ¼ 10mV/oC). If, for example, the temperature is 10oC, the output voltage will be 100mV, and if the temperature is 35oC, the output voltage of the sensor will be 350mV.

When the program is started, the following menu is displayed on the PC screen: TEMPERATURE DATA LOGGER

1. Send temperature data to the PC

2. Save temperature data in a new file

3. Append temperature data to an existing file Choice?

The user then chooses one of the three options. When an option is completed, the program does not return to the menu. To display the menu again the system has to be restarted.

The program listing of the project is shown in Figure 7.15 (program SD4.C). In this project, a file called TEMPERTRTXT is created on the SD card to store the temperature readings (the library function call will insert the “.” to make the filename “TEMPERTR.TXT”), if it does not already exist.

The following functions are created at the beginning of the program, before the main program:

Newline sends a carriage return and a line feed to the UART so the cursor moves to the next line.

Text_To_Usart receives a text string as its argument and sends it to the UART to display on the PC screen.

Get_Temperature starts the A/D conversion and receives the converted data into a variable called Vin. The voltage corresponding to this value is then calculated in millivolts and divided by 10 to find the actual measured temperature in oC. The decimal part of the found temperature is then converted into string form using function LongToStr. The leading spaces are removed from this string, and the resulting string is stored in character array temperature. Then the fractional parts of the measured temperature, a carriage return, and a line feed are added to this character array, which is later written to the SD card.

The following operations are performed inside the main program:

• Initialize the UART to 2400 baud

• Initialize the SPI bus

• Initialize the FAT file system

• Display menu on the PC screen

• Get a choice from the user (1, 2, or 3)

• If the choice ¼ 1, assign the temperature file, read the temperature records, and display them on the PC screen

Advanced PIC18 Projects—SD Card Projects-0119

Advanced PIC18 Projects—SD Card Projects-0120Advanced PIC18 Projects—SD Card Projects-0121

Advanced PIC18 Projects—SD Card Projects-0122Advanced PIC18 Projects—SD Card Projects-0123Advanced PIC18 Projects—SD Card Projects-0124

• If the choice ¼ 2, create a new temperature file, get new temperature readings every ten seconds, and store them in the file

• If the choice ¼ 3, assign to the temperature file, get new temperature readings every ten seconds, and append them to the existing temperature file

• If the choice is not 1, 2, or 3, display an error message on the screen The menu options are described here in more detail:

Option 1: The program attempts to assign the existing temperature file. If the file does not exist, the error messages “File does not exist.. .No saved data.. .” and “Restart the program and save data to the file.. .” are displayed on the screen, and the user is expected to restart the program. If, on the other hand, the temperature file already exists, then the message: “Sending saved data to the PC.. .” is displayed on the PC screen. Function Mmc_Fat_Reset is called to set the file pointer to the beginning of the file and also return the size of the file in bytes. Then a for loop is formed, temperature records are read from the card one byte at a time using function Mmc_Fat_Read, and these records are sent to the PC screen using function Usart_Write. At the end of the data the message “End of data.. .” is sent to the PC screen.

Option 2: In this option, the message “Saving data in a NEW file.. .” is sent to the PC screen, and a new file is created using function Mmc_Fat_Assign with the create flag set to 0x80. The message “TEMPERATURE DATA – SAVED EVERY 10 SECONDS” is written on the first line of the file using function Mmc_Fat_Write. Then, a for loop is formed, the SD card is set to file append mode by calling function Mmc_Fat_Append, and a new temperature reading is obtained by calling function Get_Temperature. The temperature is then written to the SD card. Also, the current record number appears on the PC screen to indicate that the program is actually working. This process is repeated after a ten-second delay.

Option 3: This option is very similar to Option 2, except that a new file is not created but rather the existing temperature file is opened in read mode. If the file does not exist, then an error message is displayed on the PC screen.

Default: If the user entry is a number other than 1, 2, or 3, then this option runs and displays the error message “Wrong choice.. .Restart the program and try again.. .” on the PC screen.

The project can be tested by connecting the output of the microcontroller to the serial port of a PC (e.g., COM1) and then running the HyperTerminal terminal emulation software. Set the communications parameters to 2400 baud, 8 data bits, 1 stop bit, and no parity bit. Figure 7.16 shows a snapshot of the PC screen when Option 2 is selected to save the temperature records in a new file. Notice that the current record numbers are displayed on the screen as they are written to the SD card.

Figure 7.17 shows a screen snapshot where Option 1 is selected to read the temperature records from the SD card and display them on the PC screen.

Advanced PIC18 Projects—SD Card Projects-0125Advanced PIC18 Projects—SD Card Projects-0126

 

Advanced PIC18 Projects—SD Card Projects:Read CID Register and Display on a PC Screen

PROJECT 7.1—Read CID Register and Display on a PC Screen

In this project a SD card is interfaced to a PIC18F452-type microcontroller. The serial output port of the microcontroller is connected to the serial input port (e.g.,

COM1) of a PC. The microcontroller reads the contents of the card CID register and sends this data to the PC so it can be displayed on the PC screen.

Figure 7.7 shows the block diagram of the project.

Advanced PIC18 Projects—SD Card Projects-0105

The circuit diagram of the project is shown in Figure 7.8. The SD card is inserted into a card holder and then connected to PORTC of a PIC18F452 microcontroller through 2.2K and 3.3K resistors, using the following pins:

• Card CS to PORTC pin RC2

• Card CLK to PORTC pin RC3

• Card DO to PORTC pin RC4

• Card DI to PORTC pin RC5

According to the SD card specifications, when the card is operating with a supply voltage of VDD ¼ 3.3V, the input-output pin voltage levels are as follows:

• Minimum produced output HIGH voltage, VOH ¼ 2.475V

• Maximum produced output LOW voltage, VOL ¼ 0.4125V

• Minimum required input HIGH voltage, VIH ¼ 2.0625

• Maximum input HIGH voltage, VIH ¼ 3.6V

• Maximum required input LOW voltage, VIL ¼ 0.825V

Advanced PIC18 Projects—SD Card Projects-0106

Although the output produced by the card (2.475V) is sufficient to drive the input port of a PIC microcontroller, the logic HIGH output of the microcontroller (about 4.3V)

is too high for the SD card inputs (maximum 3.6V). Therefore, a potential divider is set up at the three inputs of the SD card using 2.2K and 3.3K resistors. This limits the maximum voltage at the inputs of the SD card to about 2.5V:

Advanced PIC18 Projects—SD Card Projects-0107

Serial output port pin RC6 (TX) of the microcontroller is connected to a MAX232-type RS232 voltage level converter chip and then to a 9-way D-type connector so it can be connected to the serial input port of a PC.

The microcontroller is powered from a 5V supply which is obtained via a 7805-type 5V regulator with a 9V input. The 2.7V–3.6V supply required by the SD card is obtained via an MC33269DT-3.3 regulator with 3.3V output and is driven from the 5V input voltage.

The program listing of the project is given in Figure 7.9 (program SD1.C). At the beginning of the main program, character array CID is declared to have 16 bytes.

Advanced PIC18 Projects—SD Card Projects-0108

Advanced PIC18 Projects—SD Card Projects-0109

Advanced PIC18 Projects—SD Card Projects-0110

Variable msg is loaded with the message that is to be displayed when power is applied to the system. Then the UART is initialized at PORTC with a baud rate of 2400.

Before the SD card library functions are used, the function Spi_Init_Advanced must be called with the given arguments. Then the SD card bus is initialized by calling function Mmc_Init, where it is specified that the card is connected to PORTC. The program then enters an endless loop that repeats every ten seconds.

Inside this loop the heading message is displayed followed by two new-line characters. The program then reads the contents of register CID by calling function Mmc_Read_Cid and stores the data in character array CID. The data is then sent to the serial port by calling function Str_To_Usart. At the end of the loop two new-line characters are displayed, the program waits for ten seconds, and the loop is repeated.

The operation of the project can be tested by connecting the device to a PC and starting the HyperTerminal terminal emulation program on the PC. Set the communications parameters to 2400 baud, 8 data bits, 1 stop bit, and no parity bit. An example output on the screen is shown in Figure 7.10.

Advanced PIC18 Projects—SD Card Projects-0111

Advanced PIC18 Projects—SD Card Projects-0112

 

Advanced PIC18 Projects—SD Card Projects:Read/Write to SD Card Sectors

PROJECT 7.2—Read/Write to SD Card Sectors

The hardware of this project is the same as for Project 7.1 (i.e., as shown in Figure 7.8). In this project, sector 10 of the SD card is filled with “C” characters, and then this sector is read and the card data is sent to the UART.

The program listing of this project is given in Figure 7.11 (program SD2.C). Two character arrays called data1 and data2, of 512 bytes each, are declared at the beginning of the program. Array data1 is loaded with character “C,” and

the contents of this array are written to sector 10 of the SD card. Then the contents of sector 10 are read into character array data2 and sent to the UART, displaying 512 “C” characters on the PC screen. Normally, only one array is used to read and write to the SD card. Two arrays are used here to make it clear that what is sent to the UART is the card data, not the contents of array data1.