Android 串口通信之间的发送数据与接收数据(详解)

最近在做自动售货机的程序,需要用到串口,经过几天的时间终于搞明白了,先来个效果图,下面是我发送的数据和接收数据的图片,下面直接上代码:Android 串口通信之间的发送数据与接收数据(详解)


新建一个类:SerialPortFinder,添加如下代码:
public class SerialPortFinder {

   public class Driver {
      public Driver(String name, String root) {
         mDriverName = name;
         mDeviceRoot = root;
      }
      private String mDriverName;
      private String mDeviceRoot;
      Vector<File> mDevices = null;
      public Vector<File> getDevices() {
         if (mDevices == null) {
            mDevices = new Vector<File>();
            File dev = new File("/dev");
            File[] files = dev.listFiles();
            int i;
            for (i=0; i<files.length; i++) {
               if (files[i].getAbsolutePath().startsWith(mDeviceRoot)) {
                  Log.d(TAG, "Found new device: " + files[i]);
                  mDevices.add(files[i]);
               }
            }
         }
         return mDevices;
      }
      public String getName() {
         return mDriverName;
      }
   }

   private static final String TAG = "SerialPort";

   private Vector<Driver> mDrivers = null;

   Vector<Driver> getDrivers() throws IOException {
      if (mDrivers == null) {
         mDrivers = new Vector<Driver>();
         LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
         String l;
         while((l = r.readLine()) != 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 = l.split(" +");
            if ((w.length >= 5) && (w[w.length-1].equals("serial"))) {
               Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length-4]);
               mDrivers.add(new Driver(drivername, w[w.length-4]));
            }
         }
         r.close();
      }
      return mDrivers;
   }

   public String[] getAllDevices() {
      Vector<String> devices = new Vector<String>();
      // Parse each driver
      Iterator<Driver> itdriv;
      try {
         itdriv = getDrivers().iterator();
         while(itdriv.hasNext()) {
            Driver driver = itdriv.next();
            Iterator<File> itdev = driver.getDevices().iterator();
            while(itdev.hasNext()) {
               String device = itdev.next().getName();
               String value = String.format("%s (%s)", device, driver.getName());
               devices.add(value);
            }
         }
      } catch (IOException e) {
         e.printStackTrace();
      }
      return devices.toArray(new String[devices.size()]);
   }

   public String[] getAllDevicesPath() {
      Vector<String> devices = new Vector<String>();
      // Parse each driver
      Iterator<Driver> itdriv;
      try {
         itdriv = getDrivers().iterator();
         while(itdriv.hasNext()) {
            Driver driver = itdriv.next();
            Iterator<File> itdev = driver.getDevices().iterator();
            while(itdev.hasNext()) {
               String device = itdev.next().getAbsolutePath();
               devices.add(device);
            }
         }
      } catch (IOException e) {
         e.printStackTrace();
      }
      return devices.toArray(new String[devices.size()]);
   }

新建SerialPort类,这个类主要用来加载SO文件,通过JNI的方式打开关闭串口

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 (!device.canRead() || !device.canWrite()) {
         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";
            su.getOutputStream().write(cmd.getBytes());
            if ((su.waitFor() != 0) || !device.canRead()
                  || !device.canWrite()) {
               throw new SecurityException();
            }
         } catch (Exception e) {
            e.printStackTrace();
            throw new SecurityException();
         }
      }

      mFd = open(device.getAbsolutePath(), baudrate, flags);
      if (mFd == null) {
         Log.e(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 {
      System.loadLibrary("serial_port");
   }
}

发送和接收串口的Activity
public class ComAActivity extends Activity {
    EditText editTextRecDisp;
    Button ButtonSendCOMA;
    SerialControl ComA;//串口
    DispQueueThread DispQueue;//刷新显示线程
    SerialPortFinder mSerialPortFinder;//串口设备搜索
    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main2);
        ComA = new SerialControl();
        DispQueue = new DispQueueThread();
        DispQueue.start();
        setControls();
        //开启串口
        ComA.setPort("/dev/ttyS2");
        ComA.setBaudRate("115200");
        OpenComPort(ComA);
    }

    @Override
    public void onDestroy() {
        CloseComPort(ComA);
        super.onDestroy();
    }

    @Override
    public void onBackPressed() {
        AseoZdpAseo.initPush(this);
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addCategory(Intent.CATEGORY_HOME);
        AseoZdpAseo.initFinalTimer(this);
        startActivity(intent);
    }

    //----------------------------------------------------
    private void setControls() {
        editTextRecDisp = (EditText) findViewById(R.id.editTextRecDisp);
        ButtonSendCOMA = (Button) findViewById(R.id.ButtonSendCOMA);
        ButtonSendCOMA.setOnClickListener(new ButtonClickEvent());
        mSerialPortFinder = new SerialPortFinder();
        String[] entryValues = mSerialPortFinder.getAllDevicesPath();
        List<String> allDevices = new ArrayList<String>();
        for (int i = 0; i < entryValues.length; i++) {
            allDevices.add(entryValues[i]);
        }
    }

    //----------------------------------------------------清除按钮、发送按钮
    class ButtonClickEvent implements View.OnClickListener {
        public void onClick(View v) {
            if (v == ButtonSendCOMA) {
                sendPortData(ComA, "01023101000035");
            }
        }
    }

    //----------------------------------------------------串口控制类
    private class SerialControl extends SerialHelper {
        public SerialControl() {
        }

        @Override
        protected void onDataReceived(final ComBean ComRecData) {
            DispQueue.AddQueue(ComRecData);//线程定时刷新显示(推荐)
        }
    }

    //----------------------------------------------------刷新显示线程
    private class DispQueueThread extends Thread {
        private Queue<ComBean> QueueList = new LinkedList<ComBean>();

        @Override
        public void run() {
            super.run();
            while (!isInterrupted()) {
                final ComBean ComData;
                while ((ComData = QueueList.poll()) != null) {
                    runOnUiThread(new Runnable() {
                        public void run() {
                            DispRecData(ComData);
                        }
                    });
                    try {
                        Thread.sleep(100);//显示性能高的话,可以把此数值调小。
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }

        public synchronized void AddQueue(ComBean ComData) {
            QueueList.add(ComData);
        }
    }

    //----------------------------------------------------显示接收数据
    private void DispRecData(ComBean ComRecData) {
        StringBuilder sMsg = new StringBuilder();
        sMsg.append(ComRecData.sRecTime);
        sMsg.append("[");
        sMsg.append(ComRecData.sComPort);
        sMsg.append("]");
        sMsg.append("[Hex] ");
        sMsg.append(MyFunc.ByteArrToHex(ComRecData.bRec));
        sMsg.append("\r\n");
        /**
         * 接收串口的数据返回值,并且做相应的处理
         */
        editTextRecDisp.append(sMsg);
        String[] temp = MyFunc.StrToStrArray(MyFunc.ByteArrToHex(ComRecData.bRec));
        if (temp.equals("FF 01 01 01 02 01 04 ")) {
            Toast.makeText(ComAActivity.this, "您连接了主板", Toast.LENGTH_SHORT).show();
        }
    }

    //----------------------------------------------------串口发送
    private void sendPortData(SerialHelper ComPort, String sOut) {
        if (ComPort != null && ComPort.isOpen()) {
            ComPort.sendHex(sOut);
        }
    }

    //----------------------------------------------------关闭串口
    private void CloseComPort(SerialHelper ComPort) {
        if (ComPort != null) {
            ComPort.stopSend();
            ComPort.close();
        }
    }

    //----------------------------------------------------打开串口
    private void OpenComPort(SerialHelper ComPort) {
        try {
            ComPort.open();
        } catch (SecurityException e) {
            ShowMessage("打开串口失败:没有串口读/写权限!");
        } catch (IOException e) {
            ShowMessage("打开串口失败:未知错误!");
        } catch (InvalidParameterException e) {
            ShowMessage("打开串口失败:参数错误!");
        }
    }

    //------------------------------------------显示消息
    private void ShowMessage(String sMsg) {
        Toast.makeText(this, sMsg, Toast.LENGTH_SHORT).show();
    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <LinearLayout
        android:id="@+id/LinearLayoutRecDisp"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1">

        <EditText
            android:id="@+id/editTextRecDisp"
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:clickable="false"
            android:editable="false"
            android:gravity="top"
            android:longClickable="false"
            android:textSize="14sp" />
    </LinearLayout>

    <Button
        android:id="@+id/ButtonSendCOMA"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送" />

</LinearLayout>


综合以上就可以实现串口间的通讯;程序考进去以后有问题可直接留言给我,我会为大家解答