Preface
When it comes to open source, there are probably very few people who would not praise it with a big finger. Students learn knowledge through open source code, programmers gain other people's successful experience through open source class libraries and can complete the projects at hand on time, and merchants make money through open source software... In short, everyone is happy. However, the primary disadvantage of open source software or class libraries is that most of them lack detailed documentation and usage examples, or the software code is just for you to use, and you only charge money for the documentation, examples and post-service services. It's no wonder, after all, as a famous NBA player said: "I still have to support my family, so don't negotiate with me for a contract of less than 10 million US dollars, otherwise I would rather be unemployed." Yes, people who support open source also have to support their families, so charging some money is not too much. If you want to learn knowledge without spending money, you can only use the Internet and Internet. I just want to make a small contribution to the open source cause. It is enough to solve even a small problem for your project.
Although the things I introduce in this series are not web frameworks or open source servers, I believe that as a programmer, you will encounter all kinds of problems. Sometimes the simpler the problem, the more difficult it is; the smaller the place, the harder it is to find someone who can do it. As long as you don't just deal with "architecture", "component", and "framework" all day long, I believe you will definitely use what I said.
1 Introduction to serial port communication
1.1 Common Java serial port packages
1.2 Serial port package installation (under Windows)
2 Serial port API overview
2.1 javax.comm.Com mPort
2.2 javax.comm.CommPortIdentifier
2.3 javax.comm.SerialPort
2.4 Serial port API instance
2.4.1 List all available serial ports on this machine
2.4.2 Configuration of serial port parameters
2.4.3 String Reading and writing of the mouth
3 Serial communication Common patterns and their problems
3.1 Event listening model
3.2 Thread model for serial port reading data
3.3 The third method
4 Conclusion
1 Introduction to serial communication
Lots of embedded systems or sensor networks Both applications and testing require communication with embedded devices or sensor nodes through a PC. Among them, the most commonly used interfaces are RS-232 serial port and parallel port (in view of the complexity of the USB interface and the fact that it does not require a large amount of data transmission, the USB interface is still too extravagant to use here. Moreover, in addition to SUN, there is currently a package that supports USB. I haven't seen any other Java libraries that support USB directly). SUN's CommAPI provides support for commonly used RS232 serial port and IEEE1284 parallel port communications respectively. RS-232-C (also known as EIA RS-232-C, hereinafter referred to as RS232) was developed in 1970 by the Electronic Industries Association (EIA) in conjunction with Bell Systems, modem manufacturers and computer terminal manufacturers for serial communications. standards. RS232 is a full-duplex communication protocol that can receive and send data at the same time.
1.1 Common Java serial port packages
Currently, common Java serial port packages include the serial communication API released by SUN in 1998: comm2.0.jar (under Windows), comm3.0.jar (Linux/Solaris); IBM Serial communication API and an open source implementation. Since SUN's API is commonly used under Windows and IBM's implementation is the same as SUN's at the API level, the open source implementation is not as reassuring as the products of the two major manufacturers. Here we only introduce SUN's serial port communication. API usage under Windows platform.
1.2 Installation of serial port package (under Windows)
Go to SUN website and download javacomm20-win32.zip. The contents are as follows:
According to its instructions (Readme.html), if you want To use the serial port package for serial port communication, in addition to setting the environment variables, you must also copy win32com.dll to the
It is worth noting that when using the serial port API in network applications, you will encounter other more complex problems. If you are interested, you can check out the post "About the problem of Applet using javacomm20 to read the client serial port on the web page" in the CSDN community.
2 Serial Port API Overview
2.1 javax.comm.CommPort
This is an abstract class used to describe a port supported by the underlying system. It contains some high-level IO control methods that are common to all different communication ports. SerialPort and ParallelPort are both its subclasses. The former is used to control the serial port and the latter is used to control the parallel port. Both have different control methods for their 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. It is the core class for access control of the serial port. Mainly include the following methods
l Determine whether there is an available communication port . event( Event)
2.3 javax.comm.SerialPort
This class is used to describe the underlying interface of an RS-232 serial communication port. It defines the minimum set of functions required for serial communication. Through it, users can directly read, write and set up the serial port.
2.4 Serial Port API Example
A long paragraph of text cannot be as clear as a small example. Let’s take a look at the example that comes with the serial port package---a small piece of code in SerialDemo to deepen the understanding of the serial port API core class. knowledge of how to use it. " // iterate through the ports.
; hasMoreElements()) {
System.out.println(portId.getName());
The output results above are COM1 and COM3.
2.4.2 Configuration of serial port parameters
Serial ports generally have the following parameters that can be configured before opening the serial port:
Including baud rate, input/output flow control, number of data bits, stop bits and Even parity. SerialPort sPort;try { sPort.setSerialPortParams(BaudRate,Databits,Stopbits,Parity); //Set input/output control flow sPort.setFlowControlMode(FlowControlIn | FlowControlOut); sPort.setFlowControlMode(FlowControlIn | FlowControlOut); UnsupportedCommOperationException e) {}2.4.3 Serial port reading and writing Before reading and writing to the serial port, you need to open a serial port first: CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(PortName);try { SerialPort sPort = (SerialPort ) portId.open("serial port owner name", timeout waiting time); } catch (PortInUseException e) {//Throw this exception if the port is occupied-- to be thrown new SerialConnectionException(e.getMessage());
//For reading data from the serial port
InputStream is = new BufferedInputStream(sPort.getInputStream());
int receivedData = is.read();
The read out is int type, you can convert it other types as needed.
It should be noted here that since the Java language does not have unsigned types, that is, all types are signed, you should pay special attention when converting from byte to int. Because if the highest bit of byte is 1, 1 will be used as a placeholder when converted to int type. In this way, the original byte type number of 10000000 becomes int type and becomes 1111111110000000. This is a very serious problem and should be avoided.
3 The common modes and problems of serial communication
Finally finished talking about the basic knowledge that I hate most, let’s start our focus this time-the research of serial port applications. Since writing data to the serial port is very simple, here we only focus on reading data from the serial port. Usually, there are two modes for serial communication applications. One is to implement the SerialPortEventListener interface to monitor various serial port events and handle them accordingly; the other is to establish an independent receiving thread specifically responsible for receiving data. Since these two methods have serious problems in some cases (as for the problem, I will leave it open for now), so my implementation is to use the third method to solve this problem.
3.1 Event Listening Model
Now let’s take a look at how the event listening model works
:
l First you need to add “implements SerialPortEventListener” to your port control class (such as SManager)
l During initialization Add the following code:
try {
SerialPort sPort.addEventListener(SManager);
} catch (TooManyListenersException e) {
sPort.close();
Throw new SerialConnectionException("too many listeners added");
}
sPort.notifyOnDataAvailable(true);
l out out out out out out out of through using ’’ ’ ’ ’ ’ sPort.notifyOnDataAvailable(’’’-’’’ out out out---over-wrap to the public void serialEvent(SerialPortEvent e) method to judge the following events:
BI - Communication Interruption.
CD - Carrier Detection.
CTS - Clear to send.
DATA_AVAILABLE - Data arrived.
DSR - Data device ready.
FE - Frame error.
OE - Overflow error.
OUTPUT_BUFFER_EMPTY - The output buffer has been emptied.
PE - Parity check error.
RI - Ringing indication.
Generally the most commonly used one is DATA_AVAILABLE - there is a data arrival event on the serial port. That is to say, when data arrives on the serial port, you can receive and process the received data in serialEvent. However, in my practice, I encountered a very serious problem.
First describe my experiment: My application needs to receive the query data sent back by the sensor node from the serial port and display the results in the form of icons. The baud rate set by the serial port is 115200. Kawaguchi returns a set of data (about 30 bytes) every 128 milliseconds, and the period (ie, duration) is 31 seconds. During the actual measurement, more than 4900 bytes should be returned in one cycle. However, using the event listening model, I can only receive less than 1500 bytes at most. I don’t know where these bytes went, and I don’t know what was lost. That part of the data. It is worth noting that this is the result of me commenting out all the processing code in serialEvent(), leaving only the printing code. I couldn't bear the severe data loss, so I decided to use other methods.
3.2 Thread model for serial port reading data
As the name suggests, this model writes the operation of receiving data in the form of a thread:
public void startReadingDataThread() {
Thread readDataProcess = new Thread(new Runnable() {
public void run() {
newData = is.read();
System.out.println(newData); ……….
}}} A Readdataprocess.start (); }} In my application, I pack the data I received in one cache, and then start another thread to obtain and process the data from the cache. The two threads work together in the producer-consumer mode, and the data flow is as shown in the figure below:
In this way, I successfully solved the problem of data loss. However, not long after I was happy, I discovered an equally serious problem: although this time I no longer lost data, the sensor power saving stopped transmitting data after one cycle (31 seconds), but my serial port thread was still While working hard to perform the serial port reading operation, you can also see on the console that the received data is still being printed continuously. It turns out that because the data sent by the sensor node is too fast and my receiving thread cannot process it, InputStream first caches the bytes that have arrived but have not yet been processed, which leads to the fact that the sensor node no longer sends data. , but the console can still see the strange phenomenon of data being printed continuously. The only good thing is that the final data received is indeed about 4900 bytes, and there is no loss. However, it was almost a minute and a half when the last data was processed, which is much longer than the node operating cycle. This delay is a disaster for a real-time display system!
Later I thought, is it due to the synchronization and communication between the two threads that the data reception is slow? So I removed all the processing code in the code of the receiving thread, leaving only the statement for printing the received data, and the result remained the same. It seems that it is not the communication between threads that hinders the data reception speed, but the thread model that causes the data reception delay when the data transmission rate of the sender is too fast. One point to note here is that the former two models should still be useful when the data transmission rate is not so fast, but special cases should be handled specially.
3.3 The third method
After suffering for a long time (Boss urged me to L every day), by chance, I heard that there is a part in TinyOS (which is open source) that is similar to my application. So I downloaded the Java code part of its 1.x version and referred to its processing method. The way to solve the problem is actually very simple, that is, start from the root cause. Isn’t the root cause caused by the receiving thread? Well, I will simply cancel the receiving thread and the shared cache as an intermediary, and directly call the serial port reading method in the processing thread to solve the problem (what, why not also use the processing thread And cancel? ----Wouldn’t the application interface be locked if you cancel it? So it must be retained) So the program becomes like this:
public byte[] getPack(){
/ PacketLength is the length of the data packet
byte[] msgPack = new byte[PacketLength];W if ((newdata = is.read ())! = -1) {
msgpack [i] = (byte) newData; System.out.println (msgpack [i]); return msgPack; . The only thing to note here is that when the serial port stops sending data or there is no data, is.read() always returns -1. If -1 is found when it starts to receive data, ignore it and continue receiving until the actual data is received. to the data.4 Conclusion
This article introduces the basic knowledge of serial communication and several commonly used modes. Through practice, some problems were raised and solved at the end. It is worth noting that for the first method, I increased the sensor sending time from 128 milliseconds to 512 milliseconds, and there was still serious data loss, so if your application requires very precise results, transmit data If the speed is very fast, it is best not to use the first method. For the second method, since it is a problem caused by threads, it should have different performances on different machines. It should be better for machines that are better at handling multi-threads. But my machine is an Inter Pen 4 3.0 dual-core CPU + 512DDR memory. The delay is so severe, how powerful the CPU is? Therefore, for transmission with relatively large amounts of data, it is better to use the third method. However, there are many problems in this world, and there are many more unknown problems than known problems. Maybe there are other problems.