CH340与Android串口通信

CH340与Android串口通信

    • 为何要将CH340的ATD+Eclipse上的安卓工程移植到AndroidStudio
    • 移植的具体步骤
    • CH340串口通信驱动函数
    • 通信过程中重难点
    • 还存在的问题
    • CH340与Android串口通信问题的解答与思考
    • 从安卓端从接收数据到发送数据的时延。
    • CH340与安卓设备通信误码率
    • 总结

为何要将CH340的ATD+Eclipse上的安卓工程移植到AndroidStudio

为了在这个工程基础上进行改动,验证串口的数据和配置串口的参数,我首先在Eclipse上配置了安卓开发环境,注意在配置环境是需要下载一些支持包,SDK等需要科学上网,配置好环境后无法生成APK文件,找不到问题的解决方案,所以遂决定将这个工程移植到AS中。
首先在博客中找到了一些将Eclipse工程移植到AS上的方法,尝试后没有成功,可能是基础较差,出现了一些新的问题不知道怎么解决,所以我打算按照自己的方法尝试移植。

移植的具体步骤

  1. 首先我们必须明确在原ADT工程下哪些文件是必须并独特的,哪些文件是系统自动生成的,不需要复制的。
    重点文件与目录: src libs res androidManifest.xml
    需要复制的文件:
    1:src目录 MainActivity.java MyApp.java
    2:res目录 drawable/icon.png layout/main.xml my_spinner_textview.xml values/strings.xml xml/device_filter.xml
    3:libs目录 CH34xUARTDriver.jar
  2. 新建一个空白工程,布局文件使用 layout/main.xml my_spinner_textview.xml 注意将res中上述提到的文件也要复制到AS中res目录中,重复的选择覆盖。
  3. 将CH34xUARTDriver.jar粘贴到AS的libs中,选中点击右键,选择Add as libar…,完成后可以看见build.gradle中会添加
    添加JAR包.jpg
  4. 将java文件粘贴到AS中的Java目录下。
    tips: 注意在AS中使用jar包时要导入,否则用不了包中所提供的类,即在上述的JAVA文件中需要加入,在Eclipse中不需要如此操作(import cn…CH34xUARTDriver)

在布局文件中可能有些rEC中某些res中的文件没有复制到AS中的目录下,可以根据系统报的错误或提示再去复制。
通过上述的步骤,这个工程即可在AS上修改编译打包。

CH340串口通信驱动函数

驱动函数有一个详细的PDF文档说明其中的各个函数与参数设置。

通信过程中重难点

项目中整个通信过程都是单向的,所以在这里主要讨论接收数据,并不涉及到发送数据。

驱动中接收函数是
CH340与Android串口通信_第1张图片
Tips:
JAVA是对类的操作,所以[] date输入没有数据,经过处理以后它就会存储缓冲区串口发送的数据。

在安卓工程中它开了一个线程,在线程中它的代码如下

 private class readThread extends Thread {

        public void run() {

            byte[] buffer = new byte[128];

            while (true) {

                Message msg = Message.obtain();
                if (!isOpen) {
                    break;
                }
                int length = MyApp.driver.ReadData(buffer, 128);
                if (length > 0) {
					String recv = toHexString(buffer, length);
//					String recv = new String(buffer, 0, length);
                    totalrecv += length;
//                    String recv = String.valueOf(totalrecv);
                    msg.obj = totalrecv;
                    handler.sendMessage(msg);
                }
            }
        }
    }

串口读取的原理:
串口中一级缓存是程序中写的,也就是上述代码中的buffer,与驱动程序无关,驱动程序是负责来一个字节,就把这个字节填入你开的一级缓存buffer中。
byte[] buffer = new byte[a]中的a与ReadData(buffer, b)中b辨析:
a:代表你开的字节的大小,b读取的字节数,即读取缓存去buffer中的字节数。
a、b取值的可能三种情况:

  1. a>b,buffer中[b+1,…]中的数据没有意义,不是从串口写入的数据。
  2. a=b,buffer中的数据全部都是串口发送的数据。
  3. a

实验中遇到的情况:

  1. 我把a=b,而且把它设置为128及以下时,传输会出现问题,同时APP会卡死,到256或更大时就会消除这个问题。
  2. a>b,a=256,b= 10,数据不会连续,buffer中[b+1,…]中的数据没有意义,下次再去读串口是继续从buffer[b+1,…]中的添加数据,还是从buffer[0]开始存,仍有问题,下次通过实验验证下。

还存在的问题

还是串口读取的问题,串口如何读取,保证数据的实时性,比如说,通过串口给你发个4个字节的数据标志,要你读到这个数据就做出举动(要保证实时性),但是如果a=b的话(目前只有这种方式能保证数据的正确性),每次都只能读定义的整个缓冲区的大小的话,当其实你缓冲区已经接收到了这4个特定的字节时,但是由于a=b,它只能等整个缓存区填满了才能读所有的数据在进行判断,这样的话对整个实时性造成了很大的影响,改如何解决?问题所在。

询问有关经验开发人员了解。

  1. android不断接收数据放入缓冲区,满了就会覆盖。所以要及时把数据提取出来,然后再对这些数据进行提取。
  2. 由于每次都得读取整个缓冲区的数据,每个缓冲区内的数据不一定是连续的,所有需要将提取后的数据进行拼接处理,这样才能够还原每一帧的信息。
    所以说安卓端没读一次串口数据必定是将整个缓冲区里面的数据全部拿出来,不存在说有缓冲区存了一半等中断信息标志,不过在这里我们可以自己设定缓存区的大小(太小发现不行),这样的话基本来说也可以实现某些特定的操作。

CH340与Android串口通信问题的解答与思考

在上一篇博文里,我提出了下列的问题:
还是串口读取的问题,串口如何读取,保证数据的实时性,比如说,通过串口给你发个4个字节的数据标志,要你读到这个数据就做出举动(要保证实时性),但是如果a=b的话(目前只有这种方式能保证数据的正确性),每次都只能读定义的整个缓冲区的大小的话,当其实你缓冲区已经接收到了这4个特定的字节时,但是由于a=b,它只能等整个缓存区填满了才能读所有的数据在进行判断,这样的话对整个实时性造成了很大的影响,改如何解决?问题所在。
在这里做出以下解答:

  1. 串口数据不是等到把缓冲区填满才读取,而是来多少读多少。
  2. a=b一定成立,否则会造成数据丢失。
    再看一下驱动程序官方文档中的ReadDate()函数:
    CH340与Android串口通信_第2张图片
    重点我们需要关注length参数,以及返回值——返回实际读取的字节,如果length即前面假设的b比实际开的缓冲区数组的大小小的话,就会造成串口过来的某些数据丢失。返回值,说明当调用函数去读取串口的数据时,并不用等到数据全部填满缓冲区再去读取。串口数据传入安卓端后,并不是等到把缓冲区填满后,安卓端才将数据取出来,而是它会读取所有的串口缓冲区,读取串口传来的所有数据,并返回它实际读到串口缓冲区中字节的大小,通过实验可以验证。
    选择stm32作为从设备,串口每间隔一秒发送100字节的数据,安卓端接收串口数据,接收缓冲区大小设为1024字节,并将接收到的所有数据总字节数显示出来。如果按照1假设,它会每隔10s左右在原有的数字上加1024,但是实验表明,数据显示会每隔一秒累加100。证明了它不是等待缓冲区满了再读,而是串口有数据来,它就会一直读,等待一段时间,数据没有了,它就会将它已经在缓冲区接收到的数据取出来。那么这个一段时间又是多久了,间隔多少时间,它会将这段数据分为多段?需要测试,不过上述的1s是满足这样的要求的。

从安卓端从接收数据到发送数据的时延。

安卓接收到数据后立马返回一个数据,单片机端通过置io口的电平变化来显示这段时间延时。具体过程如下
单片机置A0为1,死循环先延时一秒,然后置A0为0,发送100个字节,按照1M波特率计算,这个时间为1毫秒,安卓端确认接受到100字节后,通过串口发送1个字节数据,单片机端串口接受到中断后将A0再置为1,这样整个低电平的时间=发送数据时间+延时时长+发送数据时长。通过示波器测量这个时间约为21毫秒。所以整个延时的时间为20毫秒,时延较长。将100字节改为1个字节,时延不变。通过此次实验,我们可以得出安卓端。。。为20毫秒。
CH340与安卓端串口通信的研究暂且到此为止,下面任有问题等待下一步解决:

  1. 串口有数据来,它就会一直读,等待一段时间,数据没有了,它就会将它已经在缓冲区接收到的数据取出来。那么这个一段时间又是多久了,间隔多少时间,它会将这段数据分为多段?
  2. 串口传输视频原始数据流,如何将这个数据包进行加工,能够让安卓设备播放这些视频,下一步项目工作重点。

CH340与安卓设备通信误码率

CH340按照datasheet说明,最大波特率为2M,经过具体测试,结果如下(连发计数器,接收端判断是否接收的也是计数器):

  1. 嵌入式设备与PC上位机通信,1.5M波特率时也没有误码,基本能够达到datasheet说明指标。
  2. 与安卓APP进行通信时,2.5K(附近典型值)波特率误码错码现象不存在,5.12K(典型值)波特率误码率接近5*10 - 7 次方,9K波特率误码率接近10-6次方,这种误码率现象体现在会缺失一段数据,也就是说一次误码中可能存在几十位数据的丢失。由于项目需要在1M波特率的情况下误码率小于10-7次方,所以通过CH340与安卓通信传输数据的方案基本失败。

总结

  1. CH340确实具有和安卓设备进行通信的功能,但是不能使用谷歌官方给的串口通信案例进行直接通信,需要底层驱动库,就相当于在PC端与CH340进行通信时还要安装驱动一样,在安卓APP工程中需要将底层的库依赖进去,这种库一般是出售CH340厂商提供的。
  2. 误码率问题,CH340与安卓进行通信时,经过测试发现,误码率特别严重,而且还是确实数据的情况,对通信的影响严重,具体指标测试结果已写出。
    本人水平有限,如有问题欢迎大家指正,谢谢。

你可能感兴趣的:(会议视频传输播放项目)