串口通信

    xiaoxiao2021-12-14  16

    http://blog.csdn.net/tianruxishui/article/details/37592903#comments

    1. 本地类TtyNativeControl

    package com.notioni.uart.manager;

    import Java.lang.ref.WeakReference;

    import Android.os.Handler;

    import android.os.Looper;

    import android.os.Message;

    import android.util.Log;

    /**

    本地方法类

    */

    public class TtyNativeControl {

    private final static String TAG = "TtyNativeControl";

    static{

    System.loadLibrary("uart_ctl");

    }

    private static final int TTY_MSG_RECEIVE = 1;

    private static final int TTY_CLOSE_DEVICE = TTY_MSG_RECEIVE+1;

    private EventHandler mEventHandler;

    private ReceiveCallback mReceiveCallBack;

    TtyNativeControl(){

    mReceiveCallBack = null;

    Looper looper;

    if((looper = Looper.myLooper()) != null){

    mEventHandler = new EventHandler(this, looper);

    }else if((looper = Looper.getMainLooper()) != null){

    mEventHandler = new EventHandler(this, looper);

    }else{

    mEventHandler = null;

    }

    native_setup(new WeakReference<TtyNativeControl>(this));

    }

    /**

    打开驱动

    @return 是否打开成功

    */

    public int openTty(){

    return _openTty();

    }

    /**

    关闭驱动,需要一定时间,所以采用Handler机制

    */

    public int closeTty(){

    // mEventHandler.obtainMessage(TTY_CLOSE_DEVICE).sendToTarget();

    // return 1;

    return _closeTty();

    }

    /**

    发送数据

    @param data

    @return

    */

    public int sendMsgToTty(byte[] data){

    return _sendMsgToTty(data);

    }

    /**

    接收数据

    @param callback

    */

    public final void receiveMsgFromTty(ReceiveCallback callback){

    mReceiveCallBack = callback;

    _receiveMsgFromTty();

    }

    /**

    设置串口数据位,校验位,速率,停止位

    @param databits 数据位 取值 78

    @param event 校验类型 取值N ,E, O,

    @param speed 速率 取值 2400,4800,9600,115200

    @param stopBit 停止位 取值或者 2

    */

    public int configTty(int databits,char event,int speed,int stopBit){

    return _configTty(databits, event, speed, stopBit);

    }

    /**

    @param mode 是否使用原始模式(Raw Mode)方式来通讯 取值0,1,2 说明:0=nothing,1=Raw mode,2=no raw mode

    @param showLog 打印出串口信息Log 取值1,0

    */

    public int setMode(int mode ,int showLog){

    return _setMode(mode, showLog);

    }

    /**

    接收数据回调接口

    */

    public interface ReceiveCallback{

    void onReceiveData(byte[] data,TtyNativeControl tty);

    }

    /****************************************************************

    本地方法

    */

    private native final void native_setup(Object tty_this);

    private native int _openTty();

    private native int _closeTty();

    private native int _sendMsgToTty(byte[] data);

    private native void _receiveMsgFromTty();

    private native int _configTty(int databits,char event,int speed,intstopBit);

    private native int _setMode(int mode,int showLog);

    /*

    实现底层回调

    */

    private static void postEventFromNative(Object tty_ref,int what ,intarg1,intarg2,Object obj){

    Log.i(TAG"[postEventFromNative] what:"+what);

    TtyNativeControl t = (TtyNativeControl)((WeakReference)tty_ref).get();

    if(t == null)return;

    if(t.mEventHandler != null){

    Message m = t.mEventHandler.obtainMessage(what, arg1, arg2,obj);

    t.mEventHandler.sendMessage(m);

    }

    }

    private class EventHandler extends Handler{

    private TtyNativeControl mTty;

    public EventHandler(TtyNativeControl t,Looper looper){

    super(looper);

    mTty = t;

    }

    @Override

    public void handleMessage(Message msg) {

    switch(msg.what){

    case TTY_MSG_RECEIVE://底层接收数据回调上来的事件

    if(mReceiveCallBack != null){

    mReceiveCallBack.onReceiveData((byte[])msg.obj,mTty);

    }

    return;

    case TTY_CLOSE_DEVICE://关闭驱动

    _closeTty();

    break;

    }

    }

    }

    }

    2. JNI类头文件

    #include <jni.h>

    #ifndef _Included_com_notioni_uart_manager_TtyNativeControl

    #define _Included_com_notioni_uart_manager_TtyNativeControl

    #ifdef __cplusplus

    extern "C"{

    #endif

    /**

    * Class com_notioni_uart_TtyNativeControl

    * Method

    */

    JNIEXPORT static void JNICALL com_notioni_uart_manager_TtyNativeControl_native_setup(JNIEnv *env,jobject clazz,jobject weak_this);

    JNIEXPORT static int JNICALL com_notioni_uart_manager_TtyNativeControl__openTty(JNIEnv *env,jobject clazz);

    JNIEXPORT static int JNICALL com_notioni_uart_manager_TtyNativeControl__closeTty(JNIEnv *env,jobject clazz);

    JNIEXPORT static int JNICALL com_notioni_uart_manager_TtyNativeControl__sendMsgToTty(JNIEnv *env,jobject clazz,jbyteArray data);

    JNIEXPORT static void JNICALL com_notioni_uart_manager_TtyNativeControl__receiveMsgFromTty(JNIEnv *env,jobject clazz);

    JNIEXPORT static int JNICALL com_notioni_uart_manager_TtyNativeControl__configTty(JNIEnv *env,jobject clazz,int nBits,jchar nEvent,int nSpeed,int nStop);

    JNIEXPORT static int JNICALL com_notioni_uart_manager_TtyNativeControl__setMode(JNIEnv *env,jobject clazz,int nMode,int showLog);

    //JNIEXPORT int JNICALL com_notioni_uart_manager_TtyNativeControl__setSpeed(JNIEnv *env,jobjectclazz,int speed);

    //JNIEXPORT int JNICALL com_notioni_uart_manager_TtyNativeControl__setParity(JNIEnv *env,jobjectclazz,int databits,int stopbits,int parity);

    #ifdef __cplusplus

    }

    #endif

    #endif

    3. JNI实现类

    #include "JNIHelp.h"

    #include "android_runtime/AndroidRuntime.h"

    #include <utils/misc.h>

    #include <utils/Log.h>

    #include <utils/threads.h>

    #include <pthread.h>

    #include <stdio.h>

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <fcntl.h>

    #include <string.h>

    #include <utils/Log.h>

    #include <sys/ioctl.h>

    #include <termios.h>

    #include "com_notioni_uart_manager_TtyNativeControl.h"

    using namespace android;

    struct fields_t{

    jfieldID tty;

    jmethodID post_event;

    };

    static fields_t fields;

    JavaVM* g_JavaVM;

    #define TTY_DEVICE "/dev/ttyS2"

    #define LOG_TAG "TtyNativeControl"

    #define RECEIVE_DATA_INDEX (1)

    #define POST_EVENT()

    static int mTtyfd = -1;

    static int mOpen = 0;

    /**

    * class Listener

    */

    class JNIMyObserver{

    public:

    JNIMyObserver(JNIEnv* env,jobject thiz,jobject weak_thiz);

    ~JNIMyObserver();

    void OnEvent(const char* buffer,int length,int what);

    private:

    JNIMyObserver();

    jclass mClass;

    jobject mObject;

    Mutex mLock;

    };

    JNIMyObserver::JNIMyObserver(JNIEnv* env,jobject thiz,jobject weak_thiz){

    jclass clazz = env->GetObjectClass(thiz);

    if(clazz == NULL){

    // jniThrowException(env,"java/lang/Exception",NULL);

    LOGE("clazz is null");

    return;

    }

    mClass = (jclass)env->NewGlobalRef(clazz);

    mObject = env->NewGlobalRef(weak_thiz);

    LOGW("mClass=%d",mClass);

    LOGW("mObject=%d",mObject);

    }

    JNIMyObserver::~JNIMyObserver(){

    JNIEnv *env = AndroidRuntime::getJNIEnv();

    env->DeleteGlobalRef(mObject);

    env->DeleteGlobalRef(mClass);

    }

    void JNIMyObserver::OnEvent(const char* buffer,int length,int what){

    LOGW("OnEvent");

    Mutex::Autolock _l(mLock);

    if(NULL == g_JavaVM){

    LOGE("JNIObserver::Event g_JavaVM is NULL");

    return;

    }

    bool isAttacked = false;

    /*

    创建env指针

    */

    JNIEnv* env;

    bool status = (g_JavaVM->GetEnv((void**) &env,JNI_VERSION_1_4) != JNI_OK);

    if(status){

    g_JavaVM->AttachCurrentThread(&env,NULL);

    }

    /*

    创建Java byte[]数组

    */

    jbyteArray obj = NULL;

    if(buffer !=NULL && buffer != 0){

    const jbyte* data = reinterpret_cast<const jbyte*>(buffer);

    obj = env->NewByteArray(length);

    env->SetByteArrayRegion(obj,0,length,data);

    }

    env->CallStaticVoidMethod(mClass,fields.post_event,mObject,what,0,0,obj);

    if(obj){

    env->DeleteLocalRef(obj);

    }

    if(isAttacked){

    g_JavaVM->DetachCurrentThread();//分离线程

    }

    }

    /**

    * class Listener end -----------------

    */

    JNIMyObserver* listener;

    /*

    * setup

    */

    static void JNICALL com_notioni_uart_manager_TtyNativeControl_native_setup(JNIEnv *env,jobject clazz,jobject weak_this){

    LOGW("com_notioni_uart_manager_TtyNativeControl_native_setup");

    env->GetJavaVM(&g_JavaVM);

    if(listener != NULL){

    delete listener;

    }

    listener = new JNIMyObserver(env,clazz,weak_this);

    }

    /*

    * _openTty

    */

    static int JNICALL com_notioni_uart_manager_TtyNativeControl__openTty(JNIEnv *env,jobject clazz){

    LOGW("com_notioni_uart_manager_TtyNativeControl__openTty");

    mTtyfd = open(TTY_DEVICE,O_RDWR|O_NONBLOCK);//读写方式

    if(mTtyfd < 0){

    LOGE("mTtyfd open failure");

    return -1;

    }

    if(fcntl(mTtyfd,F_SETFL,0)<0){//恢复串口为堵塞状态

    LOGE("mTtyfd fcntl failure");

    }

    // if(isatty(STDIN_FILENO)==0){//测试是否为中断设备,非0即使终端设备

    // LOGE("standard inputs is not a terminal device");

    // }else{

    // LOGE("isatty success");

    // }

    mOpen = 1;

    LOGW("open device success");

    return 1;

    }

    /*

    * _closeTty

    */

    static int JNICALL com_notioni_uart_manager_TtyNativeControl__closeTty(JNIEnv *env,jobject clazz){

    LOGW("com_notioni_uart_manager_TtyNativeControl__closeTty");

    if(mTtyfd < 0){

    LOGE("mTtyfd open failure ,non't close");

    return -1;

    }

    mOpen = 0;

    sleep(2);//等待线程退出

    int c = close(mTtyfd);

    if(c < 0){

    LOGE("mTtyfd close failure");

    return -1;

    }

    LOGW("close device success");

    return 1;

    }

    /*

    * _sendMsgToTty

    */

    static int JNICALL com_notioni_uart_manager_TtyNativeControl__sendMsgToTty(JNIEnv *env,jobject clazz,jbyteArray data){//byte[]

    LOGW("com_notioni_uart_manager_TtyNativeControl__sendMsgToTty");

    //jbyte * arrayBody = env->GetByteArrayElements(data,0); jsize theArrayLengthJ = env->GetArrayLength(data); BYTE * starter = (BYTE *)arrayBody;

    if(mTtyfd < 0){

    LOGE("mTtyfd open failure ,non't write");

    return -1;

    }

    jbyte* arrayData = (jbyte*)env->GetByteArrayElements(data,0);

    jsize arrayLength = env->GetArrayLength(data);

    char* byteData = (char*)arrayData;

    int len = (int)arrayLength;

    LOGW("write data len:%d",len);

    int re = write(mTtyfd,byteData,len);

    if(re == -1){

    LOGE("write device error");

    }

    return re;

    }

    /*

    线程Run

    */

    void* threadreadTtyData(void* arg){

    LOGW("run read data");

    if(!(arg)){

    return NULL;

    }

    char* buf = new char[200];

    int result = 0,ret;

    fd_set readfd;

    struct timeval timeout;

    while(mOpen){

    timeout.tv_sec = 2;//设定超时秒数

    timeout.tv_usec = 0;//设定超时毫秒数

    FD_ZERO(&readfd);//清空集合

    FD_SET(mTtyfd,&readfd);///* 把要检测的句柄mTtyfd加入到集合里 */

    ret = select(mTtyfd+1,&readfd,NULL,NULL,&timeout);/* 检测我们上面设置到集合readfd里的句柄是否有可读信息 */

    switch(ret){

    case -1:/* 这说明select函数出错 */

    result = -1;

    LOGE("mTtyfd read failure");

    break;

    case 0:/* 说明在我们设定的时间值5秒加0毫秒的时间内,mTty的状态没有发生变化 */

    break;

    default:/* 说明等待时间还未到5秒加0毫秒,mTty的状态发生了变化 */

    if(FD_ISSET(mTtyfd,&readfd)){/* 先判断一下mTty这外被监视的句柄是否真的变成可读的了 */

    int len = read(mTtyfd,buf,sizeof(buf));

    /**发送数据**/

    if(!(arg))break;

    JNIMyObserver *l = static_cast<JNIMyObserver *>(arg);

    l->OnEvent(buf,len,RECEIVE_DATA_INDEX);

    memset(buf,0,sizeof(buf));

    }

    break;

    }

    if(result == -1){

    break;

    }

    }

    if(buf != NULL){

    delete buf;

    buf = NULL;

    }

    LOGE("stop run!");

    return NULL;

    }

    /*

    * _receiveMsgFromTty

    */

    static void JNICALL com_notioni_uart_manager_TtyNativeControl__receiveMsgFromTty(JNIEnv *env,jobject clazz){

    LOGW("com_notioni_uart_manager_TtyNativeControl__receiveMsgFromTty");

    if(mTtyfd < 0){

    LOGE("mTtyfd open failure ,non't read");

    return ;

    }

    pthread_t id;

    int ret;

    ret = pthread_create(&id,NULL,threadreadTtyData,listener);

    if(ret != 0){

    LOGE("create receiver thread failure ");

    }else{

    LOGW("create read data thred success");

    }

    }

    /**

    设置串口数据,校验位,速率,停止位

    * @param nBits 类型 int数据位 取值 78

    * @param nEvent 类型 char 校验类型 取值N ,E, O,,S

    * @param mSpeed 类型 int 速率 取值 2400,4800,9600,115200

    * @param mStop 类型 int 停止位 取值或者 2

    */

    int set_opt(int nBits,char nEvent,int nSpeed,int nStop){

    LOGW("set_opt:nBits=%d,nEvent=%c,nSpeed=%d,nStop=%d",nBits,nEvent,nSpeed,nStop);

    struct termios newtio,oldtio;

    if(tcgetattr(mTtyfd,&oldtio) != 0){

    LOGE("setup serial failure");

    return -1;

    }

    bzero(&newtio,sizeof(newtio));

    //c_cflag标志可以定义CLOCALCREAD,这将确保该程序不被其他端口控制和信号干扰,同时串口驱动将读取进入的数据。CLOCALCREAD通常总是被是能的

    newtio.c_cflag |=CLOCAL|CREAD;

    //newtio.c_cflag &=~CSIZE;

    switch(nBits){//设置数据位数

    case 7:

    newtio.c_cflag &=~CSIZE;

    newtio.c_cflag |=CS7;

    break;

    case 8:

    newtio.c_cflag &=~CSIZE;

    newtio.c_cflag |=CS8;

    break;

    default:

    LOGW("nBits:%d,invalid param",nBits);

    break;

    }

    switch(nEvent){//设置校验位

    case 'O':

    newtio.c_cflag |=PARENB;//enable parity checking

    newtio.c_cflag |=PARODD;//奇校验位

    newtio.c_iflag |=(INPCK|ISTRIP);

    //options.c_iflag |= INPCK;//Disable parity checking

    break;

    case 'E':

    newtio.c_cflag|=PARENB;//

    newtio.c_cflag&=~PARODD;//偶校验位

    newtio.c_iflag|=(INPCK|ISTRIP);

    //options.c_iflag |= INPCK;//Disable parity checking

    break;

    case 'N':

    newtio.c_cflag &=~PARENB;//清除校验位

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

    break;

    //case 'S':

    // options.c_cflag &= ~PARENB;//清除校验位

    // options.c_cflag &=~CSTOPB;

    // options.c_iflag |=INPCK;//Disable parity checking

    // break;

    default:

    LOGW("nEvent:%c,invalid param",nEvent);

    break;

    }

    switch(nSpeed){//设置速率

    case 2400:

    LOGW("B2400:%d",B2400);

    cfsetispeed(&newtio,B2400);

    cfsetospeed(&newtio,B2400);

    break;

    case 4800:

    LOGW("B4800:%d",B4800);

    cfsetispeed(&newtio,B4800);

    cfsetospeed(&newtio,B4800);

    break;

    case 9600:

    LOGW("B9600:%d",B9600);

    cfsetispeed(&newtio,B9600);

    cfsetospeed(&newtio,B9600);

    break;

    case 115200:

    LOGW("B115200:%d",B115200);

    cfsetispeed(&newtio,B115200);

    cfsetospeed(&newtio,B115200);

    break;

    default:

    cfsetispeed(&newtio,B9600);

    cfsetospeed(&newtio,B9600);

    LOGW("nSpeed:%d,invalid param",nSpeed);

    break;

    }

    switch(nStop){//设置停止位

    case 1:

    newtio.c_cflag &= ~CSTOPB;

    break;

    case 2:

    newtio.c_cflag |= CSTOPB;

    break;

    default:

    LOGW("nStop:%d,invalid param",nStop);

    break;

    }

    newtio.c_cc[VTIME] = 0;//设置等待时间

    newtio.c_cc[VMIN] = 0;//设置最小接收字符

    tcflush(mTtyfd,TCIFLUSH);

    if(tcsetattr(mTtyfd,TCSANOW,&newtio) != 0){

    LOGE("options set error");

    return -1;

    }

    return 1;

    }

    /*

    * _configTty

    */

    static int JNICALL com_notioni_uart_manager_TtyNativeControl__configTty(JNIEnv *env,jobject clazz,int nBits,jchar nEvent,int nSpeed,int nStop){

    LOGW("com_notioni_uart_manager_TtyNativeControl__configTty");

    return set_opt(nBits,nEvent,nSpeed,nStop);

    }

    int set_mode(int nMode,int showLog){

    LOGW("set_mode:nMode%d,nshowLog=%d",nMode,showLog);

    struct termios options;

    if(tcgetattr(mTtyfd,&options) != 0){

    LOGE("setup serial failure");

    return -1;

    }

    int result = 1;

    if(nMode != 0){

    if(nMode ==1){

    options.c_lflag &=~(ICANON | ECHO | ECHOE | ISIG);//input

    options.c_oflag &=~OPOST;//out put

    }else if(nMode == 2){

    options.c_lflag |=(ICANON | ECHO | ECHOE | ISIG);//input

    options.c_oflag |=OPOST;//out put

    }

    if(tcsetattr(mTtyfd,TCSANOW,&options) != 0){

    LOGE("tcsetattr device fail");

    result = -1;

    }

    }

    if(showLog == 1){

    LOGI("options c_cflag.CS7:%d,CS8:%d",options.c_cflag & CS7,options.c_cflag & CS8);

    LOGI("options c_cflag.PARENB:%d,PARODD:%d",options.c_cflag & PARENB,options.c_cflag & PARODD);

    LOGI("options c_iflag.INPCK%d,ISTRIP:%d",options.c_iflag & INPCK,options.c_iflag & ISTRIP);

    LOGI("option c_ispeed:%d,c_ospeed:%d",cfgetispeed(&options) ,cfgetospeed(&options));

    LOGI("options c_cflag.CSTOPB:%d,",options.c_cflag & CSTOPB);

    LOGI("options c_cc.VTIME:%d,VMIN:%d",options.c_cc[VTIME],options.c_cc[VMIN]);

    LOGI("options c_cflag.CLOCAL:%d,CREAD:%d",options.c_cflag & CLOCAL,options.c_cflag&CREAD);

    LOGI("options c_lflag.ICANON:%d,ECHO:%d,ECHOE:%d,ISIG:%d",options.c_lflag & ICANON,options.c_lflag&ECHO,options.c_lflag&ECHOE,options.c_lflag&ISIG);

    LOGI("options c_oflag.OPOST:%d,",options.c_oflag &OPOST);

    }

    return result;

    }

    static int JNICALL com_notioni_uart_manager_TtyNativeControl__setMode(JNIEnv *env,jobject clazz,int nMode,int showLog){

    LOGW("com_notioni_uart_manager_TtyNativeControl__setMode");

    return set_mode(nMode,showLog);

    }

    static JNINativeMethod method_table[] = {

    {"native_setup","(Ljava/lang/Object;)V",(void*)com_notioni_uart_manager_TtyNativeControl_native_setup},

    {"_openTty","()I",(void*)com_notioni_uart_manager_TtyNativeControl__openTty},

    {"_closeTty","()I",(void*)com_notioni_uart_manager_TtyNativeControl__closeTty},

    {"_sendMsgToTty","([B)I",(void*)com_notioni_uart_manager_TtyNativeControl__sendMsgToTty},

    {"_receiveMsgFromTty","()V",(void*)com_notioni_uart_manager_TtyNativeControl__receiveMsgFromTty},

    {"_configTty","(ICII)I",(void*)com_notioni_uart_manager_TtyNativeControl__configTty},

    {"_setMode","(II)I",(void*)com_notioni_uart_manager_TtyNativeControl__setMode},

    };

    static const char* classPathName="com/notioni/uart/manager/TtyNativeControl";

    static int register_com_notioni_uart_manager_TtyNativeControl(JNIEnv *env){

    LOGW("register_com_notioni_uart_manager_TtyNativeControl");

    jclass clazz;

    clazz = env->FindClass(classPathName);

    if(clazz == NULL){

    return -1;

    }

    fields.post_event = env->GetStaticMethodID(clazz,"postEventFromNative",

    "(Ljava/lang/Object;IIILjava/lang/Object;)V");

    if(fields.post_event == NULL){

    LOGE("Can't find com/notioni/uart/manager.postEventFromNative");

    return -1;

    }

    returnAndroidRuntime::registerNativeMethods(env,classPathName,method_table,NELEM(method_table));

    }

    jint JNI_OnLoad(JavaVM* vm,void* reserved){

    LOGW("JNI_OnLoad");

    JNIEnv* env = NULL;

    jint result = -1;

    if(vm->GetEnv((void**)&env,JNI_VERSION_1_4) != JNI_OK){

    goto bail;

    }

    LOGW("register mothod");

    assert(env != NULL);

    if(register_com_notioni_uart_manager_TtyNativeControl(env) < 0){

    goto bail;

    }

    return JNI_VERSION_1_4;

    bail:

    return result;

    }

    4. JAVA层封装本地方法

    package com.notioni.uart.manager;

    import com.notioni.uart.manager.TtyNativeControl.ReceiveCallback;

    /*

    单例模式

    */

    public class UARTCTLManager {

    private TtyNativeControl mTtyControl;

    private boolean mIsOpen = false;

    private static UARTCTLManager mManager;

    private UARTCTLManager(){

    mTtyControl = new TtyNativeControl();

    }

    public static UARTCTLManager getInstance(){

    if(mManager == null){

    mManager = new UARTCTLManager();

    }

    return mManager;

    }

    /*

    打开驱动

    */

    public int openDevice(){

    int o = mTtyControl.openTty();

    o=1;

    if(o == 1){

    mIsOpen = true;

    }

    return o;

    }

    /*

    关闭驱动

    */

    public int closeDevice(){

    int c = mTtyControl.closeTty();

    if(c == 1){

    mIsOpen = false;

    }

    return c;

    }

    /*

    判断驱动是否打开

    */

    public boolean isOpenDevice(){

    return mIsOpen;

    }

    /*

    发送数据

    */

    public int sendDataToDevice(byte[] data){

    return mTtyControl.sendMsgToTty(data);

    }

    /*

    注入接收数据回调方法

    */

    public void receiveDataFromDevice(ReceiveCallback callback){

    mTtyControl.receiveMsgFromTty(callback);

    }

    /**

    设置串口数据位,校验位,速率,停止位

    @param databits 数据位 取值 78

    @param event 校验类型 取值N ,E, O,,S

    @param speed 速率 取值 2400,4800,9600,115200

    @param stopBit 停止位 取值或者 2

    */

    public int configDevice(int databits,char event,int speed,int stopBit){

    if(!mIsOpen){

    return -1;

    }

    int re = mTtyControl.configTty(databits, event, speed, stopBit);

    return re;

    }

    /**

    设置串口通信模式,打印串口信息

    @param mode 是否使用原始模式(Raw Mode)方式来通讯 取值0,1,2 说明:0=nothing,1=Raw mode,2=no raw mode

    @param showLog 打印出串口信息Log 取值1,0

    @return

    */

    public int setMode(int mode ,int showLog){

    return mTtyControl.setMode(mode, showLog);

    }

    /**

    *

    接收数据回调接口,接收驱动送到的数据要实现这个回调接口

    */

    public interface ReceiveDataCallBack extends ReceiveCallback{

    }

    }

    5. JAVA调用 Activity

    package com.notioni.uart;

    import com.notioni.uart.manager.TtyNativeControl;

    import com.notioni.uart.manager.UARTCTLManager;

    import android.app.Activity;

    import android.content.Intent;

    import android.os.Bundle;

    import android.util.Log;

    import android.view.Menu;

    import android.view.MenuItem;

    import android.view.View;

    import android.widget.Button;

    import android.widget.EditText;

    import android.widget.TextView;

    public class UARTCTLActivity extends Activity implements View.OnClickListener{

    private static final String TAG = "UARTCTLActivity";

    private UARTCTLManager mUartctlManager;

    private Button mOpenOrCloseBtn;

    private Button mSendBtn;

    private EditText mSendText;

    private TextView mReceiveText;

    private ReceiveData mReceiveData;

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    mUartctlManager = UARTCTLManager.getInstance();

    mReceiveData = new ReceiveData();

    mOpenOrCloseBtn = (Button)findViewById(R.id.openOrcloseBtn);

    mSendBtn = (Button)findViewById(R.id.sendBtn);

    mSendText = (EditText)findViewById(R.id.sendMsg);

    mReceiveText = (TextView)findViewById(R.id.receiveMsg);

    mOpenOrCloseBtn.setOnClickListener(this);

    mSendBtn.setOnClickListener(this);

    }

    @Override

    protected void onResume() {

    super.onResume();

    }

    @Override

    public void onClick(View v) {

    switch(v.getId()){

    case R.id.openOrcloseBtn://打开或关闭驱动

    Log.i(TAG"isOpen:"+mUartctlManager.isOpenDevice());

    if(mUartctlManager.isOpenDevice()){

    mUartctlManager.closeDevice();

    mOpenOrCloseBtn.setText(R.string.open);

    }else{

    int i =mUartctlManager.openDevice();

    Log.i(TAG"openDevice result:"+i);

    mOpenOrCloseBtn.setText(R.string.close);

    mUartctlManager.setMode(1, 1);//查看串口配置信息

    }

    break;

    case R.id.sendBtn:

    openDevice();

    int re = mUartctlManager.sendDataToDevice(getSendText());

    Log.i(TAG"send result:"+re);

    break;

    }

    }

    /*

    打开驱动

    */

    private void openDevice(){

    if(!mUartctlManager.isOpenDevice()){

    mUartctlManager.openDevice();

    mUartctlManager.receiveDataFromDevice(mReceiveData);

    }

    }

    /*

    关闭驱动

    */

    public void closeDevice(){

    if(mUartctlManager.isOpenDevice()){

    mUartctlManager.closeDevice();

    }

    }

    /*

    取出待发送的数据

    */

    private byte[] getSendText(){

    String st = mSendText.getText().toString()+"\r";

    if(st == null || "".equals(st)){

    return null;

    }

    return st.getBytes();

    }

    /*

    接收数据

    */

    class ReceiveData implements UARTCTLManager.ReceiveDataCallBack{

    @Override

    public void onReceiveData(byte[] data, TtyNativeControl tty) {

    if(mReceiveText != null && data != null){

    Log.w(TAG"[onReceiveData] data:"+data.toString());

    mReceiveText.setText(data.toString());

    }

    }

    }

    @Override

    public boolean onCreateOptionsMenu(Menu menu) {

    menu.add(1,1,0,R.string.config);

    return super.onCreateOptionsMenu(menu);

    }

    @Override

    public boolean onOptionsItemSelected(MenuItem item) {

    super.onOptionsItemSelected(item);

    if(item.getItemId() == 1){

    Intent intent = new Intent();

    intent.setClass(this, ConfigActivity.class);

    startActivity(intent);

    }

    return true;

    }

    @Override

    protected void onPause() {

    super.onPause();

    // closeDevice();

    }

    @Override

    protected void onDestroy() {

    closeDevice();

    super.onDestroy();

    }

    }

    6. JAVA配置串口属性

    package com.notioni.uart;

    import com.notioni.uart.manager.UARTCTLManager;

    import android.os.Bundle;

    import android.preference.ListPreference;

    import android.preference.Preference;

    import android.preference.PreferenceActivity;

    import android.preference.PreferenceScreen;

    import android.util.Log;

    import android.widget.Toast;

    public class ConfigActivity extends PreferenceActivityimplementsPreference.OnPreferenceChangeListener{

    private static final String TAG = "ConfigActivity";

    private static final String KEY_DATABITS = "tty_databits";

    private static final String KEY_EVENT = "tty_event";

    private static final String KEY_SPEED = "tty_speed";

    private static final String KEY_STOPBITS = "tty_stopbits";

    ListPreference dataBitsPrefer ;

    ListPreference eventPrefer ;

    ListPreference speedPrefer ;

    ListPreference stopBitsPrefer ;

    Object dataBitsValues = null;

    Object eventValues = null;

    Object speedValues = null;

    Object stopbitsValues = null;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    // TODO Auto-generated method stub

    super.onCreate(savedInstanceState);

    addPreferencesFromResource(R.xml.config_options);

    PreferenceScreen prefSet = getPreferenceScreen();

    dataBitsPrefer = (ListPreference)prefSet.findPreference(KEY_DATABITS);

    eventPrefer = (ListPreference)prefSet.findPreference(KEY_EVENT);

    speedPrefer = (ListPreference)prefSet.findPreference(KEY_SPEED);

    stopBitsPrefer = (ListPreference)prefSet.findPreference(KEY_STOPBITS);

    dataBitsPrefer.setValueIndex(0);

    eventPrefer.setValueIndex(0);

    speedPrefer.setValueIndex(0);

    stopBitsPrefer.setValueIndex(0);

    dataBitsPrefer.setOnPreferenceChangeListener(this);

    eventPrefer.setOnPreferenceChangeListener(this);

    speedPrefer.setOnPreferenceChangeListener(this);

    stopBitsPrefer.setOnPreferenceChangeListener(this);

    }

    @Override

    public boolean onPreferenceChange(Preference preference, Object newValue) {

    if(preference == dataBitsPrefer){

    dataBitsValues = newValue;

    }else if(preference == eventPrefer){

    eventValues = newValue;

    }else if(preference == speedPrefer){

    speedValues = newValue;

    }else if(preference == stopBitsPrefer){

    stopbitsValues = newValue;

    }

    Log.i(TAG"newValue:"+newValue);

    return false;

    }

    @Override

    protected void onPause() {

    super.onPause();

    UARTCTLManager mUartctlManager = UARTCTLManager.getInstance();

    int databits=7,speed=9600,stopbits=1;//设置默认值

    char event='N';//设置默认值

    if(dataBitsValues != null){

    databits = Integer.parseInt(dataBitsValues.toString());

    }

    if(eventValues != null){

    event = eventValues.toString().charAt(0);

    }

    if(speedValues != null){

    speed = Integer.parseInt(speedValues.toString());

    }

    if(stopbitsValues != null){

    stopbits = Integer.parseInt(stopbitsValues.toString());

    }

    if(!mUartctlManager.isOpenDevice()){

    mUartctlManager.openDevice();

    }

    Log.e(TAG,"databit="+databits+",event="+event+",speed="+speed+",stopbits="+stopbits);

    if(databits == -1 || speed == -1 || stopbits == -1 || event=='Q'){

    Toast.makeText(this"有参数没有设置,不去配置串口!", Toast.LENGTH_LONG).show();

    return;

    }

    mUartctlManager.configDevice(databits, event, speed, stopbits);

    mUartctlManager.setMode(0, 1);//查看串口配置信息

    // Log.e(TAG, "databit="+databits+",event="+event+",speed="+speed+",stopbits="+stopbits);

    }

    }

    7. config_options.xml

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

    <PreferenceScreen

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

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

    android:key="video_call_fallback_setting"

    android:title="@string/tty_settings"

    android:persistent="false">

    <ListPreference

    android:key="tty_databits"

    android:title="@string/databits"

    android:persistent="true"

    android:entries="@array/databits_entries"

    android:entryValues="@array/databits_values"

    android:summary="data bits"/>

    <ListPreference

    android:key="tty_event"

    android:title="@string/event"

    android:persistent="true"

    android:entries="@array/event_entries"

    android:entryValues="@array/event_values"

    android:summary="data bits"/>

    <ListPreference

    android:key="tty_speed"

    android:title="@string/speed"

    android:persistent="true"

    android:entries="@array/speed_entries"

    android:entryValues="@array/speed_values"

    android:summary="data bits"/>

    <ListPreference

    android:key="tty_stopbits"

    android:title="@string/stopbits"

    android:persistent="true"

    android:entries="@array/stopbits_entries"

    android:entryValues="@array/stopbits_values"

    android:summary="data bits"/>

    </PreferenceScreen>

    8. main.xml

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

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

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:orientation="vertical" >

    <LinearLayout

    android:layout_width="fill_parent"

    android:layout_height="60dip"

    android:orientation="horizontal"

    >

    <Button

    android:id="@+id/openOrcloseBtn"

    android:layout_gravity="center"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:text="@string/open"

    />

    </LinearLayout>

    <LinearLayout

    android:layout_width="fill_parent"

    android:layout_height="60dip"

    android:orientation="horizontal"

    >

    <EditText

    android:id="@+id/sendMsg"

    android:layout_gravity="left"

    android:layout_width="200dip"

    android:layout_height="50dip"

    />

    <Button

    android:id="@+id/sendBtn"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:text="@string/send"

    />

    </LinearLayout>

    <LinearLayout

    android:layout_width="fill_parent"

    android:layout_height="100dip"

    android:orientation="horizontal"

    >

    <TextView

    android:id="@+id/receiveMsg"

    android:layout_width="fill_parent"

    android:layout_height="wrap_content"

    android:text="@string/receiveData" />

    </LinearLayout>

    </LinearLayout>

    9. string.xml

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

    <resources>

    <string name="hello">Hello World, UARTCTLActivity!</string>

    <string name="receiveData">Receive data show!</string>

    <string name="app_name">UARTCTL</string>

    <string name="open">Open</string>

    <string name="close">Close</string>

    <string name="send">Send</string>

    <string name="config">Config</string>

    <string name="tty_settings">Settings</string>

    <string name="databits">Data bits</string>

    <string name="event">Event</string>

    <string name="speed">Speed</string>

    <string name="stopbits">Stop bits</string>

    <string-array name="databits_entries">

    <item>-1</item>

    <item>7</item>

    <item>8</item>

    </string-array>

    <string-array name="databits_values">

    <item>-1</item>

    <item>7</item>

    <item>8</item>

    </string-array>

    <string-array name="event_entries">

    <item>Settings</item>

    <item>None</item>

    <item>Event</item>

    <item>Odd</item>

    </string-array>

    <string-array name="event_values">

    <item>Q</item>

    <item>N</item>

    <item>E</item>

    <item>O</item>

    </string-array>

    <string-array name="speed_entries">

    <item>-1</item>

    <item>B2400</item>

    <item>B4800</item>

    <item>B9600</item>

    <item>B115200</item>

    </string-array>

    <string-array name="speed_values">

    <item>-1</item>

    <item>2400</item>

    <item>4800</item>

    <item>9600</item>

    <item>115200</item>

    </string-array>

    <string-array name="stopbits_entries">

    <item>-1</item>

    <item>1</item>

    <item>2</item>

    </string-array>

    <string-array name="stopbits_values">

    <item>-1</item>

    <item>1</item>

    <item>2</item>

    </string-array>

    </resources>

    10. Android.mk

    LOCAL_PATH:=$(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_MODULE_TAGS := optional

    LOCAL_SRC_FILES :$(call all-java-files-under,src)

    #LOCAL_JAVA_LIBRARIES := uart-ctl

    LOCAL_JNI_SHARED_LIBRARIES := uart_ctl #so文件打包到apk

    LOCAL_PACKAGE_NAME := UARTCTL

    #LOCAL_CERTIFICATE := platform

    include $(BUILD_PACKAGE)

    include $(LOCAL_PATH)/jni/Android.mk

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

    11. jni/Android.mk

    LOCAL_PATH:=$(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_MODULE_TAGS := optional

    LOCAL_SRC_FILES:= \

    com_notioni_uart_manager_TtyNativeControl.cpp

    LOCAL_C_INCLUDES := \

    $(JNI_H_INCLUDE)

    LOCAL_SHARED_LIBRARIES := \

    libcutils \

    libutils \

    libui \

    libandroid_runtime

    LOCAL_PRELINK_MODULE := false

    LOCAL_MODULE := uart_ctl

    include $(BUILD_SHARED_LIBRARY)

    转载请注明原文地址: https://ju.6miu.com/read-965580.html

    最新回复(0)