您的位置:首页 > 移动开发 > Android开发

android串口通信以及串口协议解析

2013-12-03 11:50 465 查看
转载:http://blog.csdn.net/junfeng120125/article/details/9328947

一,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重新编译了一下

简单编写步骤:

1.新建一个项目,自己起个名字

2.直接复制serialport api和jni文件夹到新建的工程,如果不想自己编译jni,就连libs文件夹也一起复制

3.去android官方网站下载NDK,解压,在CMD中转到jni目录,并执行 绝对路径\ndk-build

4.自己再封装一个工具类或直接使用SerialPort类都行,举个直接使用的例:

直接剽窃原项目的SerialPortActivity.java,并稍微改一下,重点改这里

mSerialPort = mApplication.getSerialPort();

这里可以改成

new SerialPort(new File("/dev/s3c2410_serial0"), 9600, 0);//COM0,波特率9600

5. SerialPortFinder的使用就没什么好讲的了,实例化后用.getAllDevicesPath()就能获取到所有设备了。

其它如数据转换等请参考源码

源码可以参考谷歌android-serialport-api例子 
http://code.google.com/p/android-serialport-api/source/checkout 
svn checkout http://android-serialport-api.googlecode.com/svn/trunk
二,串口通信协议解析

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.协议解析

[java]
view plaincopy

/** 
     * 读取终端设备数据 
     * @author Administrator 
     */  
    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<
4000
/span> (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);   
    } 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: