如何在python中为串行设备制作CRC?

时间:2017-02-21 13:43:27

标签: java python pyserial crc

我必须使用python构建一个串行通信应用程序,旧的应用程序只在Windows XP上工作,并用C编写。现在我必须切换到Linux,我没有一个工作的驱动程序。我自己开始编码。我从串口设备的生产公司那里得到了协议。    串行设备接收和发送由CRC结束的数据。我是python的新手,我没有解决方案,也许有人可以帮助我。

这是CRC alghoritm:

  ALGORITHM FOR CRC CALCULATION

The two CRC bytes are calculated according to the formula x^15 + 1. In the calculation are included all data bytes plus the byte for block end. Every byte passes through the calculation register from teh MSB to LSB.
Three working bytes are used - S1, S0 and TR
S1 - Most significant byte from the CRC ( it is transmitted immediatelly after END)
S0 - Least significant byte from the CRC ( It is transmitted after S1)
TR - the current transmitted byte in the block.

The CRC is calculated as follows:
1. S1 and S0 are zeroed
2. TR is loaded with the current transmitted byte. The byte is transmitted.
3. Points 3.1 and 3.2 are executed 8 times:
3.1. S1, S0 and TR are shifted one bit to the left.
3.2. If the carry bit from S1 is 1, the MSB of S1 and LSB of S0 are inverted.
Points 2 and 3 are executed for all bytes, included in the calculation of the CRC - from the first byte after BEG up to and including byte END.
4. TR is loaded with 0 and point 3 is executed
5. TR is loaded with 0 and point 3 is executed
6. Byte S1 is transmitted
7. Byte S0 is transmitted

ALGORITHM FOR CRC CHECK ON RECEIVING

Three working bytes are used S1, S0 and RC

S1 - Most significant byte from the CRC ( it is received immediately after END)
S0 - Least significant byte from the CRC ( transmitted after S1)
RC - the current received byte in the block ( beginning from the first byte after BEG and ending 2 bytes after END).

The CRC is obtained as follows:
1. S1 and S0 are zeroed
2. RC is loaded with the current received byte
3. Points 3.1 and 3.2 are executed 8 times:
3.1. S1, S0 and RC are shifted 8 times to the left
3.2. if the MSB of S1 is 1 then MSB of S1 and LSB of S0 are inverted. 
Points 2 and 3 are executed for all bytes, included in the calculation of the CRC - from the first byte after BEG up to and including 2 bytes after END.
S1 and S0 must be 0.

如果有人能告诉我该怎么做,我将非常感激。谢谢大家。

编辑1:

我设法获得了由某人制作的相同CRC程序,但它是用java制作的,我对java不太好。也许你可以引导我在python中转换它。这是代码:

public class Crc {
    public static final String CRC_NAME = "CRC-16-ECR";
    private static final int POLYNOMIAL = 32769;
    public static final int WIDTH = 16;
    public static final int TOPBIT = 32768;
    short CRC;
    short[] crcTable = new short[256];

    public Crc() {
        this.crcInit();
    }

    private void crcInit() {
        for(int dividend = 0; dividend < 256; ++dividend) {
            int remainder = dividend << 8;

            for(byte bit = 8; bit > 0; --bit) {
                if((remainder & '耀') != 0) {
                    remainder = (remainder << 1 ^ '老') & '\uffff';
                } else {
                    remainder = remainder << 1 & '\uffff';
                }
            }

            this.crcTable[dividend] = (short)remainder;
        }

    }

    public short crcFast(byte[] message, int nBytes) {
        int remainder = 0;

        for(int oneByte = 0; oneByte < nBytes; ++oneByte) {
            int data = (message[oneByte] ^ remainder >> 8) & 255;
            remainder = this.crcTable[data] ^ remainder << 8;
        }

        return (short)remainder;
    }
}

1 个答案:

答案 0 :(得分:0)

#!/usr/bin/python
import sys
crc = 0
while True:
    ch = sys.stdin.read(1)
    if not ch:
        break
    crc ^= ord(ch) << 8
    for _ in range(8):
        crc = crc << 1 if (crc & 0x8000) == 0 else (crc << 1) ^ 0x8001
    crc &= 0xffff
print(format(crc, '04x'))