Chinaunix首页 | 论坛 | 博客
  • 博客访问: 593450
  • 博文数量: 98
  • 博客积分: 4045
  • 博客等级: 上校
  • 技术积分: 1157
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-31 16:56
文章分类

全部博文(98)

文章存档

2010年(7)

2009年(15)

2007年(73)

2006年(3)

我的朋友

分类: LINUX

2007-02-06 17:11:02

Serial Communication and USB Communication

In Linux

 

1.     Serial communication in Linux

1.1 Introduction

Serial communication is a popular means of transmitting data between a computer and a peripheral device such as a programmable instrument or even another computer. Serial communication uses a transmitter to send data, one bit at a time, over a single communication line to a receiver. You can use this method when data transfer rates are low or you must transfer data over long distances. Serial communication is popular because most computers have one or more serial ports, so no extra hardware is needed other than a cable to connect the instrument to the computer or two computers together.

Serial communication requires that you specify the following four parameters:

a. Baud rate: a speed measurement for communication. It indicates the number of bit transfers per second.

b. Data bits: a measurement of the actual data bits in a transmission.

c. Stop bits: used to signal the end of communication for a single packet. Typical values are 1, 1.5, and 2 bits.

d. Parity: a simple form of error checking that is used in serial communication.

Each transmitted character is packaged in a character frame that consists of a single start bit followed by the data bits, the optional parity bit, and the stop bit or bits.

       The Linux operating system provides a very good support to the serial port, The focus of this chapter is

serial communication in Linux.  

 

1.2 Serial operation

       Serial operation needs the following head files:

       #include         

       #include        

#include        

#include      

#include       

#include         

#include        

#include    

 

1.3 Open a serial port

       The serial documents are located under /dev in Linux. The serial one is /dev/ttyS0, the serial tow is /dev/ttyS1 and so on, you can use the function open to open a serial port.

 

1.4 Serial port settings

 

The devices /dev/ttyS* are intended to hook up terminals to your Linux box, and are configured for this

use after startup. This has to be kept in mind when programming communication with a raw device. E.g. the

ports are configured to echo characters sent from the device back to it, which normally has to be changed for data transmission.

       The most basic settings of a serial port include the baud rate setting, the parity setting and stop bits setting. The serial port settings are mainly set the members of the struct termios. Set this struct is very complex, but I still know about it a little at present.

 

1.5 Reading and Writing

       After setting the serial port, reading from and writing to communications ports are very easy. Reading from and writing to communications ports in Linux is very similar to file input/output (I/O) in Linux. In fact, the functions that accomplish file I/O are the same functions used for serial I/O.

a.       Send data

We can use the function write to send data to a serial port .

b.       Receive data

We can use the function read to receive data from a serial port.

       Note: write and read are used in couples, moreover write should be used firstly.

 

1.6 Close a serial port

       Close a serial port is close a file, so we can use the function close to close the serial port.

 

 

2.     USB communication in Linux

2.1 Introduction

       USB stands for Universal Serial Bus and is basically an external interface standard that enables communication between the computer and various other peripherals. The USB is strictly hierarchical and it is controlled by one host. The host uses a master / slave protocol to communicate with attached USB devices. This means that every kind of communication is initiated by the host and devices cannot establish any direct connection to other devices.

       USB communications takes place between the host and endpoints located in the peripherals. An endpoint is a uniquely addressable portion of the peripheral that is the source or receiver of data.

       The idea of endpoints leads to an important concept in USB transactions, that of the pipe. All transfers occur through virtual pipes that connect the peripheral’s endpoints with the host. When establishing communications with the peripheral, each endpoint returns a descriptor, a data structure that tells the host about the endpoint’s configuration and expectations. Descriptors include transfer type, max size of data packets, perhaps the interval for data transfers, and in some cases the bandwidth needed. Give this data the host establishes connections to the endpoints through virtual pipes, making them analogous to household plumbing.

       According to the descriptors, the host can distinguish the kind of the peripheral, so that can use appropriate

send and receive methods to communicate with the peripheral. This chapter mainly introduce libusb communcation

and HID usb communtion.

 

2.2 Libusb communication

2.1.1 Introduction

The libusb library contains interfaces for managing USB devices without a kernel driver. It provides a way for applications to access USB devices.

      

2.1.2      Functions

There are man new functions in libusb, so I introduce a few functions that are indispensable to libusb communication.

usb_init 

void usb_init(void);

usb_init sets up some internal structures, it must be called before any other libusb functions.

usb_find_busses 

int usb_find_busses(void);

usb_find_busses will find all of the busses on the system. Returns the number of changes since previous call to this function (total of new busses and busses removed).

usb_find_devices 

int usb_find_devices(void);

usb_find_devices will find all of the devices on each bus. This should be called after usb_find_busses. Returns the number of changes since the previous call to this function (total of new device and devices removed).

              usb_get_busses   

struct usb_bus *usb_get_busses (void);

usb_get_busses simply returns the value of the global variable usb_busses.

              usb_dev_handle

           usb_dev_handle *usb_open(struct *usb_device dev);

usb_open is to be used to open up a device for use. usb_open must be called before attempting to perform any operations to the device. Returns a handle used in future communication with the device.

              usb_close 

                     int usb_close(usb_dev_handle *dev);

           usb_close closes a device opened with usb_open.

usb_set_configuration 

int usb_set_configuration(usb_dev_handle *dev, int configuration);

usb_set_configuration sets the active configuration of a device.

usb_set_altinterface

int usb_set_altinterface(usb_dev_handle *dev, int alternate);

usb_set_altinterface sets the active alternate setting of the current interface.

usb_clear_halt

int usb_clear_halt(usb_dev_handle *dev, unsigned int ep);

usb_clear_halt clears any halt status on the specified endpoint..

              usb_reset 

                     int usb_reset(usb_dev_handle *dev);

usb_reset resets the specified device by sending a RESET down the port it is connected to.

              usb_claim_interface

                     int usb_claim_interface(usb_dev_handle *dev, int interface);

usb_claim_interface claims the interface with the Operating System. It must be called before you perform any operations related to this interface (like usb_set_altinterface, etc).

              usb_control_msg 

usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);

           usb_control_msg performs a control request to the default control pipe on a device.

              usb_get_driver_np 

                     int usb_get_driver_np(usb_dev_handle *dev, int interface, char *name, int namelen);

This function will obtain the name of the driver bound to the interface specified by the parameter interface and place it into the buffer named name limited to namelen characters.

              usb_detach_kernel_driver_np 

                     int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface);

This function will detach a kernel driver from the interface specified by parameter interface. Applications using libusb can then try claiming the interface.

              usb_interrupt_read 

                     int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);

usb_interrupt_read performs a interrupt read request to the endpoint specified by ep. Returns number of bytes read on success or < 0 on error.

              usb_interrupt_write 

                     int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);

usb_interrupt_write performs an interrupt write request to the endpoint specified by ep. Returns number of bytes written on success or < 0 on error.

 

2.1.3 Open a libusb

Before opening a libusb, you should find the libusb device. You can ues the functions usb_find_busses , usb_find_devices and usb_get_busses to find a libusb. Then you can use the function usb_open to open a libusb.

       Note: Before you finding a libusb , you must use the function usb_init to initialize the libusb.

2.1.4      Setting a libusb

Before reading from or writing to a libusb, you must claim a new interface for the libusb, then set the

configuration. This operation you can use the functions usb_get_driver_np, usb_detach_kernel_driver_np       , usb_claim_interface, usb_set_altinterface and   usb_set_configuration to achieve.

2.1.5      Reading and writing

After setting a libusb, reading from or writing to a libusb is realizable. There are three methods to read and write, you can select an appropriate method according to the peripheral.

2.1.6      Close a libusb

The function usb_close is used to close a libusb that you want to close.

             

2.2 HIDusb communication

2.2.1 Introduction

The Human Interface Devices (HID) class consists primarily of devices that are used by humans to control the operation of computer systems. The hiddev interface provides access to certain HID devices at a relatively low level. It can be considered a "raw" interface to HID functionality from userspace. So HIDusb communication is a popular means of transmitting data between a computer and a HID device using the hiddev interface.

       2.2.2 Open a HIDusb

The HID device documents are located under /dev/usb in Linux. The devices /dev/usb/hiddev* are intended to hook up HID devices to your Linux box, and are configured for this use after startup. So you

can use the function open to open a HIDusb like open a file.

Note: You can use the function ioctl and HIDIOCGDEVINFO to get the vendor that identifier the kind                    of a HID device, the vendor is used to validate whether this HID device is your need.

2.2.3 Reading and writing

The hiddev API uses a read() interface, and a set of ioctl() calls to resd from and write to a HID device. HID devices exchange data with the host computer using data bundles called "reports". Each report is divided into "fields", each of which can have one or more "usages".

              read()

This is the event interface. When the HID device's state changes, it performs an interrupt transfer containing a report which contains the changed value. Before reading from a HID device, you should check the HID device's state.

              ioctl()

                     int ioctl( int fd, int cmd, arg );

       This is the control interface. The parameter cmd identifiers a control, there are a number of controls:

HIDIOCSREPORT

Instructs the kernel to send a report to the device. This report can be filled in by the user through HIDIOCSUSAGE calls (below) to fill in individual usage values in the report before sending the report in full to the device.

HIDIOCSUSAGE

       Sets the value of a usage in an output report.

        When you write to a HID device, you should use those two controls.

HIDIOCGREPORTINFO

Fills in a hiddev_report_info structure for the user. The report is looked up by type (input, output or feature) and id, so these fields must be filled in by the user.

HIDIOCGFIELDINFO

Returns the field information associated with a report in a hiddev_field_info structure. The user must fill in report_id and report_type in this structure, as above. The field_index should also be filled in.

HIDIOCGUCODE

        Returns the usage_code in a hiddev_usage_ref structure.

HIDIOCGUSAGE

        Returns the value of a usage in a hiddev_usage_ref structure.

        The four above controls are used to read from a HID device.

Excrpt the above controls, there a few other controls, I don’t introduce here.

Note: The method to read maybe different under the different system ,sometimes use the function read to read from a HID device like read a file, sometimes use the function ioctl.

       2.2.4 Close a HIDusb

           Close a HIDusb is close a file, so we can use the function close to close the HIDusb.

 

 

 

 

3. A Serial And USB communications example in Linux

       In this example, I implement serial and usb communications by the methods mentioned in chapter 1 and chapter 2.

       This procedure support two methods HIDusb communication, it uses read or ioctl to read from a HIDusb under the different system. Furthermore, some system don’t support liusb, so the code complied under the different

system are different, I use macro to realizes this.

       I simply introduce this procedure’s functions and operation here.

3.1 Complie:

       I use command make to Complie the procedure, so if the system support the libusb, I define the macro LIB_USB in the Makefile, otherwise don’t define.

3.2 Running

      Run the procedure complied above. If the system support libusb, you will can implement serial communication, libusb communication and HIDusb communication, the screen shows:

       1:COM UPS Controller

2:LIB USB UPS Controller

3:HID USB UPS Controller

0:Exit

Otherwise the screen shows:

       1:COM UPS Controller

2:HID USB UPS Controller

0:Exit

       Enter the number that you want to operate, the screen will show all the COM UPS ,or LIB USB UPS ,or HID USB UPS that it has at present. For example:

Com Ups List

Num     Com id

1       COM1

2       COM2

       Enter the number of the COM or USB that you want to operate, then you can enter a command to realizes the comuncation with the COM or USB. In addition, you can enter the command “continue” to test the communication using a group of normative commands for a long time(press any key end the test).

       Enter the command “exit”, you will exit. Then you can choice other COM or USB to communicate, or enter “0” exit.

 

 

4.     Two technical spots in above example

4.1 Select

      In above example, I often use the function select to realize reading data from serial or usb, using select solve the problems that blocking during reading data and reading data incompletely.

        int select(
  int nfds
,
  fd_set* readfds,
  fd_set* writefds,
  fd_set* exceptfds,
  const struct timeval* timeout
);

  • int nfds - The highest file descriptor in all given sets plus one
  • fd_set *readfds - File descriptors that will trigger a return when data is ready to be read
  • fd_set *writefds - File descriptors that will trigger a return when data is ready to be written to
  • fd_set *errorfds - File descriptors that will trigger a return when an exception occurs
  • struct timeval *timeout - The maximum period select() should wait for an event

        The return value indicates the number of file descriptors (fds) whose request event has been satisfied.

        You can’t modify the fd_set structure by changing its value directly. The only portable way to either set or retrieve the value is by using the provided FD_* macros:

  • FD_ZERO(fd_set *) - Initializes an fd_set to be empty
  • FD_CLR(int fd, fd_set *) - Removes the associated fd from the fd_set
  • FD_SET(int fd, fd_set *) - Adds the associated fd to the fd_set
  • FD_ISSET(int fd, fd_set *) - Returns a nonzero value if the fd is in fd_set

Upon return from select(), FD_ISSET() can be called for each fd in a given set to identify whether its condition has been met.

With the timeout value, you can specify how long select() will wait for an event. If timeout is NULL, select() will wait indefinitely for an event. If timeout's timeval structures are set to 0, select() will return immediately rather than wait for any event to occur. Otherwise, timeout defines how long select() will wait.

4.2 Press any key finish a while circulation

There is a function named kbhit to realizes pressing any key finish a while circulation, but this function  is inexistent in linux.

I use the following three functions to realizes this function.

              int kbhit()

{

                     int n;

                     ioctl(0, FIONREAD, &n);

                     if(n != 0)

                     getchar();

                     return n;

}

 

void set_keypress()

{

                     struct termios new_settings;

                     tcgetattr(0,&stored_settings);

                     new_settings = stored_settings;

                     /* Disable canonical mode, and set buffer size to 1 byte */

                     new_settings.c_lflag &= (~ICANON);

                     new_settings.c_cc[VTIME] = 0;

                     new_settings.c_cc[VMIN] = 1;

             

                     tcsetattr(0,TCSANOW,&new_settings);

}

 

void reset_keypress()

{

                     tcsetattr(0,TCSANOW,&stored_settings);

}

 

First, use set_keypress() to set the stdin only accept one char, then use kbhit() to accept the enter char, if no enter, the while continue. After finish the while circulation, use  reset_keypress() to resume the attribute of the stdin.

阅读(2408) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~