I'm trying to port the MFRC522 Arduino library (from GitHub) to the ARM MCUs. My problem is with the PCD_ReadRegister function:

 * Reads a number of bytes from the specified register in the MFRC522 chip.
 * The interface is described in the datasheet section 8.1.2.
void MFRC522::PCD_ReadRegister( byte reg,       ///< The register to read from. One of the PCD_Register enums.
                                byte count,     ///< The number of bytes to read
                                byte *values,   ///< Byte array to store the values in.
                                byte rxAlign    ///< Only bit positions rxAlign..7 in values[0] are updated.
                                ) {

    if (count == 0) {
    //Serial.print(F("Reading "));  Serial.print(count); Serial.println(F(" bytes from register."));
    byte address = 0x80 | (reg & 0x7E);     // MSB == 1 is for reading. LSB is not used in address. Datasheet section
    byte index = 0;                         // Index in values array.
    SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV4, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
    digitalWrite(_chipSelectPin, LOW);      // Select slave
    count--;                                // One read is performed outside of the loop
    SPI.transfer(address);                  // Tell MFRC522 which address we want to read
    while (index < count) {
        if (index == 0 && rxAlign) {        // Only update bit positions rxAlign..7 in values[0]
            // Create bit mask for bit positions rxAlign..7
            byte mask = 0;
            for (byte i = rxAlign; i <= 7; i++) {
                mask |= (1 << i);
            // Read value and tell that we want to read the same address again.
            byte value = SPI.transfer(address);
            // Apply mask to both current value of values[0] and the new data in value.
            values[0] = (values[index] & ~mask) | (value & mask);
        else { // Normal case
            values[index] = SPI.transfer(address);  // Read value and tell that we want to read the same address again.
    values[index] = SPI.transfer(0);            // Read the final byte. Send 0 to stop reading.
    digitalWrite(_chipSelectPin, HIGH);         // Release slave again
    SPI.endTransaction(); // Stop using the SPI bus

} // End PCD_ReadRegister()

I read the datasheet several times & can't understand what's the function of this parameter! Based on datasheet for reading a register from rc522: enter image description here

1 Answer 1


Concerning the image in your post about 'SPI Read Data', that simply says the first byte received over MISO is discarded, which is done in PCD_ReadRegister() right before the for loop, and then n bytes are read, with 0 transferred the last time to stop reading.

A quick look at the library and datasheet shows that the rxAlign argument is used in identifying the first valid bit in the first received byte. txLastBits serves a similar purpose, only for transmission of the final byte. Both are written to BitFramingReg of the MFRC522 and are necessary for bit-oriented frames between the MFRC522 and a card/tag.

For example, in the function you have above, if rxAlign = 3, it means only bits 7 to 3 are valid in the first received byte, extracted with bit mask 11111000. So the first valid 'byte' comprises bits 7 to 3 of the first received byte concatenated with bits 2 - 0 of the next received byte. Similarly, in transmission, txLastBits indicates the number of bits of the last byte that are to be transmitted to the card/tag. In both cases, what is transmitted or received over the RF field may not be a multiple of 8, hence the need for these arguments and BitFramingReg.

Anyways, this shouldn't interfere at all with porting the library. Simply replace the Arduino-specific functions/interfaces and allow the library's existing logic to remain as is.


I'll try to answer your questions:

  • In this context, 106kBd refers to the data rate between the RC522 and a card, and not between the RC522 and the MCU. The maximum is about 848kBd, i think. Check the datasheet for more details.
  • Bit-oriented frames are necessary for the anti-collision process. Superimposed bits in the Manchester encoding, when several cards attempt to communicate with the RC522 at once, require that individual bits be processed as opposed to the usual byte-sized units. Look up anti-collision techniques.
  • Anticollision is necessary if the same reader will possibly have multiple tags within its range. From an IEEE article:

Tag collisions can impose a major inefficiency in RFID systems, resulting in low identification rates, short reading range and ineffective resource utilization. They are more problematic in passive tags due to limitations on power and functionality.

So, if you will be presenting only one card at a time, then you should be safe without implementing anticollision in your code. Else, I'm afraid you have no choice unless you want to confuse the reader.

If all you want to do is read UIDs and read from/write to blocks on a card (one at a time), you may want to try porting this straightforward MFRC522 UART library, which doesnt implement anitcollision, by the way.

If you still want to port the SPI-based library, then, a few suggestions:

You want to replace the SPI interface with UART. This is low-level stuff, all contained within a few functions like PCD_ReadRegister(), PCD_WriteRegister() and a few others. These functions serve higher-level functions, which have no clue of their internal implementation, but expect certain behaviour from them. Swap the SPI functions for their UART equivalents, as soon as you understand how to talk to the reader over UART. Once your ARM UART functions behave exactly like the SPI functions, your work is almost done; there is no need to learn the reason for everything in the higher-level functions since they dont relate to anything interface-specific. This includes everything concerning rxAlign and whatnot. Good luck :).

  • Dear Tiste,Really thanks for your great description.Problem is that i must changed libraries used connection peripheral from SPI to UART.3 new question:1-Based on Datasheet page 46-table 48:These bits are only to be used for bitwise anticollision at 106 kBd, for all other modes they are set to 0.then for default 9600 baud rate in uart can i avoid this?2-second question is i understand what is do,but i don't know why we do this yet?why bytes are not formed as usual and are not valid from first bit?why there are avoidable bits in the beginning of data stream?3-is this necessary in UART mode too?
    – Mahmoud HD
    Commented Mar 14, 2016 at 7:11
  • @MahmoudHD I've edited my answer. Commented Mar 15, 2016 at 0:00
  • @MahmoudHD Does this help? Have you gotten past this? Commented Mar 17, 2016 at 14:55
  • Dear Tiste,Really appreciated you for your great guidance,I'm trying hard to port an official SPI arduino library of this chip to my target MCU,I will be place to new question here,WBR.
    – Mahmoud HD
    Commented Mar 17, 2016 at 19:52
  • @MahmoudHD You arent porting to UART anymore? Commented Mar 17, 2016 at 20:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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