美文网首页编程AndroidAndroid知识
android下变态的串口通讯

android下变态的串口通讯

作者: Souv | 来源:发表于2016-09-08 09:52 被阅读12470次

android下的串口通讯,为毛我总遇到这样的变态需求呢。

前言

随着智能化硬件的发展android跟智能硬件打交道的越来越常见。而串口通讯是硬件之间最常见的通讯方式,所以android下的串口通讯也可能在某些项目中运用到。


串口开源项目

目前android下用到的串口通讯都是由Google提供的开源项目

google串口开源项目地址

此项目下下来正常情况下是能直接使用的。如果想更深入的了解其更多知识可以查看链接中的wikis。

但是:直接能使用时因为他已经将so已经打包生成好了,如果你将.so放在你的项目中你会发现是不能使用的,原因是因为so中的方法名是通过开源项目的包名+方法名来的。放在你项目中包名都变了,所以so文件将无法找到对应的方法的,这样我们还是得自己生成so文件。


使用

因为开源项目是eclipse的,而我们现在更多使用的是android studio,如果你还没有使用android studio那就可以直接使用,但是你确定还不使用android studio么?

在android下可以下载一个“串口调试助手”App可以对你写的程序做对比。快速验证问题。

原理

android下的串口通讯是使用jni来使用的,如果你还不太了解Jni使用可以查看我另外一篇文章,其中详细介绍了JNI的使用。

像小白一样学习JNI

上面这篇文章也是基于串口下的jni写的,所以本篇文章并不介绍JNI的使用。只是说直接使用串口通讯

原理:Google开源项目直接提供了SerialPort、SerialPortFinder两个主要的类。这两个类提供了打开/关闭串口的方法。然后我们需要将java下的打开和关闭串口方法生成.h文件,然后实现.c方法;然后相应的生成.so文件。.so文件没问题之后才能正常使用。

实现

步骤一:设置串口号与波特率

我们知道串口通讯都是通过串口号与波特率来的,这跟我们tcp必须知道ip、port一样的原理。

    public SerialPort getSerialPort() throws SecurityException, IOException, InvalidParameterException {
    if (mSerialPort == null) {
        /* Read serial port parameters */
        SharedPreferences sp = getSharedPreferences("android_serialport_api.sample_preferences", MODE_PRIVATE);
        String path = sp.getString("DEVICE", "");
        int baudrate = Integer.decode(sp.getString("BAUDRATE", "-1"));

        Log.e("TAG","path="+path+"     baudrate="+baudrate);
        /* Check parameters */
        if ( (path.length() == 0) || (baudrate == -1)) {
            throw new InvalidParameterException();
        }

        /* Open the serial port */
        mSerialPort = new SerialPort(new File(path), baudrate, 0);
    }
    return mSerialPort;
}

<code>mSerialPort = new SerialPort(new File(path), baudrate, 0);</code>
这里面有3个参数;第一个参数为串口路径,第二个参数为波特率,第三个为状态
前面两个参数我们都是知道的一般为:
<code>private static int baudrate = 115200; //波特率

private static String path = "/dev/ttyS3"; //路径</code>

请根据自己的为准。

步骤二:打开串口

打开和关闭串口是使用jni来调用c方法的。我们在上层调用打开串口的方法

    Log.e(TAG,"串口打开");
        mSerialPort = serialPortUtil.getSerialPort(TokenCommon.ROBOT_SERIALPORT_BAUDRATE,TokenCommon.ROBOT_SERIALPORT_PATH);
        mOutputStream = mSerialPort.getOutputStream();
        mInputStream = mSerialPort.getInputStream();

        /* Create a receiving thread */
        mReadThread = new ReadThread();
        mReadThread.start();

打开串口成功之后会开启一个线程一直读取数据。

    private class ReadThread extends Thread {

    @Override
    public void run() {
        super.run();
        while(!isInterrupted()) {
            int size;
            try {
                byte[] buffer = new byte[64];
                if (mInputStream == null) return;
                size = mInputStream.read(buffer);
                if (size > 0) {
                    onDataReceived(buffer, size);
                }
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
        }
    }
}

如果读取数据会调用onDataReceived方法。onDataReceived个方法为接收方法,如果你需要那个类接收串口数据只要实现该方法就好了,下面我们会在数据接收的方法中说到

步骤三:发送串口数据

先看开源项目的发送源码:

    EditText Emission = (EditText) findViewById(R.id.EditTextEmission);
    Emission.setOnEditorActionListener(new OnEditorActionListener() {
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
            int i;
            CharSequence t = v.getText();
            char[] text = new char[t.length()];
            for (i=0; i<t.length(); i++) {
                text[i] = t.charAt(i);
            }
            try {
                mOutputStream.write(new String(text).getBytes());
                mOutputStream.write('\n');
            } catch (IOException e) {
                e.printStackTrace();
            }
            return false;
        }
    });

因为项目是直接将edittext输入的字符串转为byte数据直接发送。而我们项目可能是直接发送byte数组,所以我修改发送源码为:

    private void sendSerialData(){
    String content = ""; //无数据内容
    int dateLength = ByteUtil.getContentLength(content);//数据长度
    byte by[] = new byte[6];
    by[0] = TokenCommon.ANDROIDSENDROBOT;  //协议头
    by[1] = TokenCommon.ANDROIDDEVICEID;    //设备id
    by[2] = (byte) dateLength;  //  数据长度
    by[3] = (byte) (~dateLength);   //  数据长度取反
    by[4] = TokenCommon.REQUESTGETROBOTDATA; // 命令字:获取主控信息
    by[5] = ByteUtil.getCheckSum(by);
    try {
        if(null != mOutputStream){
            mOutputStream.write(by);
        } else {
            Log.e(TAG,"串口打开失败");
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

将自己的指令按照协议组成一个byte[],然后直接发送byte数组

然后我们来验证发送是否成功。我们可以将串口连接电脑在电脑上开一个串口调试助手,然后选择自己的串口号与波特率


电脑串口调试助手

我们可以看到接收区接收到了我们发送的数据,则证明发送是正常的

步骤四:接收串口数据

个人觉得串口最蛋疼的就是接收数据了,因为他是一个字符一个字符传过来的,哪怕你的是一条完整的数据,他也是一个一个字符接收。他不像我们的tcp或udp一样发送一条完整数据除非过长或网络造成的数据丢失,我们是能一次性接收一条数据的。

而串口一个一个字符接收的,而且还有可能接收的数据是乱的,还有可能接收的数据是不完整的,还有可能接收到的数据在下一条在给你,多么坑啊。好吧既然这样我们也是有办法的,这样就需要我们就必须做数据的拼接。

我们先看开源项目的接收源码

    @Override
protected void onDataReceived(final byte[] buffer, final int size) {
    runOnUiThread(new Runnable() {
        public void run() {
            if (mReception != null) {
                mReception.append(new String(buffer, 0, size));
            }
        }
    });
}

注意1:onDataReceived是实现的一个抽象方法,因为源码已经封装只要一旦有数据就会调用此方法。在步骤二中可以看到。
注意2:此方法接收数据是已字符串接收的,并且每做任何的数据处理,只是单纯的字符串追加之后显示数据,这肯定是无法满足我们的需求的,因为我们接收的数据也很有可能是一个byte数组。

所以我们自己的自己写数据处理播放。

    @Override
protected void onDataReceived(final byte[] buffer, final int size) {
    //获取串口传过来的数据
    System.arraycopy(buffer, 0, b, unDisposeLen, size);
    unDisposeLen += + size;
    int temp = 0;  //数组下标
    while(temp <= unDisposeLen){
        Log.e(TAG, "****************************"+Arrays.toString(b));//字节数组打印
        //判断数据长度是否足够:
        if(unDisposeLen - temp >= FormatToken.DATA_MIN_LEN){
            //分别判断校验头、设备id、数据长度(数据长度和数据长度校验判断是否相等)
            if(b[temp] == FormatToken.head && (b[temp + 1] == FormatToken.deviceId) && b[temp + 2] == ~b[temp + 3]){
                int dataLen = (int)b[temp + 2];
                Log.e(TAG,"数据长度="+dataLen);
                //判断校验和位数据是否相等;接收到的校验和与发送的校验和相等
                //将完整数据减掉最后的chesum之后得到一个byte[]
                byte che[] = new byte[FormatToken.DATA_MIN_LEN + dataLen - 1];
                System.arraycopy(b, temp, che, 0, FormatToken.DATA_MIN_LEN + dataLen - 1);
                //将减掉最后的chesum之后得到一个byte[]校验得到chesum
                byte chesum = ByteUtil.getCheckSum(che); //得到chesum
                //判断计算出来的chesum与命令中的chesum是否相等
                if(b[temp + dataLen + 5] == chesum){
                    //chesum相等证明为一条完整数据
                    byte by[] = new byte[FormatToken.DATA_MIN_LEN + dataLen];
                    //将完整数据从总数据中copy出来
                    System.arraycopy(b, temp, by, 0, FormatToken.DATA_MIN_LEN + dataLen);
                    Log.e(TAG, "完整数据=" + Arrays.toString(by));//字节数组打印

                    temp = temp + by.length; //移动下标
                    byte[] ret = new byte[unDisposeLen - temp];
                    //将为处理的数据copy到ret数组中
                    System.arraycopy(b,temp,ret,0,ret.length);
                    //将未处理的数据ret替换从0开始替换到
                    System.arraycopy(ret,0,b, 0 ,ret.length);
                    Log.e(TAG, "&&&&&&&&&&&&&&&&&&&&&&&&&&&&" + Arrays.toString(b));//字节数组打印
                    unDisposeLen = unDisposeLen - temp; //存储未完成的数据长度
                    temp = 0;

                    if(temp == unDisposeLen) {
                        temp = 0 ;
                        unDisposeLen = 0;
                        break;
                    }
                } else {
                    temp++;
                }
            } else {
                temp++;
            }
        } else {
            break;
        }
    }
    if(temp == unDisposeLen) {
        unDisposeLen = 0;
    }

}

上面的代码主要是将一个一个字符数据根据你的协议拼接成一条完整的数据。代码中的注释已经写的很清楚了。

然后我们验证一下:用电脑调式工具发送内容


电脑调式助手发送数据

然后看android下的数据接收

android下的数据接收

到此证明数据的接收木有问题。

思路是:获取一段串口数组数据,判断数据中是否包含协议头和设备id,如果没有则继续拼接字符串,如果有则判断数组的长度是否大于最小协议长度,如果小于则继续追加,如果大于则根据数据长度获取数据部分,然后将数据部分加上协议头等数据组成一个数组,然后判断数组检验码是否相同,如果相等证明是一条完整数据,并将拼接的数据移除掉完整数据部分(避免重复解析已经处理过的数据。)如果不是则丢弃数据。

demo的github地址 https://github.com/SouvDc/SerialPort_project

完结

OK,到这里我们已经能完整解析出数据,但是一定要根据你自己的协议来调整。


慢慢努力做好身边所有的事

求知若饥,虚心若愚

相关文章

  • android下变态的串口通讯

    android下的串口通讯,为毛我总遇到这样的变态需求呢。 前言 随着智能化硬件的发展android跟智能硬件打交...

  • Android 串口设置校验位、速率、停止位等参数

    最近业余时间有个android项目需要和硬件进行通信,通讯方式都是通过串口,android串口通讯google有个...

  • Android串口通讯

    简介 在Android上使用串口通讯一般就是用google官方的串口demo代码(android-serialpo...

  • Android串口通讯

    串口通讯的步骤: 1.打开串口。 2.串口处于监听状态 3.想串口写入数据,串口接收到数据返回数据 串口的一个基本...

  • Android 串口通讯

    概念 串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口...

  • Android串口通信SerialHelper

    SerialHelper 一个基于usb-serial-for-android封装的Android串口通讯帮助库,...

  • Android USB转串口通信

    一、引用 1、Git上最火的USB转串口通信2、Android之USB转串口通信3、安卓开发中的USB转串口通讯 ...

  • Android串口通讯开发

    1.Windows下设置模拟器串口映射,便于调试: 使用工具包: 百度网盘下载 (1)win下运行虚拟串口工具,...

  • Android串口通讯整理

    这一段时间做的项目自动售货机和无线终端设备的通讯,都是通过串口进行对接和通讯。在Android中进行串口通信方式可...

  • Android加载Class的思考

    做的一个项目需要用到串口通讯,而android恰恰有现成的串口通讯服务,但是相关的接口类都被隐藏起来了,不能被用...

网友评论

  • 1db4f00ee619:FormatToken 这个是什么值,怎么来的
  • Wu_android:老哥请问下。这个怎么设置校验位和停止位呢 谢谢?:smile:
    Souv:根据通讯协议来。
  • de8ac36aa8da:楼主,没有在你的Demo里看到你接收数据这里的处理
  • _懰軓_:大佬项目地址打不开,能发个demo吗?万分感谢!
    _懰軓_:@Souv 大佬可以加下微信指导一下吗,谢谢!122549472
    Souv:我更新了一下文字,有github地址
  • 爱学习的大宝:你好,为什么我的会有问题呢?SerialPort类中的open,close方法显示红色,找不到
    T_alon:ndk重新编译下.so文件
    _懰軓_:@爱学习的大宝 你好!你这问题解决了吗?
  • TonyEasy:大佬你好,请问我的读取的代码如下,不知道为什么一直取不到数据,mInputStream.read(buffer);执行到这里就执行不下去了,请问这是怎么回事?
    try {
    byte[] buffer = new byte[1024];
    if (mInputStream == null) return;
    size = mInputStream.read(buffer);
    if (size > 0) {
    onDataReceived(buffer, size);
    }
    } catch (IOException e) {
    e.printStackTrace();
    return;
    }
    TonyEasy:@Souv 阻塞该怎么解决呢
    Souv:估计你遇到的问题跟他们一样,就是在获取数据的时候阻塞了
  • b4abac29846d:作者能不能给个源码,就是接完整数据包那块需要点灵感
  • ChineseBoy:感觉read方法就是一个大坑啊,一直阻塞在那里,退都退不出来,请问如何处理
    ChineseBoy:@T_alon 我还没有找到很好的方案哦,现在就是保证全局开一个,然后常驻不关,你找到好的方案后可以私信我,多谢
    T_alon:大佬,关于readThread线程里面那个read方法阻塞怎么处理呢
    T_alon:大佬,这个阻塞请问你是怎么解决的?
  • 4xMzmK:作者你好!看完你的这篇博客,收益良多,非常感谢🙏!
    我现在做的这个项目是做一个Android app,实现串口调试功能,可以理解为把windows系统上的串口调试工具,在Android上实现出来。第一次接触串口这方面的东西,有点懵,有些关于串口的问题想跟你请教一下。
    我的设备是使用的3线串口。我调试的时候是把TXD和RDX接在一起。使用了一个网友基于google串口修改过的一个库。
    发送和你的步骤三基本一样,直接通过OutputStream对象write(字符串.getBytes())
    但是没有进行by[0],by[1]这些,
    1. 这是不是就是没有定义协议,直接就是裸的?
    接收是另开个进程,使用InputStream.read(buffer)读取,和你步骤二中类似,这样的做法现在的问题是我发现,发送东西的时候会截断。比如我发送qwerty,会分多次读取,第一次读取werty,第二次循环读到q,乱序的。
    2. 我遇到的这种现象是不是就是你在步骤四:接收串口数据中提到的那些坑?
    3. 因为有这些问题,所以需要进行粘包操作什么?
    4. 如果使用自己的数据处理方法,这是不是就是自己的私有协议?
    5. 那是否就意味着,不能跟其他的串口设备进行通讯了呢?因为其他设备无法知道你是怎么解析数据的,也就不能使用正确的方法发送数据。
    6. 串口通信难道没有一个通用的通信协议或者标准么?为什么一定要自己实现协议呢?可是反过来想,如果没有统一的协议标准,那网上那么多串口调试工具是如何通信的?
    如果你方便的话可否指教一下我的这些疑问?
    Souv:@singlepig xmodem,ymodem,zmodem这几个我没听说过,所以我应该没实现。:joy:
    4xMzmK:@Souv 不加班....真好:sob:
    另外串口传输文件的话是否是需要在java层去实现xmodem,ymodem,zmodem之类的协议?
    Souv:哇塞,你的有点多呀
    1、因为串口通讯不是一段一段读取的(类似socket通讯)所以就会出现“截断”的现象。
    2、是的
    3、对,粘包其实就是将“截断”的数据组合起来,组合成一条完整的数据。
    4、是的
    5、能跟其他设备进行通信,只是获取到的数据,不是根据你的协议来解析的。所以还是获取的到,只是如果其他设备的通讯协议跟你的不一样就无法知道他的通讯协议是什么意思,也就是说无法解析,如果你知道其他设备的通讯协议,也就可以按照此协议来进行解析。
    6、你说的标准应该理解的不一样,比如:我买了一个打印机设备,打印机连接到一个程序,并能进行打印。那是因为这个程序按照了通讯协议来进行打印。但是如果你理解成一个通用的标准协议,那是不是以为着所以的人,只要连接上了串口,就能打印出东西?那岂不是说这个东西很容易就被破解了?或者说协议都是公司的秘密(你如果知道其他公司的通讯协议,就可以获取到这个通讯过程中发送和接收了什么?)在如:我们微信支付等等都是由微信根据他自己的一套协议来实现的,里面实现了加密什么的。安全。这就是为什么要自己实现协议的原因。串口调试助手每次发送接收都会带一个\r\n的结束符,这里面的“\r\n”你也可以理解成协议。所以串口调试工具每次解析是否包含\r\n的字符,如果没有,就继续接收数据。如果有,则证明接收到了一条完整的数据。
    说的也比较笼统,因为要下班了。:sweat:
  • 720cd9061d3c:串口开源地址怎么在简书app里打不开?
    Souv:需要root
    720cd9061d3c:@changbill
    另外,这种需不需要手机root?
  • 新世界后半段:在Android 5.1之前这些都可以,但是在之后google 的Android团队对root进行了很严格的处理,Runtime.getRuntime().exec("/system/bin/su");这个一执行就报错,我是用系统签名的方式去回去还是会报错,不知道楼主可以好的方式来解决这个问题呢除开修改原代码
    Souv:这个我们没试过哦,因为我们是定制机。
  • cp我要吃饭:硬件设备将数据发送到服务器,然后服务器将数据发送到手机这样不是可以代替物联网么?小白不懂,只是随便问问
    Souv:不是所有硬件设备都能联网的,或者说不时所有硬件设备都要加入一个wifi模块,这样成本和配置wifi方面都很麻烦。
  • 老北瓜:爱死你了 好像有点懂了
  • 9e8d6141b418:大神,我的情况是这样的,我是用485连的两个安卓设备,主从机都是开启接收线程的,定时发数据,(数据里的计数是递增的),主机没数据是发令牌的,从机收到令牌后回复数据,结果在从机接收的数据中间会出现偶发乱码,这是怎么回事
    9e8d6141b418:@Souv 大神,问一下:我昨天做了个测试,将485通信同时连接到终端(安卓设备)和pc上,pc运行和安卓一样的java接收代码逻辑相同,主设备消息队列每10ms添加一次数据,做定时发送,(单向)挂了一夜,PC和终端接收到的结果PC就丢了一条数据包,终端数据(靠后的数据)就出现很多错数据(乱码),这是硬件问题么?
    Souv:乱码?我遇到乱码情况就是硬件接口没接好的情况,其他好像没遇到过。
  • lemonCode:你好,可以加个微信指导一下解析数据的这部分吗?为嘛我收到的数据总是丢失一部分呢,微信13421821315
  • 4fec16147732:大神,demo下载不了,能发下源码么?


    邮箱:xiaodong_lxd93@163.com

    谢谢!!!
  • 177632ce4f18:前辈,请问一下,我每次ondataReceiced的返回值都是帧头,其他的全部丢失了,我觉得好像是串口助手发送一次数据,mInputStream.read方法只执行一次,而且每次都读的帧头,您觉得可能是什么原因啊
    177632ce4f18:@Souv 刚才奇迹发生了....我把串口线拧死,数据好像都能收到了.....什么情况啊:sweat:
    177632ce4f18:@Souv 谢谢您,我昨天调试了一下,您说的第一条我这不满足,read第二次读就阻塞在那了.
    Souv:1、首先读数据肯定是一直循环读取的。
    2、读到的数据还没确认是一条完整的一定要保存起来。直到为一条完整数据在处理。
    3、数据发送要有一定的格式来确实是否为一条完整数据。
    暂时想到就这么多了。
  • a636b3b4f0ad:大神加一下QQ1063906795,指导一下,拜托啦
  • 730b384e7fc6:大神你的demo发我邮件1612626300@qq.con 感谢谢!
  • Hello鬼哥:大神,请教下。安卓下能同时打开多个串口通讯吗?目前测试过安卓下可打开一个USB转串口,但是如果连了两个USB转串口,只能打开其中一个,想问下这又是什么原因呢?
    Hello鬼哥:@Souv 另外看了下,串口直接通讯和USB转串口还是有点不太一样好像
    Hello鬼哥:@Souv 好的,谢谢。现在在测试USB转串口,连两个USB则只能打开其中一个,但单独连其中某一个都能成功通讯,这是什么原因呢
    Souv:能同时打开多个串口的。
    1、先确定串口是否有问题。
    2、确定是否权限是否打开。
    因为我那时做的时候同时打开多个串口是很顺利的,所以具体什么问题我可能也分析不出来。
  • 706bded697bb:大神 请问一下 我的是RS485的串口 串口可以打开了 点发送的时候 提示E/AudioPolicyManagerBase: output 2 no Strategy used这个 接收不到数据 这是为什么啊
    Souv:我觉得像这种整个数据链路没通的,应该去看下google提供的原始demo。
  • d5851a6ff038:你好,有个疑问可否加下qq 咨询下 1106919334
    Souv:先简单的描述一下问题吧。
  • d5851a6ff038:您好最近项目需要通讯 可否加下qq 咨询下 1106919334
  • 布条麻绳:楼主你好,我最近也在搞串口通信方面的东西,用的也是 google 的那一套,每次运行到SerialPort.c -> if (tcsetattr(fd, TCSANOW, &cfg)) 就报错,请教一下是什么原因呢?
  • gd6321374:try {
    byte[] buffer = new byte[64];
    if (mInputStream == null) return;
    size = mInputStream.read(buffer);
    if (size > 0) {
    onDataReceived(buffer, size);
    }
    } catch (IOException e) {
    e.printStackTrace();
    return;
    }

    楼主,你好。我也是使用这个开源项目和模拟器操作串口的,目前实现数据的收发,但是现在遇到的一个问题时,使用上面的代码接收数据每次不能接收大于8字节的数据,如果使用串口助手发送超过8字节的数据,模拟器立即死掉。
    请问你是否遇到过这种情况????
    上面那段接收协议完整的一包数据的,下位机或则串口调试助手最大包时多少个字节??如一个包30字节,请问你的下位机是分包发送,还是一次性发送。

    但是我看你上面的串口助手的截图,却是一次性发送了超过8字节数据,请问这有什么细节吗????
    因为我这边下位机,一般都是发送超过8字节的完整一包数据,这个问题困扰很久了,如果可以,请回复一下,先谢谢了。。
  • 小豪丶ace:最近一致在搞串口通信,解析这个部分 是真的纠结,明天用你的方法试试,对了 不一定是一个字符一个字符传的吧
    Souv:不一定哦!
  • e874dc518a41:好,eclipse下开发的有吗
    Souv:一样的,Google原生就是eclipse下的;
  • 550069f48bdf:大神,可以加个扣扣,指导下我么。
    b37f107ff87d:@Souv dalao不用回复我了,我找到问题了,原因一:我反复用几个串口试验,导致串口冲突了。原因二:我是用的3根并排的杜邦线接在usb转接口上,而这个杜邦线,竟然接触不良。
    b37f107ff87d:@Souv dalao,我想请教一下ByteUtil,TokenCommon两个类该怎么写,因为我的Android串口硬件部分已经打通了,可利用usb转接口在电脑上测试的时候却一直无法接受到数据,我想试一下你这种方法看能不能解决我的问题
    Souv:@Quietshy 已加
  • a9e1e1daf52b:大神,你有遇到读取串口数据导致阻塞的情况么
    a9e1e1daf52b:@飞兔哥 可以使用线程同步的一些手段,或者阻塞队列解决看看
    飞兔哥:这个问题解决了吗,可以分享下吗?inputStream.read 读阻塞
    Souv:好像有,但是我忘记怎么解决的了:sweat:
  • 小亮哥:能整理分享一下源码吗?
  • f8dd9d661dcc:我想请教下博主,如果是串口通讯错误或者没有心跳的话,你是怎么处理的?
    是单纯的重启串口吗?
    你的方案是怎么样的?
    指教下?
    Souv:@修修罗 我说的提醒是,开始打开串口的时候是知道的,所以提示用户,不过你也可以通过计时,如果心跳10s之内都没收到也可以认为他断开了。
    至于后面的重启就是你理解的意思。
    f8dd9d661dcc:@Souv 你的意思是失败的情况是会在界面上显示出来,建议用户重启设备类似的方案吗?
    还有你那边的硬件工程师,建议重启10次的意思是不是:
    如果重启10次以内,如果成功了,就不重启了,重启次数清零;
    如果失败,继续重启,直到成功,最大次数是10次的意思吗?
    Souv:@修修罗 不好意思,我并没有做重启的方案,如果我在接收不到的情况下会提示出来,但是并不会重启串口(因为可能存在一直启动不了的情况)。不过我们这边的硬件工程师是建议重启10次。
  • _SoftReference小:如果是要读取不同协议的数据该怎么处理呢?
    f8dd9d661dcc:@_SoftReference小 在我认为,无论是网络连接,还是串口连接,他们都是虚拟连接,虚拟连接都是不可靠的,肯定会存在掉失数据的问题,所以才需要处理粘包的问题。
    你说的攻破目前我以为的话最多就是用第三方包保证数据的完整性,然后返回一条完整的数据的接口,但也是在应用层上处理的。
    如果在硬件上处理的话,我感觉目前不太可能实现,毕竟它们都是虚拟连接。
    _SoftReference小:@Souv 现在还没有找到串口能读取一整条数据的方法吗,串口出来这么久了 还没人攻破这个问题
    Souv:根据你的协议来咯,只是思路不变啦
  • 小时不识月z:还未看源码。先请教一下,android串口的读写是需要root权限的,那么他是如何获得root权限的呢?
    Souv:对。我是root了的
    小时不识月z:@Souv /system/bin/su未root的手机下没有吧?
    Souv:@Jiesean 这个你看下源码就知道了,
    Process su;
    su = Runtime.getRuntime().exec("/system/bin/su");
    String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
    + "exit\n";
    通过su得到权限。
  • 相互交流:楼主我想问一个问题,,源码是这样的
    try {
    byte[] buffer = new byte[64];
    if (mInputStream == null) return;
    size = mInputStream.read(buffer);
    if (size > 0) {
    onDataReceived(buffer, size);
    }
    } catch (IOException e) {
    e.printStackTrace();
    return;
    }
    你刚才是说数据可能接受不完全,,我感觉只需要把byte[] buffer = new byte[64];一次性接受数据该大一点,就可以了,,毕竟设备传递的消息不会是很大,,
    Souv:@相互交流 是的,根据协议来,但是如果只是一个标记开始、结束可能还不严谨,最后是根据数据长度、chesum,和结束符一起来判断。
    相互交流:@Souv 读取到的数据如果不完整的话,,是通过和自己和硬件人员进行相应的协议来判断是否此次内容读写完整吗?就比如我们的协议是,读到开始标记,标示开始,如果包含结束标示符号,就判断此次内容读取完成..示这样进行处理的吗???望楼主解答一下。。。
    Souv:@相互交流 我说的接收不完全并不是byte buffer接收不完全,而是串口数据的传输时是字节传输的,就比如你一条完整的指令只要32个字节,那是串口一次传输只给你10个字节,那么这个就是接收不完全,所以我就需要再次接收串口数据 temp++,串口在给你10个字节,需继续接受,直到得到一个完整的指令32个字节。因为串口不是socket一样,一次就能接收到一条完整的指令。所以需要接收数据之后判断是否是一条完整指令,如果不是就继续接收。如果是就做相应的处理。
  • Souv:你可以分别在手机和pc上下载串口调试助手
  • b40dbde7fa6c:请教下您 我使用这个程序如果用真实手机和pc来测试可以吗? 如果可以的话需要什么工具吗
  • 326b763c0397:Google哪一套效率低,二来也不完整。我们都是自己另写呢。
    Souv::scream::scream::scream:另写?自己写c文件生存so 吗?不完整是指什么?
  • dfe147f4a102:想问一下通常用在那里
    Souv:@_v君 没呢,每个人接触面不一样当然就有不是很了解的地方。术业有专攻嘛
    dfe147f4a102:@Souv 可以的 感觉很先进
    Souv:@_v君 个人理解他通常用在物联网的智能硬件设备。硬件设备的主要通讯方式是串口。一般情况下都是pc通过USB或串口来连接硬件设备来跟设备进行数据的交互,但android出来之后有很多同样的应用场景也需要连接硬件设备,而PC可能在某些场景下不太合适,所以android下的串口通讯由此诞生。比如我们现在做的:平板直接连接血压、心率、体温等传感器,测量之后直接将数据通过串口发送到android端。
  • b042da3f525a:和socket很像啊,设备要开个串口才行吧。
    Souv:@stillhp 对啊,一直物联网,现在在做机器人。
    b042da3f525a:@Souv 你是做物联网的?大砖头手持机。😂
    Souv:是很像,不一样的就在于数据的传输。设备给你应该就开了串口号不然不能用。

本文标题:android下变态的串口通讯

本文链接:https://www.haomeiwen.com/subject/bstsettx.html