1. 基本原理

友情提示:本篇文章只用于学习交流使用,请不要用于其它用途

我们总共需要三个组件:树莓派,MFRC522模块,IC卡

树莓派与MFRC522模块的交互通过SPI方式:树莓派首先通过"sudo raspi-config"命令打开SPI口,然后根据协议向模块特定寄存器读写数据,以此完成数据收发操作

MFRC522模块与IC卡是通过电磁感应无接触交互的:MFRC522模块内部会产生感应电磁场,IC卡内部线圈通过电磁感应获取电能,然后解析数据,最终完成IC卡内部存储器的数据读写操作

整个系统流程就是首先树莓派通过SPI接口向MFRC522模块发送数据和命令,MFRC522模块收到数据和命令后,产生电磁场,然后IC卡通过内部感应电圈获得电能和数据,解析数据后读写存储器,最终完成IC卡数据的读写

参考资料:https://download.csdn.net/download/chenwh_cn/12746663,附件中包含了IC卡调试工具,以及IC卡和MFRC522模块的数据手册,介绍了基本组成原理和内部存储器的功能,以及各种命令交互的数据协议格式,

2. 代码实现

a. SPI 依赖库的安装

下载源代码 https://github.com/lthiery/SPI-Py.git

然后进入SPI-Py目录执行:sudo python setup.py install

该库提供了3个API接口函数用以实现SPI通信:

  1. openSPI,用于打开SPI口,同时可以设置mode, speed, bits, delay等
  2. transfer,用于收发数据
  3. closeSPI,用于关闭SPI口

b. 驱动接口实现 MFRC522.py

"__"前缀为私有函数,"MFRC522_"前缀为公有函数,开头注释描述了树莓派与MFRC522模块的连线方式

# RC522-pin     Pi-pin
# 3.3V          1(3.3V)
# RST           22(GPIO25)
# GND           6(GND)
# IRQ           none
# MISO          21(GPIO9)
# MOSI          19(GPIO10)
# SCK           23(GPIO11)
# SDA           24(GPIO8)import RPi.GPIO as GPIO
import spi
import signal
import timeclass MFRC522:PCD_IDLE        = 0x00     # cancel current commandPCD_AUTHENT     = 0x0E     # authentPCD_RECEIVE     = 0x08     # receive dataPCD_TRANSMIT    = 0x04     # send dataPCD_TRANSCEIVE  = 0x0C     # send & receive dataPCD_RESETPHASE  = 0x0F     # resetPCD_CALCCRC     = 0x03     # CRC calculatePICC_REQIDL     = 0x26     # detect cards, not sleppPICC_REQALL     = 0x52     # detect cards, all PICC_ANTICOLL   = 0x93     # anti collisionPICC_SElECTTAG  = 0x93     # select cardPICC_AUTHENT1A  = 0x60     # authent APICC_AUTHENT1B  = 0x61     # authent BPICC_READ       = 0x30     # read blockPICC_WRITE      = 0xA0     # write blockPICC_DECREMENT  = 0xC0     # dec moneyPICC_INCREMENT  = 0xC1     # inc moneyPICC_RESTORE    = 0xC2     # send data to bufPICC_TRANSFER   = 0xB0     # save date from bufPICC_HALT       = 0x50     # idle statusReserved00      = 0x00     # registerCommandReg      = 0x01CommIEnReg      = 0x02DivlEnReg       = 0x03CommIrqReg      = 0x04DivIrqReg       = 0x05ErrorReg        = 0x06Status1Reg      = 0x07Status2Reg      = 0x08FIFODataReg     = 0x09FIFOLevelReg    = 0x0AWaterLevelReg   = 0x0BControlReg      = 0x0CBitFramingReg   = 0x0DCollReg         = 0x0EReserved01      = 0x0FReserved10      = 0x10ModeReg         = 0x11TxModeReg       = 0x12RxModeReg       = 0x13TxControlReg    = 0x14TxAutoReg       = 0x15TxSelReg        = 0x16RxSelReg        = 0x17RxThresholdReg  = 0x18DemodReg        = 0x19Reserved11      = 0x1AReserved12      = 0x1BMifareReg       = 0x1CReserved13      = 0x1DReserved14      = 0x1ESerialSpeedReg  = 0x1FReserved20        = 0x20CRCResultRegM     = 0x21CRCResultRegL     = 0x22Reserved21        = 0x23ModWidthReg       = 0x24Reserved22        = 0x25RFCfgReg          = 0x26GsNReg            = 0x27CWGsPReg          = 0x28ModGsPReg         = 0x29TModeReg          = 0x2ATPrescalerReg     = 0x2BTReloadRegH       = 0x2CTReloadRegL       = 0x2DTCounterValueRegH = 0x2ETCounterValueRegL = 0x2FReserved30      = 0x30TestSel1Reg     = 0x31TestSel2Reg     = 0x32TestPinEnReg    = 0x33TestPinValueReg = 0x34TestBusReg      = 0x35AutoTestReg     = 0x36VersionReg      = 0x37AnalogTestReg   = 0x38TestDAC1Reg     = 0x39TestDAC2Reg     = 0x3ATestADCReg      = 0x3BReserved31      = 0x3CReserved32      = 0x3DReserved33      = 0x3EReserved34      = 0x3FNRSTPD          = 22MAX_LEN         = 18MI_OK           = 0MI_NOTAGERR     = 1MI_ERR          = 2MI_TIMEOUT      = 3def __init__(self, dev='/dev/spidev0.0', spd=1000000):self.dev0 = spi.openSPI(device=dev, speed=spd)GPIO.setmode(GPIO.BOARD)GPIO.setup(self.NRSTPD, GPIO.OUT)GPIO.output(self.NRSTPD, 1)self.MFRC522_Init()def __WriteReg(self, addr, val):spi.transfer(self.dev0, ((addr<<1)&0x7E, val))def __ReadReg(self, addr):val = spi.transfer(self.dev0, (((addr<<1)&0x7E) | 0x80, 0))return val[1]def __SetRegBitMask(self, reg, mask):tmp = self.__ReadReg(reg)self.__WriteReg(reg, tmp | mask)def __ClearRegBitMask(self, reg, mask):tmp = self.__ReadReg(reg)self.__WriteReg(reg, tmp & (~mask))def __ToCard(self, command, sendData):retStatus = self.MI_OKbackData = []backLen = 0irqEn = 0x00waitIRq = 0x00lastBits = Nonen = 0i = 0if command == self.PCD_AUTHENT:irqEn   = 0x12waitIRq = 0x10if command == self.PCD_TRANSCEIVE:irqEn   = 0x77waitIRq = 0x30self.__WriteReg(self.CommIEnReg, irqEn|0x80)      # enable interuptself.__ClearRegBitMask(self.CommIrqReg, 0x80)     # clear interupt flagsself.__SetRegBitMask(self.FIFOLevelReg, 0x80)     # init FIFOself.__WriteReg(self.CommandReg, self.PCD_IDLE)   # cancel current commandfor i in range(len(sendData)):self.__WriteReg(self.FIFODataReg, sendData[i])self.__WriteReg(self.CommandReg, command)if command == self.PCD_TRANSCEIVE:self.__SetRegBitMask(self.BitFramingReg, 0x80)i = 2000while True:n = self.__ReadReg(self.CommIrqReg)i -= 1if ~((i!=0) and ~(n&0x01) and ~(n&waitIRq)):breakself.__ClearRegBitMask(self.BitFramingReg, 0x80)if i != 0:if (self.__ReadReg(self.ErrorReg) & 0x1B) == 0x00:if n & irqEn & 0x01:retStatus = self.MI_NOTAGERRif command == self.PCD_TRANSCEIVE:n = self.__ReadReg(self.FIFOLevelReg)lastBits = self.__ReadReg(self.ControlReg) & 0x07if lastBits != 0:backLen = (n-1)*8 + lastBitselse:backLen = n*8if n == 0:n = 1if n > self.MAX_LEN:n = self.MAX_LENfor i in range(n):backData.append(self.__ReadReg(self.FIFODataReg))else:retStatus = self.MI_ERRelse:retStatus = self.MI_TIMEOUTreturn (retStatus, backData, backLen)def __CalulateCRC(self, indata):self.__ClearRegBitMask(self.DivIrqReg, 0x04)self.__SetRegBitMask(self.FIFOLevelReg, 0x80)for i in range(len(indata)):self.__WriteReg(self.FIFODataReg, indata[i])self.__WriteReg(self.CommandReg, self.PCD_CALCCRC)i = 255while True:n = self.__ReadReg(self.DivIrqReg)i -= 1if ~((i != 0) and ~(n&0x04)):breakcrc = []crc.append(self.__ReadReg(self.CRCResultRegL))crc.append(self.__ReadReg(self.CRCResultRegM))return crcdef MFRC522_Init(self):self.MFRC522_Reset()self.__WriteReg(self.TModeReg, 0x8D)self.__WriteReg(self.TPrescalerReg, 0x3E)self.__WriteReg(self.TReloadRegL, 30)self.__WriteReg(self.TReloadRegH, 0)self.__WriteReg(self.TxAutoReg, 0x40)self.__WriteReg(self.ModeReg, 0x3D)self.MFRC522_AntennaOn()def MFRC522_Reset(self):# reg: 0x01# buf: 0x0Fself.__WriteReg(self.CommandReg, self.PCD_RESETPHASE)def MFRC522_AntennaOn(self):# reg: 0x14# buf: 0bxxxxxx11temp = self.__ReadReg(self.TxControlReg)if not(temp & 0x03):self.__SetRegBitMask(self.TxControlReg, 0x03)def MFRC522_AntennaOff(self):# reg: 0x14# buf: 0bxxxxxx00self.__ClearRegBitMask(self.TxControlReg, 0x03)# function  : read block# parameter : blockAddr(0~63)# return    : retStatus#             backData[16]def MFRC522_ReadBolock(self, blockAddr):retStatus = self.MI_OK# cmd: 0x0c# buf: 0x30 blockAddr crc[2]buf = []buf.append(self.PICC_READ)buf.append(blockAddr)crc = self.__CalulateCRC(buf)buf.append(crc[0])buf.append(crc[1])(status, backData, backLen) = self.__ToCard(self.PCD_TRANSCEIVE, buf)if (status != self.MI_OK) or (backLen != 8*self.MAX_LEN):retStatus = self.MI_ERRreturn (retStatus, backData)# function  : write block# parameter : blockAddr(0~63)#             writeData[16]# return    : retStatusdef MFRC522_WriteBlock(self, blockAddr, writeData):retStatus = self.MI_OK# cmd: 0x0c# buf: 0xA0 blockAddr crc[2]buf = []buf.append(self.PICC_WRITE)buf.append(blockAddr)crc = self.__CalulateCRC(buf)buf.append(crc[0])buf.append(crc[1])(status, backData, backLen) = self.__ToCard(self.PCD_TRANSCEIVE, buf)if (status != self.MI_OK) or ((backData[0]&0x0F) != 0x0A) or (backLen != 4):retStatus = self.MI_ERRif status == self.MI_OK:# cmd: 0x0c# buf: writeData[16] crc[2]buf2 = []for i in range(16):buf2.append(writeData[i])crc = self.__CalulateCRC(buf2)buf2.append(crc[0])buf2.append(crc[1])(status, backData, backLen) = self.__ToCard(self.PCD_TRANSCEIVE, buf2)if (status != self.MI_OK) or ((backData[0]&0x0F) != 0x0A) or (backLen != 4):retStatus = self.MI_ERRreturn retStatus# function  : detect card# parameter : reqMode: detect mode#               0x52 = detect all cards #               0x26 = detect not sleep cards# return    : retStatus#             backData: card type(2 bytes)#               0x4400 = Mifare_UltraLight#               0x0400 = Mifare_One(S50)#               0x0200 = Mifare_One(S70)#               0x0800 = Mifare_Pro(X)#               0x4403 = Mifare_DESFiredef MFRC522_Request(self, reqMode): retStatus = self.MI_OKself.__WriteReg(self.BitFramingReg, 0x07)# cmd: 0x0c# buf: 0x26/0x52buf = []buf.append(reqMode)(status, backData, backLen) = self.__ToCard(self.PCD_TRANSCEIVE, buf)if (status != self.MI_OK) or (backLen != 0x10):retStatus = self.MI_ERRreturn (retStatus, backData)# function  : anticoll# parameter :# return    : retStatus#             backData(Uid, 4 bytes)def MFRC522_Anticoll(self):retStatus = self.MI_OKserNumCheck = 0self.__WriteReg(self.BitFramingReg, 0x00)# cmd: 0x0c# buf: 0x93 0x20buf = []buf.append(self.PICC_ANTICOLL)buf.append(0x20)(status, backData, backLen) = self.__ToCard(self.PCD_TRANSCEIVE, buf)if (status==self.MI_OK) and (len(backData)==5):for i in range(4):serNumCheck ^= backData[i]if serNumCheck != backData[4]:retStatus = self.MI_ERRelse:retStatus = self.MI_ERRreturn (retStatus, backData)# function  : select card# parameter : Uid# return    : retStatusdef MFRC522_Select(self, Uid):retStatus = self.MI_OKserNumCheck = 0# cmd: 0x0c# buf: 0x93 0x70 Uid[4] check crc[2]buf = []buf.append(self.PICC_SElECTTAG)buf.append(0x70)for i in range(4):buf.append(Uid[i])serNumCheck ^= Uid[i]buf.append(serNumCheck)crc = self.__CalulateCRC(buf)buf.append(crc[0])buf.append(crc[1])(status, backData, backLen) = self.__ToCard(self.PCD_TRANSCEIVE, buf)if (status != self.MI_OK) or (backLen != 0x18):retStatus = self.MI_ERRreturn retStatus# function  : auth sectorkey# parameter : authMode(PICC_AUTHENT1A/PICC_AUTHENT1B)#             blockAddr#             sectorkey(6 bytes)#             Uid(4 bytes)# return    : retStatusdef MFRC522_Auth(self, authMode, blockAddr, sectorkey, Uid):retStatus = self.MI_OK# cmd: 0x0e# buf: authMode blockAddr sectorkey[6] Uid[4]buf = []buf.append(authMode)buf.append(blockAddr)for i in range(6):buf.append(sectorkey[i])for i in range(4):buf.append(Uid[i])(status, backData, backLen) = self.__ToCard(self.PCD_AUTHENT, buf)if (status != self.MI_OK) or not(self.__ReadReg(self.Status2Reg)&0x08):retStatus = self.MI_ERRreturn retStatus# function  : idle# parameter :# return    : retStatusdef MFRC522_Halt(self):retStatus = self.MI_OK# cmd: 0x0c# buf: 0x50 0x00 crc[2]buf = []buf.append(self.PICC_HALT)buf.append(0)crc = self.__CalulateCRC(buf)buf.append(crc[0])buf.append(crc[1])(status, backData, backLen) = self.__ToCard(self.PCD_TRANSCEIVE, buf)retStatus = statusreturn retStatusdef MFRC522_WriteCmd40(self):retStatus = self.MI_OKself.__WriteReg(self.BitFramingReg, 0x07)# cmd: 0x0c# buf: 0x40buf = []buf.append(0x40)(status, backData, backLen) = self.__ToCard(self.PCD_TRANSCEIVE, buf)if (status != self.MI_OK) or (backData[0] != 0x0a):retStatus = statusreturn retStatusdef MFRC522_WriteCmd43(self):retStatus = self.MI_OKself.__WriteReg(self.BitFramingReg, 0x00)# cmd: 0x0c# buf: 0x43buf = []buf.append(0x43)(status, backData, backLen) = self.__ToCard(self.PCD_TRANSCEIVE, buf)if (status != self.MI_OK) or (backData[0] != 0x0a):retStatus = statusreturn retStatusdef MFRC522_StopCrypto1(self):self.__ClearRegBitMask(self.Status2Reg, 0x08)def MFRC522_CloseSPI(self):spi.closeSPI(self.dev0)

c. 复制IC卡数据实现 main.py

通过request, anticoll, select, auth, halt 等命令,首先从源卡中读取block数据,然后将数据写入到新卡对应的block中

注意:block0的数据写入与其它block的写入不同,还需要写入两个特殊的命令0x40和0x43, 参考:https://blog.csdn.net/baidu_34570497/article/details/79689778

#!/usr/bin/env python
# -*- coding: utf8 -*-import MFRC522rc = MFRC522.MFRC522()
# save src card data, then write the saved date to des card
dataBlock0 = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15]
sectorkey = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff]def read_block0():(status, tagType) = rc.MFRC522_Request(rc.PICC_REQIDL)if status != rc.MI_OK:print("MFRC522_Request error")returnprint("MFRC522_Request success, tagType: %#x %#x" %(tagType[0], tagType[1]))(status, Uid) = rc.MFRC522_Anticoll()if status != rc.MI_OK:print("MFRC522_Anticoll error")returnprint("MFRC522_Anticoll success, Uid: %#x %#x %#x %#x" %(Uid[0], Uid[1], Uid[2], Uid[3]))status = rc.MFRC522_Select(Uid)if status != rc.MI_OK:print("MFRC522_Select error")returnprint("MFRC522_Select success")status = rc.MFRC522_Auth(rc.PICC_AUTHENT1A, 1, sectorkey, Uid)if status != rc.MI_OK:print("MFRC522_Auth error")returnprint("MFRC522_Auth success")(status, dataBlock0) = rc.MFRC522_ReadBolock(0)if status != rc.MI_OK:print("MFRC522_ReadBolock error")returnprint("MFRC522_ReadBolock success, block0: %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x" %(dataBlock0[0], dataBlock0[1], dataBlock0[2], dataBlock0[3], dataBlock0[4], dataBlock0[5], dataBlock0[6], dataBlock0[7], dataBlock0[8], dataBlock0[9], dataBlock0[10], dataBlock0[11], dataBlock0[12], dataBlock0[13], dataBlock0[14], dataBlock0[15]))rc.MFRC522_StopCrypto1()def write_block0():(status, tagType) = rc.MFRC522_Request(rc.PICC_REQIDL)if status != rc.MI_OK:print("MFRC522_Request error")returnprint("MFRC522_Request success, tagType: %#x %#x" %(tagType[0], tagType[1]))(status, Uid) = rc.MFRC522_Anticoll()if status != rc.MI_OK:print("MFRC522_Anticoll error")returnprint("MFRC522_Anticoll success, Uid: %#x %#x %#x %#x" %(Uid[0], Uid[1], Uid[2], Uid[3]))status = rc.MFRC522_Select(Uid)if status != rc.MI_OK:print("MFRC522_Select error")returnprint("MFRC522_Select success")status = rc.MFRC522_Halt()print("MFRC522_Halt %d" %status)status = rc.MFRC522_WriteCmd40()if (status != rc.MI_OK):print("MFRC522_ToCard 0x40 error, status:%d" %status)returnprint("MFRC522_ToCard 0x40 success")status = rc.MFRC522_WriteCmd43()if (status != rc.MI_OK):print("MFRC522_ToCard 0x43 error, status:%d" %status)returnprint("MFRC522_ToCard 0x43 success")status = rc.MFRC522_WriteBlock(0, dataBlock0)if status != rc.MI_OK:print("MFRC522_WriteBlock error")returnprint("MFRC522_WriteBlock success")rc.MFRC522_StopCrypto1()  def closeSPI():rc.MFRC522_CloseSPI()if __name__ == '__main__':while True:action = input("Enter action r/w: ")if action == 'r':read_block0()elif action == 'w':write_block0()elif action == 'q':closeSPI()breakprint("exit procedure")

d. 运行结果

  1. 将原卡放到模块的感应区域,然后输入“r”,程序读取原卡block0数据
  2. 将新卡放到模块的感应区域,然后输入“w”,程序将读出的block0数据写入到新卡的block0
  3. 测试新卡门禁是否可用

注意:

调试过程中很可能会出现0x40和0x43写入失败的问题,定位发现是 MFRC522_Halt() 命令执行失败,排除掉其它因素后极有可能是使用的新卡不支持block0写入的,可以换个卡再试试

通常普通门禁只是读取IC卡的Uid进行校验,即block0的前4个字节,如果block0成功写入还是不能打开门禁,可能就是门禁系统还使用了其它数据进行校验,这时可以将原卡的所有block数据都读出来然后写入新卡

树莓派复制MFRC522 门禁IC卡(支持block0写入,亲测可用)相关推荐

  1. Proxmark3教程1:小白如何用PM3破解复制M1全加密门禁IC卡

    IC卡已经在我们的生活中无处不在了,门禁,电梯,吃饭,洗车,可以说与我们的生活息息相关了. 但是如果有一天,你的门禁卡丢了,怎么配呢?跟配钥匙一样的,必须现有原钥匙才可以. 那我们今天就看看,如何用P ...

  2. 【毕业设计】 树莓派寝室宿舍门禁刷卡系统 - 物联网 单片机 嵌入式

    文章目录 0 前言 1 前言 2 主要器件 3 实物效果 4 树莓派读取 RC522 RFID 标签 5 mg90s 控制原理 6 最后 0 前言

  3. 华为手机怎样复制加密门禁卡_手机NFC复制小区用的门禁卡

    我们说一说目前的门禁卡到底有哪些类型呢?门禁卡一般分为:ID卡和IC卡.而EM卡.M1卡.CPU卡等等,都是这两种卡的细分.它们能够开门,都是基于RFID感应的原理来实现开门的.  我们看一张图,在这 ...

  4. 小区门禁卡可以复制到手机上吗_如何用手机复制小区门禁卡,一招就可以解决!...

    首先要确认你手机有没有NFC功能 NFC,即近场通讯,是一种非接触式通讯技术,相比蓝牙等方式,连接速度快,不需要电源.NFC有三种工作模式,有卡模式.点对点模式.读卡器模式.NFC在门禁.公交.手机支 ...

  5. 华为复制加密门禁卡_MIUI12轻体验:关于模拟门禁卡,你想知道的都在这里

    当MIUI12正式发布的时候,点燃了亓纪想要体验新系统的决心.刚好手边有一台小米9,于是便申请了内测权限,体验到了全新的MIUI12.今天想和大家分享的是升级后感知最强的功能:模拟加密卡. 原因 作为 ...

  6. 为什么复制的门禁卡只能用一次_手机NFC为什么可以复制小区用的门禁卡?

    展开全部 NFC,即近场通讯,是一种非接触式通讯技术,相比62616964757a686964616fe4b893e5b19e31333431363534蓝牙等方式,连接速度快,不需要电源.NFC有三 ...

  7. showmodaldialog 为什么不能复制_防复制的门禁读头可以防止UID和FUID读卡器

    目前,有很多智慧小区门禁采用防复制门禁读头可以防止UID和FUID门禁读卡器-防复制的门禁读头哪家好?防复制的门禁读头可以防止UID和FUID读卡器 1.防复制的门禁读头可以防止那些复制的卡? 回答: ...

  8. python人脸识别门禁系统毕设_树莓派人脸识别门禁系统代码以及代码分析——opencv拍照调用FACE++处理...

    树莓派人脸识别门禁系统的总体设计 硬件包括:树莓派3B.电源模块.转5V降压模块.触摸感应传感器模块.声光报警模块和驱动模块. 由此设计出的人脸识别门禁系统总体结构框图如下: 总体结构框图 程序运行时 ...

  9. 人脸识别门禁_小区人脸识别门禁或取代传统门禁刷卡方式

    可以说,社区是一个人口聚集的小型社会.首先社区的人流量很大,进出是十分频繁.其次,社区的大门以及各处进出口是业主与访客.外来人员等进进出出最关键的通道.因此,每个社区都会有一套成型的门禁系统,常见的是 ...

最新文章

  1. Jrebel 热部署插件的使用和破解
  2. easyui datagrid 表格动态隐藏部分列的展示
  3. 百度程序员哀叹:回老家发现村里很多人开保时捷,道奇等豪车,比程序员有钱多了!...
  4. 京东方拟收购法国零售物联网领域公司50.1%以上股份
  5. 数据挖掘之人工神经网络BP算法
  6. python内置方法怎么使用_python中的常用内置方法
  7. Netty工作笔记0013---Channel应用案例4Copy图片
  8. android SDK安装以及环境变量配置
  9. 析构函数无法命中断点. 当前无法命中断点: 没有与此行关联的调试程序的目标代码类型的可执行代码. 可能的原因包括;条件编译, 编译器优化或者......
  10. Matlab箱线图Boxplot横坐标x轴设置
  11. Python策略模式实现源码分享
  12. 这项技术曾应用于无人驾驶,荣耀10将其移植到手机上这样操作!
  13. 剑指Offer题目汇总(持续更新中...)
  14. 2022-2027年中国沙漠旅游行业市场全景评估及发展战略规划报告
  15. WinCap数据包显示
  16. 基于C++的钻石金字塔问题算法设计
  17. [论文阅读] EIE: Efficient Inference Engine on Compressed Neural Network
  18. 微信支付签名验证失败的问题
  19. 神经性脚臭案例整理(二)
  20. 解决[WinError 87] pip自动安装不成功问题

热门文章

  1. 沁恒USB转串口主要替换FT232/230系列
  2. Android 超级用户源码(superuser.apk)免费
  3. 图片旋转动画(网页制作)
  4. 使用scrapy抓取传智播客c/c++讲师信息
  5. 【论文阅读】多粒度特征融合的维度语音情感识别方法
  6. 快速配置Veritas Flex 5150一体机IPMI
  7. 新版仿我爱广告任务网系统源码+Thinkphp内核
  8. 快播宣告破产!彻底倒闭了。。。
  9. 微信小程序——关于图片
  10. 事物运动的状态和方式是谁提出的_关于事物运动的状态和规律的表征