安卓开发板之串口通信,通过modbus Rtu协议控制下位机

  • 1.环境准备
  • 2.编写串口操作核心类
  • 3.编写测试类

前言:因为公司最近有个人脸识别门禁的项目,这个项目主要业务是实现远程人脸注册,管理员在后台管理中审核注册用户信息,到规定时间之后用户到会场即可通过刷脸进入。需要的硬件:百度人脸识别开发套件(2000rmb),支持modbus rtu协议的2 路458继电器(几十rmb),一个某宝购买的电子门禁(200多rmb)。技术难点(个人认为):百度人脸识别开发套件同步我司服务器上的人脸库(原本该开发板预装的人脸识别软件只支持离线数据库,也就是只能到场注册,现在要实现可以通过移动端口的h5界面注册,因为注册的用户信息是放到我司服务器上的数据库的,所以开发版要做的事就是将通过审核的用户人脸加载到本地数据库中),开发套件识别人脸成功后通过串口发送数据控制电子门的打开(原本以为这方面是最难的因为本人没有做过android相关的开发,更别提与串口通信了,所以最开始觉得这是不可能完成的任务,甚至想到了要重装一个linux才能实现串口通信,后来在csdn上随便下了一个代码竟然在串口收到了数据,这个最难的问题解决了后面的问题也都不是问题了)。原本本人是负责.net网站开发的,百度人脸识别开发板本来是交给另外一位之前做过一些android开发的大三的小学弟来的,后来别人听说了我们的想法,直接借口感冒一次都不来了,原本负责服务器搭建的我只好转战android开发,因为前两个月刚好看了java基础和javaEE网站开发,所以对java开发还算了解,ssh框架才只学了一半,原本准备学完之后出去外面找个javaEE网站开发工程师的工作的,后来因为一些原因辗转来到这个物联网创业公司,一切又得从头开始哇咔咔。所有android 开发 上手还是比较快的,而且不用从头开发,百度给了人脸识别软件的源码,但是大公司写的代码就是不一样,看了好几天才终于能动手,开发过程中也遇到了一系列的问题,其中最严重的问题就是软件运行容易闪退,以为是软件问题找售后解决了更新了一下版本后来还是一样容易崩,公司的人都以为是我把软件改出了bug,emmmm…。后来经过了一系列的测试终于发现是硬件问题,找到售后把板子寄回维修,再拿到它已然是一个月后,整个开发周期延后一个月,,,,依稀记得我第一次找售后的时候售后尽然和我说从来没遇到过我这样的情况,究竟是板子卖的太少还是我运气太背就不得而知了。导致了整个开发周期历时1个月又20天左右emmm.。。。现在将本人经验分享如下,这是其中的一个环节,如若需要后期更新或者其他帮助的话请在下方留言
——————helloword_xy

1.环境准备

1).使用该类需要将两个文件夹拷贝到项目目录中,这两个文件夹分别是jni,和jniLibs(jni就是Java本地接口,使用它可以实现java语言与其他语言的交互)jni和jniLibs的压缩包

2)配置app文件夹下的bulid.gradle文件(配置好后重新编译一次)

3)配置好并重新编译后调整到安卓特有的目录结构会看到,这说明环境准备完成

2.编写串口操作核心类

该类的用来控制串口的打开和关闭,并获取到对应串口的输入输出流对象。

package android_serialport_api;import android.util.Log;import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;public class SerialPort {private static final String TAG = "SerialPort";private FileDescriptor mFd;private FileInputStream mFileInputStream;private FileOutputStream mFileOutputStream;public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {//检查访问权限,如果没有读写权限,进行文件操作,修改文件访问权限if (!device.canRead() || !device.canWrite()) {try {//通过挂在到linux的方式,修改文件的操作权限Process su = Runtime.getRuntime().exec("/system/xbin/su");String cmd = "chmod 777 " + device.getAbsolutePath() + "\n" + "exit\n";su.getOutputStream().write(cmd.getBytes());if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {throw new SecurityException();}} catch (Exception e) {e.printStackTrace();throw new SecurityException();}}mFd = open(device.getAbsolutePath(), baudrate, flags);if (mFd == null) {Log.e(TAG, "native open returns null");throw new IOException();}mFileInputStream = new FileInputStream(mFd);mFileOutputStream = new FileOutputStream(mFd);}// Getters and setterspublic InputStream getInputStream() {return mFileInputStream;}public OutputStream getOutputStream() {return mFileOutputStream;}// JNI(调用java本地接口,实现串口的打开和关闭)
/**串口有五个重要的参数:串口设备名,波特率,检验位,数据位,停止位其中检验位一般默认位NONE,数据位一般默认为8,停止位默认为1*//*** @param path     串口设备的据对路径* @param baudrate 波特率* @param flags    校验位*/private native static FileDescriptor open(String path, int baudrate, int flags);public native void close();static {//加载jni下的C文件库System.loadLibrary("serial_port");}
}

3.编写测试类

(注意:红字代码只是本人在MyEclipse中调试所用,无需拷贝)
串口的打开和关闭很好实现,输入输出数据也很好实现,
关键的问题是输入的数据包下位机总是解析不出来,后来摸索了好久
终于发现问题是我发送的数据包的格式有问题。
1.首先我们要知道上位机发送给下位机的到底是什么格式的
(我就以控制从站号为1的从机的第一个线圈的开关命令为例)
开和关的16进制命令分别为:
开启第一个线圈:01 05 00 00 FF 00 8C 3A
关闭第一个线圈:01 05 00 00 00 00 CD CA
上面的命令是平常在主从机调试软件中输入的,但是下位机实际接收到的格式却并非如此)
2.首先我找了一个上位机(这里我用的是有人的网关,可以通过网页界面控制 通过rj485口
向下位机发送数据),配合usb转串口调试工具,以及串口调试软件 SSCOM32.EXE
我终于看到了这个命令的本来面目:“    ?”
what?这是什么?对,我也想问。还好SSCOM32.EXE可以选择以16进制格式显示选项
于是我就看了这个:01 05 00 00 FF 00 8C 3A。对没错,终于看到认识的了。
但是它内部是怎么实现的呢?
于是我用在网上找的字符串转16进制字符串方法
/** * 字符串转换成十六进制字符串*/
public static String str2HexStr(String str) {  char[] chars = "0123456789ABCDEF".toCharArray();  StringBuilder sb = new StringBuilder("");byte[] bs = str.getBytes();  int bit;  for (int i = 0; i < bs.length; i++) {  bit = (bs[i] & 0x0f0) >> 4;  sb.append(chars[bit]);  bit = bs[i] & 0x0f;  sb.append(chars[bit]);  }  return sb.toString();
} 调用一下:
@Test
public void run1() {
// TODO Auto-generated method stubString string1=Hex2Bytes.str2HexStr("   ?");System.out.println(string1);}
于是看到了下面的结果

看起来挺像的不过中间的空格没有了
(为什么和去除空格之后的不完全一样,可能是代码问题,所以上面的代码“字符串
转换成十六进制字符串的”不建议拷贝)
顺着这条线我们继续往下走
于是我将命令:改成:01050000FF008C3A
然后代码就变成了下面的样子(结果大功告成!!!)

测试类的真正面目(注意每个安卓开发板的串口名不一样,我的用的是百度人脸识别开发板485串口)

package com.serial_test;import android.util.Log;import java.io.File;
import java.io.IOException;
import java.io.OutputStream;import android_serialport_api.SerialPort;public class SerialTest {protected SerialPort mSerialPort;protected OutputStream mOutputStream;private static String prot = "ttysWK0";private static int baudrate = 9600;public void openDoor() {new Thread() {@Overridepublic void run() {try {mSerialPort=new SerialPort(new File("/dev/" + prot), baudrate,0);mOutputStream = mSerialPort.getOutputStream();//mInputStream = mSerialPort.getInputStream();//mOutputStream = mSerialPort.getOutputStream();byte [] bytes1=HexStrToBytes.hexToByteArray("01050000FF008C3A");mOutputStream.write(bytes1,0,bytes1.length);Thread.sleep(1000*2);byte [] bytes2=HexStrToBytes.hexToByteArray("010500000000CDCA");mOutputStream.write(bytes2,0,bytes2.length);Log.i("test", "发送成功");} catch (SecurityException e) {e.printStackTrace();} catch (IOException e) {Log.i("test", "打开失败");e.printStackTrace();}catch (Exception e){Log.i("test", "发送失败");}finally {if (mSerialPort != null) {mSerialPort.close();}if (mOutputStream != null) {try {mOutputStream.close();} catch (IOException e) {e.printStackTrace();}}}}}.start();}
}

16进制字符串与字节数组的转换工具类

package com.serial_test;public class HexStrToBytes {/*** Hex字符串转byte* @param inHex 待转换的Hex字符串* @return  转换后的byte*/public static byte hexToByte(String inHex){return (byte)Integer.parseInt(inHex,16);}/*** 16进制字符串转换为字节数组*/public static byte[] hexToByteArray(String inHex){int hexlen = inHex.length();byte[] result;if (hexlen % 2 == 1){//奇数hexlen++;result = new byte[(hexlen/2)];inHex="0"+inHex;}else {//偶数result = new byte[(hexlen/2)];}int j=0;for (int i = 0; i < hexlen; i+=2){result[j]=hexToByte(inHex.substring(i,i+2));j++;}return result;}}

特别鸣谢:作者:溪云一片闲舒卷 的Android Studio下的串口程序开发实战

安卓开发板之串口通信,通过modbus Rtu协议控制下位机相关推荐

  1. ubuntu16.04下使用Modbus RTU协议控制Robotiq

    ubuntu16.04下使用Modbus RTU协议控制Robotiq 一.设备配置 二.创建工作空间 三.安装驱动 四.配置串口 五. ROS节点控制夹爪 六.RVIZ显示模型 一.设备配置 操作系 ...

  2. Android开发串口通信之开发板的串口通信

    本人最近刚开始学习android,学习大概将近一个月.学着学着突然想做个小东西出来.因为android前面的学习主要是UI 界面的学习,就想着做一个通信的串口 来实现app与外部的数据传输.通过界面的 ...

  3. 串行通讯RS485 Modbus RTU协议控制

    一.内容简介 本文主要介绍欧姆龙CP1E做上位与SMC的LECP6电缸 之间串行通讯RS485 Modbus RTU协议程序控制说明. 二.设备简介         硬件:CP1E.CP1W-CIF1 ...

  4. (实测可用)STM32CubeMX教程-STM32L431RCT6开发板研究串口通信(DMA)

    一.开发板平台简介: 1.开发板资源简介 (1)开发板主芯片型号:STM32L431RCT6 (2)开发板主芯片封装:LQFP-64_10x10x05P (3)开发板主芯片内核:ARM® Cortex ...

  5. (实测可用)STM32CubeMX教程-STM32L431RCT6开发板研究串口通信(SPI flash)

    一.开发板平台简介: 1.开发板资源简介 (1)开发板主芯片型号:STM32L431RCT6 (2)开发板主芯片封装:LQFP-64_10x10x05P (3)开发板主芯片内核:ARM® Cortex ...

  6. (实测可用)STM32CubeMX教程-STM32L431RCT6开发板研究串口通信(printf)

    一.开发板平台简介: 1.开发板资源简介 (1)开发板主芯片型号:STM32L431RCT6 (2)开发板主芯片封装:LQFP-64_10x10x05P (3)开发板主芯片内核:ARM® Cortex ...

  7. (实测可用)STM32CubeMX教程-STM32L431RCT6开发板研究串口通信(RS485)

    一.开发板平台简介: 1.开发板资源简介 (1)开发板主芯片型号:STM32L431RCT6 (2)开发板主芯片封装:LQFP-64_10x10x05P (3)开发板主芯片内核:ARM® Cortex ...

  8. (实测可用)STM32CubeMX教程-STM32L431RCT6开发板研究串口通信(串口发送函数)

    一.开发板平台简介: 1.开发板资源简介 (1)开发板主芯片型号:STM32L431RCT6 (2)开发板主芯片封装:LQFP-64_10x10x05P (3)开发板主芯片内核:ARM® Cortex ...

  9. Android 安卓开发板 读取串口

    本文转发自 https://www.logcg.com/archives/2831.html#comments 最近接了个工程,需求是给特制的工程安卓板子做串口读写以实现一些特定外接设备的互动--是的 ...

最新文章

  1. javascript案例_如何在JavaScript中使用增强现实-一个案例研究
  2. 怎么制作营销型网站才能有效提升优化效果?
  3. 用粑粑治疗自闭症!男孩接受6次粪菌移植,目前效果显著
  4. python有趣的小项目-有趣的十个Python实战项目,让你瞬间爱上Python!
  5. Berkeley DB——Database
  6. python中格式化_Python中格式化的两种方法
  7. getclass方法_防止数据重复提交的6种方法(超简单)!
  8. ibm量子计算机 申请,【IBM量子计算机问世,造福人类的杰作!】IBM量子计算机已面前全球开放申请使用_来自网易大神圈子_科学企图玄学...
  9. xadmin 组件拓展自定义使用
  10. RobotCup2D代码学习记录(二)
  11. Excel快速填充小技巧,这几个技能你会了吗
  12. 万能科学计算机app,万能科学计算器
  13. 再更新:2022 京东/淘宝双11活动一键自动完成任务脚本app来了,顺便说个事情...
  14. kjb文件 解析_Python 之父再发文:构建一个 PEG 解析器
  15. 快递空运材积大于重量的教训
  16. 12-Gateway新一代网关
  17. 如何防止恶意攻击短信验证码接口
  18. 离散数学:用python实现关系闭包的计算,即自反、对称与传递
  19. 裸函数 __declspec(naked)
  20. 【20天快速掌握Python】day10-面向对象基础

热门文章

  1. java发送 NameValuePair格式post请求
  2. 专科程序员“霸面”蚂蚁金服,4轮面试,竟拿下offer(Java方向)
  3. matlab符号表达式vpa,对MATLAB中符号和数值型数据以及sym(),sym(''),sym(,'d'),vpa()的理解【更新版】...
  4. 4.1 -Springboot 编写http接口
  5. 19级爪哇程序设计新手赛2.0(参考题解)
  6. 分开了,伤心了,后悔了
  7. SSD中,SATA、m2、PCIE和NVME各有什么意义
  8. CSharp生成二维条码的步骤
  9. Currency Translation in Bex Query Variable 2
  10. C语言进阶--万字讲解带你学会字符串函数