android串口通信

本文介绍了如何在Android应用中使用usb-serial-for-android库进行串口通信,通过步骤演示如何配置Gradle、添加权限、编写代码来读取USB设备(七合一空气采样模块)的数据,并在UI上实时显示温度。关键点在于处理低波特率导致的数据接收频率以及如何识别和解析协议数据。

开始学android,在串口上卡了十几个小时后靠GitHub解放了我。

首先是这个库:

https://github.com/mik3y/usb-serial-for-android

按照大佬的指示,第一步添加库引用:

Add jitpack.io repository to your root build.gradle:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

Add library to dependencies

dependencies {
    implementation 'com.github.mik3y:usb-serial-for-android:3.4.2'
}

使用新版android studio的时候要注意,

maven { url 'https://jitpack.io' }

这段代码要放在setting.gradle里面。。。不然会报错说找不到。

第二步添加程序读写USB的权限。在自己的AndroidManifest.xml里面加如下内容。

<activity
    android:name="..."
    ...>
    <intent-filter>
        <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
    </intent-filter>
    <meta-data
        android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
        android:resource="@xml/device_filter" />
</activity>

然后在studio中新建device_filter.xml文件,如下图

第三步,开始写代码

代码很简单,两按钮,一个打开串口一个关闭串口。打开串口后根据协议读温度显示在TextView上。串口七合一空气采样模块的说明和购买链接见https://item.taobao.com/item.htm?spm=a230r.1.14.24.61c02c16A0NTtD&id=568535232415&ns=1&abbucket=3#detail

public class MainActivity extends AppCompatActivity {
    UsbSerialPort port;
    SerialInputOutputManager usbio;
    ArrayList<Byte> buffer;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btn_openport=(Button) this.findViewById(R.id.open_port);
        TextView tx=(TextView) this.findViewById(R.id.serial_data);
        btn_openport.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
                List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
                if (availableDrivers.isEmpty()) {
                    return;
                }

                // Open a connection to the first available driver.
                UsbSerialDriver driver = availableDrivers.get(0);
                UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
                if (connection == null) {
                    // add UsbManager.requestPermission(driver.getDevice(), ..) handling here
                    return;
                }

                port = driver.getPorts().get(0); // Most devices have just one port (port 0)
                try{
                    port.open(connection);
                    port.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
                    Log.i("port","open success");
                    buffer=new ArrayList<Byte>();
                    usbio=new SerialInputOutputManager(port, new SerialInputOutputManager.Listener() {
                        @Override
                        public void onNewData(byte[] data) {
                            Log.i("port read size",String.valueOf(data.length));
                            if(data.length>0){
                                for(int i=0;i<data.length;i++){
                                    buffer.add(data[i]);
                                    Log.i("port read",String.valueOf(data[i]));
                                }
                                if(buffer.size()>=17){
                                    for(int i=0;i<buffer.size();i++){
                                        if(buffer.get(i)==0x3c && buffer.get(i+1)==0x02 && (i+17)<=buffer.size()){
                                            Log.i("tmp",String.valueOf(buffer.get(i+12)));
                                            String temp=String.valueOf(buffer.get(i+12))+"."+String.valueOf(buffer.get(i+13));
                                            runOnUiThread(() -> {tx.setText(temp);});//把温度显示在UI上,中断函数不允许操作UI,所以要另开一个线程
                                            buffer.clear();
                                        }
                                    }
                                }
                            }
                        }

                        @Override
                        public void onRunError(Exception e) {

                        }
                    });
                    usbio.start();


                }
                catch (IOException e){

                }



            }
        });
        Button btn_closeport=(Button) this.findViewById(R.id.close_port);
        btn_closeport.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try{
                    usbio.stop();
                    port.close();
                    Log.i("port","close port");
                }
                catch (IOException e){

                }

            }
        });
    }
}

需要注意的就是onNewData基本上每来1个字节就触发一次,因为9600的波特率太低了,1ms来一个字节。。。所以需要自己维护一个数组或者队列,当数组或队列的长度足够大且检测到有一串完整协议数据的时候读出温度值 。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值