1.What is a serial port?
Before you can't use the serial port to communicate, it can be understood as "a communicable port" for the time being; the use article will not discuss theories and principles in depth. After you can understand how to use the serial port, you can check itA brief discussion on the principle of SerialPort for Android serial port communication
2. Add dependencies
1.) Add the following dependencies in dependencies in module:
dependencies { //Serial port implementation ':Android-SerialPort-API:2.0.0' }
2.) The lower version of gradle adds the following maven repository to allprojects in Project (the SerialPort cannot be loaded without adding);
allprojects { repositories { maven { url "" }//maven warehouse } }
The higher version of gradle has been abandoned. Allprojects add the following maven repository in repositories (the SerialPort cannot be loaded without adding);
dependencyResolutionManagement { (RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() jcenter() // Warning: this repository is going to shut down soon maven { url "" }//maven warehouse } }
3. Write serial port processing class
1.) Serial port processing class:SerialHandle; Simplify this class, which is to obtain two streams (input stream, output stream) through the serial port object, listen to data or write instructions through two streams, and execute after the hardware is received. At the same time, pay attention to the configuration parameters (as long as the hardware that supports serial communication, it will generally be written on the manual)
package com.; import ; import ; import ; import ; import ; import ; import ; import ; import ; /** * Serial port real processing class */ public class SerialHandle implements Runnable { private static final String TAG = "Serial port processing class"; private String path = "";//Serial port address private SerialPort mSerialPort;//Serial port object private InputStream mInputStream;//Input stream object of serial port private BufferedInputStream mBuffInputStream;// Used to listen to the information returned by the hardware private OutputStream mOutputStream;//The output stream object of the serial port is used to send instructions private SerialInter serialInter;//Serial port callback interface private ScheduledFuture readTask;//Serial port reading task /** * Add serial callback * * @param serialInter */ public void addSerialInter(SerialInter serialInter) { = serialInter; } /** * Open the serial port * * @param devicePath serial port address (fill in according to the instructions on the tablet) * @param baudrate baudrate (fill in according to the docking hardware - there will be marked in "Communication" on the hardware manual) * @param isRead Whether to continuously monitor the data returned by the serial port * @return Whether it is successfully opened */ public boolean open(String devicePath, int baudrate, boolean isRead) { return open(devicePath, baudrate, 7, 1, 2, isRead); } /** * Open the serial port * * @param devicePath serial port address (fill in according to the instructions on the tablet) * @param baudrate baudrate (fill in according to the docking hardware - there will be marked in "Communication" on the hardware manual) * @param dataBits data bits (fill in according to the docking hardware - there will be marked in "Communication" on the hardware manual) * @param stopBits stop bit (fill in according to the docking hardware - there will be annotations in "Communication" on the hardware manual) * @param parity check bit (fill in according to the docking hardware - there will be annotations in the "Communication" on the hardware manual) * @param isRead Whether to continuously monitor the data returned by the serial port * @return Whether it is successfully opened */ public boolean open(String devicePath, int baudrate, int dataBits, int stopBits, int parity, boolean isRead) { boolean isSucc = false; try { if (mSerialPort != null) close(); File device = new File(devicePath); mSerialPort = SerialPort // Serial port object .newBuilder(device, baudrate) // Serial port address, baud rate .dataBits(dataBits) // Data bit, default 8; optional values are 5~8 .stopBits(stopBits) // Stop bit, default 1; 1:1 bit stop bit; 2:2 bit stop bit .parity(parity) // Check bit; 0: No check bit (NONE, default); 1: Odd check bit (ODD); 2: Even check bit (EVEN) .build(); // Open the serial port and return mInputStream = (); mBuffInputStream = new BufferedInputStream(mInputStream); mOutputStream = (); isSucc = true; path = devicePath; if (isRead) readData();//Open recognition } catch (Throwable tr) { close(); isSucc = false; } finally { return isSucc; } } // Read data private void readData() { if (readTask != null) { (true); try { (160); } catch (InterruptedException e) { (); } //Sleep here: When the task is cancelled, the thread pool has already executed the task and cannot be cancelled, so the task waiting for the thread pool to be executed. readTask = null; } readTask = SerialManage .getInstance() .getScheduledExecutor()//Get thread pool .scheduleAtFixedRate(this, 0, 150, );//Execute a loop task } @Override//Run will be triggered every 150 milliseconds public void run() { if (().isInterrupted()) return; try { int available = (); if (available == 0) return; byte[] received = new byte[1024]; int size = (received);//Read whether there is new data on the following serial port if (size > 0 && serialInter != null) (path, received, size); } catch (IOException e) { (TAG, "Serial port read data exception:" + ()); } } /** * Close the serial port */ public void close(){ try{ if (mInputStream != null) (); }catch (Exception e){ (TAG,"Serial port input stream object close exception:" +()); } try{ if (mOutputStream != null) (); }catch (Exception e){ (TAG,"Serial port output stream object close exception:" +()); } try{ if (mSerialPort != null) (); mSerialPort = null; }catch (Exception e){ (TAG,"Serial port object closing exception:" +()); } } /** * Send commands to the serial port */ public void send(final String msg) { byte[] bytes = hexStr2bytes(msg);//Convert characters into byte array try { (bytes);//Write data through output stream } catch (Exception e) { (); } } /** * Convert a byte array string represented by hexadecimal into a hexadecimal byte array * * @param * @return byte[] */ private byte[] hexStr2bytes(String hex) { int len = (() / 2); byte[] result = new byte[len]; char[] achar = ().toCharArray(); for (int i = 0; i < len; i++) { int pos = i * 2; result[i] = (byte) (hexChar2byte(achar[pos]) << 4 | hexChar2byte(achar[pos + 1])); } return result; } /** * Convert hexadecimal characters [0123456789abcde] (including upper and lower case) into bytes * @param c * @return */ private static int hexChar2byte(char c) { switch (c) { case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; case 'a': case 'A': return 10; case 'b': case 'B': return 11; case 'c': case 'C': return 12; case 'd': case 'D': return 13; case 'e': case 'E': return 14; case 'f': case 'F': return 15; default: return -1; } }
2.) Serial port callback SerialInter;A brief summary of this class is to return the results generated in the SerialHandle class to the previous layer of business code and decouple
package com.; /** * Serial port callback */ public interface SerialInter { /** * Connection result callback * @param path serial port address (when there are multiple serial ports that need to be processed uniformly, you can use the address to distinguish it) * @param isSucc connection is successful */ void connectMsg(String path,boolean isSucc); /** * Read data callback * @param path serial port address (when there are multiple serial ports that need to be processed uniformly, you can use the address to distinguish it) * @param bytes Data read * @param size Data length */ void readData(String path,byte[] bytes,int size); }
3.) SerialManage is managed uniformly by serial port;A brief summary of this class is used to manage the connection and sending functions of the serial port, especially sending instructions, sending multiple instructions in a very short time (for example: sending 10 instructions in 1 millisecond), and multiple instructions will interfere with each other. The first instruction may have been executed, but none of them may have been executed. This class is not necessary, if there is a better way, you can define it yourself.
package com.; import ; import ; import ; import ; import ; import ; /** * Serial port management category */ public class SerialManage { private static SerialManage instance; private ScheduledExecutorService scheduledExecutor;//Thread pool has guaranteed that there is only one management in the same way private SerialHandle serialHandle;//Serial port connection Send Read processing object private Queue<String> queueMsg = new ConcurrentLinkedQueue<String>();//Thread safe to queue private ScheduledFuture sendStrTask;//Cyclical sending task private boolean isConnect = false;// Is the serial port connected? private SerialManage() { scheduledExecutor = (8);//Initialize 8 threads } public static SerialManage getInstance() { if (instance == null) { synchronized () { if (instance == null) { instance = new SerialManage(); } } } return instance; } /** * Get the thread pool * * @return */ public ScheduledExecutorService getScheduledExecutor() { return scheduledExecutor; } /** * Serial port initialization * * @param serialInter */ public void init(SerialInter serialInter) { if (serialHandle == null) { serialHandle = new SerialHandle(); startSendTask(); } (serialInter); } /** * Open the serial port */ public void open() { isConnect = ("/dev/ttyS1", 9600, true);//Set the address, baud rate, enable reading of serial port data } /** * Send command * * @param msg */ public void send(String msg) { /* There is no direct use of (msg); method to send commands Because some hardware can only respond to one instruction in a very short time, sending multiple instructions at a time will cause physical interference. Let the hardware receive instructions inaccurately; so here the instructions are added to the queue and queued to execute, ensuring that each instruction must be executed. If you don't believe it, you can try to use the (msg) method to send 10 different instructions in a loop and see the 10 instructions. execution results. */ (msg);//Add directive to the queue } /** * Close the serial port */ public void colse() { ();//Close the serial port } //Start the sending task private void startSendTask() { cancelSendTask();//Check first to check whether the task has been started? Cancel if there is //Check every 100 milliseconds whether there are new instructions in the queue to be executed sendStrTask = (new Runnable() { @Override public void run() { if (!isConnect) return;//The serial port is not connected Exit if (serialHandle == null) return;//The serial port is not initialized Exit String msg = ();//Retrieve the command if (msg == null || "".equals(msg)) return;//Invalid command Exit (msg);//Send command } }, 0, 100, ); } //Cancel the send task private void cancelSendTask() { if (sendStrTask == null) return; (true); try { (100); } catch (InterruptedException e) { (); } sendStrTask = null; } }
4. Use the serial port
package com.; import ; import ; import ; import ; import com.; import com.; public class MainActivity extends AppCompatActivity implements SerialInter { @Override protected void onCreate(Bundle savedInstanceState) { (savedInstanceState); setContentView(.activity_main); ().init(this);//Serial port initialization ().open();//Open the serial port findViewById(.send_but).setOnClickListener(new () { @Override public void onClick(View view) { ().send("Z");//Send command Z } }); } @Override public void connectMsg(String path, boolean isSucc) { String msg = isSucc ? "success" : "fail"; ("Serial Port Connection Callback", "Serial Port"+ path + " -connect" + msg); } @Override//If you pass false in the serial port opening method, no data will be returned here public void readData(String path, byte[] bytes, int size) { // ("Serial port data callback","Serial port "+ path + " -get data" + bytes); } }
5. Summary
Serial communication For Android developers, they only need to pay attention to how to connect, operate (send commands), and read data; whether it is 232, 485 or 422, it is the same for developers to connect, operate, and read code.
This is the end of this article about the use of SerialPort with Android serial port communication. For more related content on Android SerialPort, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!