android串口通信以及串口协议解析
Java Code
1
2 3 |
android串口通信大概功能是android系统端的ARM和系统外的一个MCU通信
通过android界面控制MCU上挂的设备,如radio、TV、BT等等, 过程图 |
Java Code
1
2 3 4 5 6 7 8 |
一,android串口通信
串口通信采用一个第三方开源项目,实现串口数据收发。 1 . 使用了http: //code.google.com/p/android-serialport-api/的项目的serialport api和jni; 2 . 支持4串口同时收发,有定时自动发送功能,收发模式可选Txt或Hex模式; 3 . n, 8 , 1,没得选; 4 . 为减轻界面卡顿的情况,接收区的刷新采用单独的线程进行定时刷新; 5 . 发送区的数据以及一些设置项,在程序关闭时会自动保存,打开时自动载入; 6 . jni使用最新的NDKr8b重新编译了一下 |
Java Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
二,串口通信协议解析
1 .通信基本格式 字段 描述 长度(字节) 起始符 0F,十六进制码 1 信息类型 一个字节,十六进制码(0F,F0,FF等保留码不用)1 信息长度 是信息内容的长度,ASCII码表示(0~9,A~F,最大长度为256)(例如长为11个,十六进制是0B,则两个字节就写0x30 0x42)。 注:因为最大长度256不能满足有些指令的要求,所以对长度做了扩展,下面是扩展说明: 如果第一个字节的最高位为1,则表示扩展长度。在扩展长度状态下,其他15个字节通过16进制大端模式来保存长度。比如:0x80 0x12表示长度为0x001 2,0x81 0x12表示长度为0x0112。2 信息内容 一组十六进制码 N 校验 一个字节,十六进制码,是自信息类型起至对象号止所有码的异或。1 结束符 F0,一个字节,十六进制码 (为了保证可靠性,车机下发的结束符为F0 FF) 1 2 .协议解析 /** * 读取终端设备数据 * @author */ private class ReadThread extends Thread { @Override public void run() { super .run(); // 定义一个包的最大长度 int maxLength = 2048 ; byte [] buffer = new byte [maxLength]; // 每次收到实际长度 int available = 0 ; // 当前已经收到包的总长度 int currentLength = 0 ; // 协议头长度4个字节(开始符1,类型1,长度2) int headerLength = 4 ; while (!isInterrupted()) { try { available = mInputStream.available(); if (available > 0 ) { // 防止超出数组最大长度导致溢出 if (available > maxLength - currentLength) { available = maxLength - currentLength; } mInputStream.read(buffer, currentLength, available); currentLength += available; } } catch (Exception e) { e.printStackTrace(); } int cursor = 0 ; // 如果当前收到包大于头的长度,则解析当前包 while (currentLength >= headerLength) { // 取到头部第一个字节 if (buffer[cursor] != 0x0F) { --currentLength; ++cursor; continue ; } int contentLenght = parseLen(buffer, cursor, headerLength); // 如果内容包的长度大于最大内容长度或者小于等于0,则说明这个包有问题,丢弃 if (contentLenght <= 0 || contentLenght > maxLength - 5 ) { currentLength = 0 ; break ; } // 如果当前获取到长度小于整个包的长度,则跳出循环等待继续接收数据 int factPackLen = contentLenght + 5 ; if (currentLength < contentLenght + 5 ) { break ; } // 一个完整包即产生 // proceOnePacket(buffer,i,factPackLen); onDataReceived(buffer, cursor, factPackLen); currentLength -= factPackLen; cursor += factPackLen; } // 残留字节移到缓冲区首 if (currentLength > 0 && cursor > 0 ) { System.arraycopy(buffer, cursor, buffer, 0 , currentLength); } } } } /** * 获取协议内容长度 * @param header * @return */ public int parseLen( byte buffer[], int index, int headerLength) { // if (buffer.length - index < headerLength) { return 0; } byte a = buffer[index + 2 ]; byte b = buffer[index + 3 ]; int rlt = 0 ; if (((a >> 7 ) & 0x1) == 0x1) { rlt = (((a & 0x7f) << 8 ) | b); } else { char [] tmp = new char [ 2 ]; tmp[ 0 ] = ( char ) a; tmp[ 1 ] = ( char ) b; String s = new String (tmp, 0 , 2 ); rlt = Integer.parseInt(s, 16 ); } return rlt; } protected void onDataReceived( final byte [] buffer, final int index, final int packlen) { System.out.println( "收到信息" ); byte [] buf = new byte [packlen]; System.arraycopy(buffer, index, buf, 0 , packlen); ProtocolAnalyze.getInstance(myHandler).analyze(buf); } |