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