廢話不多說,開擼代碼。
用的是谷歌開源serialPort api ,下載鏈接
下載后全部導(dǎo)入項目中,什么也不用修改
寫一個工具類SerialPortUtils,設(shè)置好波特率
記錄開始發(fā)送時間和最后一次接收時間,用超時時間來判斷串口是否能正常收發(fā)數(shù)據(jù)
如何連續(xù)三次超時就自動更換串口號,知道接收到數(shù)據(jù)為止
下面是具體的類,僅供參考
public class SerialPortUtils {
? ? private final String TAG = "SerialPortUtils";
? ? private final int baudrate = 38400;//波特率
? ? private boolean serialPortStatus = false; //是否打開串口標(biāo)志
? ? private boolean threadStatus = false; //線程狀態(tài),為了安全終止線程
? ? private SerialPort serialPort = null;//串口
? ? private InputStream inputStream = null;
? ? private OutputStream outputStream = null;
? ? private int size; //讀取數(shù)據(jù)的大小
? ? private Integer i = 0;
? ? private int j = 0;
? ? private long lastReceiveTime ;
? ? private long lastSendTime;
? ? private final long TIME_OUT = 10 * 1000;
? ? private static SerialPortUtils INSTANCE;
? ? private List<String> list=null;
? ? private SerialPortUtils() {
? ? ? ? // 記錄創(chuàng)建對象時的時間
? ? ? ? lastReceiveTime = System.currentTimeMillis();
? ? ? ? lastSendTime = System.currentTimeMillis();
? ? ? ? openSerialPort();
? ? }
? ? public static synchronized SerialPortUtils getInstance() {
? ? ? ? if (INSTANCE == null) {
? ? ? ? ? ? INSTANCE = new SerialPortUtils();
? ? ? ? }
? ? ? ? return INSTANCE;
? ? }
? ? /**
? ? * 打開串口
? ? *
? ? * @return serialPort串口對象
? ? */
? ? private void openSerialPort() {
? ? ? //? i=0;
? ? ? ? try {
? ? ? ? ? ? if (serialPort == null) {
? ? ? ? ? ? ? ? serialPort = new SerialPort(new File(ApiAddress.path), baudrate, 0);
? ? ? ? ? ? ? ? serialPortStatus = true;
? ? ? ? ? ? ? ? threadStatus = false; //線程狀態(tài)
? ? ? ? ? ? ? ? //獲取打開的串口中的輸入輸出流,以便于串口數(shù)據(jù)的收發(fā)
? ? ? ? ? ? ? ? inputStream = serialPort.getInputStream();
? ? ? ? ? ? ? ? outputStream = serialPort.getOutputStream();
? ? ? ? ? ? ? ? //開始線程監(jiān)控是否有數(shù)據(jù)要接收
? ? ? ? ? ? ? ? new ReadThread().start();
? ? ? ? ? ? ? ? Tray.putString(MyApp.myApp,"chuankou",ApiAddress.path);
? ? ? ? ? ? }
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? MainUtil.printLogger(TAG, "openSerialPort: 打開串口異常:" + e.toString());
? ? ? ? }
? ? }
? ? /**
? ? * 關(guān)閉串口
? ? */
? ? public void closeSerialPort() {
? ? ? ? try {
? ? ? ? ? ? inputStream.close();
? ? ? ? ? ? outputStream.close();
? ? ? ? ? ? serialPortStatus = false;
? ? ? ? ? ? threadStatus = true; //線程狀態(tài)
? ? ? ? ? ? serialPort.close();
? ? ? ? ? ? serialPort = null;
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? MainUtil.printLogger(TAG, "closeSerialPort: 關(guān)閉串口異常:" + e.toString());
? ? ? ? }
? ? ? ? MainUtil.printLogger(TAG, "closeSerialPort: 關(guān)閉串口成功");
? ? }
? ? /**
? ? * 發(fā)送串口指令(字符串)
? ? *
? ? * @param sendData String數(shù)據(jù)指令
? ? */
? ? public synchronized void sendSerialPort(byte[] sendData) {
? ? ? ? try {
? ? ? ? ? ? if (sendData.length > 0) {
? ? ? ? ? ? ? ? if (null != outputStream) {
? ? ? ? ? ? ? ? ? ? outputStream.write(sendData);
? ? ? ? ? ? ? ? ? ? outputStream.flush();
? ? ? ? ? ? ? ? ? ? MainUtil.printLogger(TAG, "串口發(fā)送" + ByteHEXUtils.bytesTo_HexString(sendData));
? ? ? ? ? ? ? ? ? ? lastSendTime = System.currentTimeMillis();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? long miss = lastSendTime - lastReceiveTime;
? ? ? ? ? ? ? ? if (miss > TIME_OUT) {
? ? ? ? ? ? ? ? ? ? //超時
? ? ? ? ? ? ? ? ? ? i++;
? ? ? ? ? ? ? ? ? ? if (i > 3) {
? ? ? ? ? ? ? ? ? ? ? ? if (onChuankouListener != null) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? onChuankouListener.OnChuankouChange(2);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? list=getDevices();
? ? ? ? ? ? ? ? ? ? ? ? if(null!=list){
? ? ? ? ? ? ? ? ? ? ? ? ? ? Tray.putString(MyApp.myApp,"chuankou",list.get(j));
? ? ? ? ? ? ? ? ? ? ? ? ? serialPort = null;
? ? ? ? ? ? ? ? ? ? ? ? ? openSerialPort();
? ? ? ? ? ? ? ? ? ? ? ? ? ? j++;
? ? ? ? ? ? ? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? ? ? ? ? ? ? if("/dev/ttyS1".equals(Tray.getString(MyApp.myApp, "chuankou", "/dev/ttyS2"))){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Tray.putString(MyApp.myApp,"chuankou","/dev/ttyS2");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? serialPort = null;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? openSerialPort();
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? if("/dev/ttyS2".equals(Tray.getString(MyApp.myApp, "chuankou", "/dev/ttyS2"))){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Tray.putString(MyApp.myApp,"chuankou","/dev/ttyS1");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? serialPort = null;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? openSerialPort();
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? MainUtil.printLogger(TAG, "sendSerialPort: 串口數(shù)據(jù)發(fā)送失?。? + e.toString());
? ? ? ? }
? ? }
? ? private final StringBuffer sb = new StringBuffer();
? ? /**
? ? * 單開一線程,來讀數(shù)據(jù)
? ? */
? ? private class ReadThread extends Thread {
? ? ? ? @Override
? ? ? ? public void run() {
? ? ? ? ? ? super.run();
? ? ? ? ? ? while (!threadStatus) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? Thread.sleep(100);
? ? ? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? final byte[] buffer = new byte[256];
? ? ? ? ? ? ? ? // do something
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? size = inputStream.read(buffer);
? ? ? ? ? ? ? ? ? ? String message = new String(ByteHEXUtils.bytesTo_HexString(buffer).getBytes(), 0, size * 2);
? ? ? ? ? ? ? ? ? ? if (message.startsWith("FFFF") && message.endsWith("0D0A")) {
? ? ? ? ? ? ? ? ? ? ? ? if (ByteHEXUtils.count(message, "FFFF") > 1) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? message = message.substring(message.lastIndexOf("FFFF"));
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? if (message.substring(message.length() - 6, message.length() - 4).equals(ByteHEXUtils.makeChecksum(message.substring(0, message.length() - 6))) && onDataReceiveListener != null) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? if (onChuankouListener != null) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? i = 0;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? onChuankouListener.OnChuankouChange(1);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? lastReceiveTime = System.currentTimeMillis();
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? MainUtil.printLogger(TAG, "串口回調(diào)" + message);
? ? ? ? ? ? ? ? ? ? ? ? ? ? onDataReceiveListener.onDataReceive(message, size);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? sb.setLength(0);
? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? sb.append(message);
? ? ? ? ? ? ? ? ? ? ? ? if (ByteHEXUtils.count(sb.toString(), "FFFF") > 1) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? String str = sb.toString();
? ? ? ? ? ? ? ? ? ? ? ? ? ? sb.setLength(0);
? ? ? ? ? ? ? ? ? ? ? ? ? ? sb.append(str.substring(str.lastIndexOf("FFFF")));
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? if (sb.toString().startsWith("FFFF") && sb.toString().endsWith("0D0A")) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? if (sb.substring(sb.length() - 6, sb.length() - 4).equals(ByteHEXUtils.makeChecksum(sb.substring(0, sb.length() - 6))) && onDataReceiveListener != null) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? lastReceiveTime = System.currentTimeMillis();
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (onChuankouListener != null) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? i = 0;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? onChuankouListener.OnChuankouChange(1);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? MainUtil.printLogger(TAG, "串口回調(diào)" + sb.toString());
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? onDataReceiveListener.onDataReceive(sb.toString(), size);
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? sb.setLength(0);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? private OnDataReceiveListener onDataReceiveListener = null;
? ? private OnChuankouChangeListener onChuankouListener = null;
? ? public interface OnDataReceiveListener {
? ? ? ? void onDataReceive(String buffer, int size);
? ? }
? ? public void setOnDataReceiveListener(OnDataReceiveListener dataReceiveListener) {
? ? ? ? onDataReceiveListener = dataReceiveListener;
? ? }
? ? // 自定義接口
? ? public interface OnChuankouChangeListener {
? ? ? ? void OnChuankouChange(int status);
? ? }
? ? public void setOnChuankouListener(OnChuankouChangeListener chuankouListener) {
? ? ? ? onChuankouListener = chuankouListener;
? ? }
? ? public List<String>getDevices() {
? ? ? ? if (null == list) {
? ? ? ? ? ? list = new ArrayList<>();
? ? ? ? ? ? File dev = new File("/dev");
? ? ? ? ? ? File[] files = dev.listFiles();
? ? ? ? ? ? int i;
? ? ? ? ? ? for (i = 0; i < files.length; i++) {
? ? ? ? ? ? ? ? if (files[i].getAbsolutePath().startsWith("/dev/ttyS")) {
? ? ? ? ? ? ? ? ? ? MainUtil.printLogger(TAG, "Found new device: " + files[i]);
? ? ? ? ? ? ? ? ? ? list.add(files[i].toString());
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return list;
? ? }
}
本工具類中有自動替換串口,知道可以通信為止的方法
由于android端接收串口數(shù)據(jù)并不是一次性就可以全部接收到,有可能分兩段,也有可能丟失,所有在接收消息的時候,我做了拼接校驗,比如和板子開發(fā)人員確定好頭部和尾部以及校驗位,本工具類中頭部是FFFF開頭0D0A結(jié)尾的,對不符合的數(shù)據(jù)進(jìn)行了舍棄,并及時清空緩沖區(qū)
本工具類中Tray類似于共享參數(shù),保存了串口路徑,可以用SharedPreferences或者file代替
如有不對請指正。
我的csdn地址:?https://blog.csdn.net/u011847849/article/details/105999406