返回顶部
首页 > 资讯 > 移动开发 >Android串口通讯SerialPort(使用篇)
  • 366
分享到

Android串口通讯SerialPort(使用篇)

java物联网android 2023-09-02 20:09:23 366人浏览 独家记忆
摘要

1.什么是串口? 在不会使用串口通讯之前,暂且可以把它理解为“一个可通讯的口”;使用篇不深入探讨理论及原理。能理解串口如何使用之后,可以查看Android串口通讯SerialPort(浅谈原理) 2.添加依赖 )在 module 中

1.什么是串口?

在不会使用串口通讯之前,暂且可以把它理解为“一个可通讯的口”;使用篇不深入探讨理论及原理。能理解串口如何使用之后,可以查看Android串口通讯SerialPort(浅谈原理)

2.添加依赖

)在 module 中的 build.gradle 中的 dependencies 中添加以下依赖:

dependencies {    //串口    implementation 'com.GitHub.licheedev:Android-SerialPort-api:2.0.0'}

)低版本的 gradle 在Project 中的 build.gradle 中的 allprojects 中添加以下 Maven仓库 (不添加任然无法加载SerialPort);

allprojects {    repositories {        maven { url "https://jitpack.io" }//maven仓库    }}

高版本的 gradle 已经废弃了 allprojects 在 settings.gradle 中 repositories 添加以下maven仓库(不添加任然无法加载SerialPort);

dependencyResolutionManagement {    repositoriesMode.set(RepositoriesMode.FaiL_ON_PROJECT_REPOS)    repositories {        Google()        mavenCentral()        jcenter() // Warning: this repository is going to shut down soon        maven { url "Https://jitpack.io" }//maven仓库    }}

3.编写串口处理类

)串口处理类:SerialHandle ;简单概括这个类,就是通过串口对象去获取两个流(输入流、输出流),通过者两个流来监听数据或者写入指令,硬件收到后执行。同时注意配置参数(只要支持串口通讯的硬件,一般说明书上都会有写)

package com.chj233.serialmode.serialUtil;import android.serialport.SerialPort;import android.util.Log;import java.io.BufferedInputStream;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.concurrent.ScheduledFuture;import java.util.concurrent.TimeUnit;public class SerialHandle implements Runnable {    private static final String TAG = "串口处理类";    private String path = "";//串口地址    private SerialPort mSerialPort;//串口对象    private InputStream mInputStream;//串口的输入流对象    private BufferedInputStream mBuffInputStream;//用于监听硬件返回的信息    private OutputStream mOutputStream;//串口的输出流对象 用于发送指令    private SerialInter serialInter;//串口回调接口    private ScheduledFuture readTask;//串口读取任务        public void addSerialInter(SerialInter serialInter) {        this.serialInter = serialInter;    }        public boolean open(String devicePath, int baudrate, boolean isRead) {        return open(devicePath, baudrate, 7, 1, 2, isRead);    }        public boolean open(String devicePath, int baudrate, int dataBits, int stopBits, int parity, boolean isRead) {        boolean isSucc = false;        try {            if (mSerialPort != null) close();            File device = new File(devicePath);            mSerialPort = SerialPort // 串口对象                    .newBuilder(device, baudrate) // 串口地址地址,波特率                    .dataBits(dataBits) // 数据位,默认8;可选值为5~8                    .stopBits(stopBits) // 停止位,默认1;1:1位停止位;2:2位停止位                    .parity(parity) // 校验位;0:无校验位(NONE,默认);1:奇校验位(ODD);2:偶校验位(EVEN)                    .build(); // 打开串口并返回            mInputStream = mSerialPort.getInputStream();            mBuffInputStream = new BufferedInputStream(mInputStream);            mOutputStream = mSerialPort.getOutputStream();            isSucc = true;            path = devicePath;            if (isRead) readData();//开启识别        } catch (Throwable tr) {            close();            isSucc = false;        } finally {            return isSucc;        }    }    // 读取数据    private void readData() {        if (readTask != null) {            readTask.cancel(true);            try {                Thread.sleep(160);            } catch (InterruptedException e) {                e.printStackTrace();            }            //此处睡眠:当取消任务时 线程池已经执行任务,无法取消,所以等待线程池的任务执行完毕            readTask = null;        }        readTask = SerialManage                .getInstance()                .getScheduledExecutor()//获取线程池                .scheduleAtFixedRate(this, 0, 150, TimeUnit.MILLISECONDS);//执行一个循环任务    }    @Override//每隔 150 毫秒会触发一次run    public void run() {        if (Thread.currentThread().isInterrupted()) return;        try {            int available = mBuffInputStream.available();            if (available == 0) return;            byte[] received = new byte[1024];            int size = mBuffInputStream.read(received);//读取以下串口是否有新的数据            if (size > 0 && serialInter != null) serialInter.readData(path, received, size);        } catch (IOException e) {            Log.e(TAG, "串口读取数据异常:" + e.toString());        }    }        public void close(){        try{            if (mInputStream != null) mInputStream.close();        }catch (Exception e){            Log.e(TAG,"串口输入流对象关闭异常:" +e.toString());        }        try{            if (mOutputStream != null) mOutputStream.close();        }catch (Exception e){            Log.e(TAG,"串口输出流对象关闭异常:" +e.toString());        }        try{            if (mSerialPort != null) mSerialPort.close();            mSerialPort = null;        }catch (Exception e){            Log.e(TAG,"串口对象关闭异常:" +e.toString());        }    }        public void send(final String msg) {        byte[] bytes = hexStr2bytes(msg);//字符转成byte数组        try {            mOutputStream.write(bytes);//通过输出流写入数据        } catch (Exception e) {            e.printStackTrace();        }    }        private byte[] hexStr2bytes(String hex) {        int len = (hex.length() / 2);        byte[] result = new byte[len];        char[] achar = hex.toUpperCase().toCharArray();        for (int i = 0; i < len; i++) {            int pos = i * 2;            result[i] = (byte) (hexChar2byte(achar[pos]) << 4 | hexChar2byte(achar[pos + 1]));        }        return result;    }        private static int hexChar2byte(char c) {        switch (c) {            case '0':                return 0;            case '1':                return 1;            case '2':                return 2;            case '3':                return 3;            case '4':                return 4;            case '5':                return 5;            case '6':                return 6;            case '7':                return 7;            case '8':                return 8;            case '9':                return 9;            case 'a':            case 'A':                return 10;            case 'b':            case 'B':                return 11;            case 'c':            case 'C':                return 12;            case 'd':            case 'D':                return 13;            case 'e':            case 'E':                return 14;            case 'f':            case 'F':                return 15;            default:                return -1;        }    }}

)串口回调SerialInter;简单概括一下这个类,就是将SerialHandle类中产生的结果,返回给上一层的业务代码,解偶合

package com.chj233.serialmode.serialUtil;public interface SerialInter {        void connectMsg(String path,boolean isSucc);        void readData(String path,byte[] bytes,int size);}

 3.)串口统一管理SerialManage;简单概括一下这个类,用于管理串口的连接以及发送等功能,尤其是发送指令,极短时间内发送多个指令(例如:1毫秒内发送10个指令),多个指令之间会相互干扰。可能执行了第一个指令,可能一个都没执行。这个类不是必须的,如果有更好的方法可以自己定义。

package com.chj233.serialmode.serialUtil;import java.util.Queue;import java.util.concurrent.ConcurrentLinkedQueue;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.ScheduledFuture;import java.util.concurrent.TimeUnit;public class SerialManage {    private static SerialManage instance;    private ScheduledExecutorService scheduledExecutor;//线程池 同一管理保证只有一个    private SerialHandle serialHandle;//串口连接 发送 读取处理对象    private Queue queueMsg = new ConcurrentLinkedQueue();//线程安全到队列    private ScheduledFuture sendStrTask;//循环发送任务    private boolean isConnect = false;//串口是否连接    private SerialManage() {        scheduledExecutor = Executors.newScheduledThreadPool(8);//初始化8个线程    }    public static SerialManage getInstance() {        if (instance == null) {            synchronized (SerialManage.class) {                if (instance == null) {                    instance = new SerialManage();                }            }        }        return instance;    }        public ScheduledExecutorService getScheduledExecutor() {        return scheduledExecutor;    }        public void init(SerialInter serialInter) {        if (serialHandle == null) {            serialHandle = new SerialHandle();            startSendTask();        }        serialHandle.addSerialInter(serialInter);    }        public void open() {        isConnect = serialHandle.open("/dev/ttyS1", 9600, true);//设置地址,波特率,开启读取串口数据    }        public void send(String msg) {                queueMsg.offer(msg);//向队列添加指令    }        public void colse() {        serialHandle.close();//关闭串口    }    //启动发送发送任务    private void startSendTask() {        cancelSendTask();//先检查是否已经启动了任务 ? 若有则取消        //每隔100毫秒检查一次 队列中是否有新的指令需要执行        sendStrTask = scheduledExecutor.scheduleAtFixedRate(new Runnable() {            @Override            public void run() {                if (!isConnect) return;//串口未连接 退出                if (serialHandle == null) return;//串口未初始化 退出                String msg = queueMsg.poll();//取出指令                if (msg == null || "".equals(msg)) return;//无效指令 退出                serialHandle.send(msg);//发送指令            }        }, 0, 100, TimeUnit.MILLISECONDS);    }    //取消发送任务    private void cancelSendTask() {        if (sendStrTask == null) return;        sendStrTask.cancel(true);        try {            Thread.sleep(100);        } catch (InterruptedException e) {            e.printStackTrace();        }        sendStrTask = null;    }}

4.使用串口

package com.chj233.serialmode;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import com.chj233.serialmode.serialUtil.SerialInter;import com.chj233.serialmode.serialUtil.SerialManage;public class MainActivity extends AppCompatActivity implements SerialInter {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        SerialManage.getInstance().init(this);//串口初始化        SerialManage.getInstance().open();//打开串口        findViewById(R.id.send_but).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                SerialManage.getInstance().send("Z");//发送指令 Z             }        });    }    @Override    public void connectMsg(String path, boolean isSucc) {        String msg = isSucc ? "成功" : "失败";        Log.e("串口连接回调", "串口 "+ path + " -连接" + msg);    }    @Override//若在串口开启的方法中 传入false 此处不会返回数据    public void readData(String path, byte[] bytes, int size) {//        Log.e("串口数据回调","串口 "+ path + " -获取数据" + bytes);    }}

5.多串口的使用

使用思想:一个单例对象控制一个串口,多串口时,写多个“SerialManage”就可以了。这里仅仅做举例不去考虑代码是否优雅,可以自行优化这段代码。(此案例中的SerialManage1、SerialManage2、SerialManage3、SerialManage4需要自己去复制,参照上面的SerialManage)

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //初始化串口1        SerialManage1.getInstance().init(new SerialInter(){            @Override            public void connectMsg(String path, boolean isSucc) {                String msg = isSucc ? "成功" : "失败";                Log.e("串口连接回调", "串口 "+ path + " -连接" + msg);            }            @Override//若在串口开启的方法中 传入false 此处不会返回数据            public void readData(String path, byte[] bytes, int size) {//        Log.e("串口数据回调","串口 "+ path + " -获取数据" + bytes);            }        });        //开启串口1        SerialManage1.getInstance().open();        //初始化串口2        SerialManage2.getInstance().init(new SerialInter(){            @Override            public void connectMsg(String path, boolean isSucc) {                String msg = isSucc ? "成功" : "失败";                Log.e("串口连接回调", "串口 "+ path + " -连接" + msg);            }            @Override//若在串口开启的方法中 传入false 此处不会返回数据            public void readData(String path, byte[] bytes, int size) {//        Log.e("串口数据回调","串口 "+ path + " -获取数据" + bytes);            }        });        //打开串口2        SerialManage2.getInstance().open();        //初始化串口3        SerialManage3.getInstance().init(new SerialInter(){            @Override            public void connectMsg(String path, boolean isSucc) {                String msg = isSucc ? "成功" : "失败";                Log.e("串口连接回调", "串口 "+ path + " -连接" + msg);            }            @Override//若在串口开启的方法中 传入false 此处不会返回数据            public void readData(String path, byte[] bytes, int size) {//        Log.e("串口数据回调","串口 "+ path + " -获取数据" + bytes);            }        });        //打开串口3        SerialManage3.getInstance().open();        //初始化串口4        SerialManage4.getInstance().init(new SerialInter(){            @Override            public void connectMsg(String path, boolean isSucc) {                String msg = isSucc ? "成功" : "失败";                Log.e("串口连接回调", "串口 "+ path + " -连接" + msg);            }            @Override//若在串口开启的方法中 传入false 此处不会返回数据            public void readData(String path, byte[] bytes, int size) {//        Log.e("串口数据回调","串口 "+ path + " -获取数据" + bytes);            }        });        //打开串口4        SerialManage4.getInstance().open();        findViewById(R.id.send_but1).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                SerialManage1.getInstance().send("Z");//给串口1发送指令 Z            }        });        findViewById(R.id.send_but2).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                SerialManage2.getInstance().send("Z");//给串口2发送指令 Z            }        });        findViewById(R.id.send_but3).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                SerialManage3.getInstance().send("Z");//给串口3发送指令 Z            }        });        findViewById(R.id.send_but4).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                SerialManage4.getInstance().send("Z");//给串口4发送指令 Z            }        });    }}

 

6.总结

串口通讯对于Android开发者来说,仅需关注如何连接、操作(发送指令)、读取数据;无论是232、485还是422,对于开发者来说连接、操作、读取代码都是一样的

来源地址:https://blog.csdn.net/qq_42111674/article/details/123653870

--结束END--

本文标题: Android串口通讯SerialPort(使用篇)

本文链接: https://lsjlt.com/news/391418.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Android串口通讯SerialPort(使用篇)
    1.什么是串口? 在不会使用串口通讯之前,暂且可以把它理解为“一个可通讯的口”;使用篇不深入探讨理论及原理。能理解串口如何使用之后,可以查看Android串口通讯SerialPort(浅谈原理) 2.添加依赖 )在 module 中...
    99+
    2023-09-02
    java 物联网 android
  • Android串口通讯SerialPort的使用详情
    目录1.什么是串口?2.添加依赖3.编写串口处理类4.使用串口5.总结1.什么是串口? 在不会使用串口通讯之前,暂且可以把它理解为“一个可通讯的口”;使用篇不...
    99+
    2024-04-02
  • 浅谈Android串口通讯SerialPort原理
    目录前言一、名词解释二、SerialPort的函数分析三、SerialPort打开串口的流程四、疑惑五、总结前言 通过前面这篇文章Android串口通讯SerialPort的使用详情...
    99+
    2024-04-02
  • 怎么​使用Java实现串口SerialPort通讯
    要使用Java实现串口通讯,你可以使用Java的RXTX库。下面是一个简单的示例代码: 首先,你需要下载并安装RXTX库。你可以...
    99+
    2023-10-23
    Java
  • C#基于SerialPort类实现串口通讯详解
    本文实例为大家分享了C#基于SerialPort类实现串口通讯的具体代码,供大家参考,具体内容如下 最终效果 窗体设置: using System; using System....
    99+
    2024-04-02
  • C#基于SerialPort类怎么实现串口通讯
    本篇内容主要讲解“C#基于SerialPort类怎么实现串口通讯”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#基于SerialPort类怎么实现串口通讯”吧!最终效果窗体设置:using&n...
    99+
    2023-06-29
  • Android串口使用2之使用Google官方库android-serialport-api
    Google官方库android-serialport-api GitHub:android-serialport-api 此库版本太旧了,而且...
    99+
    2022-06-06
    android串口 serialport google api Android
  • Node.js中SerialPort(串口)模块使用
    目录目的模块安装基础使用扫描端口打开端口发送数据接收数据错误处理数据解析器SerialPort类构造方法属性事件方法命令行工具总结目的 上位机与各种电路模块间常常采用串口进行通讯,N...
    99+
    2024-04-02
  • C#中的串口通信SerialPort详解
    今天这篇文章带大家学习下C#中的串口通讯。在日常的开发工作中,如果工作内容是CS方向的同学应该很容易接触到串口通讯方面的业务需求。那么也就很容易想到C#中SerialPort类,它就...
    99+
    2024-04-02
  • c#模拟串口通信SerialPort怎么实现
    这篇“c#模拟串口通信SerialPort怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“c#模拟串口通信Serial...
    99+
    2023-06-30
  • Android串口使用3之使用CMake工具完成android-serialport-api库的移植
    君问归期未有期,巴山夜雨涨秋池。 对于Android串口的使用,基本已经被写烂了,网上一搜一大堆教程,还有很多大佬也已经封装成库了,可以在项目中...
    99+
    2022-06-06
    android串口 serialport cmake api Android
  • c#模拟串口通信SerialPort的实现示例
    目录一、前导知识实现串口通信的必要设置二、实验绘制窗口测试 三、总结四、附件完整代码一、前导知识 串行口是计算机的标准接口,现在的PC机(个人电脑)一般至少有两个串行口CO...
    99+
    2024-04-02
  • Android串口开发之使用JNI实现ANDROID和串口通信
    导语:Android串口通信在物联网、智能家居等领域具有广泛的应用。本文将详细介绍如何使用JNI技术实现Android设备与串口的通信,包括串口的打开、设置参数和读写数据等过程。 目录 一...
    99+
    2023-10-20
    android java android studio 串口通信 JNI
  • 安卓与串口通信-实践篇
    前言 在上一篇文章中我们讲解了关于串口的基础知识,没有看过的同学推荐先看一下,否则你可能会不太理解这篇文章所述的某些内容。 这篇文章我们将讲解安卓端的串口通信实践,即如何使用串口通信实现安卓设备与其他设备例如PLC主板之间数据交互。 需要注...
    99+
    2023-08-19
    android linux 单片机
  • c# 使用线程对串口serialPort进行收发数据(四种)
    本文主要介绍了c# 使用线程对串口serialPort进行收发数据,分享给大家,具体如下: 一共写了四种方法,窗体界面都是一样的: 方法一: using System; using...
    99+
    2024-04-02
  • 【Android】串口通信的理论与使用教程
    Android系统诞生这十几年以来,Android开发工程师岗位经历了由盛转衰的过程,目前纯UI的Android APP已经鲜有公司愿意花费巨资去开发,Android APP开发的业务也仅剩游戏、...
    99+
    2023-10-20
    android 串口通信 serialport kotlin 串行通信
  • Android硬件通信之 串口通信
    一,串口介绍 1 串口简介 串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口; 串行接口(SerialInterface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可...
    99+
    2023-08-31
    android 硬件工程
  • Android串口使用方法
    目录 前言  一、环境介绍 二、设备介绍 二、方法一: 1.引入库        2.编写代码 三、方法二: 1.引入库        2.编写代码 四、完整代码: 五、源码: 前言 串口是一种用于android对硬件设备通信的一种...
    99+
    2023-09-01
    android java 信息与通信 物联网 iot
  • Android USB通信(host转串口)
    前言:公司属于北斗通信行业,项目大多都需要和各式各样的硬件设备相结合来满足项目需求,因此所涉及到的各种技术也相对比较冷门。前段时间有个项目用到了一款定制 Android 设备,其中有多个接口,包括两个 USB 接口和一个 RS232 串口,...
    99+
    2023-09-24
    android
  • Android 串口通信编程及串口协议分析
    Android 串口通信编程:嵌入式编程和可穿戴设备及智能设备都会用到串口,这里就带大家分析下, 一,android串口通信 串口通信采用一个第三方开源项目,实现串口数据收发...
    99+
    2022-06-06
    协议 串口 串口通信 通信 Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作