I have a project using the RC522 RFID module with my Arduino Uno board and miguelbalboa's rfid library. The example code and every other code I find on the internet work pooling the device in order to know if there is a new card present, but I intend to work with a interrupt-driven approach. I have the proper knowledge to do the hardware/arduino part, but I'm having trouble generating an interrupt in the IRQ pin when the card is present. Have anyone succeded on this?

Edit: Connection: RST -> 8

SS-> 9

MOSI -> 11

MISO -> 12

SCK -> 13

IRQ -> 2


#include <SPI.h>
#include <MFRC522.h>
#include <String.h>

#define RST_PIN     8 
#define SS_PIN      9

MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance

void setup() 
  Serial.begin(9600);       // Initialize serial communications with the PC
  while (!Serial);      // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
  SPI.begin();          // Init SPI bus
  mfrc522.PCD_Init();       // Init MFRC522
  mfrc522.PCD_WriteRegister(MFRC522::ComIrqReg, 0x80); //Clear interrupts
  mfrc522.PCD_WriteRegister(MFRC522::ComIEnReg, 0x7F); //Enable all interrupts
  mfrc522.PCD_WriteRegister(MFRC522::DivIEnReg, 0x14);
  attachInterrupt(0, isr, RISING);

void loop() 

void isr()
  mfrc522.PCD_WriteRegister(MFRC522::ComIrqReg, 0x80); //Clear interrupts

Result: I only get the "Ready..." on the Serial Monitor, no matter if there is a card present or not.

  • Welcome to Arduino SE! Code? Wiring? Commented Mar 28, 2015 at 15:38
  • @AnnonomusPenguin I have only used the example codes and wiring from the link (minor change, RST -> pin 8 and SS -> pin 9, for compatibility with the ethernet shield). As I haven't got access to an oscilloscope right now, I'm unable to check the interrupt pin, so I wrote a sketch to pool this pin and print its state via serial, 3-line code. It keeps giving me 0, no matter if the card is present or not... The documentation link says little about the interrupts and they're relation to the card reading.
    – Gus Campos
    Commented Mar 28, 2015 at 21:36
  • Does that code deal with interrupts itself or have you modified it? Commented Mar 28, 2015 at 21:53
  • The library doesn't deal with the interrupt, they don't even use the IRQ pin...
    – Gus Campos
    Commented Mar 29, 2015 at 4:14
  • So you did modify the code? Can you please add a minimal example of the problem (with the code and a circuit) to your question with an edit? Thanks Commented Mar 29, 2015 at 5:14

3 Answers 3


From your code:

void isr()
  mfrc522.PCD_WriteRegister(MFRC522::ComIrqReg, 0x80); //Clear interrupts

Do not do serial prints inside an ISR! They will eventually hang it. What you need to do is have a volatile variable (eg. a bool), set that in the ISR, and then check that in loop. If it changes, display it. Eg.

volatile bool cardPresent;

void loop() 
  if (cardPresent)
    mfrc522.PCD_WriteRegister(MFRC522::ComIrqReg, 0x80); //Clear interrupts
    cardPresent = false;


void isr()
  cardPresent = true;

The other thing I would do is put a scope or logic analyzer on the IRQ pin and see if it is actually changing. It should trigger the interrupt if it does.


I'm quite late to this party, but I was looking for a way to have the MFRC522 generate an interrupt when it detects a compatible RFID card/key fob/sticker/etc., and this is one of the hits I got from my search. I write this now for the pilgrim who follows the same breadcrumbs I have in the hopes that it will save them at least a little time.

I tried something similar to what was suggested, found that I got interrupts quite often and continuously, and looked into the situation a bit more.

The MFRC522 does not generate interrupts for card detection. The microcontroller (or microprocessor) must command it to transmit and then query it to see if there was any response. This means that the MCU cannot go into a sleep mode and get awaken by the MFRC522 when there's a card to read. The MFRC522 does have a timer that can generate an interrupt, but the maximum period of this timer is not huge, and the timer does not control the transceiver, it's there for the convenience of the application on the MCU.

Writing 0x7F to the "ComIEnReg" means the following:

  • Bit 7: IRqInv=0 - Interrupts are active high
  • Bit 6: TxIEn=1 - Transmitter interrupt is enabled
  • Bit 5: RxIEn=1 - Receive interrupt is enabled
  • Bit 4: IdleIEn=1 - Idle interrupt is enabled
  • Bit 3: HiAlertIEn=1 - "High Alert" interrupt is enabled
  • Bit 2: LoAlertIEn=1 - "Low Alert" interrupt is enabled
  • Bit 1: ErrIEn=1 - Error interrupt is enabled
  • Bit 0: TimerIEn=1 - Timer interrupt is enabled

The bits in the register "ComIrqReg" have the following meaning:

  • Bit 7: Set1 - when written as 1, a bit value of 1 in bits 6-0 of the byte written set the corresponding register bit; when written as 0, bits 6-0 clear the corresponding register bit
  • Bit 6: TxIRq - Set when the last bit of Tx data has been sent
  • Bit 5: RxIRq - Set when the receiver detects the end of a valid data stream
  • Bit 4: IdleIRq - Set when the CommandReg changes the command field to the idle command
  • Bit 3: HiAlertIRq - Set when the Status1 register HiAlert bit is set
  • Bit 2: LoAlertIRq - Set when the Status1 register LoAlert bit is set
  • Bit 1: ErrIRq - Set when any bit in ErrorReg gets set
  • Bit 0: TimerIRq - Set when the TCounterValReg decrements to zero

Writing 0x14 to the "DivIEnReg" has the following meaning:

  • Bit 7: IRQPushPull=0 - IRQ is an open-drain output pin
  • Bit 6: reserved=0 - no known effect
  • Bit 5: reserved=0 - effect unknown
  • Bit 4: MfinActEn=1 - Allow the MFIN active interrupt request to trigger IRQ
  • Bit 3: reserved=0 - boundedly undefined
  • Bit 2: CRCIEn=1 - Permit the "DivIrqReg" bit CRCIRq to trigger IRQ
  • Bit 1: reserved=0 - do not set to 1 on pain of nothing
  • Bit 0: reserved=0 - has no purpose other than to confuse

The register "DivIrqReg" corresponds to "DivIrqEn", and has the following bit definitions:

  • Bit 7: Set2 - when written as 1, a bit value of 1 in bits 6-0 of the byte written set the corresponding register bit; when written as 0, bits 6-0 clear the corresponding register bit
  • Bit 6: reserved - don't ask
  • Bit 5: reserved - don't tell
  • Bit 4: MfinActIRq - MFIN is active
  • Bit 3: reserved - just leave it at zero and back away slowly
  • Bit 2: CRCIRq - when 1, the CalcCRC command is active and all data is processed
  • Bit 1: reserved - nothing to see here
  • Bit 0: reserved - are you feeling lucky, punk?

The above register bit definitions were cribbed from the MFRC522 datasheet from NXP, titled "MFRC522 Standard performance MIFARE and NTAG frontend", Rev 3.9, 27-April-2016.

The library for the MFRC522 does have an interrupt example that uses a lighter weight means of polling the transceiver. see https://github.com/miguelbalboa/rfid/tree/master/examples/MinimalInterrupt, but it does not provide a means of waking your host from a low-power sleep mode when someone waves their magic ring over the hidden panel by the secret door, meaning that your secret lair will need to be wired to power the reader even if it is otherwise wireless; either that, or your henchmen will be forever changing batteries.


first of all, I apologize for the English, I can understand it but i use google translator to express myself in.

I don't use arduino, It's a interesting platform (for the ide, which is apparently object oriented programming POO), but extremely limited by the hardware

Well, entering the subject, I am also developing an implementation for the MRFC522, and the datasheet does not give examples of how do it, but indicates how enable interrupts (although I have not tried ,yet)

but if I'm not wrong, the following registers are involved:

ComIEnReg--> Control register bits to enable and disable the passing of interrupt requests.

DivIEnReg--> control bits to enable and disable the passing of interrupt requests.

ComIrqReg--> register Interrupt request bits. (I think it's read only)

DivIrqReg--> register bit descriptions (I think it's read only)

I think it's just properly setting the first two should be able to generate the interrupt on the pin irq. i don't know if the following is correct.

set ComIEnReg to --> (in binary) 0b01111111 //enables all al interrupts

set DivIEnReg to --> 0b10000100 //I don't understand complete about MFIN (bit4) and set it to 0 but i set CRCIEn to 1 (bit 2) and bit7 to 1 "pin IRQ is a standard CMOS output pin"

// the different posible configuration to DivIEnReg

  • yours--> 0b00010100 -->0x14
  • try 1 --> 0b00000100 -->0x04
  • try 2 --> 0b10010100 -->0X94
  • try 3 --> 0b10000100 -->0X84

if you manage to the module to do the interruption, it would be kind enough to comment on how you did

  • Unfortunatelly I was unable to use the IRQ pin. My project is stopped right now but I'll get back to it in a little and maybe figure it out. I'm pooling the module to check for a new tag for now and for what I read back then seem like no one was able to use the interruption to detect new tags. I agree with you on the Arduino, it's very limited but as I'm only working on a POC (proof of concept), is the perfect platform!
    – Gus Campos
    Commented Aug 14, 2015 at 5:49
  • As you mentioned "Arduino is limited" can you share other alternatives. Would like to explore them as-well. I am completely from the software side, and would like to understand this more.
    – karx
    Commented Jan 27, 2018 at 20:06

Not the answer you're looking for? Browse other questions tagged or ask your own question.