Androidシリアルポート使用の概要

準備オーケー

  • NDK環境
  • シリアル通信に使用するCファイル

注:cファイル内の関数名のパスを変更する必要があり、cファイルと.hヘッダーファイルの両方を変更する必要があります

基盤となるライブラリへのアクセス

SOライブラリを使用してインポート

  1. メインディレクトリに新しいjniレコードを作成し、そこにCファイルを配置します
  2. 新しいAndroid.mk、Application.mkファイルを作成し、構成します
  3. プロジェクトをコンパイルし、コンパイルされたsoライブラリファイルを取得します。コンパイルされたリリースバージョンがreleasseディレクトリにある場合、デフォルトで生成されるディレクトリはapp \ build \ intermediates \ jniLibs \ app \ debug \ armeabiです。
  4. メインディレクトリの下に新しいディレクトリjniLibsを作成し、生成されたsoライブラリをこれにコピーします
  5. appディレクトリでgradleファイルを構成します
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. コードでクラスファイルを作成し、soライブラリファイルをロードして、シリアルポートを開閉する方法を定義します

CMake紹介

  1. メインディレクトリに新しいcppフォルダーを作成し、ここにcソースファイルを配置します
  2. CMakeLists.txtファイルを構成します
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. アプリの下でgradleファイルを構成します
android {   
    defaultConfig {
        ...
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}
  1. コードでクラスファイルを作成し、soライブラリファイルをロードして、シリアルポートを開閉する方法を定義します

シリアルポートの開閉

jniで開閉

Cファイルには、シリアルポートを開く方法と閉じる方法の2つの方法が定義されています。シリアルポートを開く方法には戻り値があり、戻り値はFileDescriptorオブジェクトです。このオブジェクトを使用して、シリアルポートのデータの読み取りと書き込みを行います。

シリアルポートを開く

シリアルポートのクエリ

一部のカスタマイズされたデバイスには多くのシリアルポートがある場合があります。アプリケーションで開く必要のあるシリアルポートはどれですか。接続する必要のあるシリアルポートの名前をデバイスの製造元に問い合わせることができます。一方、すべてのシリアルポートを一覧表示して、1つずつ試すことしかできません。

すべてのシリアルポートを照会する:
SerialPortFinderクラスを定義し、/ proc / tty / driversファイルを読み取って、デバイスのすべてのシリアルポートとパスを一覧表示します。

メソッド:SerialPortFinderの getAllDevices()メソッド。特定の実装についてはコードSerialPortFinderを参照してください。

オンにする

対応するシリアルポートを見つけたら、jniメソッドを呼び出してシリアルポートを開きます。開くときは、シリアルポートパス、ボーレート、開く方法の3つのパラメータを渡す必要があります。

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

シリアルポートを開くことにより、FileDescriptorオブジェクトが取得され、そのオブジェクトに基づいて入力および出力ストリームが作成され、読み取りおよび書き込み操作が実現されます。

シリアルポートを閉じる

使用後、アプリケーションを終了する前に、シリアルポートを閉じる必要があります。これは、ファイルストリームを閉じる必要があるファイル操作と同等です。シリアル通信は本質的にファイル操作であるため、閉じる必要があります。

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

データの送信/読み取り

シリアルポートが開かれると、入力ストリームと出力ストリームが取得され、次の送信と読み取りはこのストリームで動作します。

データを送る:

送信データはバイト配列です。文字列や16進コマンドなどの場合は、バイト配列に変換して送信する必要があります。出力ストリームにデータを書き込むだけです。

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

データの読み取り:

シリアルデータをいつ送信するかわからないため、送信データに関してデータを読み取ります。データの長さを取得するタイミングを取得するには、入力ストリームからサブスレッドデータを常に開く必要があります。 0でない場合は、次のステップのためにデータを分析します

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;
}

読み取られたデータはバイト配列でもあり、データを解析する必要があります。通常、機器のサプライヤが対応する分析方法を提供します。

シリアルポートはデータの読み取りと送信を行います。識別ビットとして2〜5バイトがあり、通常は0xFFから始まります。各パケットは統合されているため、データの送信と解析には注意が必要です。

使用する

アプリケーションでシリアルポートを開き、プロジェクトのBaseActivityまたはBaseFragmentでデータの送受信方法を定義し、必要な場所で直接呼び出すことができます。

付属

Cソースファイル:

termios.h

SerialPort.h

SerialPort.c

Github

おすすめ

転載: blog.csdn.net/lizebin_bin/article/details/86159524