先贴上本人的代码:
从网上下载的SerialPort.c文件:
从网上下载的SerialPort.c文件:
#include <termios.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <jni.h> #include "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: android_serialport_SerialPort * Method: open * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; */ JNIEXPORT jobject JNICALL Java_com_zhope_SerialPort_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 */ LOGE("Invalid baudrate"); return NULL; } } /* Opening device */ { jboolean iscopy; const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy); LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags); fd = open(path_utf, O_RDWR | flags); LOGD("open() fd = %d", fd); (*env)->ReleaseStringUTFChars(env, path, path_utf); if (fd == -1) { /* Throw an exception */ LOGE("Cannot open port"); /* TODO: throw an exception */ return NULL; } } /* Configure device */ { struct termios cfg; LOGD("Configuring serial port"); if (tcgetattr(fd, &cfg)) { LOGE("tcgetattr() failed"); close(fd); /* TODO: throw an exception */ return NULL; } /*2014-1-8增加*/ cfg.c_lflag &= ~(ICANON|ECHO|ECHOE|ISIG); cfg.c_oflag &= ~OPOST;//选择原始输出 //cfg.c_cflag |= CLOCAL | CREAD | O_NDELAY; cfg.c_iflag |= IGNPAR; //忽略奇偶校验错误给数据放行 /***增加结束**/ cfg.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); cfg.c_cflag |= (CLOCAL | CREAD); cfmakeraw(&cfg); cfsetispeed(&cfg, speed); cfsetospeed(&cfg, speed); if (tcsetattr(fd, TCSANOW, &cfg)) { LOGE("tcsetattr() failed"); close(fd); /* TODO: throw an exception */ return NULL; } ioctl(fd, TIOCMGET, &cfg); cfg.c_iflag &= ~(ICRNL | IXON); ioctl(fd, TIOCMSET, &cfg); tcflush(fd, TCIFLUSH);//溢出数据可以接收,但不读 } /* 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: cedric_serial_SerialPort * Method: close * Signature: ()V */ JNIEXPORT void JNICALL Java_com_zhope_SerialPort_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); LOGD("close(fd = %d)", descriptor); close(descriptor); }
java中的接收线程:
public abstract class SerialPortDo { protected SerialPort mSerialPort; protected OutputStream mOutputStream; private InputStream mInputStream; private ReadThread mReadThread; private class ReadThread extends Thread { @Override public void run() { super.run(); while (!isInterrupted()) { int size; try { byte[] buffer = new byte[publicObject.BufferSize];//4K if (mInputStream == null) return; size = mInputStream.read(buffer); //Log.i("TAG", "数据长度:" + size); if (size > 0) { onDataReceived(buffer, size); } } catch (IOException e) { e.printStackTrace(); return; } } } }
本人把c文件用的ndk-r8e和ndk-r9编译过,现象一样。
按照协议规定,接收到的数据是0x7E+长度+数据+crc16+0x0D为完整的数据。
现在,本人接收到的数据,很多把尾部的一个或是几个字节丢了,也有部分丢的是开头的数据,另外还部分是0x7E收成了0x7F等。
本人这里使用的是android2.3.1.svn275系统,接收到的数据有差不多60%是不完整或是错误的,假如将硬件接到电脑上时,则没有这个问题。
所以,讨教高手,这种问题该怎么样解决。(本人第一次做串口开发,直接使用的手持扫描枪设备,采集模块嵌在的设备中的,CPU未知,只知道是单核的)
解决方案