Android serial port use summary

Ready to work

  • NDK environment
  • C file used for serial communication

Note: The path of the function name in the c file needs to be modified , and both the c file and the .h header file need to be modified

Access to the underlying library

Import using SO library

  1. Create a new jni record in the main directory and place the C file there
  2. Create new Android.mk , Application.mk files and configure
  3. Compile the project and get the compiled so library file. The default generated directory is app\build\intermediates\jniLibs\app\debug\armeabi, if the compiled release version is in the releasse directory
  4. Create a new directory jniLibs under the main directory and copy the generated so library to this
  5. Configure the gradle file in the app directory
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        ndk {
            moduleName "serial_port"
            ldLibs "log", "z", "m"
            abiFilters "armeabi", "x86"
        }
    }

    debug {
        ndk {
            moduleName "serial_port"
            ldLibs "log", "z", "m"
            abiFilters "armeabi", "x86"
        }
    }
}
  1. Create a Class file in the code, load the so library file, and define the method of opening and closing the serial port

CMake introduction

  1. Create a new cpp folder in the main directory and place the c source file here
  2. Configure the CMakeLists.txt file
cmake_minimum_required(VERSION 3.4.1)

# 查找cpp目录下的所有源文件
# 并将名称保存到 DIR_LIB_SRC 变量
aux_source_directory(src/main/cpp/ DIR_LIB_SRC)

#设置源文件
add_library(SerialPort SHARED ${DIR_LIB_SRC})

#表明头文件位置
#include_directories(src/main/cpp/)

find_library( # Sets the name of the path variable.
        log-lib
        log)
target_link_libraries( # Specifies the target library.
        SerialPort
        ${log-lib})
  1. Configure the gradle file under the app
android {   
    defaultConfig {
        ...
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}
  1. Create a Class file in the code, load the so library file, and define the method of opening and closing the serial port

Open/close serial port

Open and close in jni

Two methods are defined in the C file, namely opening and closing the serial port. The method of opening the serial port has a return value, and the return value is a FileDescriptor object. We use this object to read and write data to the serial port.

Open the serial port

Query serial port

Some customized devices may have many serial ports. Which serial port does our application need to open? On the one hand, you can ask the device manufacturer for the name of the serial port we need to connect to. On the other hand, we can only list all the serial ports and try them one by one.

Query all serial ports:
define the SerialPortFinder class, and list all serial ports and paths of the device by reading the /proc/tty/drivers file

Method: getAllDevices() method in SerialPortFinder , see the code SerialPortFinder for specific implementation

turn on

After finding the corresponding serial port, call the jni method to open the serial port. When opening, you need to pass in three parameters, which are the serial port path, baud rate, and opening method.

public SerialPort getSerialPort() throws SecurityException, IOException, InvalidParameterException {
    if (mSerialPort == null) {
        //这里是打开了/dev/ttyS3 串口,波特率9600,
        mSerialPort = new SerialPort(new File("/dev/ttyS3"), 9600, 0);
    }
    return mSerialPort;
}

By opening the serial port, a FileDescriptor object is obtained, and an input and output stream is created based on the object to realize read and write operations.

Close the serial port

You need to close the serial port after use and before exiting the application. It is equivalent to file operations that need to close the file stream. Serial communication is essentially a file operation, so it needs to be closed

/**
 * 关闭串口
 * 使用结束时记得关闭串口
 */
public void closeSerialPort() {
    if (mSerialPort != null) {
        //调用native方法关闭串口
        mSerialPort.close();
        mSerialPort = null;
    }
}

Send/read data

When the serial port is opened, the input and output stream is obtained, then the next sending and reading is to operate on this stream.

send data:

The sending data is a byte array. If it is a string, hexadecimal command, etc., it needs to be converted into a byte array and sent. Just write data to our output stream.

public void sendBufferToSerial(byte[] data) {
    try {
        mFileOutputStream.write(data);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Read data:

Read data with respect to the transmission data, the relative steps a little more, because we do not know when will I send serial data over , so the need to constantly open a sub-thread data from the input stream to take , when to take the data length When it is not 0, analyze the data for the next step

class ReadThread extends Thread {
    @Override
    public void run() {
        super.run();
        while (!isInterrupted()) {
            int size;
            final byte[] buffer;
            try {
                buffer = new byte[128];
                if (mFileInputStream == null) return;
                size = mFileInputStream.read(buffer);

                if (size > 0) {
                    //回调
                    if (listener != null)
                        listener.receiveData(size, buffer);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


/**
 * 开始接收串口数据
 *
 * @param onReceiveDataListener 数据回调
 */
public void startReceiveData(OnReceiveDataListener onReceiveDataListener) {
    readThread = new ReadThread();
    readThread.start();
    listener = onReceiveDataListener;
}

/**
 * 停止接收数据
 */
public void stopReceiveData() {
    if (readThread != null) {
        if (readThread.isInterrupted())
            readThread.interrupt();
    }
    readThread = null;
    listener = null;
}

The data read is also the byte array, and the data needs to be parsed. Generally, the equipment supplier will provide the corresponding analysis method.

The serial port reads and sends data, there will be 2-5 bytes as identification bits, generally starting with 0xFF, each packet is unified, and you need to pay attention when sending and parsing data

use

You can choose to open the serial port in Application, and then define the method of sending and reading data in the BaseActivity or BaseFragment of the project, and call it directly where you need to use it

Attached

C source file:

termios.h

SerialPort.h

SerialPort.c

Github

Guess you like

Origin blog.csdn.net/lizebin_bin/article/details/86159524