栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

android——串口、网口与外设进行数据交互

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

android——串口、网口与外设进行数据交互

当开始接触到传感器的时候,觉得一切都是未知的。就拿温度传感器来说,当时我在想:我怎么就通过Android板读取到当前的温度呢?我又该怎么做呢,我该怎么下手呢?于是我先上网搜了下,然后我疯狂的和传感器厂家进行交流,哈哈哈感觉人家技术支持已经烦我了。接下来,我们言归正传。

一、在什么场景下使用

一般可以通过Android板与硬件进行联动,比如温湿度的监测、蓄电池的电能、噪音监测、智能电表的相关参数、体温检测仪、血压检测仪等等,只要你能想到的,一般都能与Android板通信。当然了,前提是必须他这个硬件要支持数据的传输啦,哈哈哈。

二、常见的数据传递
我们常见的数据传递有蓝牙、串口、网口等等。而我要记录的就是网口、串口的通讯。

1、串口

  • 串口是串行接口(serialport)的简称,也称为串行通信接口或COM接口。
  • 串口通信是指采用串行通信协议(serial communication)在一条信号线上将数据一个比特一个比特地逐位进行传输的通信模式。
  • 常见的串口有,RS232,RS485等等,这是根据电气标准来分的,具体为什么这么分我也不知道。

这里我就简单的介绍了什么是串口,串口用的模式大多数都是FIFO(先进先出)的数据结构。
如下图所示,是常见的设备间串口通讯结构图。每个设备都有一个DB9接口,通过DB9接口连接RS-232标准的串口线进行数据传输。由于通过RS-232标准传输的电平信号到达设备后,不能直接被识别,所以会通过电平转换芯片转换成能识别的TTL电平信号,实现通讯。

相互通讯的两个设备间,一个设备发送数据,一个设备接收数据。一般情况下,发送数据的设备称为DTE,如计算机;接收数据的设备称为DCE,如调制解调器。

在写java代码之前,我们还得知道一个概念,就是波特率。
波特率:在信息传输通道中,携带数据信息的信号单元叫码元,每秒钟通过信道传输的码元数称为码元传输速率,简称波特率。比特率:9600bps,意思就是每秒中传输9600bit。

就拿我做的一个需求来说,就是对接智能电池的信息。大致流程就是,我通过串口去读取电池的信息,然后将读取到的数据解析。

因为要每隔一段时间读一次数据,所以我写了一个service,就命名为BatService好了,在onCreate()中进行串口的初始化工作。

a、首先就是先初始化串口,指定哪个串口,和使用的波特率大小。
b、接下来就是创建两个线程,一个用于读,一个用于写。所以我写了ReadBatThread和WriteBatThread,我这里为了简易说下流程,线程安全方面没有进行管理。初始化的时候读线程初始化就是getInputStream(),写线程初始化就是getOutputStream(),对inputstream和outputstream有不清楚的可以去看我之前有一篇文章提到过。
InputStream和OutputStream的用法

    @Override
    public void onCreate() {
        super.onCreate();
        try {

            SerialPort mbatSerialPort = new SerialPort(new File("/dev/ttyS0"), 19200, 0);
            ReadBatThread readBatThread = new ReadBatThread(mbatSerialPort.getInputStream());
            readBatThread.start();
            WriteBatThread writeBatThread = new WriteBatThread(mbatSerialPort.getOutputStream());
            writeBatThread.start();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

c、接来下就是写具体的读写线程了
先看写线程,一般写线程就是我们给所需要的读取信息的设备(我这里就是电池)发送一条指令。像我要读取电池的信息,我这里就根据定义的协议,发送一个读指令,一般为16进制数。而与设备之间传递的一般是字节流,我们发送的时候将十六进制字符串转成字节数组就可以了。

private class WriteBatThread extends Thread {
        private OutputStream mOus;

        public WriteBatThread(OutputStream ous) {
            if (ous == null) {
                throw new NullPointerException("流异常");
            }
            mOus = ous;
        }

        @Override
        public void run() {
            super.run();
            while (!this.isInterrupted()) {
                if (mOus != null) {
                    try {
                    //这里就是给设备发送读指令,readHex就是十六进制指令字符串
                        mOus.write(Transform.HexString2Bytes(readHex));
                        Thread.sleep(5000);
                    } catch (IOException | InterruptedException | NoSuchElementException pE) {
                        Log.e(TAG, pE.toString());
                    }
                }

            }
            IOUtils.close(mOus);
        }
    }

下面是16进制字符串转换成字节数组的方法,你可以把它自己的工具类中。注意在进行写的时候,要把IO进行关闭。

	// 把16进制字符串转换成字节数组
	public static byte[] HexString2Bytes(String hexStr) {
		byte[] b = new byte[hexStr.length() / 2];
		for (int i = 0; i < b.length; i++) {
            b[i] = (byte) Integer.parseInt(hexStr.substring(2 * i, 2 * i + 2), 16);
        }
		return b;
	}

这时候你已经给设备发送了你想要读取他电池信息的指令了,接下来是不是他就要给你返回电池信息了,所以就要写一个读线程。

 class ReadBatThread extends Thread {

        InputStream ins;
        public ReadBatThread(InputStream pInputStream) {
            if (pInputStream == null) {
                throw new NullPointerException("流异常");
            }
            ins = pInputStream;
        }

        @Override
        public void run() {
            super.run();
            int count = -1;
            byte[] buf = new byte[500];
            byte[] temp;
            String data;
            ArrayList procotol;
            while (!interrupted()) {
                try {
                    if ((count = ins.read(buf)) != -1) {
                        temp = new byte[count];
                        System.arraycopy(buf, 0, temp, 0, count);
                        data = Transform.bytesToHexString(temp);
                        procotol = new ArrayList<>((data.length()) / 2);
                        String item;
                        int element;
                        for (int i = 0; i < (data.length()) / 2; i++) {
                            item = data.substring(i * 2, i * 2 + 2);
                            element = Integer.parseInt(item, 16);
                            procotol.add(element);
                        }
                        //上面的操作是为了把byte转成hexString,便于观察,在这个协议中,最终又转换为了10进制数进行处理
                        //接下来就是根据指定的协议进行解析了,哪几位代表的是什么,怎么计算。举个例子,比如地址码是一个byte,你就可以用procotol.get(0),得到地址码的十进制数。
                    }
                } catch (IOException pE) {
                }
            }
            IOUtils.close(ins);
        }
    }

同样的不要忘记关流,下面是将字节数组转换成16进制字符串的方法。

	// 把字节数组转换成16进制字符串
	public static String bytesToHexString(byte[] byteArray) {
		StringBuffer hexStr = new StringBuffer(byteArray.length * 2);
		for (int i = 0; i < byteArray.length; i++) {
			String sTemp = Integer.toHexString(0xFF & byteArray[i]);
			int j = 0;
			while (j < 2 - sTemp.length()) {
				sTemp = "0" + sTemp;
				j++;
			}
			hexStr.append(sTemp.toUpperCase());
		}
		return hexStr.toString();
	}

上面就是串口的读取方式了,这样就可以使android板与外设进行通讯数据传递了。

2、网口
其实网口通讯的原理和串口通讯差不多,只是他们初始化的时候不一样,后面数据的读取可以说是一模一样。就是要让外设与你的android程序在同一个局域网内就可以进行通讯了,主要用到的就是socket。初始化的时候用socket对象的getOutputStream()和getInputStream()方法就可以了。

		String host = "1.1.1.1";//网络ip地址
        int port = 9999;//端口号
        Socket mSocket = new Socket(host, port);
        mSocket.getOutputStream();
        mSocket.getInputStream();

其实socket这个知识点可以去深入的了解一下,我这里就不说了,哈哈哈哈~~~
这样就串口和网口与外设信息交互的流程大致就到这里啦,如果有什么错误或不足的地方请各位大佬指出来哦,嘻嘻!!!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/285517.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号