1、Android 串口编程原理和实现方式附源码 提到串口编程,就不得不提到JNI,不得不提到JavaAPI中的文件描述符类:FileDescriptor。下面我分别对JNI、FileDescriptor以及串口的一些知识点和实现的源码进行分析说明。这里主要是参考了开源项目android-serialport-api。 串口编程需要了解的基本知识点:对于串口编程,我们只需对串口进行一系列的设置,然后打开串口,这些操作我们可以参考串口调试助手的源码进行学习。在Java中如果要实现串口的读写功能只需操作文件设备类:FileDescriptor即可,其他的事都由驱动来完成不用多管!当然,你想了解,那就得
2、看驱动代码了。这里并不打算对驱动进行说明,只初略阐述应用层的实现方式。(一)JNI: 关于JNI的文章网上有很多,不再多做解释,想详细了解的朋友可以查看云中漫步的技术文章,写得很好,分析也很全面,那么在这篇拙文中我强调3点: 1、如何将编译好的SO文件打包到APK中?(方法很简单,直接在工程目录下新建文件夹 libs/armeabi,将SO文件Copy到此目录即可) 2、命名要注意的地方?(在编译好的SO文件中,将文件重命名为:libfilename.so即可。其中filename.so是编译好后生成的文件) 3、MakeFile文件的编写(不用多说,可以直接参考package/apps目录下
3、用到JNI的相关项目写法) 这是关键的代码:cppview plaincopy1. intfd;2. speed_tspeed;3. jobjectmFileDescriptor;4. 5. /*Checkarguments*/6. 7. speed=getBaudrate(baudrate);8. if(speed=-1)9. /*TODO:throwanexception*/10. LOGE(Invalidbaudrate);11. returnNULL;12. 13. 14. 15. /*Openingdevice*/16. 17. jbooleaniscopy;18. constcha
4、r*path_utf=(*env)-GetStringUTFChars(env,path,&iscopy);19. LOGD(Openingserialport%swithflags0x%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. /*Throwanexception*/26. LOGE(Cannotopenport);27.
5、 /*TODO:throwanexception*/28. returnNULL;29. 30. 31. 32. /*Configuredevice*/33. 34. structtermioscfg;35. LOGD(Configuringserialport);36. if(tcgetattr(fd,&cfg)37. 38. LOGE(tcgetattr()failed);39. close(fd);40. /*TODO:throwanexception*/41. returnNULL;42. 43. 44. cfmakeraw(&cfg);45. cfsetispeed(&cfg,spe
6、ed);46. cfsetospeed(&cfg,speed);47. 48. if(tcsetattr(fd,TCSANOW,&cfg)49. 50. LOGE(tcsetattr()failed);51. close(fd);52. /*TODO:throwanexception*/53. returnNULL;54. 55. 56. (二)FileDescritor: 文件描述符类的实例用作与基础机器有关的某种结构的不透明句柄,该结构表示开放文件、开放套接字或者字节的另一个源或接收者。文件描述符的主要实际用途是创建一个包含该结构的FileInputStream或FileOutputStr
7、eam。这是API的描述,不太好理解,其实可简单的理解为:FileDescritor就是对一个文件进行读写。(三)实现串口通信细节1) 建工程:SerialDemo包名:org.winplus.serial,并在工程目录下新建jni和libs两个文件夹和一个org.winplus.serial.utils,如下图:2) 新建一个类:SerialPortFinder,添加如下代码:javaview plaincopy1. packageorg.winplus.serial.utils;2. 3. importjava.io.File;4. importjava.io.FileReader;5.
8、importjava.io.IOException;6. importjava.io.LineNumberReader;7. importjava.util.Iterator;8. importjava.util.Vector;9. 10. importandroid.util.Log;11. 12. publicclassSerialPortFinder13. 14. privatestaticfinalStringTAG=SerialPort;15. 16. privateVectormDrivers=null;17. 18. publicclassDriver19. publicDriv
9、er(Stringname,Stringroot)20. mDriverName=name;21. mDeviceRoot=root;22. 23. 24. privateStringmDriverName;25. privateStringmDeviceRoot;26. VectormDevices=null;27. 28. publicVectorgetDevices()29. if(mDevices=null)30. mDevices=newVector();31. Filedev=newFile(/dev);32. Filefiles=dev.listFiles();33. inti;
10、34. for(i=0;ifiles.length;i+)35. if(filesi.getAbsolutePath().startsWith(mDeviceRoot)36. Log.d(TAG,Foundnewdevice:+filesi);37. mDevices.add(filesi);38. 39. 40. 41. returnmDevices;42. 43. 44. publicStringgetName()45. returnmDriverName;46. 47. 48. 49. VectorgetDrivers()throwsIOException50. if(mDrivers=
11、null)51. mDrivers=newVector();52. LineNumberReaderr=newLineNumberReader(newFileReader(53. /proc/tty/drivers);54. Stringl;55. while(l=r.readLine()!=null)56. /Issue3:57. /Sincedrivernamemaycontainspaces,wedonotextract58. /drivernamewithsplit()59. Stringdrivername=l.substring(0,0x15).trim();60. Stringw
12、=l.split(+);61. if(w.length=5)&(ww.length-1.equals(serial)62. Log.d(TAG,Foundnewdriver+drivername+on63. +ww.length-4);64. mDrivers.add(newDriver(drivername,ww.length-4);65. 66. 67. r.close();68. 69. returnmDrivers;70. 71. 72. publicStringgetAllDevices()73. Vectordevices=newVector();74. /Parseeachdri
13、ver75. Iteratoritdriv;76. try77. itdriv=getDrivers().iterator();78. while(itdriv.hasNext()79. Driverdriver=itdriv.next();80. Iteratoritdev=driver.getDevices().iterator();81. while(itdev.hasNext()82. Stringdevice=itdev.next().getName();83. Stringvalue=String.format(%s(%s),device,84. driver.getName();
14、85. devices.add(value);86. 87. 88. catch(IOExceptione)89. e.printStackTrace();90. 91. returndevices.toArray(newStringdevices.size();92. 93. 94. publicStringgetAllDevicesPath()95. Vectordevices=newVector();96. /Parseeachdriver97. Iteratoritdriv;98. try99. itdriv=getDrivers().iterator();100. while(itd
15、riv.hasNext()101. Driverdriver=itdriv.next();102. Iteratoritdev=driver.getDevices().iterator();103. while(itdev.hasNext()104. Stringdevice=itdev.next().getAbsolutePath();105. devices.add(device);106. 107. 108. catch(IOExceptione)109. e.printStackTrace();110. 111. returndevices.toArray(newStringdevic
16、es.size();112. 113. 114. 上面这个类在“android-serialport-api串口工具测试随笔”中有详细的说明,我就不多说了。3)新建SerialPort类,这个类主要用来加载SO文件,通过JNI的方式打开关闭串口javaview plaincopy1. packageorg.winplus.serial.utils;2. 3. importjava.io.File;4. importjava.io.FileDescriptor;5. importjava.io.FileInputStream;6. importjava.io.FileOutputStream;7
17、. importjava.io.IOException;8. importjava.io.InputStream;9. importjava.io.OutputStream;10. 11. importandroid.util.Log;12. 13. publicclassSerialPort14. privatestaticfinalStringTAG=SerialPort;15. 16. /*17. *DonotremoveorrenamethefieldmFd:itisusedbynativemethod18. *close();19. */20. privateFileDescript
18、ormFd;21. privateFileInputStreammFileInputStream;22. privateFileOutputStreammFileOutputStream;23. 24. publicSerialPort(Filedevice,intbaudrate,intflags)25. throwsSecurityException,IOException26. 27. /*Checkaccesspermission*/28. if(!device.canRead()|!device.canWrite()29. try30. /*Missingread/writeperm
19、ission,tryingtochmodthefile*/31. Processsu;32. su=Runtime.getRuntime().exec(/system/bin/su);33. Stringcmd=chmod666+device.getAbsolutePath()+n34. +exitn;35. su.getOutputStream().write(cmd.getBytes();36. if(su.waitFor()!=0)|!device.canRead()37. |!device.canWrite()38. thrownewSecurityException();39. 40. catch(Exceptione)41. e.printStackTrace();42. thrownewSecurityException();43. 44. 45. 46. mFd=open(device.getAbsolutePath(),baudrate,flags);47. if(mFd=null)48. Log.e(TAG,nativeopenreturnsnull);49. thrownewIOException(
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1