国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android串口通信之串口讀寫實例

2019-10-22 18:12:49
字體:
來源:轉載
供稿:網友

Android串口通信:基本知識梳理的基礎上,我結合我項目中使用串口的實例,進行總結;

Android使用jni直接進行串口設備的讀寫網上已經有開源項目了,本文是基于網上的開源項目在實際項目中的使用做的調整和優化;
Google串口開源項目

下面是我項目中的相關代碼及介紹:

1、SerialPort.cpp

/*  * Copyright 2009 Cedric Priscal  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  * http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ #include <stdlib.h> #include <stdio.h> #include <jni.h> #include <assert.h>  #include <termios.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <jni.h>  #include "android/log.h" static const char *TAG = "serial_port"; #define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args) #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args) #define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)  static speed_t getBaudrate(jint baudrate) {  switch (baudrate) {  case 0:   return B0;  case 50:   return B50;  case 75:   return B75;  case 110:   return B110;  case 134:   return B134;  case 150:   return B150;  case 200:   return B200;  case 300:   return B300;  case 600:   return B600;  case 1200:   return B1200;  case 1800:   return B1800;  case 2400:   return B2400;  case 4800:   return B4800;  case 9600:   return B9600;  case 19200:   return B19200;  case 38400:   return B38400;  case 57600:   return B57600;  case 115200:   return B115200;  case 230400:   return B230400;  case 460800:   return B460800;  case 500000:   return B500000;  case 576000:   return B576000;  case 921600:   return B921600;  case 1000000:   return B1000000;  case 1152000:   return B1152000;  case 1500000:   return B1500000;  case 2000000:   return B2000000;  case 2500000:   return B2500000;  case 3000000:   return B3000000;  case 3500000:   return B3500000;  case 4000000:   return B4000000;  default:   return -1;  } }  /*  * Class:  cedric_serial_SerialPort  * Method: open  * Signature: (Ljava/lang/String;)V  */ JNIEXPORT jobject JNICALL native_open(JNIEnv *env, jobject thiz, jstring path,jint baudrate) {  int fd;  speed_t speed;  jobject mFileDescriptor;   LOGD("init native Check arguments");  /* Check arguments */  {   speed = getBaudrate(baudrate);   if (speed == -1) {    /* TODO: throw an exception */    LOGE("Invalid baudrate");    return NULL;   }  }   LOGD("init native Opening device!");  /* Opening device */  {   jboolean iscopy;   const char *path_utf = env->GetStringUTFChars(path, &iscopy);   LOGD("Opening serial port %s", path_utf); //  fd = open(path_utf, O_RDWR | O_DIRECT | O_SYNC);   fd = open(path_utf, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);   LOGD("open() fd = %d", fd);   env->ReleaseStringUTFChars(path, path_utf);   if (fd == -1) {    /* Throw an exception */    LOGE("Cannot open port %d",baudrate);    /* TODO: throw an exception */    return NULL;   }  }   LOGD("init native Configure device!");  /* Configure device */  {   struct termios cfg;   if (tcgetattr(fd, &cfg)) {    LOGE("Configure device tcgetattr() failed 1");    close(fd);    return NULL;   }    cfmakeraw(&cfg);   cfsetispeed(&cfg, speed);   cfsetospeed(&cfg, speed);    if (tcsetattr(fd, TCSANOW, &cfg)) {    LOGE("Configure device tcsetattr() failed 2");    close(fd);    /* TODO: throw an exception */    return NULL;   }  }   /* Create a corresponding file descriptor */  {   jclass cFileDescriptor = env->FindClass("java/io/FileDescriptor");   jmethodID iFileDescriptor = env->GetMethodID(cFileDescriptor,"<init>", "()V");   jfieldID descriptorID = env->GetFieldID(cFileDescriptor,"descriptor", "I");   mFileDescriptor = env->NewObject(cFileDescriptor,iFileDescriptor);   env->SetIntField(mFileDescriptor, descriptorID, (jint) fd);  }   return mFileDescriptor; }  /*  * Class:  cedric_serial_SerialPort  * Method: close  * Signature: ()V  */ JNIEXPORT jint JNICALL native_close(JNIEnv * env, jobject thiz) {  jclass SerialPortClass = env->GetObjectClass(thiz);  jclass FileDescriptorClass = env->FindClass("java/io/FileDescriptor");   jfieldID mFdID = env->GetFieldID(SerialPortClass, "mFd", "Ljava/io/FileDescriptor;");  jfieldID descriptorID = env->GetFieldID(FileDescriptorClass, "descriptor", "I");   jobject mFd = env->GetObjectField(thiz, mFdID);  jint descriptor = env->GetIntField(mFd, descriptorID);   LOGD("close(fd = %d)", descriptor);  close(descriptor);  return 1; }  static JNINativeMethod gMethods[] = {   { "open", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;",(void*) native_open },   { "close", "()I",(void*) native_close }, };  /*  * 為某一個類注冊本地方法  */ static int registerNativeMethods(JNIEnv* env, const char* className,   JNINativeMethod* gMethods, int numMethods) {  jclass clazz;  clazz = env->FindClass(className);  if (clazz == NULL) {   return JNI_FALSE;  }  if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {   return JNI_FALSE;  }   return JNI_TRUE; }  /*  * 為所有類注冊本地方法  */ static int registerNatives(JNIEnv* env) {  const char* kClassName = "com/jerome/serialport/SerialPort"; //指定要注冊的類  return registerNativeMethods(env, kClassName, gMethods,    sizeof(gMethods) / sizeof(gMethods[0])); }  /*  * System.loadLibrary("lib")時調用  * 如果成功返回JNI版本, 失敗返回-1  */ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {  JNIEnv* env = NULL;  jint result = -1;   if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {   return -1;  }  assert(env != NULL);   if (!registerNatives(env)) { //注冊   return -1;  }  //成功  result = JNI_VERSION_1_4;   return result; } 

在編譯時注意修改const char* kClassName = "com/jerome/serialport/SerialPort";為你Java層與jni對應得包名;

2、Android.mk

LOCAL_PATH := $(call my-dir)  include $(CLEAR_VARS)  TARGET_PLATFORM := android-3 LOCAL_MODULE := serial_port LOCAL_SRC_FILES := SerialPort.cpp LOCAL_LDLIBS := -llog  include $(BUILD_SHARED_LIBRARY) 

如果要修改生成so文件的名稱,請修改LOCAL_MODULE    := serial_port

3、SerialPort.java

package com.jerome.serialport;  import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;  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) throws SecurityException, IOException {   mFd = open(device.getAbsolutePath(), baudrate);   if (mFd == null) {    throw new IOException();   }   mFileInputStream = new FileInputStream(mFd);   mFileOutputStream = new FileOutputStream(mFd);  }   public InputStream getInputStream() {   return mFileInputStream;  }   public OutputStream getOutputStream() {   return mFileOutputStream;  }   private native FileDescriptor open(String path, int baudrate);  public native int close();   static {   System.loadLibrary("serial_port");  } } 

4、SerialPortUtil.java

package com.jerome.serialport;  import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter;  /**  * 串口操作類  *  * @author Jerome  *  */ public class SerialPortUtil {  private String TAG = SerialPortUtil.class.getSimpleName();  private SerialPort mSerialPort;  private OutputStream mOutputStream;  private InputStream mInputStream;  private ReadThread mReadThread;  private String path = "/dev/ttyMT1";  private int baudrate = 115200;  private static SerialPortUtil portUtil;  private OnDataReceiveListener onDataReceiveListener = null;  private boolean isStop = false;   public interface OnDataReceiveListener {   public void onDataReceive(byte[] buffer, int size);  }   public void setOnDataReceiveListener(    OnDataReceiveListener dataReceiveListener) {   onDataReceiveListener = dataReceiveListener;  }    public static SerialPortUtil getInstance() {   if (null == portUtil) {    portUtil = new SerialPortUtil();    portUtil.onCreate();   }   return portUtil;  }   /**   * 初始化串口信息   */  public void onCreate() {   try {    mSerialPort = new SerialPort(new File(path), baudrate);    mOutputStream = mSerialPort.getOutputStream();    mInputStream = mSerialPort.getInputStream();        mReadThread = new ReadThread();    isStop = false;    mReadThread.start();   } catch (Exception e) {    e.printStackTrace();   }   initBle();  }   /**   * 發送指令到串口   *   * @param cmd   * @return   */  public boolean sendCmds(String cmd) {   boolean result = true;   byte[] mBuffer = (cmd+"/r/n").getBytes(); //注意:我得項目中需要在每次發送后面加/r/n,大家根據項目項目做修改,也可以去掉,直接發送mBuffer   try {    if (mOutputStream != null) {     mOutputStream.write(mBuffer);    } else {     result = false;    }   } catch (IOException e) {    e.printStackTrace();    result = false;   }   return result;  }   public boolean sendBuffer(byte[] mBuffer) {   boolean result = true;   String tail = "/r/n";   byte[] tailBuffer = tail.getBytes();   byte[] mBufferTemp = new byte[mBuffer.length+tailBuffer.length];   System.arraycopy(mBuffer, 0, mBufferTemp, 0, mBuffer.length);   System.arraycopy(tailBuffer, 0, mBufferTemp, mBuffer.length, tailBuffer.length); //注意:我得項目中需要在每次發送后面加/r/n,大家根據項目項目做修改,也可以去掉,直接發送mBuffer   try {    if (mOutputStream != null) {     mOutputStream.write(mBufferTemp);    } else {     result = false;    }   } catch (IOException e) {    e.printStackTrace();    result = false;   }   return result;  }   private class ReadThread extends Thread {    @Override   public void run() {    super.run();    while (!isStop && !isInterrupted()) {     int size;     try {      if (mInputStream == null)       return;      byte[] buffer = new byte[512];      size = mInputStream.read(buffer);      if (size > 0) {       if(MyLog.isDyeLevel()){        MyLog.log(TAG, MyLog.DYE_LOG_LEVEL, "length is:"+size+",data is:"+new String(buffer, 0, size));       }       if (null != onDataReceiveListener) {        onDataReceiveListener.onDataReceive(buffer, size);       }      }      Thread.sleep(10);     } catch (Exception e) {      e.printStackTrace();      return;     }    }   }  }   /**   * 關閉串口   */  public void closeSerialPort() {   sendShellCommond1();   isStop = true;   if (mReadThread != null) {    mReadThread.interrupt();   }   if (mSerialPort != null) {    mSerialPort.close();   }  }   }

5、使用方法:

a、配置ndk開發環境,具體百度一下;
b、工程根目錄下新建jni文件夾,將Android.mk和SerialPort.cpp放進去;
c、ndk中進入jni目錄,編譯生成so文件,默認so生成在libs/armeabi下;
d、新建com.jerom.serialport目錄,將SerialPort和SerialPortUtil放進去;
 f、在你要使用的地方初始化SerialPortUtil,實現回調接口OnDataReceiveListener即可接受數據;

總結:

1、串口發送實質就是向串口設備(類似于文件操作)寫入字節流,串口讀取也是一樣;
2、主要jni與Java native得對應;

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 乌拉特前旗| 抚松县| 固始县| 会泽县| 长宁区| 铁岭市| 平陆县| 万州区| 都安| 长阳| 兴和县| 安阳市| 卫辉市| 卫辉市| 丰县| 昂仁县| 鹤山市| 塘沽区| 凤庆县| 上高县| 迁安市| 宣城市| 尼木县| 天峻县| 许昌县| 石台县| 恩施市| 灵川县| 宣化县| 通海县| 宁晋县| 安新县| 新源县| 新野县| 民丰县| 遂川县| 深州市| 汝阳县| 濮阳县| 尚志市| 巴楚县|