求指导决串口数据接收混乱的问题

Android 码拜 5年前 (2016-06-04) 445次浏览
先贴上本人的代码:
从网上下载的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未知,只知道是单核的)

解决方案

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明求指导决串口数据接收混乱的问题
喜欢 (0)
[1034331897@qq.com]
分享 (0)