Android串口通信:串口读写
FROM:http://blog.csdn.net/burly/article/details/50512379
公司有个项目要用到串口通信,同事有写好一个DEMO,用的时候发现会有问题,从jni读串口数据时,经常会被截断,修改select延时还是无济于事,于是想到用Java直接去读/写串口文件,经过搜索在iteye上的一篇博客1可以满足需求,但看到下面留言说有问题,自己试了下确实是有问题,经过一些小小的修改验证后没问题,并整理了一个DEMO。
项目主要代码
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 "log.h"
#include "com_skyworth_splicing_SerialPort.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 Java_com_skyworth_splicing_SerialPort_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 Java_com_skyworth_splicing_SerialPort_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/skyworth/splicing/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_6;//result = JNI_VERSION_1_4; return result;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
我把它修改成JNI通用的那种模式,把文件名和函数名改成对应JAVA文件的包名和类名,这个一定要一致,不然无法调用成功,并增加.H文件见DEMO源码的jni目录。CPP的编译直接在源码服务器编译的,没有在WINDOWS NDK下编译,有源码就没去折腾了。
JAVA代码
JAVA相关基本没改,去掉一些业务相关的代码:
SerialPort.java
package com.skyworth.splicing;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;
/*** 串口操作* * @author guoxiao* */
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");}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
SerialPortUtil.java
package com.skyworth.splicing;import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;/*** 串口操作* * @author guoxiao* */
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/ttyS3";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;}/*** 初始化串口通信*/private 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();}}/*** 发送指令到串口* * @param cmd* @return*/public boolean sendCmds(String cmd) {boolean result = true;byte[] mBuffer = cmd.getBytes();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 = "";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);try {if (mOutputStream != null) {mOutputStream.write(mBufferTemp);} else {result = false;}} catch (IOException e) {e.printStackTrace();result = false;}return result;}private class ReadThread extends Thread {@Overridepublic 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) {
// String str = new String(buffer, 0, size);
// Logger.d("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() {isStop = true;if (mReadThread != null) {mReadThread.interrupt();}if (mSerialPort != null) {mSerialPort.close();}}}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
串口工具类的调用:
package com.example.serialutil;import com.skyworth.splicing.SerialPortUtil;
import com.skyworth.splicing.SerialPortUtil.OnDataReceiveListener;import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
/** @author guoxiao* */
public class SerialActivity extends Activity {SerialPortUtil mSerialPortUtil;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_hello_world);//单模式mSerialPortUtil = SerialPortUtil.getInstance();mSerialPortUtil.setOnDataReceiveListener(new OnDataReceiveListener() {@Overridepublic void onDataReceive(byte[] buffer, int size) {// TODO Auto-generated method stubLog.d("[gx]", " DataReceive:" + new String(buffer,0,size));}});}public void onWrite(View view){mSerialPortUtil.sendCmds("<open,1,0,3,0,0,0,0,0,0,1910,1070>");}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.hello_world, menu);return true;}}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
总结:
- CPP的文件名和函数名一定要和JAVA的包名和类名对应
- 串口读操作时使用了一个线程
- 写串口时最终是byte类型,注意符号位的问题
DEMO下载地址:http://download.csdn.net/detail/burly/9402739
Android串口通信:串口读写相关推荐
- MFC串口通信串口指示灯的实现
前一段做了个串口通信小软件,当打开串口时串口指示灯亮,关闭串口时串口指示灯灭,实现方法如下: 1.在资源视图中,添加两个图标,分别为串口指示灯灭IDI_ICON1,串口指示灯亮IDI_ICON2. 2 ...
- 51单片机-串口通信(串口向电脑发送信息电脑通过串口控制LED)
文章目录 前言 一.串行通信口的功能以及串行通信口的结构及原理 1.1 串行通信口的功能 1.2 51单片机串口的结构 二.串行通信口的控制寄存器 2.1 串行控制寄存器SCON 2.2 电源控制寄存 ...
- 项目总结一:串口通信 || 串口接收数据和写入的数据不一致
在做项目串口通信时遇到一个奇怪的bug,我写入的一个两个字节short类型数据3,接受到的数据很奇怪有时是一个很大的数,有时又是300多,为了找到原因也是废了一些时间,这里给分享一下,希望对做串口通信 ...
- 串口通信—串口发送和接收代码讲解
USART 初始化结构体详解 标准库函数对每个外设都建立了一个初始化结构体,比如USART_InitTypeDef,结构体成员用于设置外设工作参数,并由外设初始化配置函数,比如USART_Init() ...
- 串口通信——串口uart
在两个mcu中发送数据,可选择串行通讯,或者并行通讯. 假设要通信传输一个十进制数198,在通信过程中转换为二进制数11000110. 串行通讯需要在MCU间连接一根数据线,按照二进制位顺序发送即可. ...
- STM32串口通信串口助手收不到数据
问题: 已经确定代码是没有问题的,但是串口调试助手就是收不到消息 解决办法: 别急,我来帮你 右击工程,选择Options for Target 'test' 然后...... 这里打勾, 然后,OK ...
- 串口通信——串口接收数据,发送数据
十六进制 HEX /hexadecimal /ˌheksəˈdesɪml/ 十进制 DEC /decimalism /'desiməlizəm/ 二进制 ...
- P27[9-3]STM32:串口通信(串口发送)(内含:1.接线图+2.实物图+3.代码部分+4.解决串口发送数据,数据是汉字,结果发送结果为乱码的现象)
1.接线图如下: 跳线帽接在4~5引脚,2,3引脚连接PA9和PA10引脚.下图也可得出USART接PA9和PA10引脚. TX和RX是交叉连接.PA9(黄线)是TX,接RXD.PA9(绿线)是RXD ...
- USB、USB转串口、串口通信的区别与实现
Android如何监听USB插拔 全网独一无二的USB.USB转串口二合一通信SDK USB通信使用系统api,USB转串口通信使用第三方库usb-serial-for-android,串口通信使用G ...
最新文章
- 本地mysql备份至rds_阿里云RDS备份在本地mysql快速还原
- linux ps查看进程命令
- 字符串匹配的KMP算法(转)
- HDU1106 排序(解法二)(废除!!!)
- poj 3278 bzoj 1646: [Usaco2007 Open]Catch That Cow 抓住那只牛(BFS)
- 孙茂松教授——自然语言处理一瞥:知往鉴今瞻未来
- paip.图片文件上传功能总结
- java代码定义窗口_代码窗口九种方式实现 javascripts 弹出对话框窗口代码
- matlab检验相关性显著性检验,基于matlab的栅格数据相关分析及显著性检验
- 工业相机镜头相关知识整理
- 如何快速上手制作高质量短视频?
- Nova 最新高度集成的SoC NT98530用于开发4K@60的IPC产品_AI算法承载硬件_开发实例
- Java开发——IDEA
- nginx安装、配置文件详解、测试
- Pytorch中的Conv1d()和Conv2d()函数
- 制作类似于淘宝点击简单的轮播图
- CSS样式:渐变色圆角边框
- idea翻译软件TKK网络连接超时
- 【STM32F407的DSP教程】第48章 STM32F407的中值滤波器实现,适合噪声和脉冲过滤(支持逐个数据的实时滤波)
- java8 51下载_JRE 8u51windows
热门文章
- 图片怎么在线转换成PDF格式
- matlab合成和弦,基于Matlab实现音乐识别与自动配置和声的功能.pdf
- 一键电子书:最好用的电子书一键生成软件
- SAP ABAP 自动批量开关账期程序 OB52和MMPV
- 卡片消除游戏 java版(代码+讲解)
- 通过python和两张图片实现漫天蝴蝶飞舞的合成图像
- Fluent网格划分经验
- tof 相机的数据读取,depth data和amplitude data以及3D数据
- java职业发展路线图_从程序员到CTO的Java技术路线图 JAVA职业规划 JAVA职业发展路线图 系统后台框架图、前端工程师技能图 B2C电子商务基础系统架构解析...
- excel统计每个单元格内的单词及空格的个数