Android 串口编程原理和实现方式(附源码).doc_第1页
Android 串口编程原理和实现方式(附源码).doc_第2页
Android 串口编程原理和实现方式(附源码).doc_第3页
Android 串口编程原理和实现方式(附源码).doc_第4页
Android 串口编程原理和实现方式(附源码).doc_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

提到串口编程,就不得不提到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的相关项目写法) 这是关键的代码: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. constchar*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. /*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,speed);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或FileOutputStream。这是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. 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. publicDriver(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;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=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=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. /Parseeachdriver75. 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();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(itdriv.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(newStringdevices.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. 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. privateFileDescriptormFd;21. privateFileInputStreammFileInputStream;22. privateFileOutputStreammFileOutputStream;23. 24. publicSerialPort(Filedevice,intbaudrate,intflags)25. throwsSecurityException,IOException26. 27. /*Checkaccesspermission*/28. if(!device.canRead()|!device.canWrite()29. try30. /*Missingread/writepermission,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();50. 51. mFileInputStream=newFileInputStream(mFd);52. mFileOutputStream=newFileOutputStream(mFd);53. 54. 55. /Gettersandsetters56. publicInputStreamgetInputStream()57. returnmFileInputStream;58. 59. 60. publicOutputStreamgetOutputStream()61. returnmFileOutputStream;62. 63. 64. /JNI65. privatenativestaticFileDescriptoropen(Stringpath,intbaudrate,66. intflags);67. 68. publicnativevoidclose();69. 70. static71. System.loadLibrary(serial_port);72. 73. 74. 4) 新建一个Application 继承android.app.Application,用来对串口进行初始化和关闭串口javaview plaincopy1. packageorg.winplus.serial;2. 3. importjava.io.File;4. importjava.io.IOException;5. importjava.security.InvalidParameterException;6. 7. importorg.winplus.serial.utils.SerialPort;8. importorg.winplus.serial.utils.SerialPortFinder;9. 10. importandroid.content.SharedPreferences;11. 12. publicclassApplicationextendsandroid.app.Application13. publicSerialPortFindermSerialPortFinder=newSerialPortFinder();14. privateSerialPortmSerialPort=null;15. 16. publicSerialPortgetSerialPort()throwsSecurityException,IOException,InvalidParameterException17. if(mSerialPort=null)18. /*Readserialportparameters*/19. SharedPreferencessp=getSharedPreferences(android_serialport_api.sample_preferences,MODE_PRIVATE);20. Stringpath=sp.getString(DEVICE,);21. intbaudrate=Integer.decode(sp.getString(BAUDRATE,-1);22. 23. /*Checkparameters*/24. if(path.length()=0)|(baudrate=-1)25. thrownewInvalidParameterException();26. 27. 28. /*Opentheserialport*/29. mSerialPort=newSerialPort(newFile(path),baudrate,0);30. 31. returnmSerialPort;32. 33. 34. publicvoidcloseSerialPort()35. if(mSerialPort!=null)36. mSerialPort.close();37. mSerialPort=null;38. 39. 40. 41. 5) 新建一个继承抽象的Activity类,主要用于读取串口的信息javaview plaincopy1. packageorg.winplus.serial;2. 3. importjava.io.IOException;4. importjava.io.InputStream;5. importjava.io.OutputStream;6. importjava.security.InvalidParameterException;7. 8. importorg.winplus.serial.utils.SerialPort;9. 10. importandroid.app.Activity;11. importandroid.app.AlertDialog;12. importandroid.content.DialogInterface;13. importandroid.content.DialogInterface.OnClickListener;14. importandroid.os.Bundle;15. 16. publicabstractclassSerialPortActivityextendsActivity17. protectedApplicationmApplication;18. protectedSerialPortmSerialPort;19. protectedOutputStreammOutputStream;20. privateInputStreammInputStream;21. privateReadThreadmReadThread;22. 23. privateclassReadThreadextendsThread24. 25. Override26. publicvoidrun()27. super.run();28. while(!isInterrupted()29. intsize;30. try31. bytebuffer=newbyte64;32. if(mInputStream=null)33. return;34. 35. /*36. *这里的read要尤其注意,它会一直等待数据,等到天荒地老,海枯石烂。如果要判断是否接受完成,只有设置结束标识,或作其他特殊的处理。37. */38. size=mInputStream.read(buffer);39. if(size0)40. onDataReceived(buffer,size);41. 42. catch(IOExceptione)43. e.printStackTrace();44. return;45. 46. 47. 48. 49. 50. privatevoidDisplayError(intresourceId)51. AlertDialog.Builderb=newAlertDialog.Builder(this);52. b.setTitle(Error);53. b.setMessage(resourceId);54. b.setPositiveButton(OK,newOnClickListener()55. publicvoidonClick(DialogInterfacedialog,intwhich)56. SerialPortActivity.this.finish();57. 58. );59. b.show();60. 61. 62. Override63. protectedvoidonCreate(BundlesavedInstanceState)64. super.onCreate(savedInstanceState);65. mApplication=(Application)getApplication();66. try67. mSerialPort=mApplication.getSerialPort();68. mOutputStream=mSerialPort.getOutputStream();69. mInputStream=mSerialPort.getInputStream();70. 71. /*Createareceivingthread*/72. mReadThread=newReadThread();73. mReadThread.start();74. catch(SecurityExceptione)75. DisplayError(R.string.error_security);76. catch(IOExceptione)77. DisplayError(R.string.error_unknown);78. catch(InvalidParameterExceptione)79. DisplayError(R.string.error_configuration);80. 81. 82. 83. protectedabstractvoidonDataReceived(finalbytebuffer,finalintsize);84. 85. Override86. protectedvoidonDestroy()87. if(mReadThread!=null)88. mReadTerrup

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论