安卓串口通讯工具库封装及使用

本文详细介绍了如何在Android平台上进行串口通信的开发,包括基本概念如波特率、数据位、停止位和校验位,以及如何使用CMake编译JNI文件生成.so库,通过Java调用 native 方法进行串口的打开、关闭操作。此外,还提供了串口读写数据的封装以及线程池管理,使得串口操作更加便捷。

在这里插入图片描述

串口通讯

引言

对于安卓开发的小伙伴来说,很少用到串口通信开发。主要用来外接一些硬件设备,例如扫码器,读卡器,体温枪等一些硬件设备。这些设备与安卓之间通过串口来交换数据。如果有安卓串口开发这方面的需求,本文将会对你有所帮助。

1.基本概念

串口的概念: 用串行通信方式的扩展接口,指数据一位一位地顺序传送。

串口操作相关参数:

  • 1.设备名(串口地址):安卓是基于Linux系统,所以通常的串口地址为:/dev/ttyS0,/dev/ttyS1… 等。可通过linux命令查看对应的串口状态。
  • 2.波特率:串口传输速率,用来衡量数据传输的快慢,即单位时间内载波参数变化的次数。波特率与距离成反比,波特率越大传输距离相应的就越短。
  • 3.数据位:衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据往往不会是8位的,标准的值是6、7和8位。如何设置取决于你想传送的信息。
  • 4.停止位:用于表示单个包的最后一位。
  • 5.校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。

注意:

在 google 官方提供的 demo 代码基本上能够应付很多在Android设备使用串口的场景,该demo中不支持设置N,8,1。N对应校验位,8对应数据位,1对应停止位。在安卓串口操作中,不需要这三个参数。

2.串口通信 lib 准备

网上提供的代码都是通过 ndk 来编译 jni 文件生成对应的.so库。通过编写 jni 文件来打开串口,获取串口的数据流,来进行相应的读写操作。

本文通过CMake来编译 jni 文件生成对应的 so 库文件。

1.创建Android-library库。

1.首先创建:seriallibrary库

通常一些独立的功能模块,可能出现复用的情况,通常建议提取到 library 中,这样整个工程架构更加清晰明了,非常建议这样做。

在这里插入图片描述

2.配置CMake支持

在seriallibrary库的 build.gradle 中添加依赖:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FFA6XM5a-1633935046145)(image-20210317190054115.png)]

3.创建 jni 文件

在 main 文件夹下创建 jni 文件夹,并创建对应的文件:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yaYkZaHs-1633935046147)(image-20210317190236684.png)]

4.编写 CMakeLists.txt 文件

这里涉及到 jni 和 cmake 编译相关知识,可以自行查阅 cmake 使用教程。

CMakeLists.txt 文件配置 如下:

cmake_minimum_required(VERSION 3.10.2)

# Declares and names the project.

project("serial_port2")

add_library( # Sets the name of the library.
             serial

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             SerialPort.c)

include_directories(src/main/jni/)

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log )

target_link_libraries( # Specifies the target library.
        serial

        # Links the target library to the log library
        # included in the NDK.
        ${
   
   log-lib} )

在编写 jni 接口时,首先需要创建对应的 java 类及对应的 native 方法,创建 SerialPort.java文件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vXL5FH4U-1633935046148)(image-20210317191826314.png)]
SerialPort.java 类有 open 和 close 方法,用来打开和关闭串口:

package com.android.library;

import java.io.FileDescriptor;

public class SerialPort {
   
   

    /**
     * 打开串口
     * @param path       串口名称
     * @param porterRate 波特率
     * @param flags
     * @return
     */
    private native static FileDescriptor open(String path, int porterRate, int flags);

    /**
     * 关闭串口
     */
    private native void close();

    /**
     * 加载 so 库,该库名称与在 CMakeLists.txt 配置的库名相同
     */
    static {
   
   
        System.loadLibrary("serial");
    }
}

open 方法对应的全路径名称为:com.android.library.SerialPort#open

close 方法对应的全路径名称为:com.android.library.SerialPort#close

编写对应的 SerialPort.h 文件:注意 JNICALL 后的方法名不要写错,open 方法路径中的 . 对应__

com.android.library.SerialPort#open -> Java_com_android_library_SerialPort_open

com.android.library.SerialPort#close -> Java_com_android_library_SerialPort_close

SerialPort.h 文件如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com.android.library.SerialPort */
#ifndef _Included_com_android_libary_SerialPort
#ifdef __cplusplus
extern "C" {
   
   
#endif
/*
 *
 * Method:    open
 * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
 */
/**
 * Class:      com.android.library.SerialPort
 * Method:    open
 * 对应的jni接口为: com_android_library_SerialPort_open
 */
JNIEXPORT jobject JNICALL Java_com_android_library_SerialPort_open
  (JNIEnv *, jclass, jstring, jint, jint);

/**
 * Class:      com.android.library.SerialPort
 * Method:    open
 * 对应的jni接口为: com_android_library_SerialPort_close
 */
JNIEXPORT void JNICALL Java_com_android_library_SerialPort_close
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

SerialPort.c 文件如下:除了 JNICALL 方法名不同,其它都一样,来自 google 提供的串口工具 demo

#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <jni.h>

#include "SerialPort.h"

#include "android/log.h"
static const char *TAG="serial_port";
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO,  TAG, fmt, ##args)
#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)

static speed_t getBaudrate(jint baudrate)
{
   
   
	switch(baudrate) {
   
   
	case 0: return B0;
	case 50: return B50;
	case 75: return B75;
	case 110: return B110;
	case 134: return B134;
	case 150: return B150;
	case 200: return B200;
	case 300: return B300;
	case 600: return B600;
	case 1200: return B1200;
	case 1800: return B1800;
	case 2400: return B2400;
	case 4800: return B4800;
	case 9600: return B9600;
	case 19200: return B19200;
	case 38400: return B38400;
	case 57600: return B57600;
	case 115200: return B115200;
	case 230400: return B230400;
	case 460800: 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值