RFID ReaderPreview Introduction I recently got a couple cheap RFID reader boards from Amazon to experiment with for a bigger project. One of them was based on an MFRC522 chip and the second was PN532. Based on the way the chips worked, the MFRC522 was more register based while the PN532 seemed to be "packeted", I decided to try the MFRC522 first. Both chips are SPI based so I decided it would be easiest to get them working with an MSP430 in assembly language. The big project goal for this would eventually be ESP32 written in C++, but just to figure out how the chips work, it's typically easier for me on the MSP430. Probably the typical user of the boards that I found are someone doing Arduino who will just use someone else's prewritten module to interface with their own code, but for this project, it was required to learn how to communicate directly to the raw chip. After trying to figure out which registers needed to be set to do what and looking at some... kind of unfun looking sample code for this chip online... I decided that life was too short and moved on to the MFRC522. To any hardware manufacturer that sells sensors like this... any sensor... it's highly recommended to add to the data sheet a list of the absolute minimum amount of registers that need to be set and some common values. Engineers want to spend time on their own code, not trying to figure out which strange combination of pizza toppings they need in order to make some sensor work. Explanation For the projects this is being used for, SPI is being used. So all examples here are assuming SPI mode. Beware: unlike normal SPI, this bus sends data least significant bit first. The SPI bus must be configured for it. Also, in SPI mode, an extra byte has to be sent before the data packet to let the PN532 if it's reading, writing, or wants a status. The PN532 transfers data using packets. The packets follow the following format:
PREAMBLE: 0x00
START CODE: 0x00 0xff
LEN: (1 byte counting TFI and all the data bytes)
LCS: (1 byte length checksum where LEN + LCS = 0x00)
TFI: (1 byte frame identifier 0xd4 for host to PN532 or 0xd5 PN532 to host)
DATA: (len - 1 bytes of data)
DCS: (1 byte data checksum: TFI + [PD0 + PD1 + ... + PDn] + DCS = 0x00)
POSTAMBLE: 0x00
The first packet sent to config the chip is SAM_CONFIGURATION. This packet sets up the chip for normal mode (0x01), a timeout of 0x14, and IRQ setting of 1 which means the PN532 uses the IRQ pin:
const uint8_t PN532::packet_sam_config[] =
{
0x00, 0x00, 0xff,
5, lcs,
0xd4, PN532_CMD_SAM_CONFIGURATION, 0x01, 0x14, 0x01,
dcs, 0x00
};
The IRQ pin stays high when idle but goes low when the PN532 wants to send data to the host. To test things are working properly, the GET_FIRMWARE_VERSION packet is used to confirm communication is working.
const uint8_t PN532::packet_get_firmware_version[] =
{
0x00, 0x00, 0xff,
2, lcs,
0xd4, PN532_CMD_GET_FIRMWARE_VERSION,
dcs, 0x00,
0
};
Source code
Copyright 1997-2025 - Michael Kohn
|