Rc522 and Pn532 Rfid Basics
Rc522 and Pn532 Rfid Basics
Rc522 and Pn532 Rfid Basics
by Boomer48
Some time ago I bought three different RFID modules a sequence of steps required to talk to the modules
for experimenting. In a previous project I detailed how and to the RFID tags. While there are lots of example
to use a simple 125-kHz module to do a basic programs online for the modules, most of them are
security function. Modules like that use read-only tags written in ‘C’ software for the Arduino and use the SPI
so the process is scan for the ID, store if desired, and interface. Also, the manuals for the chips and for the
compare against stored ID’s. The other modules I Mifare tags take a bit of deciphering. This post is
bought operate at 13.56-MHz and use tags that can primarily about the information I wish I had when I
be both read and written so it’s kind of a waste to started the project. I also include PIC assembly
simply use them for basic security. The two common software programs for performing the basic
modules use either the RC522 chip or the PN532 commands required by each module. Even if you
chip – both made by NXP. don’t use a PIC and/or assembly language, the
source code should at least provide you with a good
If you’ve read any of my other projects you know that idea of the specific commands required to perform
I like to use cheap PIC microcontrollers and program each step.
in assembly language. So what I was looking for was
Both of the chips used on these modules are capable Technically the EA pin should then be connected to
of interfacing via SPI, I2C, or UART (HSSP). The ground but not many people can pull off that soldering
PN532 module has a DIP switch that is used to select feat given the chip pin density. Not to worry, though,
the desired interface but the MFRC522 module is because the EA pin does not have an internal pull-up
hardwired for the SPI interface. I prefer to use the and doesn’t “float” like the old TTL logic inputs do.
built-in UART of the PIC, so I hunted online to see if Refer to the chip diagram and the board section
there was a way to get the MFRC522 module into the picture for the spot to cut. Make sure that you only cut
UART mode. What I found was that cutting one trace the short trace going directly to the EA pin.
on the board would do the trick. The cut effectively
removes 3.3 volts from the EA pin of the chip.
The hardware connections for UART communications The LCD connection is the standard 4-bit setup that
are shown in the diagram above. The UART has been used in a number of my previous projects.
connections for the MFRC522 are not marked on the The default format for all of the messages is set for
board but, as shown in the schematic, the SDA pin the standard 1602 LCD (16 characters by 2 lines). I
receives UART data and the MISO pin transmits also have a 40 character by 2 line LCD that I use for
UART data. The PN532 module has the UART raw data dumps during debugging so I included a
markings on the bottom side of the board. define in the software that allows me to take
advantage of the extra display space.
Both modules run on 3.3 volts and the 5-volt logic
level from the PIC TX pin also needs to be limited.
The Mifare Classic 1k tags used for this project are just the data blocks in that sector so you could have
configured as 16 sectors, four data blocks per sector, different keys and access rules for each sector. The
16 bytes per data block. Of the 64 data blocks, only default keys are set to “FF FF FF FF FFh”. For this
47 are actually usable. Data block 0 contains basic project I use just one data block and keep the
manufacturer data and blocks 3, 7, 11, 15, 19, 23, 27, default keys and access bits. There are lots of
31, 35, 39, 43, 47, 51, 55, 59, and 63 are called documents related to these cards so just do an online
Trailer blocks. The Trailer blocks are the last one in search for “Mifare” or visit the NXP website if you
each sector and they contain two keys and the block want to explore them in more depth.
access bits. The keys and block access bits apply to
While both modules are unique in the way that they that we may need to send another command to get its
are accessed and the way they access the tags, there UID. The UID is four bytes for the Mifare Classic 1k
is a general process that is required to get the job tags. If may be longer for other tags but this project
done. For this project we assume that the tags are the doesn’t address them.
Mifare Classic 1k type and that we are only allowing
one tag at a time in the antenna field. The basic steps · Select the tag (522 only): The UID is used to select
are defined below. the tag that the user wants to authenticate for reads
and writes. This is based on the possibility that there
· Initialize the module: In general this requires things may be more than one tag in the antenna field. That
such as writing values to registers in the chip, is not the case for our simple application but we need
sending “wakeup” commands, and turning power on to select the tag anyway.
to the antenna. In a battery operated application you
would want to be able to turn the antenna power on · Authenticate the tag: This step is required if we want
and off to save the battery but for this simple to do any reading or writing of the tag. If all we want
application we turn it on once and then leave it on. to do is to differentiate between tags for a simple
security application then the UID is enough.
· Clear the crypto flag (522 only): When a tag is Authentication requires that we know the UID and
authenticated a flag gets set to let the user know that that we know the crypto key for the data sector of the
communications with the tag will be encrypted. This tag we want to access. For this project we stick with
flag needs to be cleared by the user prior to the next the default keys but my follow-on project changes the
scan, even if the tag being scanned is the same one. keys so that the tag can be used as an electronic
wallet.
· Scan for a tag: The module basically asks “Is
anyone out there?” and the tag responds “I’m here”. If · Read or write the tag: Reads always return all 16
the module doesn’t get a quick response it stops bytes of the Data Block requested. Writes require that
listening. That means that we need to repeatedly all 16 bytes be written at the same time. If you want to
send scan commands to the module until it finds a read or write another block in the same data sector
tag. the tag does not need to be authenticated again. If
you want to read or write a block in a different data
· Get the tag User Identification number (UID): The sector then the tag needs to be authenticated again
tag will respond to the scan request with some limited using the key for that sector.
information such as the type of tag it is. That means
The startup routine includes these basic steps found hardware and software resets and neither fixed the
in most of the applications I looked at: problem. My solution was to add a dummy read call
to register “0” (undefined) at the start of the module
· Send dummy data byte (see the next paragraph) initialization routine. If the module sees this as data
for the unknown write command there doesn’t appear
· Soft reset to be any ill effects. If it sees it as a read command,
then nothing useful happens. It bothers me that I can’t
· Set RF receiver gain (if something other than the fully define the issue, especially given that a
default is desired) hardware reset of just the module doesn’t fix the
problem.
· Set ASK modulation percentage to 100%
The RC522 chip is composed of a number of
· Set seed value for CRC calculations registers, most of which are both read and write. To
perform a write, the register number is sent to the
· Turn on the antenna module followed by the value to write. To perform a
read, the register number has 0x80 added to it and
· Get firmware version (not required) that is sent to the module. The response to a write
command is an echo of the register accessed. The
For some unexplained reason my module powers up response to a read command is the contents of the
and thinks that it has received a write command register. The software takes advantage of that
without the data byte. I don’t know if this is just an knowledge to verify that the command was properly
issue with my module but I haven’t seen any executed.
references to it elsewhere. I experimented with both
The startup routine includes these required steps: the TFI. That consistency allows for the response
messages to be easily scanned for the relevant
· Send an initialization string: This is specific to the information.
UART interface. The manual states that the UART
interface will wake-up on the fifth rising edge detected Each command message (following the preamble)
on the interface. It recommends sending 0x55, 0x55, consists of the message length, the 2’s complement
0x00, 0x00, 0x00, 0x00. For the most part, there just of the message length, TFI, command, data,
needs to be a sufficient number of characters with checksum, and postamble. The software builds the
rising edges and they must not look like a command individual commands and then calls a routine that
preamble (00 00 FF). calculates the checksum and appends the postamble.
· Wake up the module: Buried in the user manual it The message format for the response is similar to that
shows that the module initializes into a sort of sleep
of the command. A typical response will include an
state called “LowVbat”. To exit this state we need toACK (00 00 FF 00 FF 00) followed by the specific
send a “SAMConfiguration” command. response to the command. Each command response
begins with a preamble of 00 00 FF. The response
The PN532 expects commands to be sent in a should also have a TFI byte of D5 followed by the
defined message format that includes a preamble, the command number incremented by 1. For our
message, and a postamble. The response messages “SAMConfiguration” command (14) that would be 15.
follow the same format. The command and response The “SAMConfiguration” command gets this
messages both include a TFI (Frame Identifier) and a response: 00 00 FF 00 FF 00 00 00 FF 02 FE D5 15
command version. The command uses a TFI of 0xD4 16 00.
and the response uses 0xD5. The command versions
vary but the response will always increment the There are other module-specific commands that can
command version and return it in the byte following be sent but they aren’t needed for this application. I
did, however, include a routine that can be called to FA D5 03 32 01 06 07 E8 00. The “01 06 07”
retrieve the firmware version number. A typical indicates firmware version number 1.6.7.
response (after the ACK and preamble) would be: 06
After the module gets ready, we can send commands are always done on all 16 bytes in a specified data
specific to the tags. In order to read or write tag data block. That means that the typical application will
we need to have its identification number (UID). The read the data block, modify the data as desired, and
UID and key will then be used to authorize a specific then a write the new data back to the tag.
tag data sector for reads/writes. Tag data reads/writes
The interrupt handler software gets called whenever There isn’t a need to clear the receive buffer or
the PIC UART receives a byte of data. In some of my Byte_Count because clearing the New_Msg flag will
previous UART projects I was able to just poll the RX cause Byte_Count to get cleared by the interrupt
interrupt flag instead of having to use an interrupt handler and that is what is used as the index into the
handler. That is not the case for this software, buffer. New_Msg usually gets cleared before each
especially for the PN532 which communicates at a command step so that the results specific to that
much higher baud rate than the RC522. The UART command can be easily located and verified. In the
interface of the RC522 is limited to 9600 baud while RC522 that means that the receive buffer usually has
the default for the PN532 is 115k and can be set as only 1 to 4 bytes. In some cases, such as data block
high as 1.288M baud. The received bytes are stored reads, the Read_FIFO command must be issued
in a buffer area and the main part of the software multiple times in order to move the bytes from the
retrieves them as needed. FIFO into the receive buffer. All command results for
the PN532 end up in the receive buffer so a scan
The New_Msg flag indicates that bytes have been procedure is performed to locate the specific bytes
received and Byte_Count indicates how many. I’ve needed.
included a “Disp_Buff” routine in the software that can
be called to display the contents of the receive buffer The main loop in the software scans for a tag and
during debugging. Some of the return messages will then authenticates the tag for reads/writes. For the
overflow a typical 1602 display but I have a 40 test software included here the variable Junk_Num is
character by 2 line LCD that I found at an online modified each time through the main loop and is used
surplus electronics site. The “Max_Line” define can during the write to the tag. The values written
be set for your LCD size. If “Max_Line” is reached, alternate between the value of Junk_Num and the 1’s
the “Disp_Buff” routine continues by writing to the complement of Junk_Num. Finally, the 16 written
second line. You could add a little code to that routine values are read and displayed. There are display
to continue onto lines three and four if you have a 4- messages for each step with delay routine calls to
line LCD. For the PN532 there is a flag that can be allow time to read each message. Error messages
set so that the routine either dumps all received bytes are also provided but should normally only occur if
or just dumps the 16 data bytes from a read the tag is removed during an operation.
response.
Part of the software initialization is a section of code routine which simply enables the Watchdog Timer
that is only executed on power up and is skipped if a and then goes into an infinite loop waiting for the
software reset is detected. The error messages timeout.
generally terminate with a software reset as a way to
exit the main loop. The reset happens in the “Tilt”
The RC522 chip requires more low-level instructions · Read the CRC registers and write the checksum
than the PN532 chip to accomplish communications bytes to the FIFO
with tags. It’s kind of like programming in assembly
language versus programming in “C”. Another · Send either a Transceive or Authenticate command
significant difference is that the RC522 requires that
communications with the tag get funneled through a The Transceive command will transmit the FIFO
FIFO buffer. The routines “Write_FIFO” and buffer and then automatically switch to receive mode
“Read_FIFO” handle those tasks. The MFRC522 to wait for the response from the tag. The Transceive
software includes a section for many of the lower- command must be followed by the setting of the
level commands from which the main functions are StartSend bit in the BitFramingRegister in order to
built. actually transmit the data. The Authenticate
command doesn’t have that requirement.
The tag command checksum calculation for the
RC522 is very different than for the PN532. After the In general, the Arduino “C” code applications
tag command is built in the FIFO, a module command available online use the interrupt flag registers and
is sent to calculate the checksum. The 16-bit result is the timeout register to ensure that the correct
not automatically appended to the tag command but response is received in a timely fashion. In my
is available for reading from two 8-bit registers. The opinion that is overkill for this non-time critical
checksum calculation wipes out the data in the FIFO application. Instead, I use short software timeouts to
so the required sequence is as follows: wait for the response and then verify that it is correct.
The manual for the Mifare tags details the timing for
· Build the command in the FIFO the various transactions and time is also allowed for
the expected number of bytes to be received. These
· Command a checksum calculation time delays are built into most of the low-level
command subroutines.
· Build the command in the FIFO again
Download
https://www.instructables.com/ORIG/FEO/EV2S/JT2SMF70/FEOEV2SJT2SMF70.odt
…
After the module is initialized, the steps needed to is appended to the command string just before the
find and authenticate the tag are accomplished by postamble.
writing the appropriate command followed by the
necessary data. The scan command returns the UID There is no FIFO like in the RC522 so the complete
which is then used for the authentication. After that, response messages are received automatically. The
reads and writes of the tag send or return the 16- “Find_Response” routine scans the receive data
bytes for the addressed data block. buffer for the TFI (0xD5). The routine takes advantage
of knowing what the expected messages should be
The initialize sequence was detailed earlier and the and ignores simple ACK responses that don’t include
same software routine also sends the data. Once the TFI is found, the desired responses
SAMConfiguration command to get the module out of are a known offset from it. The command echo and
the “LowVbat” state. The rest of the basic commands, command status bytes are saved off by the
such as Scan, Authenticate, Read/Write Tag, are just “Read_Buff” routine for later verification.
built sequentially in the applicable routines. The
checksum is calculated by just adding up the That’s it for this post. Check out my other electronics
command bytes, doing a complement, and then projects at: www.boomerrules.wordpress.com
adding 1 to make it a 2’s complement. The 8-bit result
Download
https://www.instructables.com/ORIG/FW4/TLYQ/JT2SMF6X/FW4TLYQJT2SMF6X.odt
…