串口的读写操作
看这篇文章前,建议先看看这篇文章: 【android 串口开发(一) 之生成so文件】
既然,我们的so已经生成了,那么接下来就是串口的读写操作啦。
下面贴出关键类的代码:
**
* 串口操作类
*/
public class SerialPortUtil {
private String TAG = SerialPortUtil.class.getSimpleName();
private SerialPort mSerialPort;
private OutputStream mOutputStream;
private InputStream mInputStream;
private ReadThread mReadThread;
private String path = "/dev/ttyS4"; //这个是我们要读取的串口路径,这个硬件开发人员会告诉我们的
private int baudrate = 9600;//这个参数,硬件开发人员也会告诉我们的
private static SerialPortUtil portUtil;
private OnDataReceiveListener onDataReceiveListener = null;
private boolean isStop = false;
public interface OnDataReceiveListener {
public void onDataReceive(byte[] buffer, int size);
}
public void setOnDataReceiveListener(OnDataReceiveListener dataReceiveListener) {
onDataReceiveListener = dataReceiveListener;
}
public static SerialPortUtil getInstance() {
if (null == portUtil) {
portUtil = new SerialPortUtil();
portUtil.onCreate();
}
return portUtil;
}
/**
* 初始化串口信息
*/
public void onCreate() {
try {
mSerialPort = new SerialPort(new File(path), baudrate, 0);
mOutputStream = mSerialPort.getOutputStream();
mInputStream = mSerialPort.getInputStream();
mReadThread = new ReadThread();
isStop = false;
mReadThread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 发送指令到串口
*
* @param cmd
* @return
*/
public boolean sendCmds(String cmd) {
boolean result = true;
String str = cmd;
str = str.replace(" ", "");
byte[] mBuffer = SerialDataUtils.HexToByteArr(str);
if (!isStop) {
try {
if (mOutputStream != null) {
mOutputStream.write(mBuffer);
} else {
result = false;
}
} catch (IOException e) {
e.printStackTrace();
result = false;
}
} else {
System.out.println("sendCmds serialPort isClose");
result = false;
}
return result;
}
private class ReadThread extends Thread {
@Override
public void run() {
super.run();
System.out.println("ReadThread.run isInterrupted()=" + isInterrupted());
while (!isStop && !isInterrupted()) {
System.out.println("ReadThread.run mInputStream=" + mInputStream);
int size;
try {
if (mInputStream == null){
System.out.println("ReadThread.run return");
return;
}
byte[] buffer = new byte[512];
System.out.println("ReadThread.run buffer");
size = mInputStream.read(buffer);//该方法读不到数据时,会阻塞在这里
System.out.println("ReadThread.run size=" + size);
if (size > 0) {
/* if(MyLog.isDyeLevel()){
MyLog.log(TAG, MyLog.DYE_LOG_LEVEL, "length is:"+size+",data is:"+new String(buffer, 0, size));
}*/
byte[] buffer2 = new byte[size];
for (int i = 0; i < size; i++) {
buffer2[i] = buffer[i];
}
if (onDataReceiveListener != null) {
onDataReceiveListener.onDataReceive(buffer2, size);
}
}
Thread.sleep(50);//延时 50 毫秒
} catch (Exception e) {
e.printStackTrace();
System.out.println("ReadThread.run e.printStackTrace() " + e);
return;
}
}
}
}
/**
* 关闭串口
*/
public void closeSerialPort() {
isStop = true;
if (mReadThread != null) {
mReadThread.interrupt();
}
if (mSerialPort != null) {
mSerialPort.close();
}
}
}
把这个进制转换的工具类也贴出一下:
package com.everyoo.serialportdaemon2;
/**
* 串口数据转换工具类
* Created by Administrator on 2016/6/2.
*/
public class SerialDataUtils {
//-------------------------------------------------------
// 判断奇数或偶数,位运算,最后一位是1则为奇数,为0是偶数
public static int isOdd(int num) {
return num & 1;
}
//-------------------------------------------------------
//Hex字符串转int
public static int HexToInt(String inHex) {
return Integer.parseInt(inHex, 16);
}
//-------------------------------------------------------
//Hex字符串转byte
public static byte HexToByte(String inHex) {
return (byte) Integer.parseInt(inHex, 16);
}
//-------------------------------------------------------
//1字节转2个Hex字符
public static String Byte2Hex(Byte inByte) {
return String.format("%02x", new Object[]{inByte}).toUpperCase();
}
//-------------------------------------------------------
//字节数组转转hex字符串
public static String ByteArrToHex(byte[] inBytArr) {
StringBuilder strBuilder = new StringBuilder();
for (byte valueOf : inBytArr) {
strBuilder.append(Byte2Hex(Byte.valueOf(valueOf)));
strBuilder.append(" ");
}
return strBuilder.toString();
}
//-------------------------------------------------------
//字节数组转转hex字符串,可选长度
public static String ByteArrToHex(byte[] inBytArr, int offset, int byteCount) {
StringBuilder strBuilder = new StringBuilder();
int j = byteCount;
for (int i = offset; i < j; i++) {
strBuilder.append(Byte2Hex(Byte.valueOf(inBytArr[i])));
}
return strBuilder.toString();
}
//-------------------------------------------------------
//转hex字符串转字节数组
public static byte[] HexToByteArr(String inHex) {
byte[] result;
int hexlen = inHex.length();
if (isOdd(hexlen) == 1) {
hexlen++;
result = new byte[(hexlen / 2)];
inHex = "0" + inHex;
} else {
result = new byte[(hexlen / 2)];
}
int j = 0;
for (int i = 0; i < hexlen; i += 2) {
result[j] = HexToByte(inHex.substring(i, i + 2));
j++;
}
return result;
}
}
最后你在你的MainActivity中,直接调用 serialPort.sendCmds(“7e01010d”) 方法即可,需要注意一点的就是:像7e01010d 是十六进制的字符:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
initEvent();
SerialPortUtil serialPort = SerialPortUtil.getInstance();
//该方法是读取数据的回调监听,一旦读取到数据,就立马回调
serialPort.setOnDataReceiveListener(new SerialPortUtil.OnDataReceiveListener() {
@Override
public void onDataReceive(byte[] buffer, int size) {
receiveString = SerialDataUtils.ByteArrToHex(buffer).trim();
System.out.println("MainActivity2.onDataReceive receiveString= " + receiveString);
runOnUiThread(new Runnable() {
@Override
public void run() {
result.append(receiveString + "\r\n");
}
});
}
});
}
CMake相关参考文章:
Android开发:JNI开发过程以及两种生成.so文件的方法
Android Studio中CMakeList的写法
Android-串口(通过jni技术生成自己的so)
google官方地址: https://github.com/cepr/android-serialport-api