1. 程式人生 > >開發實戰--CRC,校驗碼計算工具軟體的開發過程(開源)

開發實戰--CRC,校驗碼計算工具軟體的開發過程(開源)

1、專案的需求來源

      做為程式設計師碼程式碼,開發軟體,開發通訊協議,相信避免不了與各種校驗碼打交道。校驗碼是通訊協議中資料接收方用來校驗資料合法性的一個編碼。那麼舉個栗子,請看今早我和隔壁老王的對話,

        隔壁老王:今天你吃了麼?“嘎哈”

        老趙:我今天吃的是包子。“哇哈”

        哎,有人會問了,你和老王說話怎麼還帶著口頭禪,這個就是為了向你說明校驗碼,老王說話後面的加引號的“嘎哈”,我聽到後,知道老王是東北的,說話帶個“嘎哈”就驗證了這是老王說的,老王聽到我說話後面加引號的“哇哈”,知道了這是老趙說話的校驗碼,這話是老趙說的。

        根據實際的MODBUS RTU通訊協議就能更好的理解出來通訊協議中校驗碼的功能:

地址 功能程式碼 資料數量 資料1 ... 資料n CRC低位元組 CRC高位元組

這個協議中的最後兩個位元組,CRC低位元組,CRC高位元組就是校驗碼了,這個校驗碼是前面所有資料、資料數量、功能程式碼、地址這些位元組經過特殊的運算得出來。

      開發過程中今天MODBUS協議,明天ISO14443A,後天TCP/IP協議...,測試過程中要編寫各種協議,計算各種校驗碼,我想你最開始是手算或都上網找一個工具來計算,今天咱們就寫一個單機板的計算工具,具有計算異或和,累加和,MODBUS CRC,ISO14443 CRC計算功能的校驗碼計算工具。先上開發工作成果,哈哈

2、各種校驗碼的計算演算法

     (1)NOR 異或和計算

           nor = d1 ^ d2 ^ ... dn   d1 - dn是要參與計算的資料,是一個單位元組的資料,這個異或計算就是對所有資料進行邏輯按位異或

     (2)SUM累加和計算

          sum = d1 + d2 + d3...dn     d1 - dn是要參與計算的資料,是一個單位元組的資料,這個累加和計算就是對所有資料進行累加,累加的結果還是取單位元組,不考慮溢位的高位部分

     (3)ISO14443的CRC計算

           G(x)=x^16 + x ^12 + x^5 + 1,這個演算法複雜一點,具體可以參考

ISO14443協議中的第60頁,ISO14443協議中有CRC A, CRC B的計演算法,這個兩種校驗碼的演算法一樣,初始值不一樣。

      (4)MODBUS CRC計算

           這個CRC計算也複雜一點,具體可以參考MODBUS協議的第72頁,為了加快計算速度,採用查表的方法來計算CRC值。

3、設計UI介面

         開啟QtCreat新建一個UI檔案,按照你想的樣子新增控制元件,我的設計是這個樣子的。

      視窗分成上下兩個輸入輸出文字框,上面的用於輸入要計算的資料,下面的用於輸出計算結果,中間有放有單選按鈕,用於選擇計算的演算法,最下面還有兩個單選按鈕“結果取反”和“結果不取反”這個選項只對計算NOR時有效,對NOR計算的結果增加一次取反操作,其他演算法計算時無效。介面編輯完成後,儲存,工程目錄下面會生成一個mainwindow.ui的檔案,在命令列中執行pyuic5 mainwindow.ui -o mainwindow.py,把ui檔案生成了py的程式碼檔案。

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.8.2
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.setEnabled(True)
        MainWindow.resize(472, 349)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
        MainWindow.setSizePolicy(sizePolicy)
        MainWindow.setMinimumSize(QtCore.QSize(450, 349))
        MainWindow.setMaximumSize(QtCore.QSize(500, 349))
        self.centralWidget = QtWidgets.QWidget(MainWindow)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.centralWidget.sizePolicy().hasHeightForWidth())
        self.centralWidget.setSizePolicy(sizePolicy)
        self.centralWidget.setObjectName("centralWidget")
        self.label = QtWidgets.QLabel(self.centralWidget)
        self.label.setGeometry(QtCore.QRect(10, 0, 91, 16))
        self.label.setObjectName("label")
        self.textEdit = QtWidgets.QTextEdit(self.centralWidget)
        self.textEdit.setGeometry(QtCore.QRect(10, 20, 441, 101))
        self.textEdit.setObjectName("textEdit")
        self.label_2 = QtWidgets.QLabel(self.centralWidget)
        self.label_2.setGeometry(QtCore.QRect(10, 130, 81, 16))
        self.label_2.setObjectName("label_2")
        self.textEdit_2 = QtWidgets.QTextEdit(self.centralWidget)
        self.textEdit_2.setGeometry(QtCore.QRect(10, 150, 451, 101))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.textEdit_2.sizePolicy().hasHeightForWidth())
        self.textEdit_2.setSizePolicy(sizePolicy)
        self.textEdit_2.setObjectName("textEdit_2")
        self.pushButton = QtWidgets.QPushButton(self.centralWidget)
        self.pushButton.setGeometry(QtCore.QRect(380, 260, 75, 23))
        self.pushButton.setStyleSheet("color: rgb(85, 0, 255);\n"
"font: 75 9pt \"Arial\";")
        self.pushButton.setObjectName("pushButton")
        self.radioButton = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton.setGeometry(QtCore.QRect(10, 260, 89, 16))
        self.radioButton.setChecked(True)
        self.radioButton.setObjectName("radioButton")
        self.radioButton_2 = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton_2.setGeometry(QtCore.QRect(120, 260, 89, 16))
        self.radioButton_2.setObjectName("radioButton_2")
        self.radioButton_3 = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton_3.setGeometry(QtCore.QRect(90, 130, 71, 16))
        self.radioButton_3.setObjectName("radioButton_3")
        self.radioButton_4 = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton_4.setGeometry(QtCore.QRect(160, 130, 71, 16))
        self.radioButton_4.setObjectName("radioButton_4")
        self.radioButton_5 = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton_5.setGeometry(QtCore.QRect(230, 130, 81, 16))
        self.radioButton_5.setObjectName("radioButton_5")
        self.radioButton_6 = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton_6.setGeometry(QtCore.QRect(310, 130, 81, 16))
        self.radioButton_6.setObjectName("radioButton_6")
        self.radioButton_7 = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton_7.setGeometry(QtCore.QRect(390, 130, 89, 16))
        self.radioButton_7.setObjectName("radioButton_7")

        #建立一個buttongroup進行分組
        self.computButtonGroup = QtWidgets.QButtonGroup(self.centralWidget)
        self.computButtonGroup.addButton(self.radioButton_3)
        self.computButtonGroup.addButton(self.radioButton_4)
        self.computButtonGroup.addButton(self.radioButton_5)
        self.computButtonGroup.addButton(self.radioButton_6)
        self.computButtonGroup.addButton(self.radioButton_7)
        self.radioButton_3.setChecked(True)
        
        MainWindow.setCentralWidget(self.centralWidget)
        self.menuBar = QtWidgets.QMenuBar(MainWindow)
        self.menuBar.setGeometry(QtCore.QRect(0, 0, 472, 23))
        self.menuBar.setObjectName("menuBar")
        self.menu = QtWidgets.QMenu(self.menuBar)
        self.menu.setObjectName("menu")
        MainWindow.setMenuBar(self.menuBar)
        self.statusBar = QtWidgets.QStatusBar(MainWindow)
        self.statusBar.setObjectName("statusBar")
        MainWindow.setStatusBar(self.statusBar)
        self.actionud = QtWidgets.QAction(MainWindow)
        self.actionud.setObjectName("actionud")
        self.actionvec = QtWidgets.QAction(MainWindow)
        self.actionvec.setObjectName("actionvec")
        self.menu.addAction(self.actionud)
        self.menu.addAction(self.actionvec)
        self.menuBar.addAction(self.menu.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Nor computer"))
        self.label.setText(_translate("MainWindow", "輸入資料(HEX)"))
        self.textEdit.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">請輸入十六進位制資料,以空格分隔</p></body></html>"))

        #設定預設選中輸入框中的文字 zhaoshimin 20180829
        self.textEdit.selectAll()
        self.label_2.setText(_translate("MainWindow", "計算結果(HEX)"))
        self.pushButton.setText(_translate("MainWindow", "計算"))
        self.radioButton.setText(_translate("MainWindow", "結果取反"))
        self.radioButton_2.setText(_translate("MainWindow", "結果不取反"))
        self.radioButton_3.setText(_translate("MainWindow", "NOR計算"))
        self.radioButton_4.setText(_translate("MainWindow", "SUM計算"))
        self.radioButton_5.setText(_translate("MainWindow", "CRC-A計算"))
        self.radioButton_6.setText(_translate("MainWindow", "CRC-B計算"))
        self.radioButton_7.setText(_translate("MainWindow", "ModbusCRC"))
        self.menu.setTitle(_translate("MainWindow", "幫助"))
        self.actionud.setText(_translate("MainWindow", "關於"))
        self.actionvec.setText(_translate("MainWindow", "退出"))

4、編寫各個演算法的計算演算法

         另外建立一個Nor_com.py的檔案,這個檔案用於實現計算演算法,演算法和介面檔案分開,減少業務邏輯和介面的耦合性。

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtGui import QIcon
from mainwindow import Ui_MainWindow
import sys
from picon import *

aucCRCHi = [
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40]

aucCRCLo = [
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
    0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
    0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
    0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
    0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
    0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
    0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 
    0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
    0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
    0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
    0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 
    0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
    0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
    0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
    0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
    0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
    0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
    0x41, 0x81, 0x80, 0x40]
#modbus crc計算函式
def  modbus_crc(data):
    CRCHi = 0xFF
    CRCLo = 0xFF
    index = 0

    for i in range(0, len(data)):
        index = CRCLo ^ data[i]
        CRCLo = CRCHi ^ aucCRCHi[index]
        CRCHi = aucCRCLo[index]
        
        

    return ((CRCHi << 8 )| CRCLo)

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)

        
        # 設定應用程式的視窗圖示
        self.setWindowIcon(QIcon(":/NOR_computer.png"))

        
        #預設選擇結果取反
        self.radioButton.setChecked(True)
        self.pushButton.clicked.connect(self.nor_com)
        self.actionud.triggered.connect(self.about)      #選單的點選事件是triggered
        self.actionvec.triggered.connect(self.close) 
    def about(self):
        print('this is about')
        #彈出關於對話方塊
        QMessageBox.about(self,("關於"),("""Nor Computer V1.0\nSupport: [email protected]\nCopyright: 1982-2017"""))
        QMessageBox.StandardButtons(QMessageBox.Ok)
    def nor_com(self):
        self.statusBar.showMessage('開始計算')
        #從輸入框讀入字串
        input_s = self.textEdit.toPlainText()
        #刪除前面和後面的空格
        input_s = input_s.strip()
        out_s = input_s
        nor = 0
        sum = 0
        crc_type = 0x6363
        modbus_data = []
       

        if  self.radioButton_5.isChecked():
            #ISO14443A CRC A的計算初值
            crc_type = 0x6363
        elif self.radioButton_6.isChecked():
            #ISO14443A CRC B的計算初值
            crc_type = 0xFFFF

        
        while input_s !='':
            try:
                num = int(input_s[0:2],16)
            except:
                print(sys.exc_info()[0])
                self.statusBar.showMessage('計算中:ValueError')
                #彈出警告對話方塊
                QMessageBox.warning(self,("警告"),("""請輸入十六進位制位元組資料,以空格隔開"""))
                QMessageBox.StandardButtons(QMessageBox.Ok)
                return None
            

            #判斷進行nor運算還是sum運算
            if self.radioButton_3.isChecked():
                #異或和計算
                nor = nor ^ num
            elif self.radioButton_4.isChecked():
                #SUN累加和運算
                nor = nor + num
            elif self.radioButton_5.isChecked() or self.radioButton_6.isChecked():
                #ISO14443A CRC運算
                sum = num ^ (crc_type & 0xFF)
                sum = (sum ^ (sum << 4)) & 0xFF
                crc_type = (crc_type >> 8) ^ ((sum << 8) & 0xffff) ^ ((sum << 3) & 0xffff) ^ ((sum >> 4) & 0xffff)
                crc_type = crc_type & 0xFFFF
            elif self.radioButton_7.isChecked():
                #把資料放入計算列表中去
                modbus_data.append(num)
                
                
            input_s = input_s[2:]
            input_s = input_s.strip()
            
        
        #NOR SUM的計算結果取反操作
        if self.radioButton.isChecked():
            nor = ~nor
            
        else:
            pass

        
        nor = nor & 0xFF
        #print('%02x'%(nor))

        
        #狀態列顯示和輸出計算結果
        if self.radioButton_4.isChecked():
            out_s = out_s + ' ' + '{:02x}'.format(nor)
            self.statusBar.showMessage('計算完成    SUM=0x' + '{:x}'.format(nor).upper() + '(' +'{:d}'.format(nor)+')')
        elif self.radioButton_3.isChecked():
            out_s = out_s + ' ' + '{:02x}'.format(nor)
            self.statusBar.showMessage('計算完成    NOR=0x' + '{:x}'.format(nor).upper() + '(' +'{:d}'.format(nor)+')')
            
        elif self.radioButton_5.isChecked():
            #CRC A計算結果
            out_s = out_s + ' ' + '{:02x}'.format(crc_type & 0xFF) + ' ' + '{:02x}'.format(crc_type >> 8)
            self.statusBar.showMessage('計算完成  ISO14443A  CRCA=0x' + '{:x}'.format(crc_type).upper() + '(' +'{:d}'.format(crc_type)+')')
            
        elif self.radioButton_6.isChecked():
            #CRC B計算結果
            crc_type = (~crc_type) & 0xffff
            out_s = out_s + ' ' + '{:02x}'.format(crc_type >> 8) + ' ' + '{:02x}'.format(crc_type & 0xFF)
            self.statusBar.showMessage('計算完成  ISO14443B  CRCB=0x' + '{:x}'.format(crc_type).upper() + '(' +'{:d}'.format(crc_type)+')')    
            
        elif self.radioButton_7.isChecked():
            #MODBUS crc計算結果
            crc = modbus_crc(modbus_data)
            out_s = out_s + ' ' + '{:02x}'.format(crc & 0xFF) + ' ' + '{:02x}'.format((crc >> 8) & 0xFF)
            self.statusBar.showMessage('計算完成  Modbus CRC_L=0x' + '{:02X}'.format(crc & 0xFF).upper() + ' CRC_H=0x' +'{:02X}'.format(crc >> 8))  
        #轉換成大寫字母輸出
           
        self.textEdit_2.setText(out_s.upper())

        

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWindow = MainWindow()
    mainWindow.show()
    sys.exit(app.exec_())

     5、設計軟體的圖示

     軟體的圖示設計一個ico型別的檔案和png型別的檔案,兩個圖示一樣,不同的檔案格式而已,命名為Nor_commputer.ico, Nor_commputer.png,ico檔案用於打包成EXE程式裡的軟體圖示,png檔案用於在程式視窗的左上角顯示出來一個圖示。 編輯一個資原始檔nor_com.qrc,寫入軟體中要呼叫的圖片資源Nor_commputer.png。最後命令列中輸入pyrcc5 nor_com.qrc -o pyico.py生成程式內部顯示圖示使用的圖示檔案。

     6、打包生成可執行檔案

        使用pyinstaller打包,命令列中輸入 pyinstaller --icon=Nor_com.ico --paths=E:\python_test\api-ms-win -F -w Nor_com.py執行,具體使用方法可以參考我的博文python使用pyinstaller打包生成EXE可執行檔案

         如果你想直接下載可執行檔案來使用,可以到csdn下載頁中搜索NOR校驗碼計算工具來下載。

下載地址

相關推薦

開發實戰--CRC,計算工具軟體開發過程開源

1、專案的需求來源       做為程式設計師碼程式碼,開發軟體,開發通訊協議,相信避免不了與各種校驗碼打交道。校驗碼是通訊協議中資料接收方用來校驗資料合法性的一個編碼。那麼舉個栗子,請看今早我和隔壁老王的對話,         隔壁老王:今天你吃了麼?“嘎哈”    

迴圈冗餘計算CRC

CRC迴圈冗餘檢驗碼的計算題 1、若資訊碼字為11100011,生成多項式 G(X)=X5+X4+X+1,則計算出的 CRC 校驗碼為? x的最高次冪5則 資訊碼(被除數)補五個0為:111000

java modbus crc16 socket給傳送的資料新增crc

首先crc16校驗碼的生成的原理在上一篇部落格裡面已經說過了; 前提:xframe配置京金華伺服器的埠號,繫結ip地址和埠號 程式要實現什麼? 這個程式主要實現的是伺服器傳送資料到客戶端,然後客戶端傳送資料到伺服器端; 是一問一答的形式; 只有伺服器傳送,客戶端才會應答 傳送

驗證工具

直接上程式碼 package com.hzzf.framework.sms; //校驗碼驗證工具 public class IDcade { /*public static void main(String[] args) { IDcade idcade =new IDcade(

身份證的計算

PS:倒數第二位奇數為男,偶數為女 (1)十七位數字本體碼加權求和公式  S = Sum(Ai * Wi), i = 0, … , 16 ,先對前17位數字的權求和  Ai:表示第i位置上的身份證號碼數字值  Wi:表示第i位置上的加權因子&n

CRC生成與資料原始碼程式 (包括CRC-4,5,6,7,8,16,32)

C程式碼 收藏程式碼 /******************************************************************** * Name: CRC-4/ITU x4+x+1 *

資料傳輸中CRC的實現

CRC校驗碼,即迴圈冗餘校驗(Cyclic Redundancy Check),目前最為常見的一種差錯校驗碼,CRC的資訊欄位和校驗字的長度可以任意選定,在資料傳輸過程中,為了確保資料的正確性,必須使用一種資料檢錯方法,CRC便是最常用的一種。 CRC的原理是若在傳送端傳送

JAVA CRC16計算

package com.hcs.lqjc.controller.dongDaHengFeng.ModBus.utils; /** * @author lwt * @date 2018-06-26 * * CRC16校驗碼計算 * <p> * (1).

深入瞭解資料:Java Bean Validation 2.0JSR380

每篇一句 吾皇一日不退役,爾等都是臣子 相關閱讀 【小家Java】深入瞭解資料校驗(Bean Validation):基礎類打點(ValidationProvider、ConstraintDescriptor、ConstraintValidator) 對Spring感興趣可掃碼加入wx群:`Java高工

[技術棧]CRC原理及C#程式碼實現CRC16、CRC32計算FCS

1.CRC、FCS是什麼 CRC,全稱Cyclic Redundancy Check,中文名稱為迴圈冗餘校驗,是一種根據網路資料包或計算機檔案等資料產生簡短固定位數校驗碼的一種通道編碼技術,主要用來檢測或校驗資料傳輸或者儲存後可能出現的錯誤。它是利用除法及餘數的原理來作錯誤偵測的。 FCS,全稱Frame C

計算身份證最後一位

map git 校驗碼 meta ffi spa class ++ msg 在線預覽 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <

常用奇偶,海明CRC學習總結

結果 post 1的個數 增加 src 所在 如果 ble 繼續 常用校驗碼(奇偶校驗,海明校驗,CRC)學習總結 一.為什麽要有校驗碼? 因為在數據存取和傳送的過程中,由於元器件或者噪音的幹擾等原因會出現錯誤,這個時候我們就需要采取相應的措施,發現並糾正錯誤,對於錯誤的

怎麼計算crc16資料的

第一、CRC-16校驗碼計算方法: 常用查表法和計演算法。計算方法一般都是: (1)、預置1個16位的暫存器為十六進位制FFFF(即全為1),稱此暫存器為CRC暫存器; (2)、把第一個8位二進位制資料(既通訊資訊幀的第一個位元組)與16位的CRC暫存器的低    

身份證第18位計算方法

1、將前面的身份證號碼17位數分別乘以不同的係數。從第一位到第十七位的係數分別為:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。2、將這17位數字和係數相乘的結果相加。3、用加出來和除以11,看餘數是多少?4、餘數只可能有0-1-2-3-4-5-6-7-8-9-10這11個數字。其分

居民身份證號碼的奧祕及身份證第18位計算方法

居民身份證是國家法定的證明公民個人身份的證件。為了堵塞和制止假居民身份證的流通和使用,在查驗和核查居民身份證時可掌握以下幾個要點:   一、居民身份證有效期限與持證人年齡、簽發日期的關係   居民身份證的有效期限分為10年、20年、長期三種。16週歲至25週歲的,發給有效期為10年的居民身份

身份證第18位如何計算

身份證校驗碼的計算方法 1、將前面的身份證號碼17位數分別乘以不同的係數。從第一位到第十七位的係數分別為:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。 2、將這17位數字和係數相乘的結果相加。 3、用加出來和除以11,看餘數是多少? 4、餘數只可能有0-1

crc多項式

藉助於多項式除法,其餘數為校驗欄位。 例如:資訊欄位程式碼為: 1011001;對應m(x)=x6+x4+x3+1 假設生成多項式為:g(x)=x4+x3+1;則對應g(x)的程式碼為: 11001 x4m(x)=x10+x8+x7+x4 對應的程式碼記為:1011

JS-計算身份證最後一位

線上預覽 <!DOCTYPE html> <html lang="en"> <head> <title>Document</title> <style> #msg{ color: red; }

迴圈冗餘CRC應用總結(包括C++原始碼)

 最近在實習期間需要用到資料的校驗,所選為CRC16,那麼就在此總結一番吧。 現在此說明下什麼是CRC:迴圈冗餘碼校驗 英文名稱為Cyclical Redundancy Check,簡稱CRC,它是利用除法及餘數的原理來作錯誤偵測(Error Detecting)的。實際應

Qt:計算CRCCRC16和CRC32

CRC有非常多的模式,我沒有全部都做,目前支援 CRC16-Modbus CRC16-X25 CRC32 使用方法 auto data = QByteArray::fromHex( "01