STM32——NFC門(mén)禁模塊(RC522)(含代碼)
大家好,今天給大家介紹,文章末尾附有本畢業(yè)設(shè)計(jì)的論文和源碼的獲取方式,也可現(xiàn)在直接進(jìn)群免費(fèi)領(lǐng)取。
1. 前言(包括一些個(gè)人理解)
(2021/11/1編輯)
在項(xiàng)目需要做一個(gè)NFC門(mén)禁功能的時(shí)候,突然發(fā)現(xiàn)有個(gè)RC522丟在我的桌面,甚至不知道它上面的引腳什么意思(還不會(huì)SPI通訊),搜索關(guān)鍵詞“RC522”去看博客搜索資料,發(fā)現(xiàn)了很多都在說(shuō)扇區(qū),塊,S50(M1)卡,然后就給代碼,一開(kāi)始我還以為S50是內(nèi)嵌在這個(gè)模塊里面的一個(gè)存儲(chǔ)器,然后越看越怪,后面去淘寶搜索S50,才發(fā)現(xiàn)S50其實(shí)是我們的門(mén)禁卡,RC522是用來(lái)感應(yīng)和判斷的。
- PCD是接近式卡。PICC是接近式耦合設(shè)備。
- 在通信過(guò)程中實(shí)際上是使用PCD命令控制RC522發(fā)出PICC命令與卡進(jìn)行交互。
2. RC522門(mén)禁工作過(guò)程
- 過(guò)程:尋卡->防沖突->選卡->操作卡
- PCD命令
/*MFRC522命令集,中文手冊(cè)P59*/ #define MFRC_IDLE 0x00 //取消當(dāng)前命令的執(zhí)行 #define MFRC_TRANSMIT 0x04 //發(fā)送FIFO緩沖區(qū)內(nèi)容 #define MFRC_RECEIVE 0x08 //激活接收器接收數(shù)據(jù) #define MFRC_TRANSCEIVE 0x0C //發(fā)送并接收數(shù)據(jù) #define MFRC_AUTHENT 0x0E //執(zhí)行Mifare認(rèn)證(驗(yàn)證密鑰) #define MFRC_RESETPHASE 0x0F //復(fù)位MFRC522 #define MFRC_CALCCRC 0x03 //激活CRC計(jì)算 #define MFRC_NOCMDCHANGE 0x07 //無(wú)命令改變
- PICC命令
/*Mifare1卡片命令字*/ #define PICC_REQIDL 0x26 //尋天線區(qū)內(nèi)未進(jìn)入休眠狀態(tài)的卡 #define PICC_REQALL 0x52 //尋天線區(qū)內(nèi)全部卡 #define PICC_ANTICOLL1 0x93 //防沖撞 #define PICC_ANTICOLL2 0x95 //防沖撞 #define PICC_AUTHENT1A 0x60 //驗(yàn)證A密鑰 #define PICC_AUTHENT1B 0x61 //驗(yàn)證B密鑰 #define PICC_READ 0x30 //讀塊 #define PICC_WRITE 0xA0 //寫(xiě)塊 #define PICC_DECREMENT 0xC0 //減值(扣除) #define PICC_INCREMENT 0xC1 //增值(充值) #define PICC_TRANSFER 0xB0 //轉(zhuǎn)存(傳送) #define PICC_RESTORE 0xC2 //恢復(fù)(重儲(chǔ)) #define PICC_HALT 0x50 //休眠
3. CubeMx配置
3.1 SPI通訊的配置
打開(kāi)SPI模式設(shè)置為:Full-Duplex Master(全雙工主機(jī)模式)
- 分頻設(shè)置為8~256都行,這樣隨之波特率也會(huì)改變,波特率越小通信速度越快
- Clock Phase (CPHA) 設(shè)置為第一個(gè)上升沿這里一定要1Edge
- 不開(kāi)啟CRC檢測(cè)
3.2 SDA和REST引腳的配置
隨后再定義兩個(gè)普通的OUTPUT輸出的引腳作為復(fù)位和使能引腳
4. 外設(shè)代碼函數(shù)編寫(xiě)
4.1 主函數(shù)能調(diào)用的接口函數(shù)
- 初始化
/*************************************************************************************** * 函數(shù)名稱:PCD_Init * 功能描述:讀寫(xiě)器初始化 * 入口參數(shù):無(wú) * 出口參數(shù):無(wú) * 返 回 值:無(wú) * 說(shuō) 明:無(wú) ***************************************************************************************/
void PCD_Init(void)
{ MFRC_Init(); //MFRC管腳配置 PCD_Reset(); //PCD復(fù)位 并初始化配置 PCD_AntennaOff(); //關(guān)閉天線 PCD_AntennaOn(); //開(kāi)啟天線 PCD_Reset(); }
- 尋卡
/*************************************************************************************** * 函數(shù)名稱:PCD_Request * 功能描述:尋卡 * 入口參數(shù): -RequestMode:尋卡方式 * PICC_REQIDL:尋天線區(qū)內(nèi)未進(jìn)入休眠狀態(tài) * PICC_REQALL:尋天線區(qū)內(nèi)全部卡 * -pCardType:用于保存卡片類型 * 出口參數(shù):-pCardType:卡片類型 * 0x4400:Mifare_UltraLight * 0x0400:Mifare_One(S50) * 0x0200:Mifare_One(S70) * 0x0800:Mifare_Pro(X) * 0x4403:Mifare_DESFire * 返 回 值:-status:錯(cuò)誤代碼(PCD_OK、PCD_NOTAGERR、PCD_ERR) * 說(shuō) 明:無(wú) ***************************************************************************************/
char PCD_Request(uint8_t RequestMode, uint8_t *pCardType)
{ int status; uint16_t unLen; uint8_t CmdFrameBuf[MFRC_MAXRLEN]; MFRC_ClrBitMask(MFRC_Status2Reg, 0x08);//關(guān)內(nèi)部溫度傳感器 MFRC_WriteReg(MFRC_BitFramingReg, 0x07); //存儲(chǔ)模式,發(fā)送模式,是否啟動(dòng)發(fā)送等 MFRC_SetBitMask(MFRC_TxControlReg, 0x03);//配置調(diào)制信號(hào)13.56MHZ CmdFrameBuf[0] = RequestMode; status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 1, CmdFrameBuf, &unLen); if((status == PCD_OK) && (unLen == 0x10)) { *pCardType = CmdFrameBuf[0]; *(pCardType + 1) = CmdFrameBuf[1]; } return status; }
- 防沖撞
4.2 二級(jí)內(nèi)部調(diào)用函數(shù)
- 宏定義
- MFRC管腳配置
- PCD復(fù)位 并初始化配置
- 關(guān)閉天線
- 開(kāi)啟天線
- RC與M1卡通訊幀函數(shù)
4.3 第三級(jí)最底層函數(shù)
- 讀一個(gè)寄存器
- 設(shè)置寄存器的位
- 清除寄存器的位
4.4 頭文件
5. 使用教程
//先用CubeMx初始化 PCD_Init();//RC522初始化 /*
* 函數(shù)功能:驗(yàn)證刷卡人,以及發(fā)送上位機(jī)刷卡人身份
* 參 數(shù):無(wú)
* 返 回 值:無(wú)
* 注 意:無(wú)
* 作 者:蘇釋州
*/ void NFC(void) { //尋卡 if (PCD_Request(PICC_REQALL, RxBuffer)!=0)//返回值為0,代表尋卡成功;并把卡類型存入RxBuffer中) { /*果然這里要清空一下不然就會(huì)亂,會(huì)有一些RxBuffer沒(méi)用的在那里占位*/ memset(RxBuffer, 0, sizeof(RxBuffer));//清空字符串 return;//如果不加這個(gè)判斷的話,則會(huì)無(wú)論尋卡是否成功都會(huì)有值000 } //防沖撞 if (PCD_Anticoll(RxBuffer)!=0)//防沖撞,完成這部就可以簡(jiǎn)單地 讀取卡號(hào) { memset(RxBuffer, 0, sizeof(RxBuffer));//清空字符串 return;//如果不加這個(gè)判斷的話,則會(huì)無(wú)論尋卡是否成功都會(huì)擾亂卡號(hào) } //處理卡號(hào)數(shù)據(jù) sprintf(Card_ID,"%x%x%x%x",RxBuffer[0],RxBuffer[1],RxBuffer[2],RxBuffer[3]); //對(duì)卡號(hào)進(jìn)行權(quán)限的判斷 if(strcmp(Card_ID,"b59dfcaa")==0)//賣(mài)家配的卡 {
DoorControl(1);//開(kāi)門(mén) HAL_TIM_Base_Start_IT(&htim5);//開(kāi)門(mén)的時(shí)候開(kāi)啟定時(shí)器5的中斷,進(jìn)入關(guān)門(mén)計(jì)時(shí) memset(RxBuffer, 0, sizeof(RxBuffer));//清空字符串,這里要清除RxBuffer才行,否則Card_ID又會(huì)被組起來(lái) } else if(strcmp(Card_ID,"e1eff3cc")==0)//劉駿帆手機(jī)本科生證 {
DoorControl(1);//開(kāi)門(mén) HAL_TIM_Base_Start_IT(&htim5);//開(kāi)啟定時(shí)器5的中斷 memset(RxBuffer, 0, sizeof(RxBuffer));//清空字符串,這里要清除RxBuffer才行,否則Card_ID又會(huì)被組起來(lái) } else {
DoorControl(1);//開(kāi)門(mén) HAL_TIM_Base_Start_IT(&htim5);//開(kāi)啟定時(shí)器5的中斷 memset(RxBuffer, 0, sizeof(RxBuffer));//清空字符串 }
HAL_Delay(100); return;
}
完整代碼可進(jìn)群免費(fèi)領(lǐng)取!!!
嵌入式物聯(lián)網(wǎng)的學(xué)習(xí)之路非常漫長(zhǎng),不少人因?yàn)閷W(xué)習(xí)路線不對(duì)或者學(xué)習(xí)內(nèi)容不夠?qū)I(yè)而錯(cuò)失高薪offer。不過(guò)別擔(dān)心,我為大家整理了一份150多G的學(xué)習(xí)資源,基本上涵蓋了嵌入式物聯(lián)網(wǎng)學(xué)習(xí)的所有內(nèi)容。點(diǎn)擊下方鏈接,0元領(lǐng)取學(xué)習(xí)資源,讓你的學(xué)習(xí)之路更加順暢!記得點(diǎn)贊、關(guān)注、收藏、轉(zhuǎn)發(fā)哦!
- 贊