STM32——NFC门禁模块(RC522)(1)

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

char PCD_Request(uint8_t RequestMode, uint8_t *pCardType)
{
int status;
uint16_t unLen;
uint8_t CmdFrameBuf[MFRC_MAXRLEN];

MFRC\_ClrBitMask(MFRC_Status2Reg, 0x08);//关内部温度传感器
MFRC\_WriteReg(MFRC_BitFramingReg, 0x07); //存储模式,发送模式,是否启动发送等
MFRC\_SetBitMask(MFRC_TxControlReg, 0x03);//配置调制信号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;

}


* 防冲撞



/***************************************************************************************
* 函数名称:PCD_Anticoll
* 功能描述:防冲突,获取卡号
* 入口参数:-pSnr:用于保存卡片序列号,4字节
* 出口参数:-pSnr:卡片序列号,4字节
* 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
* 说 明:无
***************************************************************************************/
char PCD_Anticoll(uint8_t *pSnr)
{
char status;
uint8_t i, snr_check = 0;
uint16_t unLen;
uint8_t CmdFrameBuf[MFRC_MAXRLEN];

MFRC\_ClrBitMask(MFRC_Status2Reg, 0x08);
MFRC\_WriteReg(MFRC_BitFramingReg, 0x00);
MFRC\_ClrBitMask(MFRC_CollReg, 0x80);

CmdFrameBuf[0] = PICC_ANTICOLL1;
CmdFrameBuf[1] = 0x20;

status = MFRC\_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 2, CmdFrameBuf, &unLen);
if(status == PCD_OK)
{
    for(i = 0; i < 4; i++)
    {
        \*(pSnr + i)  = CmdFrameBuf[i];
        snr_check ^= CmdFrameBuf[i];
    }
    if(snr_check != CmdFrameBuf[i])
    {
        status = PCD_ERR;
    }
}
	switch (status)
	{
		case PCD_OK:					
            printf("寻卡OK\r\n");break;
		case PCD_ERR:					
            printf("寻卡ERROR\r\n");break;
		case PCD_NOTAGERR:		
            printf("无卡\r\n");break;
	}

MFRC\_SetBitMask(MFRC_CollReg, 0x80);
return status;

}


### 4.2 二级内部调用函数


* 宏定义



//三目运算符true取前面那个
#define RS522_RST(N) HAL_GPIO_WritePin(RC522_RST_GPIO_Port, RC522_RST_Pin, N1?GPIO_PIN_SET:GPIO_PIN_RESET)
#define RS522_NSS(N) HAL_GPIO_WritePin(RC522_CS_GPIO_Port, RC522_CS_Pin, N
1?GPIO_PIN_SET:GPIO_PIN_RESET)
#define osDelay HAL_Delay


* MFRC管脚配置



/**************************************************************************************
* 函数名称:MFRC_Init
* 功能描述:MFRC初始化
* 入口参数:无
* 出口参数:无
* 返 回 值:无
* 说 明:MFRC的SPI接口速率为0~10Mbps
***************************************************************************************/
void MFRC_Init(void)
{
RS522_NSS(1);
RS522_RST(1);
}


* PCD复位 并初始化配置



/**************************************************************************************
* 函数名称:PCD_Reset
* 功能描述:PCD复位
* 入口参数:无
* 出口参数:无
* 返 回 值:无
* 说 明:无
***************************************************************************************/
void PCD_Reset(void)
{
/*硬复位*/
RS522_RST(1);//用到我们的复位引脚
osDelay(2);
RS522_RST(0);
osDelay(2);
RS522_RST(1);
osDelay(2);

/\*软复位\*/
MFRC\_WriteReg(MFRC_CommandReg, MFRC_RESETPHASE);
osDelay(2);

/\*复位后的初始化配置\*/
MFRC\_WriteReg(MFRC_ModeReg, 0x3D);              //CRC初始值0x6363
MFRC\_WriteReg(MFRC_TReloadRegL, 30);            //定时器重装值
MFRC\_WriteReg(MFRC_TReloadRegH, 0);
MFRC\_WriteReg(MFRC_TModeReg, 0x8D);             //定时器设置
MFRC\_WriteReg(MFRC_TPrescalerReg, 0x3E);        //定时器预分频值
MFRC\_WriteReg(MFRC_TxAutoReg, 0x40);            //100%ASK

PCD\_AntennaOff();                               //关天线
osDelay(2);
PCD\_AntennaOn();                                //开天线

}


* 关闭天线



/**************************************************************************************
* 函数名称:PCD_AntennaOn
* 功能描述:开启天线,使能PCD发送能量载波信号
* 入口参数:无
* 出口参数:无
* 返 回 值:无
* 说 明:每次开启或关闭天线之间应至少有1ms的间隔
***************************************************************************************/
void PCD_AntennaOn(void)
{
uint8_t temp;
temp = MFRC_ReadReg(MFRC_TxControlReg);
if (!(temp & 0x03))
{
MFRC_SetBitMask(MFRC_TxControlReg, 0x03);
}
}


* 开启天线



/**************************************************************************************
* 函数名称:PCD_AntennaOff
* 功能描述:关闭天线,失能PCD发送能量载波信号
* 入口参数:无
* 出口参数:无
* 返 回 值:无
* 说 明:每次开启或关闭天线之间应至少有1ms的间隔
***************************************************************************************/
void PCD_AntennaOff(void)
{
MFRC_ClrBitMask(MFRC_TxControlReg, 0x03);
}


* RC与M1卡通讯帧函数



/**************************************************************************************
* 函数名称:MFRC_CmdFrame
* 功能描述:MFRC522和ISO14443A卡通讯的命令帧函数
* 入口参数:-cmd:MFRC522命令字
* -pIndata:MFRC522发送给MF1卡的数据的缓冲区首地址
* -InLenByte:发送数据的字节长度
* -pOutdata:用于接收MF1卡片返回数据的缓冲区首地址
* -pOutLenBit:MF1卡返回数据的位长度
* 出口参数:-pOutdata:用于接收MF1卡片返回数据的缓冲区首地址
* -pOutLenBit:用于MF1卡返回数据位长度的首地址
* 返 回 值:-status:错误代码(MFRC_OK、MFRC_NOTAGERR、MFRC_ERR)
* 说 明:无
***************************************************************************************/
char MFRC_CmdFrame(uint8_t cmd, uint8_t *pInData, uint8_t InLenByte, uint8_t *pOutData, uint16_t *pOutLenBit)
{
uint8_t lastBits;
uint8_t n;
uint32_t i;
char status = MFRC_ERR;
uint8_t irqEn = 0x00;
uint8_t waitFor = 0x00;

/\*根据命令设置标志位\*/
switch(cmd)
{
    case MFRC_AUTHENT:                  //Mifare认证
        irqEn = 0x12;
        waitFor = 0x10;                 //idleIRq中断标志
        break;
    case MFRC_TRANSCEIVE:               //发送并接收数据
        irqEn = 0x77;
        waitFor = 0x30;                 //RxIRq和idleIRq中断标志
        break;
}

/\*发送命令帧前准备\*/
MFRC\_WriteReg(MFRC_ComIEnReg, irqEn | 0x80);    //开中断
MFRC\_ClrBitMask(MFRC_ComIrqReg, 0x80);          //清除中断标志位SET1
MFRC\_WriteReg(MFRC_CommandReg, MFRC_IDLE);      //取消当前命令的执行
MFRC\_SetBitMask(MFRC_FIFOLevelReg, 0x80);       //清除FIFO缓冲区及其标志位

/\*发送命令帧\*/
for(i = 0; i < InLenByte; i++)                  //写入命令参数
{
    MFRC\_WriteReg(MFRC_FIFODataReg, pInData[i]);
}
MFRC\_WriteReg(MFRC_CommandReg, cmd);            //执行命令
if(cmd == MFRC_TRANSCEIVE)
{
    MFRC\_SetBitMask(MFRC_BitFramingReg, 0x80);  //启动发送
}
i = 300000;                                     //根据时钟频率调整,操作M1卡最大等待时间25ms
do
{
    n = MFRC\_ReadReg(MFRC_ComIrqReg);
    i--;
}
while((i != 0) && !(n & 0x01) && !(n & waitFor));     //等待命令完成
MFRC\_ClrBitMask(MFRC_BitFramingReg, 0x80);          //停止发送

/\*处理接收的数据\*/
if(i != 0)
{
    if(!(MFRC\_ReadReg(MFRC_ErrorReg) & 0x1B))
    {
        status = MFRC_OK;
        if(n & irqEn & 0x01)
        {
            status = MFRC_NOTAGERR;
        }
        if(cmd == MFRC_TRANSCEIVE)
        {
            n = MFRC\_ReadReg(MFRC_FIFOLevelReg);
            lastBits = MFRC\_ReadReg(MFRC_ControlReg) & 0x07;
            if (lastBits)
            {
                \*pOutLenBit = (n - 1) \* 8 + lastBits;
            }
            else
            {
                \*pOutLenBit = n \* 8;
            }
            if(n == 0)
            {
                n = 1;
            }
            if(n > MFRC_MAXRLEN)
            {
                n = MFRC_MAXRLEN;
            }
            for(i = 0; i < n; i++)
            {
                pOutData[i] = MFRC\_ReadReg(MFRC_FIFODataReg);
            }
        }
    }
    else
    {
        status = MFRC_ERR;
    }
}

MFRC\_SetBitMask(MFRC_ControlReg, 0x80);               //停止定时器运行
MFRC\_WriteReg(MFRC_CommandReg, MFRC_IDLE);            //取消当前命令的执行

return status;

}


### 4.3 第三级最底层函数


* 读一个寄存器



/**************************************************************************************
* 函数名称:MFRC_ReadReg
* 功能描述:读一个寄存器
* 入口参数:-addr:待读的寄存器地址
* 出口参数:无
* 返 回 值:-data:读到寄存器的数据
* 说 明:无
***************************************************************************************/
uint8_t MFRC_ReadReg(uint8_t addr)
{
uint8_t AddrByte, data;
AddrByte = ((addr << 1 ) & 0x7E ) | 0x80; //求出地址字节
RS522_NSS(0); //NSS拉低
SPI2_RW_Byte(AddrByte); //写地址字节
data = SPI2_RW_Byte(0x00); //读数据
RS522_NSS(1); //NSS拉高
return data;
}


* 设置寄存器的位



/**************************************************************************************
* 函数名称:MFRC_SetBitMask
* 功能描述:设置寄存器的位
* 入口参数:-addr:待设置的寄存器地址
* -mask:待设置寄存器的位(可同时设置多个bit)
* 出口参数:无
* 返 回 值:无
* 说 明:无
***************************************************************************************/
void MFRC_SetBitMask(uint8_t addr, uint8_t mask)
{
uint8_t temp;
temp = MFRC_ReadReg(addr); //先读回寄存器的值
MFRC_WriteReg(addr, temp | mask); //处理过的数据再写入寄存器
}


* 清除寄存器的位



/**************************************************************************************
* 函数名称:MFRC_ClrBitMask
* 功能描述:清除寄存器的位
* 入口参数:-addr:待清除的寄存器地址
* -mask:待清除寄存器的位(可同时清除多个bit)
* 出口参数:无
* 返 回 值:无
* 说 明:无
***************************************************************************************/
void MFRC_ClrBitMask(uint8_t addr, uint8_t mask)
{
uint8_t temp;
temp = MFRC_ReadReg(addr); //先读回寄存器的值
MFRC_WriteReg(addr, temp & ~mask); //处理过的数据再写入寄存器
}


### 4.4 头文件



#ifndef _RC522_H
#define _RC522_H

//头文件
//************************************************
#include “gpio.h”//要一些引脚上的宏定义
#include “spi.h”//硬件SPI的定义
#include “printf.h”
#include “main.h”//Laber User上的宏定义
//************************************************

//MFRC522驱动程序
//************************************************

/*MFRC522寄存器定义*/
//PAGE0
#define MFRC_RFU00 0x00
#define MFRC_CommandReg 0x01
#define MFRC_ComIEnReg 0x02
#define MFRC_DivlEnReg 0x03
#define MFRC_ComIrqReg 0x04
#define MFRC_DivIrqReg 0x05
#define MFRC_ErrorReg 0x06
#define MFRC_Status1Reg 0x07
#define MFRC_Status2Reg 0x08
#define MFRC_FIFODataReg 0x09
#define MFRC_FIFOLevelReg 0x0A
#define MFRC_WaterLevelReg 0x0B
#define MFRC_ControlReg 0x0C
#define MFRC_BitFramingReg 0x0D
#define MFRC_CollReg 0x0E
#define MFRC_RFU0F 0x0F
//PAGE1
#define MFRC_RFU10 0x10
#define MFRC_ModeReg 0x11
#define MFRC_TxModeReg 0x12
#define MFRC_RxModeReg 0x13
#define MFRC_TxControlReg 0x14
#define MFRC_TxAutoReg 0x15 //中文手册有误
#define MFRC_TxSelReg 0x16
#define MFRC_RxSelReg 0x17
#define MFRC_RxThresholdReg 0x18
#define MFRC_DemodReg 0x19
#define MFRC_RFU1A 0x1A
#define MFRC_RFU1B 0x1B
#define MFRC_MifareReg 0x1C
#define MFRC_RFU1D 0x1D
#define MFRC_RFU1E 0x1E
#define MFRC_SerialSpeedReg 0x1F
//PAGE2
#define MFRC_RFU20 0x20
#define MFRC_CRCResultRegM 0x21
#define MFRC_CRCResultRegL 0x22
#define MFRC_RFU23 0x23
#define MFRC_ModWidthReg 0x24
#define MFRC_RFU25 0x25
#define MFRC_RFCfgReg 0x26
#define MFRC_GsNReg 0x27
#define MFRC_CWGsCfgReg 0x28
#define MFRC_ModGsCfgReg 0x29
#define MFRC_TModeReg 0x2A
#define MFRC_TPrescalerReg 0x2B
#define MFRC_TReloadRegH 0x2C
#define MFRC_TReloadRegL 0x2D
#define MFRC_TCounterValueRegH 0x2E
#define MFRC_TCounterValueRegL 0x2F

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

adRegH 0x2C
#define MFRC_TReloadRegL 0x2D
#define MFRC_TCounterValueRegH 0x2E
#define MFRC_TCounterValueRegL 0x2F

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
[外链图片转存中…(img-j205M7iW-1715909797731)]
[外链图片转存中…(img-k4T4LlEo-1715909797732)]

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PN532是一款常用的NFC读写芯片,支持ISO14443A/B、FeliCa以及ISO18092标准。在STM32中使用PN532可以实现NFC功能,下面是使用PN532的基本步骤: 1. 硬件连接:将PN532的SDA、SCK、MISO、MOSI、NSS、IRQ、RST引脚分别连接到STM32的对应引脚,同时将PN532的VCC和GND引脚连接到STM32的电源和地。 2. 初始化:使用SPI总线与PN532进行通信,并初始化PN532芯片,可以使用以下代码: ```C void PN532_Init(void) { HAL_GPIO_WritePin(PN532_CS_GPIO_Port, PN532_CS_Pin, GPIO_PIN_RESET); HAL_Delay(100); PN532_Reset(); HAL_Delay(100); PN532_Wakeup(); HAL_Delay(100); } void PN532_Reset(void) { HAL_GPIO_WritePin(PN532_RST_GPIO_Port, PN532_RST_Pin, GPIO_PIN_RESET); HAL_Delay(10); HAL_GPIO_WritePin(PN532_RST_GPIO_Port, PN532_RST_Pin, GPIO_PIN_SET); HAL_Delay(10); } void PN532_Wakeup(void) { uint8_t cmd[] = {0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; HAL_SPI_Transmit(&hspi1, cmd, sizeof(cmd), 100); } ``` 3. 发送命令:PN532可以执行多种命令,如初始化、读写卡片等,可以使用以下代码发送命令: ```C uint8_t PN532_SendCmd(uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uint8_t resplen) { HAL_GPIO_WritePin(PN532_CS_GPIO_Port, PN532_CS_Pin, GPIO_PIN_RESET); HAL_Delay(10); HAL_SPI_Transmit(&hspi1, cmd, cmdlen, 100); HAL_Delay(10); HAL_SPI_Receive(&hspi1, response, resplen, 100); HAL_Delay(10); HAL_GPIO_WritePin(PN532_CS_GPIO_Port, PN532_CS_Pin, GPIO_PIN_SET); return response[0]; } ``` 4. 读写卡片:PN532可以读写ISO14443A/B、FeliCa以及ISO18092标准的卡片,可以使用以下代码读写卡片: ```C uint8_t PN532_ReadCard(uint8_t *cardData, uint8_t *cardLen) { uint8_t cmd[] = {0xD4, 0x4A, 0x01, 0x00}; uint8_t response[32]; uint8_t responseLen = 0; PN532_SendCmd(cmd, sizeof(cmd), response, sizeof(response)); if (response[0] != 0x01) { return 0; } responseLen = response[1] - 1; memcpy(cardData, &response[2], responseLen); *cardLen = responseLen; return 1; } ``` 以上代码仅为参考,具体使用时需要根据实际情况进行修改和完善。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值