android串口通信—— 自动轮寻可以通信的串口

废话不多说,开撸代码。

  1. 用的是谷歌开源serialPort api ,下载链接
  2. 下载后全部导入项目中,什么也不用修改
  3. 写一个工具类SerialPortUtils,设置好波特率
  4. 记录开始发送时间和最后一次接收时间,用超时时间来判断串口是否能正常收发数据
  5. 如何连续三次超时就自动更换串口号,知道接收到数据为止

下面是具体的类,仅供参考


public class SerialPortUtils {

    private final String TAG = "SerialPortUtils";

    private final int baudrate = 38400;//波特率

    private boolean serialPortStatus = false; //是否打开串口标志

    private boolean threadStatus = false; //线程状态,为了安全终止线程

    private SerialPort serialPort = null;//串口
    private InputStream inputStream = null;
    private OutputStream outputStream = null;

    private int size; //读取数据的大小
    private Integer i = 0;
    private int j = 0;

    private long lastReceiveTime ;
    private long lastSendTime;
    private final long TIME_OUT = 10 * 1000;

    private static SerialPortUtils INSTANCE;
    private List<String> list=null;
    private SerialPortUtils() {
        // 记录创建对象时的时间
        lastReceiveTime = System.currentTimeMillis();
        lastSendTime = System.currentTimeMillis();
        openSerialPort();
    }

    public static synchronized SerialPortUtils getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new SerialPortUtils();
        }
        return INSTANCE;
    }


    /**
     * 打开串口
     *
     * @return serialPort串口对象
     */
    private void openSerialPort() {
      //  i=0;
        try {
            if (serialPort == null) {

                serialPort = new SerialPort(new File(ApiAddress.path), baudrate, 0);
                serialPortStatus = true;
                threadStatus = false; //线程状态

                //获取打开的串口中的输入输出流,以便于串口数据的收发
                inputStream = serialPort.getInputStream();
                outputStream = serialPort.getOutputStream();

                //开始线程监控是否有数据要接收
                new ReadThread().start();

                Tray.putString(MyApp.myApp,"chuankou",ApiAddress.path);
            }
        } catch (IOException e) {

            MainUtil.printLogger(TAG, "openSerialPort: 打开串口异常:" + e.toString());
        }

    }

    /**
     * 关闭串口
     */
    public void closeSerialPort() {
        try {
            inputStream.close();
            outputStream.close();

            serialPortStatus = false;
            threadStatus = true; //线程状态
            serialPort.close();
            serialPort = null;
        } catch (IOException e) {

            MainUtil.printLogger(TAG, "closeSerialPort: 关闭串口异常:" + e.toString());
        }

        MainUtil.printLogger(TAG, "closeSerialPort: 关闭串口成功");
    }

    /**
     * 发送串口指令(字符串)
     *
     * @param sendData String数据指令
     */
    public synchronized void sendSerialPort(byte[] sendData) {
        try {
            if (sendData.length > 0) {
                if (null != outputStream) {
                    outputStream.write(sendData);
                    outputStream.flush();
                    MainUtil.printLogger(TAG, "串口发送" + ByteHEXUtils.bytesTo_HexString(sendData));
                    lastSendTime = System.currentTimeMillis();
                }



                long miss = lastSendTime - lastReceiveTime;

                if (miss > TIME_OUT) {
                    //超时

                    i++;
                    if (i > 3) {
                        if (onChuankouListener != null) {

                            onChuankouListener.OnChuankouChange(2);
                        }
                        list=getDevices();
                        if(null!=list){
                            Tray.putString(MyApp.myApp,"chuankou",list.get(j));
                           serialPort = null;
                           openSerialPort();
                            j++;
                        }else {
                            if("/dev/ttyS1".equals(Tray.getString(MyApp.myApp, "chuankou", "/dev/ttyS2"))){
                                Tray.putString(MyApp.myApp,"chuankou","/dev/ttyS2");
                                serialPort = null;
                                openSerialPort();
                            }
                            if("/dev/ttyS2".equals(Tray.getString(MyApp.myApp, "chuankou", "/dev/ttyS2"))){
                                Tray.putString(MyApp.myApp,"chuankou","/dev/ttyS1");
                                serialPort = null;
                                openSerialPort();
                            }
                      }

                    }
                }

            }
        } catch (IOException e) {

            MainUtil.printLogger(TAG, "sendSerialPort: 串口数据发送失败:" + e.toString());
        }
    }

    private final StringBuffer sb = new StringBuffer();

    /**
     * 单开一线程,来读数据
     */
    private class ReadThread extends Thread {

        @Override
        public void run() {
            super.run();
            while (!threadStatus) {


                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                final byte[] buffer = new byte[256];
                // do something
                try {
                    size = inputStream.read(buffer);



                    String message = new String(ByteHEXUtils.bytesTo_HexString(buffer).getBytes(), 0, size * 2);

                    if (message.startsWith("FFFF") && message.endsWith("0D0A")) {
                        if (ByteHEXUtils.count(message, "FFFF") > 1) {

                            message = message.substring(message.lastIndexOf("FFFF"));

                        }


                        if (message.substring(message.length() - 6, message.length() - 4).equals(ByteHEXUtils.makeChecksum(message.substring(0, message.length() - 6))) && onDataReceiveListener != null) {

                            if (onChuankouListener != null) {
                                i = 0;
                                onChuankouListener.OnChuankouChange(1);
                                lastReceiveTime = System.currentTimeMillis();
                            }

                            MainUtil.printLogger(TAG, "串口回调" + message);
                            onDataReceiveListener.onDataReceive(message, size);


                        }
                        sb.setLength(0);
                    } else {
                        sb.append(message);

                        if (ByteHEXUtils.count(sb.toString(), "FFFF") > 1) {
                            String str = sb.toString();

                            sb.setLength(0);
                            sb.append(str.substring(str.lastIndexOf("FFFF")));

                        }
                        if (sb.toString().startsWith("FFFF") && sb.toString().endsWith("0D0A")) {

                            if (sb.substring(sb.length() - 6, sb.length() - 4).equals(ByteHEXUtils.makeChecksum(sb.substring(0, sb.length() - 6))) && onDataReceiveListener != null) {
                                lastReceiveTime = System.currentTimeMillis();
                                if (onChuankouListener != null) {
                                    i = 0;
                                    onChuankouListener.OnChuankouChange(1);
                                }
                                MainUtil.printLogger(TAG, "串口回调" + sb.toString());
                                onDataReceiveListener.onDataReceive(sb.toString(), size);
                            }
                            sb.setLength(0);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }


        }
    }

    private OnDataReceiveListener onDataReceiveListener = null;
    private OnChuankouChangeListener onChuankouListener = null;

    public interface OnDataReceiveListener {
        void onDataReceive(String buffer, int size);
    }

    public void setOnDataReceiveListener(OnDataReceiveListener dataReceiveListener) {
        onDataReceiveListener = dataReceiveListener;
    }

    // 自定义接口
    public interface OnChuankouChangeListener {
        void OnChuankouChange(int status);
    }

    public void setOnChuankouListener(OnChuankouChangeListener chuankouListener) {
        onChuankouListener = chuankouListener;
    }
    public List<String>getDevices() {

        if (null == list) {

            list = new ArrayList<>();

            File dev = new File("/dev");

            File[] files = dev.listFiles();

            int i;

            for (i = 0; i < files.length; i++) {

                if (files[i].getAbsolutePath().startsWith("/dev/ttyS")) {


                    MainUtil.printLogger(TAG, "Found new device: " + files[i]);

                    list.add(files[i].toString());

                }

            }
        }
        return list;
    }
}
  • 本工具类中有自动替换串口,知道可以通信为止的方法
  • 由于android端接收串口数据并不是一次性就可以全部接收到,有可能分两段,也有可能丢失,所有在接收消息的时候,我做了拼接校验,比如和板子开发人员确定好头部和尾部以及校验位,本工具类中头部是FFFF开头0D0A结尾的,对不符合的数据进行了舍弃,并及时清空缓冲区
  • 本工具类中Tray类似于共享参数,保存了串口路径,可以用SharedPreferences或者file代替
  • 如有不对请指正。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值