Android 之 串口通信

阅读前提:串口通信是单片机采用RS232与Android板进行通信,首先要了解RS232发送数据的工作原理:RS232发送数据的时候是通过一个字节接着一个字节,将数据发送出去,所以当接收数据时候也应当一个字节一个字节接受

在AndroidManifest.xml中加入权限

/*允许程序对SD卡进行写入*/
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
/*允许程序对SD卡进行读取*/
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

1.登陆GitHub下载android-serialport-api

下载地址:GitHub-android-serialport-api


项目目录

①首先,在main的文件夹中新建一个叫android_serialport_api的文件夹,并且把android_serialport_api中的中的SerialPort中的文件复制到文件夹

②新建一个jni和jniLibs的文件夹,把android_serialport_api对应的文件复制过来

2.建立SerialPortUtil单例模式

这里简单介绍:

详细请看:StormZhang的Android设计模式之单例模式

单例模式:单例模式就是保证你全局有且只有这个类的一个实例,这个实例可以在全局使用,并且这个实例会为全局提供访问的节点

全局的概念:全局在这里可以理解为整一个Application,这个类在整个Application中永远只会被实例化一次(即new),当JVM检测到这个实例不再使用就会被垃圾回收机制回收了,那么当代码运行到需要这个实例的时候,发现这个实例不存在就会把这个类再实例化一次,这样就保证了内存中只有一个类的实例而不是多个实例

为什么类只实例化一个:这里涉及到一个内存的使用的问题,如果一个类被实例化了多次,在内存中就会占有多个同一个类的多个实例,这样就浪费内存,减慢代码运行效率。只使用一个实例可以节省内存,提高代码的运行效率。

在我这里使用的是一个叫懒汉模式的单例模式

public class SerialPortUtil {   
    //这个就是需要被实例化的类
    private static SerialPortUtil INSTANCE = null;
    //这里必须需要一个私有的构造器
    private SerialPortUtil(){

    }
    //这里为全局提供访问的节点
    public static SerialPortUtil getInstance(){
        //涉及延时加载,当需要这个类的时候才会被实例化
        if (INSTANCE == null){

            INSTANCE = new SerialPortUtil();
        }

        return INSTANCE;
    }
}

当对串口进行数据的通信时候,进行四个步骤:①打开串口、②发送数据、③接受数据、④关闭串口

    //打开串口
    private void openSerialPort(){

        try {
            /*设置打开的串口*/
            final String portPath = "/dev/ttyS0";
            /*设置波特率*/
            final int baudRate = 115200;

            serialPort = new SerialPort(new File(portPath),baudRate,0);
            outputStream = serialPort.getOutputStream();
            inputStream = serialPort.getInputStream();

            /*开启线程读取数据*/
            new ReadThread().start();

        }catch (IOException e){

            e.printStackTrace();
        }

    }

    //关闭串口
    private void closeSerialPort(){

        try{

            inputStream.close();
            outputStream.close();
            serialPort.close();

        }catch (IOException e){

            e.printStackTrace();
        }
    }

    //发送数据
    private void sendDataToSerialPort(byte[] data){

        try{

            int dataLength = data.length;
            Log.d("DATASIZE",String.valueOf(dataLength));

            if(dataLength > 0){

                outputStream.write(data);
                outputStream.write('\n');
                outputStream.flush();
            }

        }catch (IOException e){

            e.printStackTrace();
        }
    }

    //接收数据的线程
    private class ReadThread extends Thread {

        @Override
        public void run() {
            super.run();
            while(!isInterrupted()) {
                int size;
                try {
                    byte[] buffer = new byte[64];
                    if (inputStream == null) return;
                    size = inputStream.read(buffer);
                    if (size > 0) {
                            SCMDataReceiveListener.dataRecevie(buffer, size);//监听数据的传输
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    return;
                }
            }
        }
    }

接收数据通过接口进行接收数据

    //设置监听接口
    public void setSCMDataReceiveListener(SCMDataReceiveListener SCMDataReceiveListener) {

        this.SCMDataReceiveListener = SCMDataReceiveListener;
    }

3.SerialPortUtil源码

public class SerialPortUtil {

    private static SerialPortUtil INSTANCE = null;
    private SerialPort serialPort;
    private OutputStream outputStream;
    private InputStream inputStream;
    private SCMDataReceiveListener SCMDataReceiveListener;

    private SerialPortUtil(){

    }

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

    public void setSCMDataReceiveListener(SCMDataReceiveListener SCMDataReceiveListener) {
        this.SCMDataReceiveListener = SCMDataReceiveListener;
    }

    private void openSerialPort(){

        try {

            final String portPath = "/dev/ttyS0";
            final int baudRate = 115200;

            serialPort = new SerialPort(new File(portPath),baudRate,0);
            outputStream = serialPort.getOutputStream();
            inputStream = serialPort.getInputStream();

            new ReadThread().start();

        }catch (IOException e){

            e.printStackTrace();
        }

    }

    public void closeSerialPort(){

        try{

            inputStream.close();
            outputStream.close();
            serialPort.close();

        }catch (IOException e){

            e.printStackTrace();
        }
    }

    private void sendDataToSerialPort(byte[] data){

        try{

            int dataLength = data.length;
            Log.d("DATASIZE",String.valueOf(dataLength));

            if(dataLength > 0){

                outputStream.write(data);
                outputStream.write('\n');
                outputStream.flush();
            }

        }catch (IOException e){

            e.printStackTrace();
        }
    }

    private class ReadThread extends Thread {

        @Override
        public void run() {
            super.run();
            while(!isInterrupted()) {
                int size;
                try {
                    byte[] buffer = new byte[1];
                    if (inputStream == null) return;
                    size = inputStream.read(buffer);
                    if (size > 0) {
                        /*监听数据接收*/
                        SCMDataReceiveListener.dataRecevie(buffer, size);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    return;
                }
            }
        }
    }

}

4.设置串口监听回调接口

public interface SCMDataReceiveListener {
    void dataRecevie(byte[] data,int size);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值