通过SPI控制多个RFID RC522
RFID大家都很常用吧,会单片机Arduino的同学一般都用过RC522,但是你有没有试过将多个RC522级联在一起呢。有试过被网上的回复坑过的吧,如何通过SPI如何控制多个RC522呢,请细看文章吧。
单个RC522 SPI连接方式
- 单个RC522连接很简单,连接方法如下
MCU(SPI主机) RC522(SPI从机)
MOSI <---------> MOSI (SPI主输出)
MISO <---------> MISO(SPI主输入)
SCK <---------> SCK(SPI时钟信号)
RST <---------> RST(RFID复位,高电平复位)
SS <---------> NSS(片选,低电平使能)
在单个器件控制上SS(片选)可以直接接地,RST可直接接低电平可节省两个IO口。
为什么不用I2C级联多个RC522
为什么用SPI不用I2C呢?原因很简单,就是因为大家都是淘宝买的成品,I2C地址都相同,所以必须选择SPI的连接方式。
如果你是打算自己拼版打PCB,那我建议你使用I2C的方式驱动,RC522有3个控制I2C地址的IO口,也就是说使用I2C最大级联7个RC522,超过7个还是需要其他方式的。
多个RC522 SPI连接方式
MCU(SPI主机) RC522(SPI从机1) RC522(SPI从机2)
MOSI <-------------> MOSI <-------------> MOSI(SPI主输出)
MISO <-------------> MISO <-------------> MISO(SPI主输入)
SCK <-------------> SCK <-------------> SCK(SPI时钟信号)
RST <-------------> RST <-------------> RST(RFID复位引脚,高电平复位)
SS1 <-------------> NSS1(片选,低电平使能)
SS2 <----------------------------------------> NSS2(片选,低电平使能)
不可缺省RST和SS(片选引脚)。
经过我的测试每次切换RC522模块都需要走一遍RST的流程(如果有能力解决这个问题的朋友请告诉我),SS引脚是位选引脚,每一个RC522的位选引脚都不同,这样会很占用单片机的IO,所以我使用38译码器(74HC138)去选择我要使用的RC522模块,38译码器在被选到的器件是低电平,NSS也是低电平使能所以不需要反转输出。其余SCK,MOSI,MISO和RST引脚都分别使用同一条线连接在一起。
附上STM32写的一段级联程序
下面是使用STM32控制多个RC522的一小段程序,正常使用,如有问题请留言。
//更新片选引脚,顺便复位(函数在外部使用)
void renew_RC522CS(uint8_t vul)
{
rfid.device = vul;
Reset_RC522();
}
//设置片选引脚
void SET_RC522_CS(void)
{
if(rfid.device == 0)
{
HAL_GPIO_WritePin(SPIx_CS3_GPIO_PORT, SPIx_CS3_PIN,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(SPIx_CS1_GPIO_PORT, SPIx_CS1_PIN | SPIx_CS2_PIN,GPIO_PIN_SET);
HAL_GPIO_WritePin(SPIx_CS4_GPIO_PORT, SPIx_CS4_PIN,GPIO_PIN_SET);
}
}
//清除片选引脚
void CLR_RC522_CS(void)
{
if(rfid.device == 0)
{
HAL_GPIO_WritePin(SPIx_CS3_GPIO_PORT, SPIx_CS3_PIN,GPIO_PIN_RESET);
}
else if(rfid.device == 1)
{
HAL_GPIO_WritePin(SPIx_CS2_GPIO_PORT, SPIx_CS2_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(SPIx_CS1_GPIO_PORT, SPIx_CS1_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(SPIx_CS4_GPIO_PORT, SPIx_CS4_PIN,GPIO_PIN_RESET);
}
else if(rfid.device == 2)
{
HAL_GPIO_WritePin(SPIx_CS2_GPIO_PORT, SPIx_CS2_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(SPIx_CS1_GPIO_PORT, SPIx_CS1_PIN,GPIO_PIN_RESET);
}
else if(rfid.device == 3)
{
HAL_GPIO_WritePin(SPIx_CS2_GPIO_PORT, SPIx_CS2_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(SPIx_CS4_GPIO_PORT, SPIx_CS4_PIN,GPIO_PIN_RESET);
}
else if(rfid.device == 4)
{
HAL_GPIO_WritePin(SPIx_CS2_GPIO_PORT, SPIx_CS2_PIN,GPIO_PIN_RESET);
}
}
//初始化RC522
void InitRc522(void)
{
SPIx_Init();
PcdReset();
PcdAntennaOff();
delay_ms(2);
PcdAntennaOn();
M500PcdConfigISOType( 'A' );
}
//复位RC522
void Reset_RC522(void)
{
PcdReset(); //引脚复位
PcdAntennaOff(); //关闭天线
delay_ms(2); //等待一段时间
PcdAntennaOn(); //开启天线
}