本文为博主原创文章,未经博主允许不得转载。如有问题,请与我联系( QQ:3290985311)朱小姐。
本篇实战是在Android下的串口通信实战之控制客显的基础上修改的。
上一篇的实战demo只用了Android设备向硬件发送指令。但是串口通信是双向通信,所以这篇实战讲的是双向通信交互。本篇的例子直接使用上一篇的例子继续。
1、硬件设备
Android平板,电子秤
2、通信过程
a、设置波特率和串口地址---demo里用的波特率是9600,串口地址是"/dev/ttyS3"
b、打开串口
private SerialPort mSerialPort = null;
String path = "/dev/ttyS3";
int baudrate = 9600;
private FileDescriptor mFd;
private FileInputStream mFileInputStream;
private FileOutputStream mFileOutputStream;
mSerialPort = new SerialPort(new File(path), baudrate, 0);
public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
/* Check access permission */
if (!device.canRead() || !device.canWrite()) {
try {
/* Missing read/write permission, trying to chmod the file */
Process su;
su = Runtime.getRuntime().exec("/system/bin/su");
String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ "exit\n";
su.getOutputStream().write(cmd.getBytes());
if ((su.waitFor() != 0) || !device.canRead()
|| !device.canWrite()) {
throw new SecurityException();
}
} catch (Exception e) {
e.printStackTrace();
throw new SecurityException();
}
}
mFd = open(device.getAbsolutePath(), baudrate, flags);
if (mFd == null) {
Log.e(TAG, "native open returns null");
throw new IOException();
}
mFileInputStream = new FileInputStream(mFd);
mFileOutputStream = new FileOutputStream(mFd);
}
注意上面代码,打开串口地址时,已经获取了输入流和输出流。mFileInputStream用来读取硬件返回的数据,mFileOutputStream用来向硬件发送指令数据。
串口通信有一个特点,外设会不停地返回数据,也没有停止的标志或指令。所以开一个读线程去读取串口返回数据,并用接口返回byte数据。
private class ReadThread extends Thread {
@Override
public void run() {
super.run();
while(!isInterrupted()) {
int size;
try {
byte[] buffer = new byte[512];
if (mInputStream == null) return;
size = mInputStream.read(buffer);
if (size > 0) {
onDataReceived(buffer, size);//返回数据的接口
}
try
{
Thread.sleep(50);
} catch (InterruptedException e)
{
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
}
接口的定义
protected abstract void onDataReceived(final byte[] buffer, final int size);
在需要处理串口数据的界面实现接口方法
@Override
protected void onDataReceived(byte[] buffer, int size) {
// TODO Auto-generated method stub
String result = new String(buffer,0,size);
if(result.length()>0){
String data = "";
Matcher matcher = Pattern.compile("[0-9]\\d{3}").matcher(result);
if(matcher.find()){
data = matcher.group();
}
//最终拿到符合条件的data
}
Log.d("zhu", "onDataReceived="+result);
}
因为本例中使用的电子秤是大华的。大华电子秤直接返回重量数据,例如电子秤上显示的是0.255kg,返回的数据就是0255,因为会不停得向串口发送数据,所以接收的数据有可能是0255 0255 0255等,所以使用正则表达式直接拿到4位数字,注意数据与数据之间还有可能有换行。所以使用正则会比使用split更精确。
注意:不同的设备,返回的数据不一样。要具体情况具体处理数据
上一篇讲的就是使用串口发送数据,以上讲的是接收串口数据。其实对于串口通信,发送数据和接收数据的过程是一样的。不同的是,发送的指令和接收的指令会根据不同的设备而有所不同。
附上上一篇的串口发送数据代码
private class SendingThread extends Thread {
private SendingThread() {
}
public void run() {
while (true) {
if (isInterrupted())
return;
try {
if (mOutputStream != null)
mOutputStream.write(mBuffer);//关键代码
} catch (IOException localIOException) {
localIOException.printStackTrace();
}
}
}
}
不开线程的话,就不需要这么处理了,直接一句话搞定
public void SendStr(byte[] paramArrayOfByte) {
try {
if (this.mOutputStream != null)
this.mOutputStream.write(paramArrayOfByte);
return;
} catch (IOException localIOException) {
localIOException.printStackTrace();
}
}
其中mBuffer是你要传送的数据的字节数组。
源码链接