2019级软件工程应用与实践-人工智能快递柜(代码分析11)

2021SC@SDUSC

CRC8Util 类

这个类主要描写了如何利用串口数据对柜子的状态进行操作

    static int crc8_maxim(int[] data, int length) {
        int end = length;
        int i, j = 0;
        int crc = 0;
        while (length > 0) {
            crc ^= data[j ++];
            for (i = 0; i < 8; i ++) {
                if ((crc & 1) == 1) {
                    crc = (crc >> 1) ^ 0x8C; // 0x8C = reverse 0x31
                } else {
                    crc >>= 1;
                }
            }
            length--;
        }
        data[end] = crc;
        return crc;
    }

本项目在使用的CRC-8/MAXIM,它的参数模型为x8+x5+x4+1。所以,CRC校验的等效多项式是: CRC = x8 + x5 + x4 + 1

原理解析:
for (i = 0; i < 8; i ++)数据往左移了8位,因此需要计算8次。使用if ((crc & 1) == 1)进行最高位的判断,如果最高位为1,不需要异或,往左移一位,然后与0x8C异或,如果最高位为0时,不需要异或,整体数据往左移一位。最后可以得到相应的校验数据。

    static boolean checkCrc(int[] data) {
        if (data.length <= 1) {
            return false;
        }
        int end = data[data.length - 1];
        int check = crc8_maxim(data, data.length - 1);
        return end == check;
    }

}

调用crc8_maxim()函数 校验Crc 的结果,最后一位是校验位

public static int[] getUnLockCRC8Data(int tableNum, int lockNum) {
        int[] data = new int[] {0xAA, 0x55, 0x03, tableNum, 0x50, lockNum, 0x00};
        CRC8Util.crc8_maxim(data, 6);

        return data;
    }
    
public static String getUnLockCrc8String(int tableNum, int lockNum) {
        int[] temp = getUnLockCRC8Data(tableNum, lockNum);

        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < temp.length; i ++) {
            buffer.append(temp[i] < 16 ? ("0" + Integer.toHexString(temp[i])) : Integer.toHexString(temp[i]));
        }
        return buffer.toString();
    }

getUnLockCRC8Data()方法中,tableNum为锁控版编号,lockNum为锁编号,通过这两个参数获得UnLockCRC8数据,并将其转换成字符串,获取解锁命令。

static boolean getLockState(int[] retData, int lockNum) {
        lockNum--;
        int byteNum = lockNum / 8;
        int bitNum = lockNum % 8;
        int checkBit = 1 << bitNum;
        int tempByte = retData[5 + byteNum];
        return (checkBit & tempByte) != checkBit;

    }

retData为串口返回的数据, RLC-18E对应9字节,RLC-24E对应10字节
lockNum为锁编号,从1开始,最大24
只有当retData和lockNum相匹配,符合要求规范时,快递柜才能拥有开锁的状态。
此方法从响应值中获取某锁的状态。

public static boolean checkLockRet(int[] retData, int tableNum, int lockNum) {
        
        if (!checkResponseForm(retData, tableNum)) {
            System.out.println("数据格式错误");
            return false;
        }
        return getLockState(retData, lockNum);
    }

使用if (!checkResponseForm(retData, tableNum))检验数据格式是否错误,如果格式错误直接返回false,接着调用getLockState()函数检查开锁命令的响应值,验证锁是否打开。true表示锁已开,false表示锁未开。

    static boolean checkResponseForm(int[] retData, int tableNum) {
        if (retData[0] != 0xAA 
                || retData[1] != 0x55 
                || retData[3] != tableNum 
                || retData[2] + 4 != retData.length 
        ) {
            return false;
        }
        return checkCrc(retData);
    }

此方法检查串口的响应的数据格式,包括(两个帧头,版地址,校验位,数据总长度)。其中,0xAA为帧头1,0x55为帧头2,tableNum为板地址,retData.length为数据长度,通过或运算,如果有一项不符合要求则返回false。最后通过checkCrc(retData)计算校验位是否正确。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值