特别声明:尊重原创,原文链接:http://blog.csdn.net/junfeng120125/article/details/9328947

一,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);       } 

android-serialport-api源码:http://download.csdn.net/detail/nadeal/9860093

更多相关文章

  1. Android 利用JNI实现串口通信
  2. android 串口通信,蓝牙通信等需要输出十六进制数据的方法
  3. Android 中获取屏幕长度及宽度
  4. android中限制EditText最大输入字节数
  5. Android串口通信:基本知识梳理
  6. Android 串口通讯-------android -serialport-api
  7. Android 串口开发知识总结(未完待续)
  8. android:限制文本长度加省略号用ellipsize
  9. Android studio 使用NDK 实现串口 动态库

随机推荐

  1. Android屏幕适配 重点盘点
  2. Android之使用Android-query框架进行开发
  3. Android中WebView拦截替换网络请求数据
  4. ANDROID物联网开发
  5. Android开发资源完全汇总
  6. Android(安卓)APK包文件解析
  7. 跨平台应用app开发实践方案 Qt5 for Andr
  8. Android开发:最全面、最易懂的Android屏幕
  9. 【android】android 开发错误点滴积累5月
  10. Android开发资源完全汇总