当前位置:   article > 正文

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

安卓串口通信

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

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

  1. public class SerialPortFinder {
  2. public class Driver {
  3. public Driver(String name, String root) {
  4. mDriverName = name;
  5. mDeviceRoot = root;
  6. }
  7. private String mDriverName;
  8. private String mDeviceRoot;
  9. Vector<File> mDevices = null;
  10. public Vector<File> getDevices() {
  11. if (mDevices == null) {
  12. mDevices = new Vector<File>();
  13. File dev = new File("/dev");
  14. File[] files = dev.listFiles();
  15. int i;
  16. for (i=0; i<files.length; i++) {
  17. if (files[i].getAbsolutePath().startsWith(mDeviceRoot)) {
  18. Log.d(TAG, "Found new device: " + files[i]);
  19. mDevices.add(files[i]);
  20. }
  21. }
  22. }
  23. return mDevices;
  24. }
  25. public String getName() {
  26. return mDriverName;
  27. }
  28. }
  29. private static final String TAG = "SerialPort";
  30. private Vector<Driver> mDrivers = null;
  31. Vector<Driver> getDrivers() throws IOException {
  32. if (mDrivers == null) {
  33. mDrivers = new Vector<Driver>();
  34. LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
  35. String l;
  36. while((l = r.readLine()) != null) {
  37. // Issue 3:
  38. // Since driver name may contain spaces, we do not extract driver name with split()
  39. String drivername = l.substring(0, 0x15).trim();
  40. String[] w = l.split(" +");
  41. if ((w.length >= 5) && (w[w.length-1].equals("serial"))) {
  42. Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length-4]);
  43. mDrivers.add(new Driver(drivername, w[w.length-4]));
  44. }
  45. }
  46. r.close();
  47. }
  48. return mDrivers;
  49. }
  50. public String[] getAllDevices() {
  51. Vector<String> devices = new Vector<String>();
  52. // Parse each driver
  53. Iterator<Driver> itdriv;
  54. try {
  55. itdriv = getDrivers().iterator();
  56. while(itdriv.hasNext()) {
  57. Driver driver = itdriv.next();
  58. Iterator<File> itdev = driver.getDevices().iterator();
  59. while(itdev.hasNext()) {
  60. String device = itdev.next().getName();
  61. String value = String.format("%s (%s)", device, driver.getName());
  62. devices.add(value);
  63. }
  64. }
  65. } catch (IOException e) {
  66. e.printStackTrace();
  67. }
  68. return devices.toArray(new String[devices.size()]);
  69. }
  70. public String[] getAllDevicesPath() {
  71. Vector<String> devices = new Vector<String>();
  72. // Parse each driver
  73. Iterator<Driver> itdriv;
  74. try {
  75. itdriv = getDrivers().iterator();
  76. while(itdriv.hasNext()) {
  77. Driver driver = itdriv.next();
  78. Iterator<File> itdev = driver.getDevices().iterator();
  79. while(itdev.hasNext()) {
  80. String device = itdev.next().getAbsolutePath();
  81. devices.add(device);
  82. }
  83. }
  84. } catch (IOException e) {
  85. e.printStackTrace();
  86. }
  87. return devices.toArray(new String[devices.size()]);
  88. }

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

  1. public class SerialPort {
  2. private static final String TAG = "SerialPort";
  3. /*
  4. * Do not remove or rename the field mFd: it is used by native method close();
  5. */
  6. private FileDescriptor mFd;
  7. private FileInputStream mFileInputStream;
  8. private FileOutputStream mFileOutputStream;
  9. public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
  10. /* Check access permission */
  11. if (!device.canRead() || !device.canWrite()) {
  12. try {
  13. /* Missing read/write permission, trying to chmod the file */
  14. Process su;
  15. su = Runtime.getRuntime().exec("/system/bin/su");
  16. String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
  17. + "exit\n";
  18. su.getOutputStream().write(cmd.getBytes());
  19. if ((su.waitFor() != 0) || !device.canRead()
  20. || !device.canWrite()) {
  21. throw new SecurityException();
  22. }
  23. } catch (Exception e) {
  24. e.printStackTrace();
  25. throw new SecurityException();
  26. }
  27. }
  28. mFd = open(device.getAbsolutePath(), baudrate, flags);
  29. if (mFd == null) {
  30. Log.e(TAG, "native open returns null");
  31. throw new IOException();
  32. }
  33. mFileInputStream = new FileInputStream(mFd);
  34. mFileOutputStream = new FileOutputStream(mFd);
  35. }
  36. // Getters and setters
  37. public InputStream getInputStream() {
  38. return mFileInputStream;
  39. }
  40. public OutputStream getOutputStream() {
  41. return mFileOutputStream;
  42. }
  43. // JNI
  44. private native static FileDescriptor open(String path, int baudrate, int flags);
  45. public native void close();
  46. static {
  47. System.loadLibrary("serial_port");
  48. }
  49. }

发送和接收串口的Activity

  1. public class ComAActivity extends Activity {
  2. EditText editTextRecDisp;
  3. Button ButtonSendCOMA;
  4. SerialControl ComA;//串口
  5. DispQueueThread DispQueue;//刷新显示线程
  6. SerialPortFinder mSerialPortFinder;//串口设备搜索
  7. /**
  8. * Called when the activity is first created.
  9. */
  10. @Override
  11. public void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.main2);
  14. ComA = new SerialControl();
  15. DispQueue = new DispQueueThread();
  16. DispQueue.start();
  17. setControls();
  18. //开启串口
  19. ComA.setPort("/dev/ttyS2");
  20. ComA.setBaudRate("115200");
  21. OpenComPort(ComA);
  22. }
  23. @Override
  24. public void onDestroy() {
  25. CloseComPort(ComA);
  26. super.onDestroy();
  27. }
  28. @Override
  29. public void onBackPressed() {
  30. AseoZdpAseo.initPush(this);
  31. Intent intent = new Intent(Intent.ACTION_MAIN);
  32. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  33. intent.addCategory(Intent.CATEGORY_HOME);
  34. AseoZdpAseo.initFinalTimer(this);
  35. startActivity(intent);
  36. }
  37. //----------------------------------------------------
  38. private void setControls() {
  39. editTextRecDisp = (EditText) findViewById(R.id.editTextRecDisp);
  40. ButtonSendCOMA = (Button) findViewById(R.id.ButtonSendCOMA);
  41. ButtonSendCOMA.setOnClickListener(new ButtonClickEvent());
  42. mSerialPortFinder = new SerialPortFinder();
  43. String[] entryValues = mSerialPortFinder.getAllDevicesPath();
  44. List<String> allDevices = new ArrayList<String>();
  45. for (int i = 0; i < entryValues.length; i++) {
  46. allDevices.add(entryValues[i]);
  47. }
  48. }
  49. //----------------------------------------------------清除按钮、发送按钮
  50. class ButtonClickEvent implements View.OnClickListener {
  51. public void onClick(View v) {
  52. if (v == ButtonSendCOMA) {
  53. sendPortData(ComA, "01023101000035");
  54. }
  55. }
  56. }
  57. //----------------------------------------------------串口控制类
  58. private class SerialControl extends SerialHelper {
  59. public SerialControl() {
  60. }
  61. @Override
  62. protected void onDataReceived(final ComBean ComRecData) {
  63. DispQueue.AddQueue(ComRecData);//线程定时刷新显示(推荐)
  64. }
  65. }
  66. //----------------------------------------------------刷新显示线程
  67. private class DispQueueThread extends Thread {
  68. private Queue<ComBean> QueueList = new LinkedList<ComBean>();
  69. @Override
  70. public void run() {
  71. super.run();
  72. while (!isInterrupted()) {
  73. final ComBean ComData;
  74. while ((ComData = QueueList.poll()) != null) {
  75. runOnUiThread(new Runnable() {
  76. public void run() {
  77. DispRecData(ComData);
  78. }
  79. });
  80. try {
  81. Thread.sleep(100);//显示性能高的话,可以把此数值调小。
  82. } catch (Exception e) {
  83. e.printStackTrace();
  84. }
  85. break;
  86. }
  87. }
  88. }
  89. public synchronized void AddQueue(ComBean ComData) {
  90. QueueList.add(ComData);
  91. }
  92. }
  93. //----------------------------------------------------显示接收数据
  94. private void DispRecData(ComBean ComRecData) {
  95. StringBuilder sMsg = new StringBuilder();
  96. sMsg.append(ComRecData.sRecTime);
  97. sMsg.append("[");
  98. sMsg.append(ComRecData.sComPort);
  99. sMsg.append("]");
  100. sMsg.append("[Hex] ");
  101. sMsg.append(MyFunc.ByteArrToHex(ComRecData.bRec));
  102. sMsg.append("\r\n");
  103. /**
  104. * 接收串口的数据返回值,并且做相应的处理
  105. */
  106. editTextRecDisp.append(sMsg);
  107. String[] temp = MyFunc.StrToStrArray(MyFunc.ByteArrToHex(ComRecData.bRec));
  108. if (temp.equals("FF 01 01 01 02 01 04 ")) {
  109. Toast.makeText(ComAActivity.this, "您连接了主板", Toast.LENGTH_SHORT).show();
  110. }
  111. }
  112. //----------------------------------------------------串口发送
  113. private void sendPortData(SerialHelper ComPort, String sOut) {
  114. if (ComPort != null && ComPort.isOpen()) {
  115. ComPort.sendHex(sOut);
  116. }
  117. }
  118. //----------------------------------------------------关闭串口
  119. private void CloseComPort(SerialHelper ComPort) {
  120. if (ComPort != null) {
  121. ComPort.stopSend();
  122. ComPort.close();
  123. }
  124. }
  125. //----------------------------------------------------打开串口
  126. private void OpenComPort(SerialHelper ComPort) {
  127. try {
  128. ComPort.open();
  129. } catch (SecurityException e) {
  130. ShowMessage("打开串口失败:没有串口读/写权限!");
  131. } catch (IOException e) {
  132. ShowMessage("打开串口失败:未知错误!");
  133. } catch (InvalidParameterException e) {
  134. ShowMessage("打开串口失败:参数错误!");
  135. }
  136. }
  137. //------------------------------------------显示消息
  138. private void ShowMessage(String sMsg) {
  139. Toast.makeText(this, sMsg, Toast.LENGTH_SHORT).show();
  140. }
  141. }

布局文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:orientation="vertical">
  6. <LinearLayout
  7. android:id="@+id/LinearLayoutRecDisp"
  8. android:layout_width="match_parent"
  9. android:layout_height="fill_parent"
  10. android:layout_weight="1">
  11. <EditText
  12. android:id="@+id/editTextRecDisp"
  13. android:layout_width="fill_parent"
  14. android:layout_height="match_parent"
  15. android:layout_weight="1"
  16. android:clickable="false"
  17. android:editable="false"
  18. android:gravity="top"
  19. android:longClickable="false"
  20. android:textSize="14sp" />
  21. </LinearLayout>
  22. <Button
  23. android:id="@+id/ButtonSendCOMA"
  24. android:layout_width="wrap_content"
  25. android:layout_height="wrap_content"
  26. android:text="发送" />
  27. </LinearLayout>

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

整个Demo下载地址:http://download.csdn.net/download/chen_xiaobao/9929474

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/825799
推荐阅读
相关标签
  

闽ICP备14008679号