android4.2串口jni收发数据(基于自定义协议)

代码已经验证过,没问题 !但界面部分没有贴,只是提供思路!

代码层次结构:

|-----serial_communication_class---

|                     |-------src---------

|                                  |------com------

|                                             |----object-----

|                                                      |------nvs------

|                                                                     |-----client------

|                                                                                   |---MainActivity.java

|                                                                                   |----SerialJNI.java

|                     |--------jni-----------------------------------------------------

|                                    |------- Android.mk

|                                    |--------object_nvs_client_SerialJNI.c

|                     |--------Android.mk

|                     |---------AndroidManifest.xml

现在贴代码:

-------------------------------------------SerialJNI.java---------------------------------------------------

package object.nvs.client;


public class SerialJNI{

     

public native int open_dev(String dev, int baudrate);

    public native int send_command(int fd, char[] sb, int len);

    public native void receive_data(int fd, int len);

    public native int close_dev(int fd);

         

    static{

        System.loadLibrary("serialjni");//与jni中的Android.mk中的jni模块名LOCAL_MODULE:= libserialjni相比少了lib

    }

  public byte[] bytes = new byte[32]; //Accessing Fields,用于装载JNI中的返回数据


public void callback() {//方法回调,JNI中一有数据此方法就被回调一次,所以对数据的所有操作建议都放于此

int i;

for(i=0;i<32;i++){

System.out.println(bytes[i]&0xff);

}

}

}

---------------------------------------------------end--------------------------------------------------

应用层调用:

---------------------------------------------MainActivity.java-------------------------------------------

package object.nvs.client;


import com.test.serial.R;


import android.os.Bundle;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.app.Activity;


public class MainActivity extends Activity {

final char stop2[]={0xFF,0x20,0x01,0x40,0x1D,0x07,0x12,0x01,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA4};

private Button btn_send;

SerialJNI serialPort;

int fd;

Thread thread;

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

btn_send = (Button)findViewById(R.id.button1);

serialPort = new SerialJNI();

fd = serialPort.open_dev("/dev/ttyS7", 38400);

thread = new Thread(new Runnable() {

private String TAG = "serial";


@Override

public void run() { 

// TODO Auto-generated method stub

serialPort.receive_data(fd, 32);//此方法必须在APP起来时候就调用,串口初始化的的操作都在此方法里,而且必须启用线程来操作

Log.i(TAG , "do it receive_datadown");

}

});

thread.start();

btn_send.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View arg0) {

// TODO Auto-generated method stub

int ret = serialPort.send_command(fd, stop2, 32);

System.out.println("btn_send--- send command\n");

if(ret < 0)

System.out.println("send command error!\n");

}

});

--------------------------------------------end--------------------------------------------------------

jni部分:

----------------------------------object_nvs_client_SerialJNI.c------------------------------

/*

 * Copyright (C) 2009 The Android Open Source Project

 *

 * 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.

 * wangjian1937@live.cn

 */


#include   <stdarg.h>

#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   <string.h>

#include <jni.h>

#include   <pthread.h>

#include <android/log.h>

#include <sys/file.h>


#define LOG    "serial-jni"

#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG,__VA_ARGS__)  

#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG,__VA_ARGS__) 

#define LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG,__VA_ARGS__)  

#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG,__VA_ARGS__)  

#define LOGF(...)  __android_log_print(ANDROID_LOG_FATAL,LOG,__VA_ARGS__)

#define TRUE 1

#define FALSE -1

#define BUFSIZE 32


int BaudRate = B9600;

static int speed_arr[] = {B115200,B38400,B19200,B9600,B4800,B2400,B1200,B300,

    B38400,B19200,B9600,B4800,B2400,B1200,B300};

static int name_arr[] = {115200,38400,19200,9600,4800,2400,1200,300,

    38400,19200,9600,4800,2400,1200,300};

char resend[]={0xFF,0x20,0x02,0x01,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0E}; 

char stop[]={0xFF,0x20,0x02,0x02,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0F};


/*

 *Native Method

 *Method : setTermios

 */

void setTermios(struct termios * pNewtio, int uBaudRate)

{

    bzero(pNewtio, sizeof(struct termios));


    //8N1

    pNewtio->c_cflag = uBaudRate | CS8 | CREAD | CLOCAL;

    pNewtio->c_iflag = IGNPAR;

    pNewtio->c_oflag = 0;

    pNewtio->c_lflag = 0; //non ICANON

   

    pNewtio->c_cc[VINTR] = 0;

    pNewtio->c_cc[VQUIT] = 0;

    pNewtio->c_cc[VERASE] = 0;

    pNewtio->c_cc[VKILL] = 0;

    pNewtio->c_cc[VEOF] = 4;

    pNewtio->c_cc[VTIME] = 5;

    pNewtio->c_cc[VMIN] = 0;

    pNewtio->c_cc[VSWTC] = 0;

    pNewtio->c_cc[VSTART] = 0;

    pNewtio->c_cc[VSTOP] = 0;

    pNewtio->c_cc[VSUSP] = 0;

    pNewtio->c_cc[VEOL] = 0;

    pNewtio->c_cc[VREPRINT] = 0;

    pNewtio->c_cc[VDISCARD] = 0;

    pNewtio->c_cc[VWERASE] = 0;

    pNewtio->c_cc[VLNEXT] = 0;

    pNewtio->c_cc[VEOL2] = 0;

}


/*

 * Class:     object_nvs_client_SerialJNI

 * Method:    open_dev

 * Signature: (Ljava/lang/String;)I

 */

JNIEXPORT jint JNICALL Java_object_nvs_client_SerialJNI_open_1dev

  (JNIEnv *env, jobject obj, jstring dev, jint baudrate){

  int i;

 const char *Dev_utf = (*env)->GetStringUTFChars(env, dev, JNI_FALSE);

    int fd = open(Dev_utf, O_RDWR);

    (*env)->ReleaseStringUTFChars(env, dev, Dev_utf);

if (-1 == fd)

{ /*设置数据位数*/

LOGE("Can't Open Serial Port\n");

return -1;

}

  for(i=0; i<sizeof(speed_arr)/sizeof(int); i++)

    {

      if(baudrate == name_arr[i])

      {

BaudRate = speed_arr[i];

        break ;

      }

    }

    LOGD("Open Serial Port:%s,set speed:%d\n", Dev_utf, baudrate);

return fd;

  }

 

/*

 * Class:     object_nvs_client_SerialJNI

 * Method:    close_dev

 * Signature: (I)I

 */

JNIEXPORT jint JNICALL Java_object_nvs_client_SerialJNI_close_1dev

  (JNIEnv *env, jobject obj, jint fd){

close(fd);

return TRUE;

}

 


/*

 * Native Method 

 * Method:    set_Parity

 */

int serial_set_parity(int fd, int databits, int stopbits, int parity){

  struct termios options;

 if(tcgetattr(fd, &options)  !=  0)

 {

  LOGE("SetupSerial 1.");

  return(FALSE);

 } 

 options.c_cflag &= ~CSIZE;

 switch(databits) /*设置数据位数*/

 {

  case 7:

  options.c_cflag |= CS7;

  break;

  case 8:

options.c_cflag |= CS8;

break;

 default:

LOGE("Unsupported data size");

return (FALSE);

}

 switch(parity)

  {

  /* 没有校验 */

  case 'n':

case 'N':

options.c_cflag &= ~PARENB;   /* Clear parity enable */

options.c_iflag &= ~INPCK;     /* Enable parity checking */

break;

/* 奇校验 */

case 'o':

case 'O':

options.c_cflag |= (PARODD | PARENB);  /* 设置为奇效验*/ 

options.c_iflag |= INPCK;             /* Disnable parity checking */

break;

/* 偶校验 */

case 'e':

case 'E':

options.c_cflag |= PARENB;     /* Enable parity */

options.c_cflag &= ~PARODD;   /* 转换为偶效验*/  

options.c_iflag |= INPCK;       /* Disnable parity checking */

break;

case 'S':

case 's':  /*as no parity*/

options.c_cflag &= ~PARENB;

options.c_cflag &= ~CSTOPB;

break;

default:

LOGE("Unsupported parity.");

return (FALSE);

}

 /* 设置停止位*/   

 switch(stopbits)

  {

  case 1:

  options.c_cflag &= ~CSTOPB;

break;

case 2:

options.c_cflag |= CSTOPB;

break;

default:

LOGE("Unsupported stop bits");

return (FALSE);

}

 /* Set input parity option */

 if(parity != 'n')

  options.c_iflag |= INPCK;

 options.c_cc[VTIME] = 150; // 15 seconds

 options.c_cc[VMIN] = 0;

 tcflush(fd,TCIFLUSH); /* Update the options and do it NOW */

 if(tcsetattr(fd,TCSANOW,&options) != 0)

{

LOGE("SetupSerial 3");

return (FALSE);

}

 return (TRUE);

  }

 

void serial_close(int fd)

{

close(fd);

}

 

/*

 * Class:     object_nvs_client_SerialJNI

 * Method:    send_command

 * Signature: (I[CI)I

 */

JNIEXPORT jint JNICALL Java_object_nvs_client_SerialJNI_send_1command

  (JNIEnv *env, jobject obj, jint fd, jcharArray buff, jint len){

  int i;

  char command[BUFSIZE+1] = {0}; 

  jchar *jc = (*env)->GetCharArrayElements(env, buff, NULL);

  //LOGD("Send_command %d\n", fd);

  for(i=0;i<BUFSIZE;i++){

  command[i] = (char)jc[i]&0xff;//java中char[]数组元素是char类型占2个字节和jni中的jchar相同,要转换成一个字节的char类型所以要去掉一个字节,方法就是将每个元素&oxff

  }

  if(write(fd, command, BUFSIZE)>0)

    {

        LOGD("write success !\n");

    }

    else

    {

        LOGE("write failed!\n");

    }

  (*env)->ReleaseCharArrayElements(env, buff, jc, 0);

  return 0;  

  }

 

 /*

 * Class:     object_nvs_client_SerialJNI

 * Method:    receive_data

 * Signature: (II)V

 */

JNIEXPORT void JNICALL Java_object_nvs_client_SerialJNI_receive_1data

  (JNIEnv *env, jobject obj, jint fd, jint len){

  jstring jstr;

  jfieldID fid;

  jbyteArray bytearray;

  const char *str;

int i;

int sum = 0;

    int nread,nwrite;

    char buff[BUFSIZE+1];

    char buff1[BUFSIZE+1];

    char buff2[BUFSIZE+1];

    struct termios oldtio, newtio;

    struct timeval tv;

    fd_set rfds;

    

bzero(buff, BUFSIZE+1);

bzero(buff1, BUFSIZE+1);

bzero(buff2, BUFSIZE+1);


tcgetattr(fd, &oldtio);

setTermios(&newtio, BaudRate);

    tcflush(fd, TCIFLUSH);

    tcsetattr(fd, TCSANOW, &newtio);

    if (serial_set_parity(fd,8,1,'N') == FALSE)

 {

   LOGE("Set Parity Error\n");

   serial_close(fd);

   return;

 }

    tv.tv_sec=30;

    tv.tv_usec=0;

    

    bytearray = (*env)->NewByteArray(env,BUFSIZE+1);

    jclass cls1 = (*env)->GetObjectClass(env, obj);

    jclass cls2 = (*env)->GetObjectClass(env, obj);

    fid = (*env)->GetFieldID(env, cls1, "bytes", "[B");

    if (fid == NULL) 

    {

    LOGE("failed to find the field!");

    serial_close(fd);

return; /* failed to find the field */

}

jmethodID mid = (*env)->GetMethodID(env, cls2, "callback", "()V");

if (mid == NULL) 

{

LOGE("method not found!");

serial_close(fd);

return; /* method not found */

}

    while(TRUE)

    {

    sum = 0;

    sleep(1);

   LOGD("wait wait...");

   FD_ZERO(&rfds);

   FD_SET(fd, &rfds);

   if(select(1+fd, &rfds, &rfds, NULL, &tv)>0)

   {

      if(FD_ISSET(fd, &rfds))

        {

        nread=read(fd, buff, BUFSIZE);

        LOGD("Accept date nread = %d, fd = %d", nread, fd);

           if(nread == BUFSIZE)

  {

  //LOGD("BUFSIZE:%d", BUFSIZE);      

             //printf("readlength=%d\n", nread);

             buff[nread]='\0';

             //printf("buff[1]=%c\n", buff[0]);


           if((buff[0] == 0xff) && (buff[1] == 0x20))

           {

            for(i=1;i<=nread-2;i++)

           {

            sum += buff[i];

            //LOGD("buff[%d]=%0x, sum =%0x", i, buff[i], (char)sum);

           }

            //printf("(buff[0] == 0xff) && (buff[1] == 0x0b)\n");           

             if(buff[nread-1] == (char)sum)

            { 

            LOGD("Accept frame correct!");

            switch(buff[2])

            {

            case 0X01:

            if(memcpy(buff1, buff, nread) != NULL)

            {

            LOGD("memcpy success!");

            //buff[2]=0x03;

            //buff[nread-1] = buff[nread-1]+0x02;

            //nwrite=write(fd, buff, BUFSIZE);

            //if(nwrite == BUFSIZE)

//{

//LOGD("write_response_length=%d", nwrite);

//if(memcpy(buff2, buff, nread) != NULL)

//LOGD("response buff memcpy to buff2 success!");

(*env)->SetByteArrayRegion(env, bytearray, 0, BUFSIZE+1, buff1);

(*env)->SetObjectField(env, obj, fid, bytearray);

(*env)->CallVoidMethod(env, obj, mid);

//}

            }else

            {

            LOGE("memcpy fail!");

            nwrite=write(fd, resend, BUFSIZE);

            if(nwrite == BUFSIZE)

{

if(memcpy(buff2, resend, nread) == NULL)

LOGE("resend buff memcpy to buff2 failed!");

//LOGD("write_resend_length=%d", nwrite);

}

            }

            tcflush(fd, TCIOFLUSH);            

            continue;

            case 0X02:

            switch(buff[3])

            {

            case 0x01:

            LOGD("resend command!");

            nwrite=write(fd, buff2, BUFSIZE);

            if(nwrite == BUFSIZE)

{

if(memmove(buff2, buff2, nread) == NULL)

LOGE("resend buff memcpy to buff2 failed!\n");

//LOGD("write_buff2_length=%d", nwrite);

}

tcflush(fd, TCIOFLUSH);            

            continue;

            case 0x02:

            LOGD("stop send command!");

            tcflush(fd, TCIOFLUSH);

            continue;

            case 0x03:

            LOGD("open rf receive command!");

            tcflush(fd, TCIOFLUSH);

            continue;

            case 0x04:

            LOGD("open rf send command!");

            tcflush(fd, TCIOFLUSH);

            continue;

            case 0x05:

            LOGD("close rf command!");

            tcflush(fd, TCIOFLUSH);

            continue;

            case 0x06:

            LOGD("rf send command!");

            tcflush(fd, TCIOFLUSH);

            continue;

            case 0x07:

            LOGD("get client rf state!");

            tcflush(fd, TCIOFLUSH);

            continue;

            default :

            LOGD("other command!");

            tcflush(fd, TCIOFLUSH);

            continue;            

            }

            case 0X03:

            switch(buff[4])

            {

            case 0X01:

            LOGD("Execute/receive successfully!");

            tcflush(fd, TCIOFLUSH);

            continue;

            case 0X02:

            LOGE("receive fail(client)!");

            nwrite=write(fd, buff2, BUFSIZE);

            if(nwrite == BUFSIZE)

{

if(memmove(buff2, buff2, nread) == NULL)

LOGE("resend buff memcpy to buff2 failed!\n");

//LOGD("write_buff2_length=%d\n", nwrite);

}

tcflush(fd, TCIOFLUSH);

            continue;

            case 0X03:

            LOGD("not support!");

            tcflush(fd, TCIOFLUSH);

            continue;

            case 0X04:

            LOGE("Execute fail!");

            nwrite=write(fd, buff2, BUFSIZE);

            if(nwrite == BUFSIZE)

{

if(memmove(buff2, buff2, nread) == NULL)

LOGE("resend buff memcpy to buff2 failed!");

//LOGE("write_buff2_length=%d", nwrite);

}

tcflush(fd, TCIOFLUSH);

            continue;

            case 0X05:

            LOGD("send success!");

            tcflush(fd, TCIOFLUSH);

            continue;

            case 0X06:

            LOGD("not response!");

            tcflush(fd, TCIOFLUSH);

            continue;            

            default:

            LOGD("other state!");

            tcflush(fd, TCIOFLUSH);

            continue;

            }

            default :

            LOGD("not correct fomart!");

            tcflush(fd, TCIOFLUSH);            

            continue;

            }            

            }else

            {

            LOGE("buff[nread-1] != (char)sum,Accept frame wrong!");

            nwrite=write(fd, resend, BUFSIZE);

            if(nwrite == BUFSIZE)

{

if(memcpy(buff2, resend, nread) == NULL)

LOGE("resend buff memcpy to buff2 failed!\n");

//LOGD("write_resend_length=%d", nwrite);

}

            }

            }else

            {

            LOGD("buff[0] != 0xff || buff[1] != 0x0b");

            }

          }             

        }

    }

   tcflush(fd, TCIOFLUSH);

    }

    tcsetattr(fd, TCSANOW, &oldtio);

    serial_close(fd);

return;

  }

  ----------------------------------------------end----------------------------------------------------------

  顶层makefile:

---------------------------------------Android.mk---------------------------------------------

#

# Copyright (C) 2008 The Android Open Source Project

#

# 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.

#


# This makefile shows how to build a shared library and an activity that

# bundles the shared library and calls it using JNI.


TOP_LOCAL_PATH:= $(call my-dir)


# Build activity



LOCAL_PATH:= $(TOP_LOCAL_PATH)

include $(CLEAR_VARS)


LOCAL_MODULE_TAGS := optional


LOCAL_SRC_FILES := $(call all-subdir-java-files)


LOCAL_PACKAGE_NAME := Serial


LOCAL_JNI_SHARED_LIBRARIES := libSerialjni


LOCAL_PROGUARD_ENABLED := disabled


LOCAL_SDK_VERSION := current


include $(BUILD_PACKAGE)


# ============================================================


# Also build all of the sub-targets under this one: the shared library.

include $(call all-makefiles-under,$(LOCAL_PATH))

-------------------------------------------end--------------------------------------------------------------

jni下的MAKEFILE

-----------------------------------------Android.mk--------------------------------------------------------

#

# Copyright (C) 2008 The Android Open Source Project

#

# 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.

#


# This makefile supplies the rules for building a library of JNI code for

# use by our example of how to bundle a shared library with an APK.


LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)


LOCAL_MODULE_TAGS := optional


# This is the target being built.

LOCAL_MODULE:= libserialjni


LOCAL_LDLIBS :=-llog


# All of the source files that we will compile.

LOCAL_SRC_FILES:= \

    object_nvs_client_SerialJNI.c


# All of the shared libraries we link against.

LOCAL_SHARED_LIBRARIES := \

libutils\


# No static libraries.

LOCAL_STATIC_LIBRARIES := 


# Also need the JNI headers.

LOCAL_C_INCLUDES += \

$(JNI_H_INCLUDE)\


# No special compiler flags.

LOCAL_CFLAGS +=


include $(BUILD_SHARED_LIBRARY)

--------------------------------------------------------end-----------------------------------------------

AndroidManifest.xml

--------------------------------------------AndroidManifest.xml--------------------------------------

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="serial"

    android:versionCode="1"

    android:versionName="1.0" >


    <uses-sdk

        android:minSdkVersion="8"

        android:targetSdkVersion="17" />


    <application

        android:allowBackup="true"

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name"

        android:theme="@style/AppTheme" >

        <activity

            android:name="object.nvs.client.MainActivity"

            android:label="@string/app_name" >

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

    </application>


</manifest>

-------------------------------------------------------end-------------------------------------------

 



转载于:https://my.oschina.net/u/1176566/blog/291671

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值