Android 串口通信编程及串口协议分析

Android 串口通信编程:嵌入式编程和可穿戴设备及智能设备都会用到串口,这里就带大家分析下,

一,android串口通信

串口通信采用一个第三方开源项目,实现串口数据收发。

1. 使用了http://code.google.com/p/android-serialport-api/的项目的serialport api和jni;
2. 支持4串口同时收发,有定时自动发送功能,收发模式可选Txt或Hex模式;
3.  n,8,1,没得选;
4. 为减轻界面卡顿的情况,接收区的刷新采用单独的线程进行定时刷新;
5. 发送区的数据以及一些设置项,在程序关闭时会自动保存,打开时自动载入;
6. jni使用最新的NDKr8b重新编译了一下

简单编写步骤:

1.新建一个项目,自己起个名字
2.直接复制serialport api和jni文件夹到新建的工程,如果不想自己编译jni,就连libs文件夹也一起复制
3.去android官方网站下载NDK,解压,在CMD中转到jni目录,并执行 绝对路径\ndk-build
4.自己再封装一个工具类或直接使用SerialPort类都行,举个直接使用的例:
直接剽窃原项目的SerialPortActivity.java,并稍微改一下,重点改这里
mSerialPort = mApplication.getSerialPort();
这里可以改成
new SerialPort(new File("/dev/s3c2410_serial0"), 9600, 0);//COM0,波特率9600
5. SerialPortFinder的使用就没什么好讲的了,实例化后用.getAllDevicesPath()就能获取到所有设备了。
其它如数据转换等请参考源码

源码可以参考谷歌android-serialport-api例子

http://code.google.com/p/android-serialport-api/source/checkout
svn checkout http://android-serialport-api.googlecode.com/svn/trunk

二,串口通信协议解析

1.通信基本格式

字段 描述 长度(字节)
起始符 0F,十六进制码  1
信息类型 一个字节,十六进制码(0F,F0,FF等保留码不用)1
信息长度 是信息内容的长度,ASCII码表示(0~9,A~F,最大长度为256)(例如长为11个,十六进制是0B,则两个字节就写0x30 0x42)。
注:因为最大长度256不能满足有些指令的要求,所以对长度做了扩展,下面是扩展说明:
如果第一个字节的最高位为1,则表示扩展长度。在扩展长度状态下,其他15个字节通过16进制大端模式来保存长度。比如:0x80 0x12表示长度为0x001 2,0x81 0x12表示长度为0x0112。2
信息内容 一组十六进制码  N
校验 一个字节,十六进制码,是自信息类型起至对象号止所有码的异或。1
结束符 F0,一个字节,十六进制码 (为了保证可靠性,车机下发的结束符为F0 FF)1

2.协议解析


/**
   * 读取终端设备数据
   * @author Administrator
   */
  private class ReadThread extends Thread { 

    @Override
    public void run() {
      super.run(); 

      // 定义一个包的最大长度
      int maxLength = 2048;
      byte[] buffer = new byte[maxLength];
      // 每次收到实际长度
      int available = 0;
      // 当前已经收到包的总长度
      int currentLength = 0;
      // 协议头长度4个字节(开始符1,类型1,长度2)
      int headerLength = 4; 

      while (!isInterrupted()) {
        try {
          available = mInputStream.available();
          if (available > 0) {
            // 防止超出数组最大长度导致溢出
            if (available > maxLength - currentLength) {
              available = maxLength - currentLength;
            }
            mInputStream.read(buffer, currentLength, available);
            currentLength += available;
          } 

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

        int cursor = 0;
        // 如果当前收到包大于头的长度,则解析当前包
        while (currentLength >= headerLength) {
          // 取到头部第一个字节
          if (buffer[cursor] != 0x0F) {
            --currentLength;
            ++cursor;
            continue;
          } 

          int contentLenght = parseLen(buffer, cursor, headerLength);
          // 如果内容包的长度大于最大内容长度或者小于等于0,则说明这个包有问题,丢弃
          if (contentLenght <= 0 || contentLenght > maxLength - 5) {
            currentLength = 0;
            break;
          }
          // 如果当前获取到长度小于整个包的长度,则跳出循环等待继续接收数据
          int factPackLen = contentLenght + 5;
          if (currentLength < contentLenght + 5) {
            break;
          } 

          // 一个完整包即产生
          // proceOnePacket(buffer,i,factPackLen);
          onDataReceived(buffer, cursor, factPackLen);
          currentLength -= factPackLen;
          cursor += factPackLen;
        }
        // 残留字节移到缓冲区首
        if (currentLength > 0 && cursor > 0) {
          System.arraycopy(buffer, cursor, buffer, 0, currentLength);
        }
      }
    }
  } 

  /**
   * 获取协议内容长度
   * @param header
   * @return
   */
  public int parseLen(byte buffer[], int index, int headerLength) { 

//   if (buffer.length - index < headerLength) { return 0; }
    byte a = buffer[index + 2];
    byte b = buffer[index + 3];
    int rlt = 0;
    if (((a >> 7) & 0x1) == 0x1) {
      rlt = (((a & 0x7f) << 8) | b);
    }
    else {
      char[] tmp = new char[2];
      tmp[0] = (char) a;
      tmp[1] = (char) b;
      String s = new String(tmp, 0, 2);
      rlt = Integer.parseInt(s, 16);
    } 

    return rlt;
  } 

protected void onDataReceived(final byte[] buffer, final int index, final int packlen) {
    System.out.println("收到信息");
    byte[] buf = new byte[packlen];
    System.arraycopy(buffer, index, buf, 0, packlen);
    ProtocolAnalyze.getInstance(myHandler).analyze(buf);
  }

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Android USB转串口通信开发实例详解

     Android USB转串口通信开发实例详解 好久没有写文章了,年前公司新开了一个项目,是和usb转串口通信相关的,需求是用安卓平板通过usb转接后与好几个外设进行通信,一直忙到最近,才慢慢闲下来,趁着这个周末不忙,记录下usb转串口通信开发的基本流程. 我们开发使用的是usb主机模式,即:安卓平板作为主机,usb外设作为从机进行数据通信.整个开发流程可以总结为以下几点: 1.发现设备 UsbManager usbManager = (UsbManager) context.getSystem

  • Android 串口通信编程及串口协议分析

    Android 串口通信编程:嵌入式编程和可穿戴设备及智能设备都会用到串口,这里就带大家分析下, 一,android串口通信 串口通信采用一个第三方开源项目,实现串口数据收发. 1. 使用了http://code.google.com/p/android-serialport-api/的项目的serialport api和jni: 2. 支持4串口同时收发,有定时自动发送功能,收发模式可选Txt或Hex模式: 3.  n,8,1,没得选: 4. 为减轻界面卡顿的情况,接收区的刷新采用单独的线程进

  • 深入分析Visual C++进行串口通信编程的详解

    利用Visual C++在windows环境下设计异步串行通信程序可以使用不同的方法.一种方法可以使用windows系统提供的串行口API函数:另一种方法可以直接使用Microsoft公司提供的ActiveX控件MSCOMM.OCX.利用MSCOMM.OCX控件进行串行口程序设计相对比较简单,只要对该控件的属性.事件和方法进行设置和操作,就能完成简单的串行通信功能.而直接使用windows系统提供的串行口API函数则相对较为灵活.试验中,可根据自己的情况任意其中一种进行编程.以下针对如何使用wi

  • Android蓝牙通信编程

    项目涉及蓝牙通信,所以就简单的学了学,下面是自己参考了一些资料后的总结,希望对大家有帮助.  以下是开发中的几个关键步骤: 1.首先开启蓝牙  2.搜索可用设备  3.创建蓝牙socket,获取输入输出流  4.读取和写入数据 5.断开连接关闭蓝牙 下面是一个蓝牙聊天demo  效果图: 在使用蓝牙是 BluetoothAdapter 对蓝牙开启,关闭,获取设备列表,发现设备,搜索等核心功能 下面对它进行封装: package com.xiaoyu.bluetooth; import java.

  • Android串口通信之串口读写实例

    在Android串口通信:基本知识梳理的基础上,我结合我项目中使用串口的实例,进行总结: Android使用jni直接进行串口设备的读写网上已经有开源项目了,本文是基于网上的开源项目在实际项目中的使用做的调整和优化: Google串口开源项目 下面是我项目中的相关代码及介绍: 1.SerialPort.cpp /* * Copyright 2009 Cedric Priscal * * Licensed under the Apache License, Version 2.0 (the "Li

  • C#串口通信程序实例详解

    创建C#串口通信程序之命名空间 System.IO.Ports命名空间中最重用的是SerialPort 类. 创建C#串口通信程序之创建SerialPort 对象 通过创建SerialPort 对象,我们可以在程序中控制串口通信的全过程. 我们将要用到的SerialPort 类的方法: ReadLine():从输入缓冲区读一新行的值,如果没有,会返回NULLWriteLine(string):写入输出缓冲Open():打开一个新的串口连接Close():关闭 复制代码 代码如下: SerialP

  • Android串口通信apk源码详解(附完整源码)

    1.SerialPortHelper「Android串口通信」介绍 原项目地址 https://github.com/freyskill/SerialPortHelper Android串口通讯助手可以用于需要使用串口通信的Android外设,该库有如下特点: 1.串口通信部分使用C++实现,在笔者接触的部分设备上实测,使用C++实现与Google官方提供的Demo的方式要快: 2.支持且必须设置串口接收最大数据长度,初始化库时填入该参数,这样设置的原因是考虑在实际使用中,规定的串口通信协议格式

  • Android串口通信封装之OkUSB的示例代码

    本文介绍了Android串口通信封装之OkUSB的示例代码,分享给大家.具体如下: Github传送门:OkUSB OkUSB 一个简洁的Android串口通信框架. 功能简介 支持设置波特率 支持设置数据位 支持设置停止位 支持设置校验位 支持DTS和RTS 支持串口连接状态监听 用法简介 Gradle allprojects { repositories { ... maven { url 'https://jitpack.io' } } } dependencies { compile '

  • Android串口开发之使用JNI实现ANDROID和串口通信详解

    一:串口通信简介 前段时间因为工作需要研究了一下android的串口通信,网上有很多讲串口通信的文章,我在做的时候也参考了很多文章,现在就将我学习过程中的一些心得分享给大家,由于串口开发涉及到jni,所以开发环境需要支持ndk开发,如果未配置ndk配置的朋友,或者对jni不熟悉的朋友,请查看上一篇文章,android 串口开发第一篇:搭建ndk开发环境以及第一个jni调用程序 ,串口通信和java操作io类似,先打开串口,然后向串口发送或者读取数据,最后关闭串口,所以基本思路就是: 1.对串口文

  • Android实现串口通信

    本文实例为大家分享了Android实现串口通信的具体代码,供大家参考,具体内容如下 生成so文件 首先确保已经安装了NDK和CMake 然后创建一个SerialPort.java文件 主要用来处理so文件 注意包名一旦写好不要更改位置,具体代码: import android.util.Log; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.Fi

  • Java实现的串口通信功能示例

    本文实例讲述了Java实现的串口通信功能.分享给大家供大家参考,具体如下: 用Java实现串口通信(windows系统下),需要用到sun提供的串口包 javacomm20-win32.zip.其中要用到三个文件,配置如下: 1.comm.jar放置到 JAVA_HOME/jre/lib/ext; 2.win32com.dll放置到 JAVA_HOME/bin; 3.javax.comm.properties 两个地方都要放     jre/lib(也就是在JAVA文件夹下的jre)    JA

随机推荐