美文网首页Android进阶之路Android开发Android开发经验谈
android串口通信—— 自动轮寻可以通信的串口

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

作者: 花椒粑粑_27a4 | 来源:发表于2020-05-08 16:38 被阅读0次

    废话不多说,开撸代码。

    用的是谷歌开源serialPort api ,下载链接

    下载后全部导入项目中,什么也不用修改

    写一个工具类SerialPortUtils,设置好波特率

    记录开始发送时间和最后一次接收时间,用超时时间来判断串口是否能正常收发数据

    如何连续三次超时就自动更换串口号,知道接收到数据为止

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

    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代替

    如有不对请指正。

    我的csdn地址: https://blog.csdn.net/u011847849/article/details/105999406

    相关文章

      网友评论

        本文标题:android串口通信—— 自动轮寻可以通信的串口

        本文链接:https://www.haomeiwen.com/subject/awofnhtx.html