zoukankan      html  css  js  c++  java
  • 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目录,并执行 绝对路径 dk-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.协议解析

    [java] view plain copy
     
      1. /** 
      2.      * 读取终端设备数据 
      3.      * @author Administrator 
      4.      */  
      5.     private class ReadThread extends Thread {  
      6.   
      7.         @Override  
      8.         public void run() {  
      9.             super.run();  
      10.   
      11.             // 定义一个包的最大长度  
      12.             int maxLength = 2048;  
      13.             byte[] buffer = new byte[maxLength];  
      14.             // 每次收到实际长度  
      15.             int available = 0;  
      16.             // 当前已经收到包的总长度  
      17.             int currentLength = 0;  
      18.             // 协议头长度4个字节(开始符1,类型1,长度2)  
      19.             int headerLength = 4;  
      20.   
      21.             while (!isInterrupted()) {  
      22.                 try {  
      23.                     available = mInputStream.available();  
      24.                     if (available > 0) {  
      25.                         // 防止超出数组最大长度导致溢出  
      26.                         if (available > maxLength - currentLength) {  
      27.                             available = maxLength - currentLength;  
      28.                         }  
      29.                         mInputStream.read(buffer, currentLength, available);  
      30.                         currentLength += available;  
      31.                     }  
      32.                       
      33.                 }  
      34.                 catch (Exception e) {  
      35.                     e.printStackTrace();  
      36.                 }  
      37.   
      38.                 int cursor = 0;  
      39.                 // 如果当前收到包大于头的长度,则解析当前包  
      40.                 while (currentLength >= headerLength) {  
      41.                     // 取到头部第一个字节  
      42.                     if (buffer[cursor] != 0x0F) {  
      43.                         --currentLength;  
      44.                         ++cursor;  
      45.                         continue;  
      46.                     }  
      47.                       
      48.                     int contentLenght = parseLen(buffer, cursor, headerLength);  
      49.                     // 如果内容包的长度大于最大内容长度或者小于等于0,则说明这个包有问题,丢弃  
      50.                     if (contentLenght <= 0 || contentLenght > maxLength - 5) {  
      51.                         currentLength = 0;  
      52.                         break;  
      53.                     }  
      54.                     // 如果当前获取到长度小于整个包的长度,则跳出循环等待继续接收数据  
      55.                     int factPackLen = contentLenght + 5;  
      56.                     if (currentLength < contentLenght + 5) {  
      57.                         break;  
      58.                     }  
      59.   
      60.                     // 一个完整包即产生  
      61.                     // proceOnePacket(buffer,i,factPackLen);  
      62.                     onDataReceived(buffer, cursor, factPackLen);  
      63.                     currentLength -= factPackLen;  
      64.                     cursor += factPackLen;   
      65.                 }  
      66.                 // 残留字节移到缓冲区首  
      67.                 if (currentLength > 0 && cursor > 0) {  
      68.                     System.arraycopy(buffer, cursor, buffer, 0, currentLength);  
      69.                 }  
      70.             }  
      71.         }  
      72.     }  
      73.   
      74.     /** 
      75.      * 获取协议内容长度 
      76.      * @param header 
      77.      * @return 
      78.      */  
      79.     public int parseLen(byte buffer[], int index, int headerLength) {  
      80.   
      81. //      if (buffer.length - index < headerLength) { return 0; }  
      82.         byte a = buffer[index + 2];  
      83.         byte b = buffer[index + 3];  
      84.         int rlt = 0;  
      85.         if (((a >> 7) & 0x1) == 0x1) {  
      86.             rlt = (((a & 0x7f) << 8) | b);  
      87.         }  
      88.         else {  
      89.             char[] tmp = new char[2];  
      90.             tmp[0] = (char) a;  
      91.             tmp[1] = (char) b;  
      92.             String s = new String(tmp, 0, 2);  
      93.             rlt = Integer.parseInt(s, 16);  
      94.         }  
      95.   
      96.         return rlt;  
      97.     }  
      98.   
      99. protected void onDataReceived(final byte[] buffer, final int index, final int packlen) {  
      100.         System.out.println("收到信息");  
      101.         byte[] buf = new byte[packlen];  
      102.         System.arraycopy(buffer, index, buf, 0, packlen);  
      103.         ProtocolAnalyze.getInstance(myHandler).analyze(buf);   
      104.     }  
  • 相关阅读:
    SQL查询语句中,any和all有什么区别?
    $(function(){...});
    在ASP.NET中TextBox和TextBoxFor的区别以及ValidationMessageFor的作用以及EditorFor等的作用和用法什么?
    Brt课程设计day3
    Brt课程设计day2
    day1
    .net 高级写法总结
    可能是目前最完整的前端框架 Vue.js 全面介绍
    redis live 如何安装
    百万级PHP网站架构工具箱
  • 原文地址:https://www.cnblogs.com/cliuwei/p/5799915.html
Copyright © 2011-2022 走看看