电子工坊

通过SPI控制多个RFID RC522

RFID大家都很常用吧,会单片机Arduino的同学一般都用过RC522,但是你有没有试过将多个RC522级联在一起呢。有试过被网上的回复坑过的吧,如何通过SPI如何控制多个RC522呢,请细看文章吧。

单个RC522 SPI连接方式

为什么不用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();       //开启天线
}