首页 Android 串口编程原理和实现方式(附源码)

Android 串口编程原理和实现方式(附源码)

举报
开通vip

Android 串口编程原理和实现方式(附源码)------------------------------------------作者xxxx------------------------------------------日期xxxxAndroid串口编程原理和实现方式(附源码)【精品文档】【精品文档】【精品文档】【精品文档】【精品文档】【精品文档】 提到串口编程,就不得不提到JNI,不得不提到JavaAPI中的文件描述符类:FileDescriptor。下面我分别对JNI、FileDescriptor以及串口的一些知识点和实现的源码进行分析说明。这里主要...

Android 串口编程原理和实现方式(附源码)
------------------------------------------作者xxxx------------------------------------------日期xxxxAndroid串口编程原理和实现方式(附源码)【精品文档】【精品文档】【精品文档】【精品文档】【精品文档】【精品文档】 提到串口编程,就不得不提到JNI,不得不提到JavaAPI中的文件描述符类:FileDescriptor。下面我分别对JNI、FileDescriptor以及串口的一些知识点和实现的源码进行 分析 定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析 说明。这里主要是参考了开源项目HYPERLINK"http://code.google.com/p/android-serialport-api/"android-serialport-api。  串口编程需要了解的基本知识点:对于串口编程,我们只需对串口进行一系列的设置,然后打开串口,这些操作我们可以参考HYPERLINK"http://www.gjwtech.com/vcandc/scommassistantcode.htm"串口调试助手的源码进行学习。在Java中如果要实现串口的读写功能只需操作文件设备类:FileDescriptor即可,其他的事都由驱动来完成不用多管!当然,你想了解,那就得看驱动代码了。这里并不打算对驱动进行说明,只初略阐述应用层的实现方式。 (一)JNI:  关于JNI的文章网上有很多,不再多做解释,想详细了解的朋友可以查看HYPERLINK"http://my.unix-center.net/~Simon_fu/?cat=3&paged=2"云中漫步的技术文章,写得很好,分析也很全面,那么在这篇拙文中我强调3点:  1、如何将编译好的SO文件打包到APK中?(方法很简单,直接在 工程 路基工程安全技术交底工程项目施工成本控制工程量增项单年度零星工程技术标正投影法基本原理 目录下新建文件夹libs/armeabi,将SO文件Copy到此目录即可)  2、命名要注意的地方?(在编译好的SO文件中,将文件重命名为:即可。其中是编译好后生成的文件)  3、MakeFile文件的编写(不用多说,可以直接参考package/apps目录下用到JNI的相关项目写法)  这是关键的代码:[cpp] HYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"viewplain"viewplainHYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"copy"copy        int fd;          speed_t speed;          jobject mFileDescriptor;            /* Check arguments */          {                  speed = getBaudrate(baudrate);                  if (speed == -1) {                          /* TODO: throw an exception */                          LOGE("Invalid baudrate");                          return NULL;                  }          }            /* Opening device */          {                  jboolean iscopy;                  const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);                  LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags);                  fd = open(path_utf, O_RDWR | flags);                  LOGD("open() fd = %d", fd);                  (*env)->ReleaseStringUTFChars(env, path, path_utf);                  if (fd == -1)                  {                          /* Throw an exception */                          LOGE("Cannot open port");                          /* TODO: throw an exception */                          return NULL;                  }          }            /* Configure device */          {                  struct termios cfg;                  LOGD("Configuring serial port");                  if (tcgetattr(fd, &cfg))                  {                          LOGE("tcgetattr() failed");                          close(fd);                          /* TODO: throw an exception */                          return NULL;                  }                    cfmakeraw(&cfg);                  cfsetispeed(&cfg, speed);                  cfsetospeed(&cfg, speed);                    if (tcsetattr(fd, TCSANOW, &cfg))                  {                          LOGE("tcsetattr() failed");                          close(fd);                          /* TODO: throw an exception */                          return NULL;                  }          }    (二)FileDescritor:  文件描述符类的实例用作与基础机器有关的某种结构的不透明句柄,该结构 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 示开放文件、开放套接字或者字节的另一个源或接收者。文件描述符的主要实际用途是创建一个包含该结构的FileInputStream 或FileOutputStream。这是API的描述,不太好理解,其实可简单的理解为:FileDescritor就是对一个文件进行读写。(三)实现串口通信细节1) 建工程:SerialDemo包名:,并在工程目录下新建jni和libs两个文件夹和一个,如下图:2)新建一个类:SerialPortFinder,添加如下代码:[java] HYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"viewplain"viewplainHYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"copy"copypackage org.winplus.serial.utils;    import ;  import ;  import ;  import ;  import ;  import ;    import ;    public class SerialPortFinder {        private static final String TAG = "SerialPort";        private Vector mDrivers = null;        public class Driver {          public Driver(String name, String root) {              mDriverName = name;              mDeviceRoot = root;          }            private String mDriverName;          private String mDeviceRoot;          Vector mDevices = null;            public Vector getDevices() {              if (mDevices == null) {                  mDevices = new Vector();                  File dev = new File("/dev");                  File[] files = ();                  int i;                  for (i = 0; i < ; i++) {                      if (files[i].getAbsolutePath().startsWith(mDeviceRoot)) {                          Log.d(TAG, "Found new device: " + files[i]);                          (files[i]);                      }                  }              }              return mDevices;          }            public String getName() {              return mDriverName;          }      }        Vector getDrivers() throws IOException {          if (mDrivers == null) {              mDrivers = new Vector();              LineNumberReader r = new LineNumberReader(new FileReader(                      "/proc/tty/drivers"));              String l;              while ((l = ()) != null) {                  // Issue 3:                  // Since driver name may contain spaces, we do not extract                  // driver name with split()                  String drivername = l.substring(0, 0x15).trim();                  String[] w = (" +");                  if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {                      Log.d(TAG, "Found new driver " + drivername + " on "                              + w[ - 4]);                      mDrivers.add(new Driver(drivername, w[w.length - 4]));                  }              }              ();          }          return mDrivers;      }        public String[] getAllDevices() {          Vector devices = new Vector();          // Parse each driver          Iterator itdriv;          try {              itdriv = getDrivers().iterator();              while (()) {                  Driver driver = itdriv.next();                  Iterator itdev = driver.getDevices().iterator();                  while (()) {                      String device = ().getName();                      String value = String.format("%s (%s)", device,                              ());                      (value);                  }              }          } catch (IOException e) {              ();          }          return (new String[()]);      }        public String[] getAllDevicesPath() {          Vector devices = new Vector();          // Parse each driver          Iterator itdriv;          try {              itdriv = getDrivers().iterator();              while (()) {                  Driver driver = itdriv.next();                  Iterator itdev = driver.getDevices().iterator();                  while (()) {                      String device = itdev.next().getAbsolutePath();                      (device);                  }              }          } catch (IOException e) {              ();          }          return (new String[()]);      }  }    上面这个类在“HYPERLINK"http://blog.csdn.net/lightsoure/article/details/6833450"\o"android-serialport-api串口工具测试随笔"android-serialport-api串口工具测试随笔”中有详细的说明,我就不多说了。3)新建SerialPort类,这个类主要用来加载SO文件,通过JNI的方式打开关闭串口[java] HYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"viewplain"viewplainHYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"copy"copypackage org.winplus.serial.utils;    import ;  import ;  import ;  import ;  import ;  import ;  import ;    import ;    public class SerialPort {      private static final String TAG = "SerialPort";        /*      * Do not remove or rename the field mFd: it is used by native method      * close();      */      private FileDescriptor mFd;      private FileInputStream mFileInputStream;      private FileOutputStream mFileOutputStream;        public SerialPort(File device, int baudrate, int flags)              throws SecurityException, IOException {            /* Check access permission */          if (!() || !()) {              try {                  /* Missing read/write permission, trying to chmod the file */                  Process su;                  su = Runtime.getRuntime().exec("/system/bin/su");                  String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"                          + "exit\n";                  ().write(());                  if ((() != 0) || !()                          || !()) {                      throw new SecurityException();                  }              } catch (Exception e) {                  ();                  throw new SecurityException();              }          }            mFd = open((), baudrate, flags);          if (mFd == null) {              (TAG, "native open returns null");              throw new IOException();          }          mFileInputStream = new FileInputStream(mFd);          mFileOutputStream = new FileOutputStream(mFd);      }        // Getters and setters      public InputStream getInputStream() {          return mFileInputStream;      }        public OutputStream getOutputStream() {          return mFileOutputStream;      }        // JNI      private native static FileDescriptor open(String path, int baudrate,              int flags);        public native void close();        static {          ("serial_port");      }  }    4)新建一个Application继承,用来对串口进行初始化和关闭串口[java] HYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"viewplain"viewplainHYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"copy"copypackage ;    import ;  import ;  import ;    import ;  import ;    import ;    public class Application extends  {      public SerialPortFinder mSerialPortFinder = new SerialPortFinder();      private SerialPort mSerialPort = null;        public SerialPort getSerialPort() throws SecurityException, IOException, InvalidParameterException {              if (mSerialPort == null) {                      /* Read serial port parameters */                      SharedPreferences sp = getSharedPreferences("android_serialport_api.sample_preferences", MODE_PRIVATE);                      String path = ("DEVICE", "");                      int baudrate = Integer.decode(sp.getString("BAUDRATE", "-1"));                        /* Check parameters */                      if ( (path.length() == 0) || (baudrate == -1)) {                              throw new InvalidParameterException();                      }                        /* Open the serial port */                      mSerialPort = new SerialPort(new File(path), baudrate, 0);              }              return mSerialPort;      }        public void closeSerialPort() {              if (mSerialPort != null) {                      ();                      mSerialPort = null;              }      }  }    5)新建一个继承抽象的Activity类,主要用于读取串口的信息[java] HYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"viewplain"viewplainHYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"copy"copypackage ;    import ;  import ;  import ;  import ;    import ;    import ;  import ;  import ;  import ;  import ;    public abstract class SerialPortActivity extends Activity {      protected Application mApplication;      protected SerialPort mSerialPort;      protected OutputStream mOutputStream;      private InputStream mInputStream;      private ReadThread mReadThread;        private class ReadThread extends Thread {            @Override          public void run() {              super.run();              while (!isInterrupted()) {                  int size;                  try {                      byte[] buffer = new byte[64];                      if (mInputStream == null)                          return;                                            /**                      * 这里的read要尤其注意,它会一直等待数据,等到天荒地老,海枯石烂。如果要判断是否接受完成,只有设置结束标识,或作其他特殊的处理。                      */                      size = (buffer);                      if (size > 0) {                          onDataReceived(buffer, size);                      }                  } catch (IOException e) {                      ();                      return;                  }              }          }      }        private void DisplayError(int resourceId) {           b = new (this);          ("Error");          (resourceId);          ("OK", new OnClickListener() {              public void onClick(DialogInterface dialog, int which) {                  SerialPortActivity.this.finish();              }          });          ();      }        @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          mApplication = (Application) getApplication();          try {              mSerialPort = ();              mOutputStream = ();              mInputStream = ();                /* Create a receiving thread */              mReadThread = new ReadThread();              ();          } catch (SecurityException e) {              DisplayError();          } catch (IOException e) {              DisplayError();          } catch (InvalidParameterException e) {              DisplayError();          }      }        protected abstract void onDataReceived(final byte[] buffer, final int size);        @Override      protected void onDestroy() {          if (mReadThread != null)              ();          ();          mSerialPort = null;          super.onDestroy();      }  }    6)编写string.xml以及文件   在文件中添加:[html] HYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"viewplain"viewplainHYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"copy"copy    Please configure your serial port first.      You do not have read/write permission to the serial  port.      The serial port can not be opened for an unknown  reason.    在文件中添加[html] HYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"viewplain"viewplainHYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"copy"copy                    50          75          110          134          150          200          300          600          1200          1800          2400          4800          9600          19200          38400          57600          115200          230400          460800          500000          576000          921600          1000000          1152000          1500000          2000000          2500000          3000000          3500000          4000000                      50          75          110          134          150          200          300          600          1200          1800          2400          4800          9600          19200          38400          57600          115200          230400          460800          500000          576000          921600          1000000          1152000          1500000          2000000          2500000          3000000          3500000          4000000              7)开始编写界面了:在布局文件中添加两个编辑框,一个用来发送命令,一个用来接收命令:[html] HYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"viewplain"viewplainHYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"copy"copy                                      8)SerialDemoActivity类的实现:[java] HYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"viewplain"viewplainHYPERLINK"http://blog.csdn.net/tangcheng_ok/article/details/7021470"\o"copy"copypackage ;    import ;    import ;  import ;  import ;  import ;  import ;    public class SerialDemoActivity extends SerialPortActivity{      EditText mReception;        @Override      protected void onCreate(Bundle savedInstanceState) {              super.onCreate(savedInstanceState);              setContentView();    //          setTitle("Loopback test");              mReception = (EditText) findViewById(R.id.EditTextReception);                EditText Emission = (EditText) findViewById(R.id.EditTextEmission);              Emission.setOnEditorActionListener(new OnEditorActionListener() {                      public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {                              int i;                              CharSequence t = ();                              char[] text = new char[t.length()];                              for (i=0; i<(); i++) {                                      text[i] = (i);                              }                              try {                                      mOutputStream.write(new String(text).getBytes());                                      ('\n');                              } catch (IOException e) {                                      ();                              }                              return false;                      }              });      }        @Override      protected void onDataReceived(final byte[] buffer, final int size) {              runOnUiThread(new Runnable() {                      public void run() {                              if (mReception != null) {                                      mReception.append(new String(buffer, 0, size));                              }                      }              });      }  }      写到这里,代码基本上写完了。下面就是要实现JNI层的功能了,要实现JNI,必须首先生成头文件,头文件的生成方式也很简单,我们编译工程,在终端输入javah则会生成头文件:,这个头文件的名字可以随意命名。我们将它命名为:拷贝到新建的目录jni中,新建文件,这两个文件的代码就不贴出来了。直接到上传的代码中看吧。(四)串口的应用,可实现扫描头,指纹识别等外围USB转串口的特色应用。
本文档为【Android 串口编程原理和实现方式(附源码)】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
个人认证用户
simle
我是一线教师 有丰富的 教学经验
格式:doc
大小:271KB
软件:Word
页数:0
分类:
上传时间:2021-10-13
浏览量:87