文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2022-06-06 07:06

关注

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.协议解析


 
  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); 
        } 
      } 
    } 
  } 
   
  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 USB转串口通信开发实例详解


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯