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

废话不多说,开撸代码。

用的是谷歌开源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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358