APP下载

一种融合USB-CDC与JNI技术的数据通信方式

2017-04-19张海峰徐杭男杨伟锋

单片机与嵌入式系统应用 2017年2期
关键词:调用底层串口

张海峰,徐杭男,杨伟锋

(杭州电子科技大学 电子信息学院,杭州 310018)

一种融合USB-CDC与JNI技术的数据通信方式

张海峰,徐杭男,杨伟锋

(杭州电子科技大学 电子信息学院,杭州 310018)

本文采用STM32F407为主控制器,根据板载USB接口的特点,设计基于通信设备类(CDC)的USB通信传输模块,然后在裁减配置好的Android系统上利用多线程读取由STM32采集到的原始数据并作处理;STM32利用ST公司提供的驱动程序,实现以USB设备为虚拟串口,利用Android源码编译Android程序的JNI部分的链接库文件以串行总线(COM)方式达到访问底层USB端口的目的。实验结果表明,该采集传输方式在数据稳定高速传输上性能显著。

STM32F407;Android;USB-CDC;虚拟串口

引 言

在声学测量领域,声信号A/D转化后的数据必须保证实时性稳定传输,并且不发生丢包现象。只有传输数据能快速稳定,才能对后续连续频谱化分析影响降低至最小化。Cortex-M4架构的ARM处理器集结了高性能、低功耗、外设资源丰富且廉价等优点[1-2];而Android系统是基于Linux系统,源码公开[3],可依据喜好裁减;USB的通用串行总线具有高传输速率、支持热插拔等优点[4]。综合以上,本文提出了结合Android系统板和STM32板载USB模块的声信号采集传输技术,在Android系统端编写APP,以多线程的方式和JNI库函数实现数据接收,使整机系统更符合当下人机关系[5-6]。

1 系统设计

整体系统结构框架图如图1所示,该系统主要由底层系统采集传输和上层系统接收处理构成。底层系统采集传输模块通过STM32F407处理器、电源模块、声信号放大与A/D采集模块、电平转换模块等组成下位机;上层系统接收处理模块通过访问USB虚拟串口,实现数据接收和处理。

图1 系统框图

8 MHz外部晶振倍频为168 MHz后作为微处理器主频,168 MHz再经过分频后得到精确的48 MHz作为USB通信时钟,专用PLLI2S为I2S接口实现高品质音频性能提供了保障;为了满足转换的量程要求,模拟信号经过信号调理模块,利用OP2177和THS4521构成的二级放大器作为输入衰减器,量程的切换可通过控制光耦通断来实现;信号稳定后由专业的A/D音频芯片PCM1861进行A/D转换,将采集的原始数据以I2S协议发送到STM32F407;STM32板载USB模块以热插拔的方式接入Android系统中,在Android系统会出现一个虚拟COM串口,通过把Linux底层的read函数封装成JNI函数库,用JAVA的API接口去读取传输通道的数据。虚拟串口由下位机USB枚举产生,作为大批量数据传输通道。

1.1 STM32F407与Exynos4412

STM32F4系列包含了众多高性能的外设,尤其常用于高速、大容量的分布式数据采集系统,本文中采用的STM32F407包含2个DMA控制器(总共16个数据流),每个数据流多达8个通道、17个定时器、3个I2C接口、3个SPI接口,支持USB2.0高速传输[1-2]。除此之外,多达1 MB的Flash内存和196 KB的SRAM满足大批量数据采集缓存的需求。而Exynos4412作为四核处理器,拥有1.6 GHz主频,GPU Mali-400MP,同时辅以2 GB运行内存,满足数据高效处理需求,运行Android系统不会有卡滞的情况。

1.2 USB数据接口类和通信接口类

通用串行总线(USB)是当下计算机连接外部设备装置的一个高速串行通信协议标准[7],比如OTG方式使USB设备间能够独立地进行数据交换。常见的USB设备类如HID(Human Interface Device)和CDC(Communication Device Class)在安卓系统上自带了驱动程序,因此只要配置好Android的Linux内核支持上述功能即可使用。因为HID的传输速度很有限,在高速模式下传输速度也不过64 kbps,因此为了提高传输速率,采用USB-CDC协议来完成Android与STM32之间的USB通信。

USB-CDC是由通信接口类和数据接口类组合而成的。只需要为CDC类添加数据接口类,并且为数据接口添加一对批量传输模式(Bulk Transfer)的输入端点和输出端点就能完成基本数据收发功能。首先USB设备被USB Core所识别和描述,然后将信息上传至tty协议层,最后通过线路规程的方式,将tty协议层和USB协议层结合使用。Android中SDK并没有开发CDC特定的API,但是通过USB相关的操作,如设备枚举、设备打开、接口操作、端口操作等完成CDC类的数据批量传输。图2所示是Android与STM32的USB设备通信图。

图2 Android与STM32的USB设备通信图

2 软件设计

声信号数据接收过程主要包含了STM32下 USB传输过程、Android的底层JNI库函数开发和上位机接收过程。

2.1 STM32下USB传输过程

STM32板载的USB模块为了识别COM端口,需要根据CDC规范编写程序。一般传输类型有:控制传输、块传输、中断传输和同步传输。比较4种传输方式,适合少量数据传输,且对传输时间和速率都不要求的是控制传输;适合大量数据,但对时间和速率不要求的是块传输;中断传输适合少量或者中量且对传输时间有要求的数据;同步传输适合大量数据传输且速率恒定,对时间有要求。由于STM32F407封装了USB-CDC的函数库,所以只需要调用应用程序接口层中的代码,配置设备端口响应Android的USB主机的读写请求,获得USB设备与USB主机的连接,初始化USB传输模式为同步传输类型,然后开始数据采集,设计数据枚举成功标志位,当枚举成功的时候才能发送数据。该过程的数据采集发送流程图如图3所示。

图3 数据采集发送流程图

2.2 Android的底层JNI库函数开发

Android基于Linux的开源系统,要对串口进行操作读写,就要使用在用户空间执行的API接口,使其能够在Linux应用层对底层串口设备进行读写、控制等操作,这就需要JNI的封装库。JNI程序虽然遵循C/C++程序的语法,但此程序要作为Android程序的SO库文件调用,需要作一些改变。首先如同Linux访问串口的应用程序一样,进行波特率通信格式的初始化,设置串口数据位、停止位和校验位。然后打开USB设备节点名称,可在JAVA层以函数参数传入,清除输入输出缓冲区,配置设备把终端属性设置成原始属性,创建read、write、close、open等本地函数供JAVA层调用,因为在本文研究只需要高速发送数据,所以将新建内存空间用来存取读取数据,再拷贝到JAVA传入的用来存储接收数据的字节型数组中。为了匹配JAVA层需要调用的本地方法与C/C++层的方法,需要进行相应的匹配,过程如下:

static const JNINativeMethod methods[] = {

{"Open","(Ljava/lang/String;I)I",(void *)Java_com_example_xhn_datafromanlog_Open },

{"Setopt","(IIICI)I",(void *)Java_com_example_xhn_datafromanlog_Setopt },

{"Close","(I)I",(void *)Java_com_example_xhn_datafromanlog_Close },

{"Write","(I[BI)I",(void *)Java_com_example_xhn_datafromanlog_Write },

{"Read","(I[B)I",(void *)Java_com_example_xhn_datafromanlog_Read },

};

实现JNI_OnLoad的注册:

if ((*env)->RegisterNatives(env,cls,methods,sizeof(methods)/sizeof(methods[0]))< 0)

使用C/C++语言依次实现USB设备的打开、初始化、读、关闭操作,具体如下所示:

① 波特率通信格式转换的本地函数

Java_com_example_xhn_datafromanlog_Setopt(JNIEnv *env,jobject cls,jint fd,jint nSpeed,jint nBits,jchar nEvent,jint nStop);

② 打开串口的函数

Java_com_example_xhn_datafromanlog_Open(JNIEnv *env,jobject cls,jstring filename,jint flag);

③ 关闭串口的函数

Java_com_example_xhn_datafromanlog_Close(JNIEnv *env,jobject cls,jstring filename,jint flag);

④ 读取底层数据的函数

Java_com_example_xhn_datafromanlog_Read(JNIEnv *env,jobject cls,jint fd,jbyteArray buf);

最后将JNI文件放入Linux环境下的Android原生代码,运行命令“arm-linux-gcc-fPIC-shared uartcontrol.c-o libuartcontrol.so-I/usr/lib/jvm/java-1.7.0-openjdk-amd64/include/-nostdlib/work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/libc.so”,可以生成JAVA调用的uartcontrol.so库文件。

2.3 上位机接收过程处理

利用多线程应用编程,开启单独一个线程循环读取底层数据,主要利用面向对象的方式,封装JNI库里的本地函数进行调用,关键是在Android Studio中加载libuartcontrol.so函数库,利用“System.loadLibrary(“uartcontrol”)”和“nread=UartControl.Read(devfd,buf_read)”完成数据收取。最后将读取的数据在另外一个线程新建内存存储,然后调用Zoom-FFT算法进行频谱、频率计权处理,在界面进行绘图等。

3 测试结果分析

本系统在Android启动时,设置用户权限模式为系统用户,首先通过PC机的上位机可以查找到STM32的USB设备被识别为/dev/usb/tty1-2.3,正如同前文所论述的那样是通过产品ID和厂商ID进行过滤匹配USB设备的,如图4中圈出所示。

图4 USB设备节点图

STM32在通过PC机模拟虚拟串口接收时,可以清楚看到数据并没有发生丢包的现象,在串口调试助手看到USB设备发送的A/D数据。显示的信息具体如图5所示。

图5 PC总线模拟接收图

一般24位音频A/D在双通道8位模式下的采样个数为 24K×2×8=384K个数据,通过整机系统联调,在Android Studio软件的打印信息中可以看见logcat窗口栏每秒打印的个数基本在384 000个,验证了数据传输的高速稳定性与可靠性,基本与理论值一致。具体每秒实时收到的字节数如图6所示。在数据没有丢失的情况下,本文在测试时输入频率为1000 Hz,幅度为10 V,幅度衰减为39 dB的正弦信号,测试显示如图7所示,完美的正弦曲线可以显示在Android平台里,并没有发生断层或者缺失,由此验证了这种传输方式的可靠性。

图6 USB-CDC数据通信速率曲线

图7 系统显示测试

结 语

[1] STMicroelectronics.STM32F10XXX USB development Kit,2008.

[2] STMicroelectronics.ARM based 32-bit MCU STM32F101xx and STM32F103xx firmware library User manual,2008.

[3] 罗升阳.Android系统源代码情景分析[M].北京:电子工业出版社,2012.

[4] 宋宝华.Linux设备驱动开发详解[M].2版.北京:人民邮电出版社,2010.

[5] 王立萍,吴黎明.基于嵌入式的USB数据采集系统的设计开发[J].电子测量技术,2007,30(9):42-46.

[6] 罗钧,桂杰出.USB协议及其接口实现[J].仪器仪表学报,2004(4).

[7] 吴明琪,马潮.嵌入式系统的USB虚拟串口设计[J].单片机与嵌入式系统应用,2005(4):62-63,66.

张海峰(副教授),主要研究方向为物联网应用与嵌入式开发;徐杭男、杨伟锋(硕士研究生),主要研究方向为电子与通信工程。

Data Communication Method Combining USB-CDC and JNI Technology

Zhang Haifeng,Xu Hangnan,Yang Weifeng

(School of Electronics Information,Hangzhou Dianzi University,Hangzhou 310018,China)

In the paper,the STM32F407 is used as the control core,according to the characteristics of on-board USB interface,a USB communication transmission module based on communication equipment class(CDC) is proposed.Then,the Android system which is well configured reads the original data collected by STM32 using the multi thread.The STM32 uses the USB driver provided by ST to change USB device to virtual serial port,and compiles JNI program which is loaded read USB port by the way of COM in the environment of Android source code.The experiment results show that the method is significant in data stable and high-speed transmission.

STM32F407;Android;USB-CDC;virtual port

TP391

A

�士然

2016-09-20)

猜你喜欢

调用底层串口
航天企业提升采购能力的底层逻辑
浅谈AB PLC串口跟RFID传感器的通讯应用
核电项目物项调用管理的应用研究
LabWindows/CVI下基于ActiveX技术的Excel调用
基于系统调用的恶意软件检测技术研究
数字电源内部数据传输的串口通信方法实现
USB接口的多串口数据并行接收方法探索
基于蓝牙串口适配器的GPS接收机与AutoCAD的实时无线通信
回到现实底层与悲悯情怀
中国底层电影研究探略