Android硬流控(CTS|RTS)的调试

文章讲述了作者在安卓设备上进行串口调试的需求,遇到Android10上访问/proc/tty/drivers权限问题,通过降低编译和目标SDK版本解决了问题。还介绍了如何使用CTS和RTS进行硬件流控的实现过程。
摘要由CSDN通过智能技术生成

一.为什么做这个事  

      这个事情的前提,最近有个需求需要通过安卓设备进行串口调试,还要在使用RS232硬流控功能,直接调试过一些串口的例子,主要是基于google开源的串口助手,但是大部分都不包含流控功能。就在github是找了一个带流控的案例进行测试和调试。

参考项目地址Android-Serialport

二.遇到的问题

        首先是把这个项目clone下来编译,一切ok,在安卓8版本上运行没发现什么问题,但是在安卓10上出现权限问题,无法访问“ /proc/tty/drivers”

LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));

报错代码这一行,多次尝试和查找解决问题,把项目的编译版本降低

compileSdk 29
defaultConfig {
    applicationId "com.ex.serialport"
    minSdk 14
    targetSdk 29
    versionCode 1
    versionName "1.0"
}

compileSdk 29和targetSdk 29从33降到了29后不再报错。

参考java.io.FileNotFoundException: /proc/tty/drivers: read failed: EACCES (Permission denied)_Engineer-Jsp的博客-CSDN博客

这个问题解决后测试可以正常开启流控。

三.CTS和RTS控制

        但是要用硬流控我需要测试设备是否真正具有流控功能。那就需要添加一个CTS和TRTS的控制,这部分代码需要在jni进行控制

安卓端设置RTC,设置为false后,安卓端电平拉低,不再接收数据,电脑端无法发生数据。

    public native void setRTC(boolean isOpen);
JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_setRTC
        (JNIEnv *env, jobject thiz,jboolean isOpen) {
    jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);
    jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor");

    jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd", "Ljava/io/FileDescriptor;");
    jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I");

    jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);
    jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);
    int rts_flag = TIOCM_RTS;
    if (isOpen){
        // 设置 RTS 信号(发送方准备好发送)
        ioctl(descriptor, TIOCMBIS, &rts_flag);
    } else{
        //         清除 RTS 信号
        ioctl(descriptor, TIOCMBIC, &rts_flag);
    }
    int rst_state ;
    ioctl(descriptor, TIOCMGET, &rst_state);
    if (rst_state & TIOCM_RTS) {
        LOGE("RTS signal is high\n");  // 接收方准备好接收
    } else {
        LOGE("RTS signal is low\n");   // 接收方未准备好接收
    }
}

读取CTS状态,CTS是由电脑端的RTS控制

    public native boolean startCTSListener();

// 开始监听 CTS 信号状态
JNIEXPORT jboolean JNICALL Java_android_1serialport_1api_SerialPort_startCTSListener(JNIEnv *env,
                                                                              jobject thiz) {
    // 获取 Java 回调对象
    jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);
    jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor");

    jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd", "Ljava/io/FileDescriptor;");
    jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I");

    jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);
    jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);

    // 在这里实现 CTS 信号状态监听逻辑,类似上面的 C 代码

    // 获取CTS信号状态
    int cts_flag;
    ioctl(descriptor, TIOCMGET, &cts_flag);
    int current_cts_state = (cts_flag & TIOCM_CTS) ? 1 : 0;
    // CTS信号状态变化时输出
    if (current_cts_state) {
        LOGE("CTS signal is high - Ready to receive\n");
    } else {
        LOGE("CTS signal is low - Not ready to receive\n");
    }
    return current_cts_state;
}

在串口打开的时候开始循环去读取CTS状态


    private class CTSThread
            extends Thread {
        private CTSThread() {
        }

        public void run() {
            super.run();
            while (!isInterrupted()&&isOpen()) {
                    CTSIsOpen(mSerialPort.startCTSListener());
                try {
                    sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

没有做太多的修改,这里就不贴源码了,可以看上面git地址的,另外

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值