android 串口一直打开_Android串口使用总结

准备工作

NDK环境

串口通信使用的C文件

注意:c文件中需要修改函数名为当前包名的路径,c文件和.h头文件都需要修改

接入底层库

使用SO库引入

main目录下新建jni录,将C文件置于该处

新建Android.mk、Application.mk文件并配置

编译项目,得到编译好的so库文件,生成目录默认为:app\build\intermediates\jniLibs\app\debug\armeabi,如果编译的是release版本则在releasse目录下

main目录下新建目录jniLibs,将生成的so库拷贝到此

配置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"

}

}

}

代码中创建Class文件,加载这个so库文件,并定义打开、关闭串口的方法

CMake方式引入

main目录下新建cpp文件夹,将c源文件置于此

配置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})

配置app下gradle文件

android {

defaultConfig {

...

externalNativeBuild {

cmake {

cppFlags ""

}

}

}

externalNativeBuild {

cmake {

path "CMakeLists.txt"

}

}

}

代码中创建Class文件,加载这个so库文件,并定义打开、关闭串口的方法

打开/关闭串口

jni中的打开关闭

C文件中定义了两个方法,分别为打开、关闭串口。打开串口方法具有返回值,返回值为FileDescriptor对象,我们通过这个对象实现对串口的数据读取和写入操作

打开串口

查询串口

一些定制的设备可能会有很多串口,我们应用究竟需要打开哪一个串口呢?一方面,可以询问设备厂商我们需要连接的串口名,另一方面就只能列出所有串口然后一个一个试了

查询所有串口:

定义SerialPortFinder类,通过读取/proc/tty/drivers文件,列举出设备的所有串口和路径

方法:SerialPortFinder中的getAllDevices()方法,具体实现见代码SerialPortFinder

打开

找到相应的串口后,调用jni方法打开串口,打开时需要传入三个参数,分别是串口路径,波特率,打开方式

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;

}

}

发送/读取数据

打开串口时获取到了输入输出流,那么接下来的发送和读取就是对这个流进行操作了。

发送数据:

发送数据为byte数组,如果是字符串啊、十六进制指令啊等等,都需要转换成byte数组发送。向我们的输出流写数据即可。

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;

}

读取到的同样是byte数组的数据,需要对数据进行解析,一般设备供应商会提供相应的解析方式。

串口的读取、发送数据,都会有2-5个字节作为识别位,一般都是0xFF开头,每个包都是统一的,发送和解析数据时需要注意

使用

可以选择在Application中打开串口,然后在项目的BaseActivity或者BaseFragment中定义好发送、读取数据的方法,需要使用的地方直接调用

C源文件:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值