现在的位置: 首页 > 综合 > 正文

【Android应用开发】-(19)Android 串口编程原理和实现方式(附源码) Android应用开发】-(19)Android 串口编程原理和实现方式(附源码)

2013年08月27日 ⁄ 综合 ⁄ 共 5435字 ⁄ 字号 评论关闭

Android应用开发】-(19)Android 串口编程原理和实现方式(附源码)

  提到串口编程,就不得不提到JNI,不得不提到JavaAPI中的文件描述符类:FileDescriptor。下面我分别对JNI、FileDescriptor以及串口的一些知识点和实现的源码进行分析说明。这里主要是参考了开源项目android-serialport-api

    串口编程需要了解的基本知识点:对于串口编程,我们只需对串口进行一系列的设置,然后打开串口,这些操作我们可以参考串口调试助手的源码进行学习。在Java中如果要实现串口的读写功能只需操作文件设备类:FileDescriptor即可,其他的事都由驱动来完成不用多管!当然,你想了解,那就得看驱动代码了。这里并不打算对驱动进行说明,只初略阐述应用层的实现方式。

 

(一)JNI:

    关于JNI的文章网上有很多,不再多做解释,想详细了解的朋友可以查看云中漫步的技术文章,写得很好,分析也很全面,那么在这篇拙文中我强调3点:

    1、如何将编译好的SO文件打包到APK中?(方法很简单,直接在工程目录下新建文件夹 libs/armeabi,将SO文件Copy到此目录即可)

    2、命名要注意的地方?(在编译好的SO文件中,将文件重命名为:libfilename.so即可。其中filename.so是编译好后生成的文件)

    3、MakeFile文件的编写(不用多说,可以直接参考package/apps目录下用到JNI的相关项目写法)

    这是关键的代码:

 

  1. <span style="font-size:18px;">        int fd;  
  2.         speed_t speed;  
  3.         jobject mFileDescriptor;  
  4.   
  5.         /* Check arguments */  
  6.         {  
  7.                 speed = getBaudrate(baudrate);  
  8.                 if (speed == -1) {  
  9.                         /* TODO: throw an exception */  
  10.                         LOGE("Invalid baudrate");  
  11.                         return NULL;  
  12.                 }  
  13.         }  
  14.   
  15.         /* Opening device */  
  16.         {  
  17.                 jboolean iscopy;  
  18.                 const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);  
  19.                 LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags);  
  20.                 fd = open(path_utf, O_RDWR | flags);  
  21.                 LOGD("open() fd = %d", fd);  
  22.                 (*env)->ReleaseStringUTFChars(env, path, path_utf);  
  23.                 if (fd == -1)  
  24.                 {  
  25.                         /* Throw an exception */  
  26.                         LOGE("Cannot open port");  
  27.                         /* TODO: throw an exception */  
  28.                         return NULL;  
  29.                 }  
  30.         }  
  31.   
  32.         /* Configure device */  
  33.         {  
  34.                 struct termios cfg;  
  35.                 LOGD("Configuring serial port");  
  36.                 if (tcgetattr(fd, &cfg))  
  37.                 {  
  38.                         LOGE("tcgetattr() failed");  
  39.                         close(fd);  
  40.                         /* TODO: throw an exception */  
  41.                         return NULL;  
  42.                 }  
  43.   
  44.                 cfmakeraw(&cfg);  
  45.                 cfsetispeed(&cfg, speed);  
  46.                 cfsetospeed(&cfg, speed);  
  47.   
  48.                 if (tcsetattr(fd, TCSANOW, &cfg))  
  49.                 {  
  50.                         LOGE("tcsetattr() failed");  
  51.                         close(fd);  
  52.                         /* TODO: throw an exception */  
  53.                         return NULL;  
  54.                 }  
  55.         }  
  56. </span>  


 

(二)FileDescritor:

 

    文件描述符类的实例用作与基础机器有关的某种结构的不透明句柄,该结构表示开放文件、开放套接字或者字节的另一个源或接收者。文件描述符的主要实际用途是创建一个包含该结构的FileInputStream FileOutputStream。这是API的描述,不太好理解,其实可简单的理解为:FileDescritor就是对一个文件进行读写。

(三)实现串口通信细节

1)  建工程:SerialDemo包名:org.winplus.serial,并在工程目录下新建jni和libs两个文件夹和一个org.winplus.serial.utils,如下图:


 

2) 新建一个类:SerialPortFinder,添加如下代码:

 

  1. <span style="font-size:18px;">package org.winplus.serial.utils;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileReader;  
  5. import java.io.IOException;  
  6. import java.io.LineNumberReader;  
  7. import java.util.Iterator;  
  8. import java.util.Vector;  
  9.   
  10. import android.util.Log;  
  11.   
  12. public class SerialPortFinder {  
  13.   
  14.     private static final String TAG = "SerialPort";  
  15.   
  16.     private Vector<Driver> mDrivers = null;  
  17.   
  18.     public class Driver {  
  19.         public Driver(String name, String root) {  
  20.             mDriverName = name;  
  21.             mDeviceRoot = root;  
  22.         }  
  23.   
  24.         private String mDriverName;  
  25.         private String mDeviceRoot;  
  26.         Vector<File> mDevices = null;  
  27.   
  28.         public Vector<File> getDevices() {  
  29.             if (mDevices == null) {  
  30.                 mDevices = new Vector<File>();  
  31.                 File dev = new File("/dev");  
  32.                 File[] files = dev.listFiles();  
  33.                 int i;  
  34.                 for (i = 0; i < files.length; i++) {  
  35.                     if (files[i].getAbsolutePath().startsWith(mDeviceRoot)) {  
  36.                         Log.d(TAG, "Found new device: " + files[i]);  
  37.                         mDevices.add(files[i]);  
  38.                     }  
  39.                 }  
  40.             }  
  41.             return mDevices;  
  42.         }  
  43.   
  44.         public String getName() {  
  45.             return mDriverName;  
  46.         }  
  47.     }  
  48.   
  49.     Vector<Driver> getDrivers() throws IOException {  
  50.         if (mDrivers == null) {  
  51.             mDrivers = new Vector<Driver>();  
  52.             LineNumberReader r = new LineNumberReader(new FileReader(  
  53.                     "/proc/tty/drivers"));  
  54.             String l;  
  55.             while ((l = r.readLine()) != null) {  
  56.                 // Issue 3:  
  57.                 // Since driver name may contain spaces, we do not extract  
  58.                 // driver name with split()  
  59.                 String drivername = l.substring(00x15).trim();  
  60.                 String[] w = l.split(" +");  
  61.                 if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {  
  62.                     Log.d(TAG, "Found new driver " + drivername + " on "  
  63.                             + w[w.length - 4]);  
  64.                     mDrivers.add(new Driver(drivername, w[w.length - 4]));  
  65.                 }  
  66.             }  
  67.             r.close();  
  68.         }  
  69.         return mDrivers;  
  70.     }  
  71.   
  72.     public String[] getAllDevices() {  
  73.         Vector<String> devices = new Vector<String>();  
  74.         // Parse each driver  
  75.         Iterator<Driver> itdriv;  
  76.         try {  
  77.             itdriv = getDrivers().iterator();  

抱歉!评论已关闭.