Android串口通讯

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android串口通讯相关的知识,希望对你有一定的参考价值。

参考技术A 1.打开串口。

2.串口处于监听状态

3.想串口写入数据,串口接收到数据返回数据

SerialPort类所在的包一定要和上图包名一直,因为串口通讯需要使用jni中的函数。

package android_serialport_api;

import java.io.File;

import java.io.FileDescriptor;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import com.fx.serialporttest.L;

public class SerialPort

/*

* Do not remove or rename the field mFd: it is used by native method

* close();

*/

private FileDescriptor mFd;

private FileInputStream mFileInputStream;

private FileOutputStream mFileOutputStream;

/**

* 构造方法

* @param device 串口地址

* @param baurate 波特率

* @param flags

* @throws IOException

* @throws InterruptedException

*/

public SerialPort(File device,int baudrate,int flags)

/*

* 检测是否有访问权限

*/

if(!device.canRead()||!device.canWrite())

//如果没有读写权限,尝试chmod命令这个文件

L.tag("没有读写权限");

Process su;

try

su = Runtime.getRuntime().exec("/system/bin/su");//获取root读写权限

String cmd = "chmod 777"+device.getAbsolutePath()+"\n"+"exit\n";

su.getOutputStream().write(cmd.getBytes()); //向此路径文件写入命令

if((su.waitFor()!=0||!device.canRead()||!device.canWrite()))

throw new SecurityException();



catch (Exception e)

// TODO Auto-generated catch block

e.printStackTrace();





mFd = open(device.getAbsolutePath(),baudrate,flags);

if(mFd==null)

mFd = open(device.getAbsolutePath(),baudrate,flags);

L.tag("native open return null");



mFileInputStream = new FileInputStream(mFd);

mFileOutputStream = new FileOutputStream(mFd);



public FileInputStream getmFileInputStream()

return mFileInputStream;



public void setmFileInputStream(FileInputStream mFileInputStream)

this.mFileInputStream = mFileInputStream;



public FileOutputStream getmFileOutputStream()

return mFileOutputStream;



public void setmFileOutputStream(FileOutputStream mFileOutputStream)

this.mFileOutputStream = mFileOutputStream;



//JNI

private native static FileDescriptor open(String path,int baudrate,int flags);

public native void close();

static

System.loadLibrary("serial_port");





package android_serialport_api;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import com.fx.serialporttest.L;

public  class SerialPortFinger

private static ReadThread readThread;

private static FileInputStream mFileInputStream;

private static FileOutputStream mFileOutputStream;

static String path = "/dev/ttyS0";//设备主板的串口地址,地址有所不同

public  void startListener()

SerialPort serialPort = new SerialPort(new File(path), 9600, 0);//9600是波特率,这个也是有所不同,具体要看设备

mFileInputStream = serialPort.getmFileInputStream();

mFileOutputStream = serialPort.getmFileOutputStream();//获取串口写入流

readThread  = new ReadThread();

readThread.start();//开启监听



/**

* 发送指令到串口

*

* @param cmd

* @return

*/

public boolean sendCmds(String cmd)

boolean result = true;

byte[] mBuffer = (cmd+"\r\n").getBytes();

try

if (mFileOutputStream != null)

mFileOutputStream.write(mBuffer);

else

result = false;



catch (IOException e)

e.printStackTrace();

result = false;



return result;



static class ReadThread extends Thread

@Override

public void run()

// TODO Auto-generated method stub

super.run();

int len;

StringBuffer sb = new StringBuffer("");

while(true) //循环监听串口,读取返回的数据

byte[] buffer = new byte[1024];

if(mFileInputStream==null)

return;



try

len = mFileInputStream.read(buffer);

if(len>0)

sb.append(new String(buffer, 0, len));



if(!sb.toString().equals(""))



L.tag(sb.toString());//收到串口的返回数据,在日志中打印出来



catch (IOException e)

// TODO Auto-generated catch block

e.printStackTrace();



L.tag("接受完成");







Android通过JNI实现与C语言的串口通讯操作蓝牙硬件模块

一直想写一份技术文档,但因为自感能力有限而无从下笔,近期做了个关于Android平台下实现与C语言的通讯来操作蓝牙模块的项目,中间碰到了很多问题,也在网上查了很多资料,在完毕主要功能后。也有一些人在网上问我一些问题。这里写下这篇文档算是一个阶段性的总结。

假设反响好。兴许将会发上Android Stub与新版Android HAL的学习文档。

因为蓝牙模块是串口通讯机制。使用C语言来訪问,而Android的应用层採用Java。无法直接操作硬件。故使用JNI的技术实现主要功能。Android的JNI应该属于Android HAL的一部分,因为Android的HAL机制眼下还没全然摸索透,所以这里的程序架构算是老版本号的HAL机制。程序架构例如以下图。

技术分享

一、 什么是JNI?

JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1開始,Java Native Interface(JNI)标准成为java平台的一部分,它同意Java代码和其它语言写的代码进行交互。

JNI一開始是为了本地已编译语言。尤其是C和C++而设计的,可是它并最好还是碍你使用其它语言,仅仅要调用约定受支持就能够了。(以上内容摘自百度百科)

二、 怎样使用JNI?

1、在使用JNI之前,你要确保你的电脑中安装下面软件环境:

Android SDK :版本号与你硬件測试环境版本号同样,在Google的Android官网下载

Android NDK :用于编译C文件为.so的共享库。假设你是在Linux下进行开发而又具有Android的全然SDK,则不须要

Cygwin :用于编译C文件

Android 开发环境 :android开发环境的配置网上一大堆,这里不再赘述

2、程序中因为仅仅用到Java调C,而不须要C调Java,所以在应用层调C的函数非常easy,仅仅须要在一个方法前增加nativekeyword(native的方法不能有方法体),然后将编译的共享库导入就可以。

例如以下:

public class BluetoothJNI {

static{

System.loadLibrary("jni");

}

public native static int bluetoothOn(String strAT);

public native static void bluetoothOff(String strAT);

public native static String readSerial();

public native static void write(String strAT);

}

 

3Eclipse在保存project后,会自己主动把Java文件编译为class文件。我们使用javah命令把class文件编译成C头文件。例如以下:

 技术分享

运行此命令后将会在project的bin文件夹下生成一个.h的C头文件。

头文件里会生成相应Java native方法的函数声明。

新建一个与头文件同名的C文件并实现全部函数。

 技术分享

4、因为Android的底层是基于Linux内核。所以一些Windows下的系统函数不可用。Linux下的串口通讯文章网上有非常多,此处代码繁多,就不贴出来了。。我们在C文件里引入jni.h与刚生成的头文件以确保JNI能调用。注意:整个程序的核心部分便是在此处,C语言与蓝牙模块的串口通讯处,我在此处碰到的问题也是最多的。

三、编译C文件

1、在Android-ndk-r5b\samples\下新建文件夹Bluetooth\jni,将C文件与头文件复制过来,新建Makefile。

例如以下:

LOCAL_PATH := $(call my-dir)

 

include $(CLEAR_VARS)

 

LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)

LOCAL_LDLIBS := -lm -llog

 

LOCAL_MODULE    := jni

LOCAL_SRC_FILES := com_android_semisky_bluetooth_util_BluetoothJNI.c

 

include $(BUILD_SHARED_LIBRARY)

2、打开Cygwin bash shell,进入Bluetooth文件夹。运行ndk-build进行编译。

 技术分享

3、将libs/armeabi下生成的libjni.so文件拷入到Androidproject的libs/armeabi文件夹下。安装apk到开发板。运行程序。

四、可能出现的问题

1、串口读写权限的问题

网上的方法是在Java中获取su账号来改权限或者在init.rc中加入命令来改动权限最后编译成img烧录进开发板。而这两种方法我都没成功,最后没办法在dos下运行shell命令来改动

2、C文件的串口读写问题

我不知道是我的程序有问题还是蓝牙模块的问题,在蓝牙模块返回数据稍大的时候。会出现数据有时返回有时不返回的情况。

3、乱码问题

蓝牙返回的数据时而出现乱码,未解决。

4、串口号的问题

假设你open的时候返回的fd小于1,确保你的开发板串口号是否正确。协议是否正确,权限是否改动。

5、最大大大的问题

读取串口代码段的算法问题,优化问题,不然数据会返回不正常。

以上是关于Android串口通讯的主要内容,如果未能解决你的问题,请参考以下文章

Android OTG之USB转串口模块通讯

Android项目实战(四十五):Usb转串口通讯(CH34xUARTDriver)

Android通过JNI实现与C语言的串口通讯操作蓝牙硬件模块

手机USB接口能与电脑串口连接通讯吗

Android项目实战(四十五):Usb转串口通讯(CH34xUARTDriver)

STM32串口通讯问题