该库采用C++实现异步线程读写串口。上层使用无需过多关心异步线程读写问题。
arm64-v8a、armeabi-v7a
函数名称 | 说明 | 返回值 | 备注 |
LSerialPort.openSerialPort | 开启串口 | 0:成功 1:失败 |
对串口读写前必须先使用该函数打开串口, |
LSerialPort.sendMsg | 发送二进制数据 | 0:成功 1:失败 |
异步发送消息给串口。底层使用queue+mutex维护实现一个线程安全消息队列。上层可在任意线程内调用该函数。 |
LSerialPort.setOnLSerialPortListener | 设置串口接收监听器 | 0:成功 1:失败 |
当接收到串口数据时会调用该回调 注意!!!该回调线程为底层读线程,不推荐在该回调线程做任何耗时操作,以免影响线程消息读取。 |
LSerialPort.closeSerialPort | 关闭串口 | 0:成功 1:失败 |
停止底层线程并关闭串口,该函数会阻塞调用线程直到资源释放完毕。 |
LSerialPort.hasOpen | 检查串口是否打开 | true:已打开false:未打开 |
函数名称 | 说明 | 返回值 |
LSerialPort.native_openSerialPort | 开启串口 | 0:成功 1:失败 |
LSerialPort.native_sendMsg | 发送二进制数据 | 0:成功 1:失败 |
LSerialPort.native_setLSerialPortDataListener | 设置串口接收监听器 | 无 |
LSerialPort.native_closeSerialPort | 关闭串口 | 0:成功 1:失败 |
LSerialPort.native_hasOpen | 检查串口是否打开 | true:成功 false:失败 |
- 下载 AAR包放入工程内libs目录下
- 在build.gradle中dependencies内添加引用声明
implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
开始使用(Kotlin)参考代码
//打开串口/dev/ttysWK0,波特率为9600
val result = LSerialPort.openSerialPort(path = "/dev/ttysWK0",baudrate = BaudRate.B_9600)
//当然也可以分别定制数据位,校验位,停止位。
//默认数据位:8,校验位:无,停止位:1
val result = LSerialPort.openSerialPort(
path = "/dev/ttysWK0", //串口地址
baudrate = BaudRate.B_9600,//波特率
dataBits = DataBits.EIGHT,//数据位
parity = Parity.NONE,//校验位
stopBits = StopBits.ONE//停止位
)
//如果需要一次返回尽量多一些数据。可以设置checkIntervalWaitMills参数。
//该函数是线程循环检查串口是否有数据并通知回传的等待时间,设置等待时间越长,数据返回量越大,当然数据回调的间隔也会越久,酌情配置。
//默认等待时间:0 单位:毫秒
val result = LSerialPort.openSerialPort(
path = "/dev/ttysWK0",
baudrate = BaudRate.B_9600,
checkIntervalWaitMills = 100//设置等待时间100ms
)
//打开串口后发送数据
val msg = byteArrayOf(0xFF.toByte(),0x01.toByte(),0x02.toByte(),0x03.toByte(),0x04.toByte(),0x05.toByte(),0xFE.toByte())
val result = LSerialPort.sendMsg("/dev/ttysWK0",msg)
//可以在子线程内发送数据,发送线程以及队列由C++部分维护,无需关心线程同步问题
Thread{
val msg = byteArrayOf(0xFF.toByte(),0x01.toByte(),0x02.toByte(),0x03.toByte(),0xFE.toByte())
val result = LSerialPort.sendMsg("/dev/ttysWK0",msg)
}.start()
//打开串口后设置监听器 返回数据为byteArray
//注意! 如果进行多次设置,每次会覆盖掉前一个监听器。
val result = LSerialPort.setOnLSerialPortListener("/dev/ttysWK0") { msg ->
Log.d("LSerialPort","接收到数据长度:${msg.size}")
}
//调用时该函数会阻塞等待C++线程退出,需要一定耗时
val result = LSerialPort.closeSerialPort("/dev/ttysWK0")
//使用该函数判断串口是否已经打开
val isOpened:Boolean = LSerialPort.hasOpen("/dev/ttysWK0")
Log.d("LSerialPort","串口/dev/ttysWK0是否已打开:$isOpened}")
NDK :23.1.7779620
C++ :17
Android Gradle Plugin :7.4.1
Gradle :7.5
Android Studio :Android Studio Electric Eel | 2022.1.1 Patch 1
- 导入工程配置后选择Android Studio 中的build -> Refresh Linked C++ Projects 等待Gradle build完成。
- Gradle build完成后选择Rebuild Project 等待Gradle build完成。
- 完成后在LSerialPort/build/outputs/aar/目录下会看到LSerialPort-debug.aar文件
返回错误码-1时,logcat中会打印错误信息,可以通过Error等级寻找"LSerialPortLog"关键字查看。
package:mine level:error LSerialPortLog
首先,打开Studio的Tools -> SDK Manage
最后,勾选Show Package Details选项即可下载想要版本的NDK
打开LSerialPort库的Modele Gradle,在NDK内填写需要的架构,如下图内的x86
打开studio的Build Variants。app与LSerialPort都改为release后,创建release需要的签名文件并重新打包
先把app以及LSerialPort目录下的build删除,然后重新Refresh Linked C++ Projects以及Rebuild Project,如果还是没有生成多rebuild几次
最近学了点C++,总感觉需要上手撸点东西。正好公司项目有使用串口的场景,但是发现大多数串口库一般都需要使用者自己在上层实现对串口多线程管理读写,有些不方便。在网上发现个优秀的C++底层实现多线程串口读写管理的库[MserialPort] https://github.com/flykule/MserialPort) ,遂按照该库的代码思路写了LSerialPort。一方面巩固刚学习学习的C++知识,另一方面是重拾很久没用过的JNI、NDK。