Android 串口通信实例分析,用的时开源的android-serialport-api
这个是用android ndk实现的串口通信,我把他做了一个简化,适合于一般的程序的串口通信移植,欢迎拍砖~~~~~~~~~
先说jni接口吧,原本文件太多,其实只需要SerialPort.c和Android.mk就可以实现
Serialport.c
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <termios.h>
- #include <errno.h>
- #include <jni.h>
- #include <android/log.h>
- #define LOGI(…) ((void)__android_log_print(ANDROID_LOG_INFO, “”, __VA_ARGS__))//在logcat上打印信息用
- //#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: com.huangcheng.serial.SerialPort
- * Method: open
- * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
- *
- * 用于打开串口,配置串口参数,包括的参数有path(需要打开的串口设备文件路径),baudrate(波特率),flags(打开串口的参数,如O_NONBLOCK之类的,可以随不同情况设置)
- * 其串口数据的读取是用FileDescriptor来实现的
- *
- */
- JNIEXPORT jobject JNICALL Java_com_huangcheng_serial_SerialPort_open
- (JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags)
- {
- int fd;
- speed_t speed;
- jobject mFileDescriptor;
- /* Check arguments */
- {
- speed = getBaudrate(baudrate);
- if (speed == –1) {
- /* TODO: throw an exception */
- LOGI(“Invalid baudrate”);
- return NULL;
- }
- }
- /* Opening device */
- {
- jboolean iscopy;
- const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);
- LOGI(“Opening serial port %s with flags 0x%x”, path_utf, O_RDWR | flags);
- fd = open(path_utf, O_RDWR | flags);
- LOGI(“open() fd = %d”, fd);
- (*env)->ReleaseStringUTFChars(env, path, path_utf);
- if (fd == –1)
- {
- /* Throw an exception */
- LOGI(“Cannot open port”);
- /* TODO: throw an exception */
- return NULL;
- }
- }
- /* Configure device */
- {
- struct termios cfg;
- LOGI(“Configuring serial port”);
- if (tcgetattr(fd, &cfg))
- {
- LOGI(“tcgetattr() failed”);
- close(fd);
- /* TODO: throw an exception */
- return NULL;
- }
- cfmakeraw(&cfg);
- cfsetispeed(&cfg, speed);
- cfsetospeed(&cfg, speed);
- if (tcsetattr(fd, TCSANOW, &cfg))
- {
- LOGI(“tcsetattr() failed”);
- close(fd);
- /* TODO: throw an exception */
- return NULL;
- }
- }
- /* Create a corresponding file descriptor */
- {
- jclass cFileDescriptor = (*env)->FindClass(env, “java/io/FileDescriptor”);
- jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, “<init>”, “()V”);
- jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, “descriptor”, “I”);
- mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor);
- (*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint)fd);
- }
- return mFileDescriptor;
- }
- /*
- * Class: com.huangcheng.serial.SerialPort
- * Method: close
- * Signature: ()V
- *
- * 用于串口关闭
- */
- JNIEXPORT void JNICALL Java_com_huangcheng_serial_SerialPort_close
- (JNIEnv *env, jobject thiz)
- {
- jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);
- jclass FileDescriptorClass = (*env)->FindClass(env, “java/io/FileDescriptor”);
- jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, “mFd”, “Ljava/io/FileDescriptor;”);
- jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, “descriptor”, “I”);
- jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);
- jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);
- LOGI(“close(fd = %d)”, descriptor);
- close(descriptor);
- }