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);
- }