Java Serial communication detailed (GO)Author: denimcc Date: 2007-05-11 Preface
When it comes to open source, I'm afraid few people don't pick Osashi praise. The students learned the knowledge through open source code, the programmer gained the successful experience of others through the open source Library and the ability to finish the project at hand on time, and the merchant made the money through open source software. However, the first drawback of open source software or class libraries is that most of the lack of detailed documentation and use of examples, or software code you use, that is, documents, examples and late services to collect money.
It's no wonder, after all, as some famous NBA player said: "I have a family to support, so don't talk to me about a contract under the dollar, or I'd rather be unemployed." Yes, people who support open source also have to raise a family, and they can't pay a penny. If you want to not spend money and learn knowledge can only use the network and the "programmer" magazine J, I just want to make a small contribution to open source business, can solve even a minor problem for your project, it is enough.
Although my introduction to this series of things is not a web framework, nor any open source server, but I believe that as a programmer, what kind of problems will be encountered. Sometimes the more simple the problem is, the less it is, the harder it is to find the guy. As long as you are not dealing with "architecture", "widget" or "frame" all day, believe what I say you will use.
1 Introduction to Serial communication
Many applications and tests for embedded systems or sensor networks require communication with embedded devices or sensor nodes through a PC. Among them, the most commonly used interface is the RS-232 serial port and the same port (due to the complexity of the USB interface and does not require a large amount of data transmission, USB interface used here or is too extravagant, and currently in addition to Sun has a support USB package outside, I haven't seen other Java class libraries that support USB directly. Sun's Commapi provides support for commonly used RS232 serial ports and IEEE1284 parallel port communication. Rs-232-c (also known as EIA Rs-232-c, hereinafter referred to as RS232) was established in 1970 by the American Electronics Industry Association (EIA) Joint Bell System, modem manufacturers and computer terminal manufacturers for serial communication standards. RS232 is a full-duplex communication protocol that allows data to be received and sent at the same time.
1.1 Common Java Serial-port packages
At present, the common Java serial port package has Sun in 1998 released the serial Communication Api:comm2.0.jar (Windows), Comm3.0.jar (Linux/solaris), IBM's serial Communication API and an open source implementation. Given that the Sun's API in Windows is more commonly used and IBM's implementation is the same as Sun's at the API level, the open source implementation is not as reassuring as the two giant products, and this is just about the use of the Sun's serial communication API under the Windows platform.
1.2 Installation of the serial port package (under Windows)
To the Sun's website download Javacomm20-win32.zip, which contains the following items:
According to its usage instructions (readme.html), to use the serial port packet for serial communication, in addition to setting the environment variables, but also to copy the Win32com.dll into the <jdk>/bin directory; copy Comm.jar to <JDK> /lib, Javax.comm.properties also copied to the <jdk>/lib directory. However, when it comes to running a serial package, it's not enough. Because it is common to run "Java MyApp", the virtual machine under the JRE starts MyApp. And we only copy the above files to the JDK directory, so the application will be prompted not to find the serial port. The solution to this problem is simple, we just need to put the above mentioned file in the corresponding directory of the JRE.
It is important to note that when using the serial port API in a Web application, there are other more complex issues to be encountered. If you are interested, you can check the CSDN community "about the page applet with JAVACOMM20 read the client serial port problem" post.
2 Overview of the serial Port API
2.1 Javax.comm.CommPort
This is an abstract class used to describe a port that is supported by the underlying system. It includes some high-level IO control methods that are common to all different communication ports. Both SerialPort and Parallelport are its subclasses, which are used to control the serial port while the latter is used for controlling this parallel port, both of which have different control methods for their respective underlying physical ports. Here we only care about SerialPort.
2.2 Javax.comm.CommPortIdentifier
This class is mainly used to manage and set up the serial port, which is the core class of access control for the serial port. Mainly includes the following methods
L Determine if there is a communication port available
L Open communication port for IO operation
L Determine ownership of ports
L contention for handling port ownership
L Management Port Ownership Change events (event)
2.3 Javax.comm.SerialPort
This class is used to describe the underlying interface of a RS-232 serial communication port, which defines the minimum feature set required for serial communication. Through it, the user can directly to the serial port to read, write and set up work.
2.4 Example of a serial port API
Large paragraph of the text is not as clear as a small example, let's take a look at the example of the serial port package---serialdemo a small piece of code to deepen the serial Port API core class use method of understanding.
2.4.1 Lists all available serial ports of the machine
void Listportchoices () {
Commportidentifier Portid;
Enumeration en = Commportidentifier.getportidentifiers ();
Iterate through the ports.
while (En.hasmoreelements ()) {
Portid = (commportidentifier) en.nextelement ();
if (portid.getporttype () = = commportidentifier.port_serial) {
System.out.println (Portid.getname ());
}
}
Portchoice.select (Parameters.getportname ());
}
The above code can enumerate all the available serial port names of the current system, and the results on my machine are COM1 and COM3.
2.4.2 configuration of serial port parameters
The serial port usually has the following parameters can be configured to open the previous configuration of the serial port:
Includes baud rate, input/output stream control, data bits, stop bit, and parity parity.
SerialPort SPort;
try {
Sport.setserialportparams (baudrate,databits,stopbits,parity);
Setting the input/output control flow
Sport.setflowcontrolmode (Flowcontrolin | Flowcontrolout);
} catch (Unsupportedcommoperationexception e) {}
2.4.3 Serial port Reading and writing
To read and write to the serial port before you need to open a serial port:
Commportidentifier Portid = Commportidentifier.getportidentifier (portname);
try {
SerialPort SPort = (SerialPort) portid.open ("Serial owner name", timeout wait time);
} catch (Portinuseexception e) {//If the port is occupied, this exception is thrown
throw new Serialconnectionexception (E.getmessage ());
}
For writing data to the serial port
OutputStream OS = new Bufferedoutputstream (Sport.getoutputstream ());
Os.write (int data);
For reading data from the serial port
InputStream is = new Bufferedinputstream (Sport.getinputstream ());
int receiveddata = Is.read ();
The int type is read, and you can convert it to the other type you want.
It is important to note that since the Java language does not have an unsigned type, that is, all types are signed and should be noted especially when they are from byte to int. Because if the highest bit of byte is 1, it will be used as a placeholder when it is converted to type int. In this way, the number of byte type that originally is 10000000 becomes int type becomes 1111111110000000, this is very serious problem, should pay attention to avoid.
The common mode of 3 serial communication and its problems
Finally nagging my most hated basic knowledge, the following begins our focus--serial port application research. Since writing data to the serial port is simple, here we only focus on reading data from the serial port. Usually, the serial communication application has two modes, one is to implement the Serialporteventlistener interface, monitor various serial port events and handle them accordingly; the other is to establish a separate receiving thread that is responsible for receiving data. Since these two methods have serious problems in some cases (as for what's the problem of selling a Xiaoguanzi J first), my implementation is using a third approach to solve the problem.
3.1 Event Listener Model
Now let's see how the event listener model works.
:
L first need to add "implements Serialporteventlistener" to your port control class (e.g. Smanager)
• Add the following code when initializing:
try {
SerialPort Sport.addeventlistener (Smanager);
} catch (Toomanylistenersexception e) {
Sport.close ();
throw new Serialconnectionexception ("Too many listeners added");
}
Sport.notifyondataavailable (TRUE);
L OVERWRITE the public void serialevent (Serialportevent e) method, in which the following events are judged:
BI-Communication interrupted.
CD-carrier detection.
CTS-Clears the send.
Data_available-There is data to arrive.
DSR-Data devices are ready.
FE-Frame error.
OE-Overflow error.
Output_buffer_empty-The output buffer has been emptied.
PE-Parity error.
RI-ringing indication.
Generally the most commonly used is the data_available--serial port has data arrival events. This means that when the serial port has data arrival, you can receive and process the received data in the serialevent. In my practice, however, a very serious problem has been encountered.
First describe my experiment: my application needs to receive the query data sent back from the serial port by the sensor node and display the result as an icon. The baud rate set by the serial port is 115200, and the Cks returns a set of data (about 30 bytes or so) every 128 milliseconds, and the period (i.e. duration) is 31 seconds. The measured time in a cycle should return more than 4,900 bytes, and the event listener model I can only receive a maximum of 1500 bytes, do not know where these bytes are running, it is not clear what is missing is that part of the data. It is worth noting that this is the result of all the processing code in Serialevent () that I have left out, leaving only the printed code. The loss of data was so severe that I could not bear it, so I decided to use other methods.
3.2 Threading model for serial read data
The model, as its name implies, is to write the operation that receives the data in the form of a thread:
public void Startreadingdatathread () {
Thread readdataprocess = new Thread (new Runnable () {
public void Run () {
while (NewData! =-1) {
try {
NewData = Is.read ();
System.out.println (NewData);
Other processing procedures
..........
} catch (IOException ex) {
System.err.println (ex);
Return
}
}
Readdataprocess.start ();
}
In my application, I package the received data into one cache, and then start another thread to fetch and process the data from the cache. Two threads work together in a producer-consumer pattern, where the flow of data is as follows:
In this way, I solved the problem of data loss satisfactorily. However, I have not been happy for a long time I found an equally serious problem: although this time no longer lost data, but the original period (31 seconds) after the sensor power saving has stopped transmitting data, but my serial thread is still trying to perform the read serial operation, the console can also see the data received is still continuously printing. Originally, because the sensor node sent too fast data, and my receiving thread processing, so InputStream first to have arrived but not processed bytes cache, so that the obvious sensor node has no longer send data, and the console can still see the data continue to print this strange phenomenon. The only thing to be thankful for is that the last data received is really about 4900 bytes, and there is no loss. However, when the last data is processed by 1.5, this time is much larger than the node running cycle. This delay is a disaster for a real-time display system!
Then I thought, was it because the synchronization and communication between the two threads caused the data to receive slowly? So I removed all the processing code in the receiving thread's code, leaving only the statements that printed the received data, and the result remains the same. It does not appear that communication between threads hinders the reception of data, but rather the use of threading models to delay the reception of data that is too fast for send-side data. Here is a point, that is, for the data transmission rate is not so fast in the case of the front two models should still be useful, but special circumstances or should be special treatment.
3.3 Third method
Pain for a long time (boss urge me every day) after the occasional opportunity, I heard that TinyOS (again open source) part is similar to my application serial communication part, so I downloaded its 1.x version of the Java Code section, referring to its processing methods. The way to solve the problem is actually very simple, that is, from the root. is not the root cause of the receiving thread, well, I simply cancel the receive thread and the shared cache as a mediator, and directly in the processing thread call the serial read data method to solve the problem (what, why not the processing thread is also canceled?). ----Cancel the application interface is it not locked? So it has to be kept) and the program becomes this way:
Public byte[] Getpack () {
while (true) {
Packetlength for Packet length
byte[] Msgpack = new Byte[packetlength];
for (int i = 0; i < packetlength; i++) {
if ((NewData = Is.read ())! =-1) {
Msgpack[i] = (byte) newdata;
System.out.println (Msgpack[i]);
}
}
return msgpack;
}
}
Call this method in the processing thread to return the required sequence of data and process it, so that not only there is no data loss of the phenomenon of the row, there is no data received delay. The only thing to note here is that when the serial port stops sending data or has no data, is.read () always returns-1, and if it is found at the beginning of receiving data-1 then ignore it and continue to receive until the actual data is received.
4 concluding remarks
This paper introduces the basic knowledge of serial communication and several common modes. Through practice, some problems are raised and solved at last. It is important to note that for the first method, I have increased the time that the sensor was sent from 128 milliseconds to 512 milliseconds, and there is still a serious loss of data, so if your application requires very sophisticated results and the rate of data transfer is fast, it is best not to use the first method. For the second method, because it is a thread-caused problem, so for different machines should have different performance, for those who deal with multi-threaded better machine, should be better. But my machine is Inter Ben 3.0 dual core CPU+512DDR memory, so the delay is so strong, how much stronger CPU? So for a large amount of data transmission, still use a third method.
Java Serial communication detailed (GO)