Android 串口编程原理和实现方式附源码.docx
- 文档编号:5930626
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:21
- 大小:60.94KB
Android 串口编程原理和实现方式附源码.docx
《Android 串口编程原理和实现方式附源码.docx》由会员分享,可在线阅读,更多相关《Android 串口编程原理和实现方式附源码.docx(21页珍藏版)》请在冰豆网上搜索。
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的相关项目写法)
这是关键的代码:
[cpp] viewplaincopy
1. 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.
(二)FileDescritor:
文件描述符类的实例用作与基础机器有关的某种结构的不透明句柄,该结构表示开放文件、开放套接字或者字节的另一个源或接收者。
文件描述符的主要实际用途是创建一个包含该结构的FileInputStream 或FileOutputStream。
这是API的描述,不太好理解,其实可简单的理解为:
FileDescritor就是对一个文件进行读写。
(三)实现串口通信细节
1) 建工程:
SerialDemo包名:
org.winplus.serial,并在工程目录下新建jni和libs两个文件夹和一个org.winplus.serial.utils,如下图:
2)新建一个类:
SerialPortFinder,添加如下代码:
[java] viewplaincopy
1. 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 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 27. 28. public Vector 29. if (mDevices == null) { 30. mDevices = new Vector 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 50. if (mDrivers == null) { 51. mDrivers = new Vector 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(0, 0x15).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 74. // Parse each driver 75. Iterator 76. try { 77. itdriv = getDrivers().iterator(); 78. while (itdriv.hasNext()) { 79. Driver driver = itdriv.next(); 80. Iterator 81. while (itdev.hasNext()) { 82. String device = itdev.next().getName(); 83. String value = String.format("%s (%s)", device, 84. driver.getName()); 85. devices.add(value); 86. } 87. } 88. } catch (IOException e) { 89. e.printStackTrace(); 90. } 91. return devices.toArray(new String[devices.size()]); 92. } 93. 94. public String[] getAllDevicesPath() { 95. Vector 96. // Parse each driver 97. Iterator 98. try { 99. itdriv = getDrivers().iterator(); 100. while (itdriv.hasNext()) { 101. Driver driver = itdriv.next(); 102. Iterator 103. while (itdev.hasNext()) { 104. String device = itdev.next().getAbsolutePath(); 105. devices.add(device); 106. } 107. } 108. } catch (IOException e) { 109. e.printStackTrace(); 110. } 111. return devices.toArray(new String[devices.size()]); 112. } 113.} 114.
上面这个类在“android-serialport-api串口工具测试随笔”中有详细的说明,我就不多说了。
3)新建SerialPort类,这个类主要用来加载SO文件,通过JNI的方式打开关闭串口
[java] viewplaincopy
1. 18px;">package org.winplus.serial.utils; 2. 3.import java.io.File; 4.import java.io.FileDescriptor; 5.import java.io.FileInputStream; 6.import java.io.FileOutputStream; 7.import java.io.IOException; 8.import java.io.InputStream; 9.import java.io.OutputStream; 10. 11.import android.util.Log; 12. 13.public class SerialPort { 14. private static final String TAG = "SerialPort"; 15. 16. /* 17. * Do not remove or rename the field mFd: it is used by native method 18. * close(); 19. */ 20. private FileDescriptor mFd; 21. private FileInputStream mFileInputStream; 22. private FileOutputStream mFileOutputStream; 23. 24. public SerialPort(File device, int baudrate, int flags) 25. throws SecurityException, IOException { 26. 27. /* Check access permission */ 28. if (! device.canRead() || ! device.canWrite()) { 29. try { 30. /* Missing read/write permission, trying to chmod the file */ 31. Process su; 32. su = Runtime.getRuntime().exec("/system/bin/su"); 33. String cmd = "chmod 666 " + device.getAbsolutePath() + "\n" 34. + "exit\n"; 35. su.getOutputStream().write(cmd.getBytes()); 36. if ((su.waitFor() ! = 0) || ! device.canRead() 37. || ! device.canWrite()) { 38. throw new SecurityException(); 39. } 40. } catch (Exception e) { 41. e.printStackTrace(); 42. throw new SecurityException(); 43. } 44. } 45. 46. mFd = open(device.getAbsolutePath(), baudrate, flags); 47. if (mFd == null) { 48. Log.e(TAG, "native open returns null"); 49. throw new IOException(
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 串口编程原理和实现方式附源码 串口 编程 原理 实现 方式 源码