stm32F1门禁卡RC522模块快速上手心得
作者:互联网
##stm32F1门禁卡RC522模块快速上手心得
1.配置GPIO
//LED 推挽输出 GPIOC GPIO13
//NSS 推挽输出 GPIOB GPIO12
//SCK 推挽输出 GPIOB GPIO14
//M0SI 推挽输出 GPIOA GPIO8
//MSIO 浮空输入 GPIOA GPIO10
//RST 推挽输出 GPIOA GPIO12
void GPIO_init(void)
{
RCC->APB2ENR|=1<<2; //gpioA 时钟
RCC->APB2ENR|=1<<3; //gpioB 时钟
RCC->APB2ENR|=1<<4; //gpioC 时钟
GPIOA->CRH&=0XFFF0F000;
GPIOA->CRH|=0X000304B3;
GPIOA->CRL&=0XFFFFFFFF;
GPIOA->CRL|=0X00000000;
GPIOA->ODR|=1<<8; // 输出端口数据位 复位脚拉高
GPIOB->CRH&=0XF0F0FFFF;
GPIOB->CRH|=0X03030000; // gpiob 8-15
GPIOB->CRL&=0XFFFFFFFF;
GPIOB->CRL|=0X00000000; // gpiob 0-7
GPIOB->ODR&=0;
GPIOC->CRH&=0XFF0FFFFF;
GPIOC->CRH|=0X00300000;
GPIOC->CRL&=0XFFFFFFFF;
GPIOC->CRL|=0X00000000;
GPIOC->ODR=0;
}
2.写SPI通信
void Write_addr_dat(unsigned char addr,unsigned char dat)
{
unsigned char i;
NSS=0;
SCK=0;
addr=((addr<<1)&0x7E);
for(i=0;i<8;i++)
{
if(addr&0x80) MOSI=1;
else MOSI=0;
SCK=1;
addr<<=1;
SCK=0;
}
for(i=0;i<8;i++)
{
if(dat&0x80) MOSI=1;
else MOSI=0;
SCK=1;
dat<<=1;
SCK=0;
}
NSS=1;
SCK=1;
}
unsigned char Read_dat(unsigned char addr)
{
unsigned char i;
unsigned char dat=0;
NSS=0;
addr=((addr<<1)&0x7E)|0x80;
for(i=0;i<8;i++)
{
SCK=0;
if(addr&0x80) MOSI=1;
else MOSI=0;
SCK=1;
addr<<=1;
}
for(i=0;i<8;i++)
{
SCK=0;
dat<<=1;
SCK=1;
if(MISO) dat|=1;
}
NSS=1;
SCK=1;
return dat;
}
3.读RC522寄存器原理
/
//MF522命令字
/
#define PCD_IDLE 0x00 //取消当前命令
#define PCD_AUTHENT 0x0E //验证密钥
#define PCD_RECEIVE 0x08 //接收数据
#define PCD_TRANSMIT 0x04 //发送数据
#define PCD_TRANSCEIVE 0x0C //发送并接收数据
#define PCD_RESETPHASE 0x0F //复位
#define PCD_CALCCRC 0x03 //CRC计算
/
//Mifare_One卡片命令字
/
#define PICC_REQIDL 0x26 //寻天线区内未进入休眠状态
#define PICC_REQALL 0x52 //寻天线区内全部卡
#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 //调块数据到缓冲区
#define PICC_TRANSFER 0xB0 //保存缓冲区中数据
#define PICC_HALT 0x50 //休眠
/
//MF522 FIFO长度定义
/
#define DEF_FIFO_LENGTH 64 //FIFO size=64byte
/
//MF522寄存器定义
/
// 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 //包含CRC 、中断和FIFO缓冲区的状态标志
#define Status2Reg 0x08 //包含接收器、发送器和数据模式检测器的状态标志
#define FIFODataReg 0x09 //64字节FIFO缓冲的输出和输入
#define FIFOLevelReg 0x0A //指示FIFO中保存的字节数
#define WaterLevelReg 0x0B //定义FIFO下溢和上溢报警的FIFO深度
#define ControlReg 0x0C //包含不同的控制位
#define BitFramingReg 0x0D //面向位的帧的调节
#define CollReg 0x0E //定义在RF接口上检测到的第一个冲突
#define RFU0F 0x0F //RFU 保留为将来用的寄存器
// PAGE 1
#define RFU10 0x10 //RFU 保留为将来用的寄存器
#define ModeReg 0x11 //定义发送和接收的常用模式
#define TxModeReg 0x12 //定义发送过程的数据速率
#define RxModeReg 0x13 //定义接收过程的数据速率
#define TxControlReg 0x14 //控制天线驱动器管脚TX1和TX2的逻辑操作
#define TxAutoReg 0x15 //RFU 保留为将来用的寄存器
#define TxSelReg 0x16 //选择模拟部分的内部源
#define RxSelReg 0x17 //选择内部接收器的设置
#define RxThresholdReg 0x18 //选择位译码器的阈值
#define DemodReg 0x19 //定义解调器的设置
//RFU //保留为将来用的寄存器
#define RFU1A 0x1A
#define RFU1B 0x1B
#define MifareReg 0x1C
//RFU //保留为将来用的寄存器
#define RFU1D 0x1D
#define RFU1E 0x1E
#define SerialSpeedReg 0x1F //选择串行UART接口的速率
//PAGE 2
#define RFU20 0x20 //RFU //保留为将来用的寄存器
//显示CRC计算的实际MSB和LSB值
#define CRCResultRegM 0x21
#define CRCResultRegL 0x22
#define RFU23 0x23 //RFU
#define ModWidthReg 0x24 //控制调制宽度的设置
#define RFU25 0x25 //保留为将来用的寄存器
#define RFCfgReg 0x26 //配置接收器增益
#define GsNReg 0x27 //选择天线驱动器管脚TX1和TX2的N驱动器的电导
#define CWGsCfgReg 0x28 //定义P驱动器的电导
#define ModGsCfgReg 0x29 //定义驱动器P输出电导,便于时间调制
//内部定时器配置
#define TModeReg 0x2A
#define TPrescalerReg 0x2B
//描述16位长的定时器重装值
#define TReloadRegH 0x2C // 高位
#define TReloadRegL 0x2D // 低位
//定义定时器的当前值
#define TCounterValueRegH 0x2E //定时器的当前值,高八位
#define TCounterValueRegL 0x2F //定时器的当前值,低八位
// PAGE 3
#define RFU30 0x30 //保留寄存器
#define TestSel1Reg 0x31 //常用测试信号配置
#define TestSel2Reg 0x32 //常用测试信号配置和PRBS控制
#define TestPinEnReg 0x33 //使能测试总线的管脚输出驱动器
#define TestPinValueReg 0x34 //定义测试端口用作I/O时的值
#define TestBusReg 0x35 //使能测试总线的管脚输出驱动器
#define AutoTestReg 0x36 //控制数字自测试
#define VersionReg 0x37 // 显示版本
#define AnalogTestReg 0x38 //estReg 描述位
#define TestDAC1Reg 0x39 //bit5-0 定义TestDAC1的测试值
#define TestDAC2Reg 0x3A //bit5-0 定义TestDAC2的测试值
#define TestADCReg 0x3B //bit7-4 显示adc_I通道 3-0 显示 adc_Q通道
4.其它
关于他们具体通信代码,就不做讲解了,一般百度或者买模块的淘宝卖家会提供。下文主要讲解如何修改密码和写入扇区数据。
扇区3为例,一般扇区的初始A和初始密码B 都是6个0XFF字节,修改密码和写入块数据如下操作。
unsigned char buf[16]={0x01,0x02,0x03,0x04,0x05,0x06,0xff
,0x07,0x80,0x69,0x18,0x17,0x16,0x15,0x14,0x13}; //要写入的密码,中间0XFF,0X07,0X80,0X69 为控制字节
unsigned char DefaultKey[6] ={0x01,0x02,0x03,0x04,0x05,0x06};//密码A
unsigned char DefaultKey1[6]={0x18,0x17,0x16,0x15,0x14,0x13}; //密码B
unsigned char DefaultKey2[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0XFF};//初始密码
while(1)
{
status= PcdRequest(REQ_ALL,TagType);
if(!status)
{
status = PcdAnticoll(SelectedSnr);
if(!status)
{
status=PcdSelect(SelectedSnr);
if(!status)
{
snr = 3; //扇区号3
status = PcdAuthState(PICC_AUTHENT1A, (snr*4+3), DefaultKey2, SelectedSnr);// 校验3扇区密码A
if(!status)
{
status = PcdAuthState(PICC_AUTHENT1B, (snr*4+3), DefaultKey2, SelectedSnr);// 校验3扇区密码B
if(!status)
{
LED=~LED;
status = PcdWrite((snr*4+3), buf); // 写卡,写新密码 将buf[0]-buf[16]写入1扇区0块
// status = PcdRead((snr*4+1), buf2); // 读卡,读取3扇区0块数据到buf[0]-buf[16]
if(!status)
{
WaitCardOff();
}
}
}
}
}
}
}
/*****************************
如上代码,验证密码A和密码B后,将新密码写入扇区3块3中,如果下次在想进入扇区3,就要用新的密码A和密码B,写数据也一样只要操作写函数,就能写入新的数据。
******************************/
标签:status,addr,门禁卡,扇区,RC522,寄存器,define,stm32F1,PICC 来源: https://blog.csdn.net/qq_38716551/article/details/110678001