RC522(RFID)读写驱动
文章目錄
- 1、RC522驅(qū)動原理
- 2、手機APP查看卡信息
- 3、驅(qū)動移植
- 4、讀寫卡
- 5、源碼
1、RC522驅(qū)動原理
我們常見的RC522大概如下所示,PCB部分是主機,然后白色的和綠色的都是IC卡,IC卡可以存儲信息,通過靠近PCB主機部分就可以被感應(yīng)到從而觸發(fā)主機做出相應(yīng)的動作,比如讀取IC卡信息,寫入數(shù)據(jù)等操作。
主機模塊板載的芯片為MF_RC522,是應(yīng)用于 13.56MHz 非接觸式通信中高集成度讀寫卡系列芯片中的一員。是 NXP 公司針對“三表”應(yīng)用推出的一款低 電壓、低成本、體積小的非接觸式讀寫卡芯片,是智能儀表和便攜 式手持設(shè)備研發(fā)的較好選擇,芯片引腳圖如下所示:
關(guān)于他的讀寫,官方也提供了API函數(shù),可以查詢API手冊,這里不做具體介紹,網(wǎng)上找到的資料我看大部分都是已經(jīng)移植好的,而且基本也是同一套的模版。
下面我來介紹下IC卡的原理
首先是工作原理:卡片的電氣部分只由一個天線和ASIC組成。天線:卡片的天線是只有幾組繞線的線圈,很適于封裝到I卡片中。ASIC:卡片的ASIC由一個高速(106KB波特率)的RF接口,一個控制單元和一個8K位EEPROM組成。
那么這個卡他不帶電,他是怎么工作的呢?工作原理如下
讀寫器向M1卡發(fā)一組固定頻率的電磁波,卡片內(nèi)有一個LC串聯(lián)諧振電路,其頻率與讀寫器發(fā)射的頻率相同,在電磁波的激勵下,LC諧振電路產(chǎn)生共振,從而使電容內(nèi)有了電荷,在這個電容的另一端,接有一個單向?qū)ǖ碾娮颖?#xff0c;將電容內(nèi)的電荷送到另一個電容內(nèi)儲存,當所積累的電荷達到2V時,此電容可做為電源為其它電路提供工作電壓,將卡內(nèi)數(shù)據(jù)發(fā)射出去或接取讀寫器的數(shù)據(jù)。
下面再來說下卡片的內(nèi)部儲存信息
卡片容量為8K位EEPROM,分為16個扇區(qū),每個扇區(qū)為4塊,每塊16個字節(jié),以塊為存取單位每個扇區(qū)有獨立的一組密碼及訪問控制每張卡有唯一序列號,為32位,我們也將16個扇區(qū)的64個塊按絕對地址編號為063,存貯結(jié)構(gòu)如下圖所示:
這里注意:第0扇區(qū)的塊0(即絕對地址0塊),它用于存放廠商代碼,已經(jīng)固化,不可更改。每個扇區(qū)的塊0、塊1、塊2為數(shù)據(jù)塊,可用于存貯數(shù)據(jù)。
根據(jù)官方手冊的推薦,一般我們對卡的操作流程如下,這也將在程序中體現(xiàn)出來:
2、手機APP查看卡信息
這里我參考的這篇博主的文章,講的還是蠻詳細的:https://blog.csdn.net/Ikaros_521/article/details/115958888
使用的APP如下所示:
可以按照軟件操作讀取一個卡的信息如下所示,可以看到他是16個扇區(qū),每個扇區(qū)有四個塊,所以就一共是64塊,儲存的信息數(shù)量是1024byte,計算方式為16416=1024。
下面的幾頁信息如下所示:
因此我們通過這些方法就可以查看卡的數(shù)據(jù)了,下面的部分我們也將用這個APP來查看我們對卡的操作,包括卡片ID的選擇,然后寫入的信息等等!
3、驅(qū)動移植
先在這里配置我們的SPI的外設(shè),這里除了速率,其他基本上默認即可,這里有的博主說不要設(shè)置的太快,這里我實測應(yīng)該是沒有影響的,感覺還是可以正常使用的!
下面配置下其他的一些引腳,主要是片選信號還有復(fù)位引腳
之后就可以生成代碼了,這里我們代碼部分以移植為主,主要就是這個讀寫數(shù)據(jù)的函數(shù),這里我卡了很久,一直都沒有實現(xiàn)成功,如果有看到這篇文章并且實現(xiàn)了的兄弟可以跟我交流下。
這里最終采用的讀寫函數(shù)如下所示,如果是僅僅讀寫一個位的話,就可以吧senddatanum去掉即可,當然這樣寫我們主要把senddatanum這個參數(shù)設(shè)置為1就是讀寫一個了,這樣兼容性更好!
之后就可以編寫讀寫函數(shù)了
除此之外的其他部分代碼都還是兼容的,只要直接復(fù)制就行了,我看目前網(wǎng)上大多采用的也是這一套的代碼,比較方便,這里可以關(guān)注下復(fù)位的這個流程,這里我將杜威的過程寫成了函數(shù),用起來方便點。
4、讀寫卡
這里我們首先讀取卡的ID試試
將程序下載到開發(fā)板,可以看到成功讀取
下面我們來進行寫卡的操作,大概流程是選中卡片,然后在指定區(qū)塊寫入數(shù)據(jù),然后在指定區(qū)塊讀取數(shù)據(jù),最后當我們執(zhí)行完所有操作就可以退出選中,讓卡片進入休眠了!
將程序下載到開發(fā)板,可以看到打印的程執(zhí)行結(jié)果是符合我們預(yù)期的,效果也是正常的!
再次用手機讀卡,可以看到我們寫入的數(shù)據(jù)如下所示:
5、源碼
RC522.c
/** RC522.c** Created on: Mar 23, 2022* Author: LX*/#include "RC522.h" #include "stdio.h"#define RC522_RST_HIGH HAL_GPIO_WritePin(RC522_RST_GPIO_Port, RC522_RST_Pin, GPIO_PIN_SET); #define RC522_RST_LOW HAL_GPIO_WritePin(RC522_RST_GPIO_Port, RC522_RST_Pin, GPIO_PIN_RESET);#define RC522_ENABLE HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); #define RC522_DISABLE HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);extern SPI_HandleTypeDef hspi1;#define fac_us 72 //時鐘頻率,單位MHZ/*微秒級延時函數(shù)*/ void delay_us(uint32_t nus) {uint32_t ticks;uint32_t told,tnow,tcnt=0;uint32_t reload=SysTick->LOAD; //LOAD的值ticks=nus*fac_us; //需要的節(jié)拍數(shù)told=SysTick->VAL; //剛進入時的計數(shù)器值while(1){tnow=SysTick->VAL;if(tnow!=told){if(tnow<told)tcnt+=told-tnow; //這里注意一下SYSTICK是一個遞減的計數(shù)器就可以了.else tcnt+=reload-tnow+told;told=tnow;if(tcnt>=ticks)break; //時間超過/等于要延遲的時間,則退出.}} } int32_t SPI_WriteNBytes(SPI_TypeDef* SPIx, uint8_t *p_TxData,uint32_t sendDataNum) {uint8_t retry=0;while(sendDataNum--){while((SPIx->SR&SPI_FLAG_TXE)==0)//等待發(fā)送區(qū)空{retry++;if(retry>20000)return -1;}SPIx->DR=*p_TxData++;//發(fā)送一個byteretry=0;while((SPIx->SR&SPI_FLAG_RXNE)==0)//等待接收完一個byte{SPIx->SR = SPIx->SR;retry++;if(retry>20000)return -1;}SPIx->DR;}return 0; } int32_t SPI_ReadNBytes(SPI_TypeDef* SPIx, uint8_t *p_RxData,uint32_t readDataNum) {uint8_t retry=0;while(readDataNum--){SPIx->DR = 0xFF;while(!(SPIx->SR&SPI_FLAG_TXE)){retry++;if(retry>20000)return -1;}retry = 0;while(!(SPIx->SR&SPI_FLAG_RXNE)){retry++;if(retry>20000)return -1;}*p_RxData++ = SPIx->DR;}return 0; } void RC522_Init(void) {RC522_ENABLE;HAL_SPI_Transmit(&hspi1, (uint8_t *)0xaa, sizeof((uint8_t *)0xaa), 0xFF);//啟動傳輸RC522_DISABLE;HAL_Delay(50);PcdReset();//復(fù)位RC522讀卡器HAL_Delay(10);PcdReset();//復(fù)位RC522讀卡器HAL_Delay(10);PcdAntennaOff();//關(guān)閉天線發(fā)射HAL_Delay(10);PcdAntennaOn();//開啟天線發(fā)射printf("RFID-MFRC522 初始化完成\r\nFindCard Starting ...\r\n"); //測試引腳初始化完成 }//功 能:尋卡 //參數(shù)說明: req_code[IN]:尋卡方式 // 0x52 = 尋感應(yīng)區(qū)內(nèi)所有符合14443A標準的卡 // 0x26 = 尋未進入休眠狀態(tài)的卡 // pTagType[OUT]:卡片類型代碼 // 0x4400 = Mifare_UltraLight // 0x0400 = Mifare_One(S50) // 0x0200 = Mifare_One(S70) // 0x0800 = Mifare_Pro(X) // 0x4403 = Mifare_DESFire //返 回: 成功返回MI_OK char PcdRequest(unsigned char req_code, unsigned char *pTagType) {char status;unsigned int unLen;unsigned char ucComMF522Buf[MAXRLEN];ClearBitMask(Status2Reg, 0x08); //清RC522寄存位WriteRawRC(BitFramingReg, 0x07); //寫RC623寄存器SetBitMask(TxControlReg, 0x03); //置RC522寄存位ucComMF522Buf[0] = req_code;status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 1, ucComMF522Buf, &unLen);if ((status == MI_OK) && (unLen == 0x10)){*pTagType = ucComMF522Buf[0];*(pTagType + 1) = ucComMF522Buf[1];}else{status = MI_ERR;}return status; } //功 能:防沖撞 //參數(shù)說明: pSnr[OUT]:卡片序列號,4字節(jié) //返 回: 成功返回MI_OK char PcdAnticoll(unsigned char *pSnr) {char status;unsigned char i, snr_check = 0;unsigned int unLen;unsigned char ucComMF522Buf[MAXRLEN];ClearBitMask(Status2Reg, 0x08);WriteRawRC(BitFramingReg, 0x00);ClearBitMask(CollReg, 0x80);ucComMF522Buf[0] = PICC_ANTICOLL1;ucComMF522Buf[1] = 0x20;status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 2, ucComMF522Buf, &unLen);if (status == MI_OK){for (i = 0; i < 4; i++){*(pSnr + i) = ucComMF522Buf[i];snr_check ^= ucComMF522Buf[i];}if (snr_check != ucComMF522Buf[i]){status = MI_ERR;}}SetBitMask(CollReg, 0x80);return status; } //功 能:選定卡片 //參數(shù)說明: pSnr[IN]:卡片序列號,4字節(jié) //返 回: 成功返回MI_OK char PcdSelect(unsigned char *pSnr) {char status;unsigned char i;unsigned int unLen;unsigned char ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = PICC_ANTICOLL1;ucComMF522Buf[1] = 0x70;ucComMF522Buf[6] = 0;for (i = 0; i < 4; i++){ucComMF522Buf[i + 2] = *(pSnr + i);ucComMF522Buf[6] ^= *(pSnr + i);}CalulateCRC(ucComMF522Buf, 7, &ucComMF522Buf[7]);ClearBitMask(Status2Reg, 0x08);status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 9, ucComMF522Buf, &unLen);if ((status == MI_OK) && (unLen == 0x18)){status = MI_OK;}else{status = MI_ERR;}return status; } //功 能:驗證卡片密碼 //參數(shù)說明: auth_mode[IN]: 密碼驗證模式 // 0x60 = 驗證A密鑰 // 0x61 = 驗證B密鑰 // addr[IN]:塊地址 // pKey[IN]:密碼 // pSnr[IN]:卡片序列號,4字節(jié) //返 回: 成功返回MI_OK char PcdAuthState(unsigned char auth_mode, unsigned char addr, unsigned char *pKey, unsigned char *pSnr) {char status;unsigned int unLen;unsigned char i, ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = auth_mode;ucComMF522Buf[1] = addr;for (i = 0; i < 6; i++){ucComMF522Buf[i + 2] = *(pKey + i);}for (i = 0; i < 6; i++){ucComMF522Buf[i + 8] = *(pSnr + i);}status = PcdComMF522(PCD_AUTHENT, ucComMF522Buf, 12, ucComMF522Buf, &unLen);if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08))){status = MI_ERR;}return status; } //功 能:讀取M1卡一塊數(shù)據(jù) //參數(shù)說明: addr[IN]:塊地址 // p [OUT]:讀出的數(shù)據(jù),16字節(jié) //返 回: 成功返回MI_OK char PcdRead(unsigned char addr, unsigned char *pData) {char status;unsigned int unLen;unsigned char i, ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = PICC_READ;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);if ((status == MI_OK) && (unLen == 0x90)){for (i = 0; i < 16; i++){*(pData + i) = ucComMF522Buf[i];}}else{status = MI_ERR;}return status; } //功 能:寫數(shù)據(jù)到M1卡一塊 //參數(shù)說明: addr[IN]:塊地址 // p [IN]:寫入的數(shù)據(jù),16字節(jié) //返 回: 成功返回MI_OK char PcdWrite(unsigned char addr, unsigned char *pData) {char status;unsigned int unLen;unsigned char i, ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = PICC_WRITE;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)){status = MI_ERR;}if (status == MI_OK){for (i = 0; i < 16; i++){ucComMF522Buf[i] = *(pData + i);}CalulateCRC(ucComMF522Buf, 16, &ucComMF522Buf[16]);status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 18, ucComMF522Buf, &unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)){status = MI_ERR;}}return status; } //功 能:扣款和充值 //參數(shù)說明: dd_mode[IN]:命令字 // 0xC0 = 扣款 // 0xC1 = 充值 // addr[IN]:錢包地址 // pValue[IN]:4字節(jié)增(減)值,低位在前 //返 回: 成功返回MI_OK char PcdValue(unsigned char dd_mode, unsigned char addr, unsigned char *pValue) {char status;unsigned int unLen;unsigned char i, ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = dd_mode;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)){status = MI_ERR;}if (status == MI_OK){for (i = 0; i < 16; i++){ucComMF522Buf[i] = *(pValue + i);}CalulateCRC(ucComMF522Buf, 4, &ucComMF522Buf[4]);unLen = 0;status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 6, ucComMF522Buf, &unLen);if (status != MI_ERR){status = MI_OK;}}if (status == MI_OK){ucComMF522Buf[0] = PICC_TRANSFER;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)){status = MI_ERR;}}return status; } //功 能:備份錢包 //參數(shù)說明: sourceaddr[IN]:源地址 // goaladdr[IN]:目標地址 //返 回: 成功返回MI_OK char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr) {char status;unsigned int unLen;unsigned char ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = PICC_RESTORE;ucComMF522Buf[1] = sourceaddr;CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)){status = MI_ERR;}if (status == MI_OK){ucComMF522Buf[0] = 0;ucComMF522Buf[1] = 0;ucComMF522Buf[2] = 0;ucComMF522Buf[3] = 0;CalulateCRC(ucComMF522Buf, 4, &ucComMF522Buf[4]);status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 6, ucComMF522Buf, &unLen);if (status != MI_ERR){status = MI_OK;}}if (status != MI_OK){return MI_ERR;}ucComMF522Buf[0] = PICC_TRANSFER;ucComMF522Buf[1] = goaladdr;CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)){status = MI_ERR;}return status; } //功 能:命令卡片進入休眠狀態(tài) //返 回: 成功返回MI_OK char PcdHalt(void) {// char status;unsigned int unLen;unsigned char ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = PICC_HALT;ucComMF522Buf[1] = 0;CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);return MI_OK; } //用MF522計算CRC16函數(shù) void CalulateCRC(unsigned char *pIndata, unsigned char len, unsigned char *pOutData) {unsigned char i, n;ClearBitMask(DivIrqReg, 0x04);WriteRawRC(CommandReg, PCD_IDLE);SetBitMask(FIFOLevelReg, 0x80);for (i = 0; i < len; i++){WriteRawRC(FIFODataReg, *(pIndata + i));}WriteRawRC(CommandReg, PCD_CALCCRC);i = 0xFF;do{n = ReadRawRC(DivIrqReg);i--;} while ((i != 0) && !(n & 0x04));pOutData[0] = ReadRawRC(CRCResultRegL);pOutData[1] = ReadRawRC(CRCResultRegM); } //功 能:復(fù)位RC522 //返 回: 成功返回MI_OK char PcdReset(void) {RC522_RST_HIGH;delay_us(10);RC522_RST_LOW;HAL_Delay(60);RC522_RST_HIGH;delay_us(500);WriteRawRC(CommandReg, PCD_RESETPHASE);HAL_Delay(2);WriteRawRC(ModeReg, 0x3D);WriteRawRC(TReloadRegL, 30);WriteRawRC(TReloadRegH, 0);WriteRawRC(TModeReg, 0x8D);WriteRawRC(TPrescalerReg, 0x3E);WriteRawRC(TxAutoReg, 0x40);ClearBitMask(TestPinEnReg, 0x80);WriteRawRC(TxAutoReg, 0x40);return MI_OK; } //功 能:讀RC632寄存器 //參數(shù)說明:Address[IN]:寄存器地址 //返 回:讀出的值 unsigned char ReadRawRC(unsigned char Address) {unsigned char ucAddr;unsigned char ucResult = 0;ucAddr = ((Address << 1) & 0x7E) | 0x80;HAL_Delay(1);RC522_ENABLE;SPI_WriteNBytes(SPI1, &ucAddr, 1); //向總線寫多個數(shù)據(jù)SPI_ReadNBytes(SPI1, &ucResult, 1); //向總線讀多個數(shù)據(jù) // HAL_SPI_Transmit(&hspi1,&ucAddr,1,0xff); // HAL_SPI_Receive(&hspi1,&ucResult,1,0xff); // while(HAL_SPI_Transmit(&hspi1,&ucAddr,1,0xff) == HAL_OK); // while(HAL_SPI_Receive(&hspi1,&ucResult,1,0xff) == HAL_OK);RC522_DISABLE;return ucResult; } //功 能:寫RC632寄存器 //參數(shù)說明:Address[IN]:寄存器地址 // value[IN]:寫入的值 void WriteRawRC(unsigned char Address, unsigned char value) {unsigned char ucAddr;uint8_t write_buffer[2] = {0};ucAddr = ((Address << 1) & 0x7E);write_buffer[0] = ucAddr;write_buffer[1] = value;HAL_Delay(1);RC522_ENABLE;SPI_WriteNBytes(SPI1, write_buffer, 2); // HAL_SPI_Transmit(&hspi1,write_buffer,2,0xff); // while(HAL_SPI_Transmit(&hspi1,write_buffer,2,0xff) == HAL_OK);RC522_DISABLE; } //功 能:置RC522寄存器位 //參數(shù)說明:reg[IN]:寄存器地址 // mask[IN]:置位值 void SetBitMask(unsigned char reg, unsigned char mask) {char tmp = 0x0;tmp = ReadRawRC(reg); //讀RC632寄存器WriteRawRC(reg, tmp | mask); // set bit mask } //功 能:清RC522寄存器位 //參數(shù)說明:reg[IN]:寄存器地址 // mask[IN]:清位值 void ClearBitMask(unsigned char reg, unsigned char mask) {char tmp = 0x0;tmp = ReadRawRC(reg);WriteRawRC(reg, tmp & ~mask); // clear bit mask } //功 能:通過RC522和ISO14443卡通訊 //參數(shù)說明:Command[IN]:RC522命令字 // pIn [IN]:通過RC522發(fā)送到卡片的數(shù)據(jù) // InLenByte[IN]:發(fā)送數(shù)據(jù)的字節(jié)長度 // pOut [OUT]:接收到的卡片返回數(shù)據(jù) // *pOutLenBit[OUT]:返回數(shù)據(jù)的位長度 char PcdComMF522(unsigned char Command,unsigned char *pInData,unsigned char InLenByte,unsigned char *pOutData,unsigned int *pOutLenBit) {char status = MI_ERR;unsigned char irqEn = 0x00;unsigned char waitFor = 0x00;unsigned char lastBits;unsigned char n;unsigned int i;switch (Command){case PCD_AUTHENT:irqEn = 0x12;waitFor = 0x10;break;case PCD_TRANSCEIVE:irqEn = 0x77;waitFor = 0x30;break;default:break;}WriteRawRC(ComIEnReg, irqEn | 0x80);ClearBitMask(ComIrqReg, 0x80);WriteRawRC(CommandReg, PCD_IDLE);SetBitMask(FIFOLevelReg, 0x80);for (i = 0; i < InLenByte; i++){WriteRawRC(FIFODataReg, pInData[i]);}WriteRawRC(CommandReg, Command);if (Command == PCD_TRANSCEIVE){SetBitMask(BitFramingReg, 0x80);}i = 800;do{n = ReadRawRC(ComIrqReg);i--;} while ((i != 0) && !(n & 0x01) && !(n & waitFor));ClearBitMask(BitFramingReg, 0x80);if (i != 0){if (!(ReadRawRC(ErrorReg) & 0x1B)){status = MI_OK;if (n & irqEn & 0x01){status = MI_NOTAGERR;}if (Command == PCD_TRANSCEIVE){n = ReadRawRC(FIFOLevelReg);lastBits = ReadRawRC(ControlReg) & 0x07;if (lastBits){*pOutLenBit = (n - 1) * 8 + lastBits;}else{*pOutLenBit = n * 8;}if (n == 0){n = 1;}if (n > MAXRLEN){n = MAXRLEN;}for (i = 0; i < n; i++){pOutData[i] = ReadRawRC(FIFODataReg);}}}else{status = MI_ERR;}}SetBitMask(ControlReg, 0x80); // stop timer nowWriteRawRC(CommandReg, PCD_IDLE);return status; } //開啟天線 //每次啟動或關(guān)閉天險發(fā)射之間應(yīng)至少有1ms的間隔 void PcdAntennaOn(void) {unsigned char i;i = ReadRawRC(TxControlReg);if (!(i & 0x03)){SetBitMask(TxControlReg, 0x03);} } //關(guān)閉天線 void PcdAntennaOff(void) {ClearBitMask(TxControlReg, 0x03); }void RC522_Config(unsigned char Card_Type) {ClearBitMask(Status2Reg, 0x08);WriteRawRC(ModeReg, 0x3D);WriteRawRC(RxSelReg, 0x86);WriteRawRC(RFCfgReg, 0x7F);WriteRawRC(TReloadRegL, 30);WriteRawRC(TReloadRegH, 0);WriteRawRC(TModeReg, 0x8D);WriteRawRC(TPrescalerReg, 0x3E);HAL_Delay(5);PcdAntennaOn(); }RC522.h
/** RC522.h** Created on: Mar 23, 2022* Author: LX*/#ifndef RC522_H_ #define RC522_H_#include "main.h"#define PCD_IDLE 0x00 //取消當前命令 #define PCD_AUTHENT 0x0E //驗證密鑰 #define PCD_RECEIVE 0x08 //接收數(shù)據(jù) #define PCD_TRANSMIT 0x04 //發(fā)送數(shù)據(jù) #define PCD_TRANSCEIVE 0x0C //發(fā)送并接收數(shù)據(jù) #define PCD_RESETPHASE 0x0F //復(fù)位 #define PCD_CALCCRC 0x03 //CRC計算 #define PICC_REQIDL 0x26 //尋天線區(qū)內(nèi)未進入休眠狀態(tài) #define PICC_REQALL 0x52 //尋天線區(qū)內(nèi)全部卡 #define PICC_ANTICOLL1 0x93 //防沖撞 #define PICC_ANTICOLL2 0x95 //防沖撞 #define PICC_AUTHENT1A 0x60 //驗證A密鑰 #define PICC_AUTHENT1B 0x61 //驗證B密鑰 #define PICC_READ 0x30 //讀塊 #define PICC_WRITE 0xA0 //寫塊 #define PICC_DECREMENT 0xC0 //扣款 #define PICC_INCREMENT 0xC1 //充值 #define PICC_RESTORE 0xC2 //調(diào)塊數(shù)據(jù)到緩沖區(qū) #define PICC_TRANSFER 0xB0 //保存緩沖區(qū)中數(shù)據(jù) #define PICC_HALT 0x50 //休眠#define DEF_FIFO_LENGTH 64 //FIFO size=64byte// PAGE 0 #define RFU00 0x00 #define CommandReg 0x01 #define ComIEnReg 0x02 #define DivlEnReg 0x03 #define ComIrqReg 0x04 #define DivIrqReg 0x05 #define ErrorReg 0x06 #define Status1Reg 0x07 #define Status2Reg 0x08 #define FIFODataReg 0x09 #define FIFOLevelReg 0x0A #define WaterLevelReg 0x0B #define ControlReg 0x0C #define BitFramingReg 0x0D #define CollReg 0x0E #define RFU0F 0x0F // PAGE 1 #define RFU10 0x10 #define ModeReg 0x11 #define TxModeReg 0x12 #define RxModeReg 0x13 #define TxControlReg 0x14 #define TxAutoReg 0x15 #define TxSelReg 0x16 #define RxSelReg 0x17 #define RxThresholdReg 0x18 #define DemodReg 0x19 #define RFU1A 0x1A #define RFU1B 0x1B #define MifareReg 0x1C #define RFU1D 0x1D #define RFU1E 0x1E #define SerialSpeedReg 0x1F // PAGE 2 #define RFU20 0x20 #define CRCResultRegM 0x21 #define CRCResultRegL 0x22 #define RFU23 0x23 #define ModWidthReg 0x24 #define RFU25 0x25 #define RFCfgReg 0x26 #define GsNReg 0x27 #define CWGsCfgReg 0x28 #define ModGsCfgReg 0x29 #define TModeReg 0x2A #define TPrescalerReg 0x2B #define TReloadRegH 0x2C #define TReloadRegL 0x2D #define TCounterValueRegH 0x2E #define TCounterValueRegL 0x2F // PAGE 3 #define RFU30 0x30 #define TestSel1Reg 0x31 #define TestSel2Reg 0x32 #define TestPinEnReg 0x33 #define TestPinValueReg 0x34 #define TestBusReg 0x35 #define AutoTestReg 0x36 #define VersionReg 0x37 #define AnalogTestReg 0x38 #define TestDAC1Reg 0x39 #define TestDAC2Reg 0x3A #define TestADCReg 0x3B #define RFU3C 0x3C #define RFU3D 0x3D #define RFU3E 0x3E #define RFU3F 0x3F#define MI_OK 0 #define MI_NOTAGERR 1 //(-1) #define MI_ERR 2 //(-2)#define MAXRLEN 18void RC522_Init(void); char PcdRequest(unsigned char req_code,unsigned char *pTagType); char PcdAnticoll(unsigned char *pSnr); char PcdSelect(unsigned char *pSnr); char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr); char PcdRead(unsigned char addr,unsigned char *pData); char PcdWrite(unsigned char addr,unsigned char *pData); char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue); char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr); char PcdHalt(void); void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData); char PcdReset(void); unsigned char ReadRawRC(unsigned char Address); void WriteRawRC(unsigned char Address, unsigned char value); void SetBitMask(unsigned char reg,unsigned char mask); void ClearBitMask(unsigned char reg,unsigned char mask); char PcdComMF522(unsigned char Command,unsigned char *pInData,unsigned char InLenByte,unsigned char *pOutData,unsigned int *pOutLenBit); void PcdAntennaOn(void); void PcdAntennaOff(void); void RC522_Config(unsigned char Card_Type);#endif /* RC522_H_ */總結(jié)
以上是生活随笔為你收集整理的RC522(RFID)读写驱动的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: zui php,ZUI前端html5框架
- 下一篇: Google DFP广告管理系统简介:开