{"id":768,"date":"2022-02-15T04:54:50","date_gmt":"2022-02-15T04:54:50","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=768"},"modified":"2022-02-15T04:54:52","modified_gmt":"2022-02-15T04:54:52","slug":"working-with-stm32-and-rc522-rfid-reader-spi-based-module","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=768","title":{"rendered":"Working with STM32 and RC522 RFID reader: SPI based module"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img decoding=\"async\" src=\"https:\/\/cdn.sick.com\/media\/content\/he4\/h1b\/10817580793886.jpg\" alt=\"\" \/><\/figure><\/div>\n\n\n\n<p class=\"has-text-align-left\">In this article, we will took at the RFID and how it does work and use RC522 to read RFID tag and display the tag ID on I2C LCD.<\/p>\n\n\n\n<p>In this article, we will cover the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>What is RFID.<\/li><li>RC522 RFID module.<\/li><li>Connection with STM32.<\/li><li>Code.<\/li><li>Demo.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. What is RFID:<\/h2>\n\n\n\n<p class=\"has-text-align-left\">RFID (radio frequency identification) is a form of\u00a0wireless\u00a0communication that incorporates the use of electromagnetic or electrostatic coupling in the radio frequency portion of the electromagnetic spectrum to uniquely identify an object, animal or person.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How does RFID work?<\/h3>\n\n\n\n<p>Every RFID system consists of three components: a scanning\u00a0antenna, a\u00a0transceiver\u00a0and a\u00a0transponder. When the scanning antenna and transceiver are combined, they are referred to as an RFID reader or interrogator. There are two types of RFID readers &#8212; fixed readers and mobile readers. The RFID reader is a network-connected device that can be portable or permanently attached. It uses radio\u00a0waves to transmit signals that activate the tag. Once activated, the tag sends a wave back to the antenna, where it is translated into data.<\/p>\n\n\n\n<p>The transponder is in the RFID tag itself. The read range for RFID tags varies based on factors including the type of tag, type of reader, RFID frequency and interference in the surrounding environment or from other RFID tags and readers. Tags that have a stronger power source also have a longer read range.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>For more information, please check this youtube video (<a rel=\"noreferrer noopener\" href=\"https:\/\/www.youtube.com\/watch?v=Ukfpq71BoMo\" data-type=\"URL\" data-id=\"https:\/\/www.youtube.com\/watch?v=Ukfpq71BoMo\" target=\"_blank\">here<\/a>).<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2.1 RC522 RFID module:<\/h2>\n\n\n\n<p>The RC522 RFID module based on\u00a0<a href=\"https:\/\/www.nxp.com\/products\/identification-and-security\/nfc\/nfc-reader-ics\/standard-performance-mifare-and-ntag-frontend:MFRC52202HN1\">MFRC522 IC from NXP<\/a>\u00a0is one of the most inexpensive RFID options that you can get online for less than four dollars. It usually comes with a RFID card tag and key fob tag having 1KB memory. And best of all, it can write a tag, so you can store your some sort of secret message in it.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.direnc.net\/rc522-rfid-okuyucu-1356mhz-en-wireless-communication-china-20893-36-B.jpg\" alt=\"\" width=\"563\" height=\"563\" \/><\/figure><\/div>\n\n\n\n<p>he RC522 RFID Reader module is designed to create a 13.56MHz electromagnetic field that it uses to communicate with the RFID tags (ISO 14443A standard tags). The reader can communicate with a microcontroller over a 4-pin Serial Peripheral Interface (<strong>SPI<\/strong>) with a maximum data rate of&nbsp;<strong>10Mbps<\/strong>. It also supports communication over I2C and UART protocols.<\/p>\n\n\n\n<p>The module comes with an interrupt pin. It is handy because instead of constantly asking the RFID module \u201cis there a card in view yet? \u201c, the module will alert us when a tag comes into its vicinity.<\/p>\n\n\n\n<p>The operating voltage of the module is from\u00a0<strong>2.5 to 3.3V<\/strong>, but the good news is that the\u00a0<strong>logic pins are 5-volt tolerant<\/strong>, so we can easily connect it to any 5V logic microcontroller without using any logic level converter.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Here are complete specifications:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><tbody><tr><td>Frequency Range<\/td><td>13.56 MHz ISM Band<\/td><\/tr><tr><td>Host Interface<\/td><td>SPI \/ I2C \/ UART<\/td><\/tr><tr><td>Operating Supply Voltage<\/td><td>2.5 V to 3.3 V<\/td><\/tr><tr><td>Max. Operating Current<\/td><td>13-26mA<\/td><\/tr><tr><td>Min. Current(Power down)<\/td><td>10\u00b5A<\/td><\/tr><tr><td>Logic Inputs<\/td><td>5V Tolerant<\/td><\/tr><tr><td>Read Range<\/td><td>5 cm<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2.2 RC522 pinout:<\/h2>\n\n\n\n<p>The RC522 module has total 8 pins that interface it to the outside world. The connections are as follows:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img decoding=\"async\" src=\"https:\/\/www.electrovigyan.com\/wp-content\/uploads\/2021\/04\/pinout.jpg\" alt=\"\" \/><\/figure><\/div>\n\n\n\n<figure class=\"wp-block-table aligncenter is-style-stripes\"><table><tbody><tr><td class=\"has-text-align-center\" data-align=\"center\">Pin<\/td><td class=\"has-text-align-center\" data-align=\"center\">Description <\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">VCC<\/td><td class=\"has-text-align-center\" data-align=\"center\">supplies power for the module. This can be anywhere from 2.5 to 3.3 volts. You can connect it to 3.3V output. Remember connecting it to 5V pin will likely destroy your module!<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">RST<\/td><td class=\"has-text-align-center\" data-align=\"center\">an input for Reset and power-down. When this pin goes low, hard power-down is enabled. This turns off all internal current sinks including the oscillator and the input pins are disconnected from the outside world. On the rising edge, the module is reset.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">GND<\/td><td class=\"has-text-align-center\" data-align=\"center\">the Ground Pin and needs to be connected to GND pin on the Arduino.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">IRQ<\/td><td class=\"has-text-align-center\" data-align=\"center\">pin acts as Master-In-Slave-Out when SPI interface is enabled, acts as serial clock when I2C interface is enabled and acts as serial data output when UART interface is enabled.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">MISO<\/td><td class=\"has-text-align-center\" data-align=\"center\">is SPI input to the RC522 module.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">MOSI<\/td><td class=\"has-text-align-center\" data-align=\"center\">\u00a0is SPI input to the RC522 module.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">SCK<\/td><td class=\"has-text-align-center\" data-align=\"center\">accepts clock pulses provided by the SPI bus Master.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">SS<\/td><td class=\"has-text-align-center\" data-align=\"center\">pin acts as Signal input when SPI interface is enabled, acts as serial data when I2C interface is enabled and acts as serial data input when UART interface is enabled. This pin is usually marked by encasing the pin in a square so it can be used as a reference for identifying the other pins.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">3. Connection with STM32F446 Nucleo:<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"660\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/Screen-Shot-2022-02-15-at-7.34.12-AM-1024x660.png\" alt=\"\" class=\"wp-image-770\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/Screen-Shot-2022-02-15-at-7.34.12-AM-1024x660.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/Screen-Shot-2022-02-15-at-7.34.12-AM-300x193.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/Screen-Shot-2022-02-15-at-7.34.12-AM-768x495.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/Screen-Shot-2022-02-15-at-7.34.12-AM-1536x990.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/Screen-Shot-2022-02-15-at-7.34.12-AM-2048x1320.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/Screen-Shot-2022-02-15-at-7.34.12-AM-1150x741.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/Screen-Shot-2022-02-15-at-7.34.12-AM-750x483.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/Screen-Shot-2022-02-15-at-7.34.12-AM-400x258.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/Screen-Shot-2022-02-15-at-7.34.12-AM-250x161.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-table is-style-regular\"><table><tbody><tr><td>RC522<\/td><td>STM32F446 Nucleo<\/td><\/tr><tr><td>Vcc<\/td><td>3V3<\/td><\/tr><tr><td>RST<\/td><td>PA8 (D7)<\/td><\/tr><tr><td>GND<\/td><td>GND<\/td><\/tr><tr><td>MOSI<\/td><td>PA7 (D11)<\/td><\/tr><tr><td>MISO<\/td><td>PA6 (D12)<\/td><\/tr><tr><td>SCK<\/td><td>PA5 (D13)<\/td><\/tr><tr><td>CS<\/td><td>PB0 (A3)<\/td><\/tr><tr><td>IRQ<\/td><td>Not connected<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">4. Code:<\/h2>\n\n\n\n<p>We start off by configuring SPI as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\nvoid SPI_Init(void)\n{\n\t#define AF5 0x05\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN; \/\/enable clock forn gpio a\n\tRCC-&gt;APB2ENR|=RCC_APB2ENR_SPI1EN; \/\/enable clock for spi1\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE5_1|GPIO_MODER_MODE6_1|GPIO_MODER_MODE7_1;\n\tGPIOA-&gt;MODER&amp;=~(GPIO_MODER_MODE5_0|GPIO_MODER_MODE6_0|GPIO_MODER_MODE7_0);\n\tGPIOA-&gt;OSPEEDR|=GPIO_OSPEEDER_OSPEEDR5|GPIO_OSPEEDER_OSPEEDR6|GPIO_OSPEEDER_OSPEEDR7;\n\n\tGPIOA-&gt;AFR[0]|=(AF5&lt;&lt;20)|(AF5&lt;&lt;24)|(AF5&lt;&lt;28);\n\tSPI1-&gt;CR2=0;\n\tSPI1-&gt;CR1=SPI_CR1_SSM|SPI_CR1_MSTR|SPI_CR1_BR_2|SPI_CR1_SSI|SPI_CR1_SPE;\n}\n<\/pre><\/div>\n\n\n\n<p>Then SPI transmit as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\nint8_t SPI_Transmit(uint8_t *data, uint32_t size)\n{\n\n\n\tuint32_t i\t\t=0;\n\tuint8_t  temp\t=0;\n\tuint32_t start=millis();\n\ttemp =SPI1-&gt;DR;\n\ttemp=SPI1-&gt;SR;\n\twhile(i&lt;size)\n\t\t{\n\t\twhile(!((SPI1-&gt;SR)&amp;SPI_SR_TXE)){if(millis()-start&gt;1000){\n\t\t\tprintf(&quot;TXE timed out\\r\\n&quot;);\n\t\t\treturn -1;}} \/\/ wait to transmision buffer to be emplty\n\t\tSPI1-&gt;DR= data[i];\n\t\twhile(!(SPI1-&gt;SR&amp;SPI_SR_BSY)){if(millis()-start&gt;1000){printf(&quot;BSY timed out\\r\\n&quot;);return -1;}}\n\t\ti++;\n\t\t}\nwhile(!((SPI1-&gt;SR)&amp;SPI_SR_TXE)){if(millis()-start&gt;1000){printf(&quot;TXE2 time dout\\r\\n&quot;);return -1;}}\nwhile((SPI1-&gt;SR)&amp;SPI_SR_BSY){if(millis()-start&gt;1000){printf(&quot;BSY2 timed out\\r\\n&quot;); return -1;}}\ntemp =SPI1-&gt;DR;\ntemp=SPI1-&gt;SR;\nreturn 0;\n}\n<\/pre><\/div>\n\n\n\n<p>SPI receive function:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\nint8_t SPI_Receive(uint8_t *data, uint32_t size)\n{\nwhile(size)\n\t\t{\n\tuint32_t start=millis();\n\t\tSPI1-&gt;DR=0;\n\t\twhile(!(SPI1-&gt;SR&amp;SPI_SR_RXNE)){if(millis()-start&gt;200){return -1;}}\n\t\t*data++=(SPI1-&gt;DR);\n\t\t\tsize--;\n\t\t}\nreturn 0;\n}\n\n<\/pre><\/div>\n\n\n\n<p>Now for the RC522 initializing function as following: <\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\nvoid rc522_init(void)\n{\n\t\/*\n\t * STM32 -&gt;RFID\n\t * SPI  -&gt; SPI\n\t * PA8  -&gt;RST\n\t * PB0  -&gt;CS\n\t * *\/\n  SPI_Init();\n  GPIOA-&gt;MODER|=GPIO_MODER_MODE8_0;\n  GPIOA-&gt;MODER&amp;=~GPIO_MODER_MODE8_1;\n\n  RCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOBEN;\n\n  GPIOB-&gt;MODER|=GPIO_MODER_MODE0_0;\n  GPIOB-&gt;MODER&amp;=~GPIO_MODER_MODE0_1;\n  GPIOA-&gt;BSRR=GPIO_BSRR_BR8;\n  for(volatile int i=0;i&lt;100000;i++);\n  GPIOA-&gt;BSRR=GPIO_BSRR_BS8;\n  for(volatile int i=0;i&lt;100000;i++);\n  rc522_reset();\n\n  rc522_regWrite8(MFRC522_REG_T_MODE, 0x80);\n  rc522_regWrite8(MFRC522_REG_T_PRESCALER, 0xA9);\n  rc522_regWrite8(MFRC522_REG_T_RELOAD_L, 0xE8);\n  rc522_regWrite8(MFRC522_REG_T_RELOAD_H, 0x03);\n\n\n  rc522_regWrite8(MFRC522_REG_TX_AUTO, 0x40);\n  rc522_regWrite8(MFRC522_REG_MODE, 0x3D);\n\n  rc522_antennaON();   \/\/Open the antenna\n}\n\n<\/pre><\/div>\n\n\n\n<p>Register read and write:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\nuint8_t rc522_regRead8(uint8_t reg)\n{\n  spi_cs_rfid_write(0);\n  reg = ((reg &lt;&lt; 1) &amp; 0x7E) | 0x80;\n  SPI_Transmit(&amp;reg, 1);\n  uint8_t dataRd=0;\n  SPI_Receive(&amp;dataRd, 1);\n  spi_cs_rfid_write(1);\n  return dataRd;\n}\n\n\/**\n * @brief write register\n *\/\nvoid rc522_regWrite8(uint8_t reg, uint8_t data8)\n{\n  spi_cs_rfid_write(0);\n  uint8_t txData[2] = {0x7E&amp;(reg &lt;&lt; 1), data8};\n  SPI_Transmit(txData, 2);\n  spi_cs_rfid_write(1);\n}<\/pre><\/div>\n\n\n\n<p>other functions required:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">bool rc522_toCard(\n    uint8_t command,\n    uint8_t* sendData,\n    uint8_t sendLen,\n    uint8_t* backData,\n    uint16_t* backLen);\n\nbool rc522_request(uint8_t reqMode, uint8_t *tagType);\n\nbool rc522_antiColl(uint8_t* serNum);\n\nvoid spi_cs_rfid_write(bool state)\n{\n\tif(state)\n\t  {\n\t    GPIOB-&gt;ODR |= (1UL &lt;&lt; 0);\n\t  }\n\t  else\n\t  {\n\t    GPIOB-&gt;ODR &amp;= ~(1UL &lt;&lt; 0);\n\t  }\n}\n\n\/**\n * @brief set bit\n *\/\nvoid rc522_setBit(uint8_t reg, uint8_t mask)\n{\n  rc522_regWrite8(reg, rc522_regRead8(reg)|mask);\n}\n\n\/**\n * @brief clear bit\n *\/\nvoid rc522_clearBit(uint8_t reg, uint8_t mask)\n{\n  rc522_regWrite8(reg, rc522_regRead8(reg)&amp;(~mask));\n}\n\n\/**\n * @brief reset function\n *\/\nvoid rc522_reset(void)\n{\n  rc522_regWrite8(0x01, 0x0F);\n}\n\n\/**\n * @brief Antenna ON\n *\/\nvoid rc522_antennaON(void)\n{\n  uint8_t temp;\n\n  temp = rc522_regRead8(MFRC522_REG_TX_CONTROL);\n  if (!(temp &amp; 0x03)) {\n    rc522_setBit(MFRC522_REG_TX_CONTROL, 0x03);\n  }\n}\n\n\/**\n * @brief Check card\n *\/\nbool rc522_checkCard(uint8_t *id)\n{\n  bool status=false;\n  \/\/Find cards, return card type\n    status = rc522_request(PICC_REQIDL, id);\n    if (status == true) {\n      \/\/Card detected\n      \/\/Anti-collision, return card serial number 4 bytes\n      status = rc522_antiColl(id);\n    }\n    rc522_halt();      \/\/Command card into hibernation\n\n    return status;\n}\n\n\/**\n * @brief Request function\n *\/\nbool rc522_request(uint8_t reqMode, uint8_t *tagType)\n{\n  bool status=false;\n  uint16_t backBits;\n  rc522_regWrite8(MFRC522_REG_BIT_FRAMING, 0x07);\n  tagType[0] = reqMode;\n  status = rc522_toCard(PCD_TRANSCEIVE, tagType, 1, tagType, &amp;backBits);\n  if ((status != true) || (backBits != 0x10)) {\n    status = false;\n  }\n  return status;\n}\n\n\/**\n * @brief to Card\n *\/\nbool rc522_toCard(\n    uint8_t command,\n    uint8_t* sendData,\n    uint8_t sendLen,\n    uint8_t* backData,\n    uint16_t* backLen)\n{\n  bool status = false;\n  uint8_t irqEn = 0x00;\n  uint8_t waitIRq = 0x00;\n  uint8_t lastBits;\n  uint8_t n;\n  uint16_t i;\n\n  switch (command) {\n    case PCD_AUTHENT: {\n      irqEn = 0x12;\n      waitIRq = 0x10;\n      break;\n    }\n    case PCD_TRANSCEIVE: {\n      irqEn = 0x77;\n      waitIRq = 0x30;\n      break;\n    }\n    default:\n      break;\n  }\n\n  rc522_regWrite8(MFRC522_REG_COMM_IE_N, irqEn | 0x80);\n  rc522_clearBit(MFRC522_REG_COMM_IRQ, 0x80);\n  rc522_setBit(MFRC522_REG_FIFO_LEVEL, 0x80);\n\n  rc522_regWrite8(MFRC522_REG_COMMAND, PCD_IDLE);\n\n  \/\/Writing data to the FIFO\n  for (i = 0; i &lt; sendLen; i++) {\n    rc522_regWrite8(MFRC522_REG_FIFO_DATA, sendData[i]);\n  }\n\n  \/\/Execute the command\n  rc522_regWrite8(MFRC522_REG_COMMAND, command);\n  if (command == PCD_TRANSCEIVE) {\n    rc522_setBit(MFRC522_REG_BIT_FRAMING, 0x80);   \/\/StartSend=1,transmission of data starts\n  }\n\n  \/\/Waiting to receive data to complete\n  i = 100;  \/\/i according to the clock frequency adjustment, the operator M1 card maximum waiting time 25ms???\n  do {\n    \/\/CommIrqReg[7..0]\n    \/\/Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq\n    n = rc522_regRead8(MFRC522_REG_COMM_IRQ);\n    i--;\n  } while ((i!=0) &amp;&amp; !(n&amp;0x01) &amp;&amp; !(n&amp;waitIRq));\n\n  rc522_clearBit(MFRC522_REG_BIT_FRAMING, 0x80);     \/\/StartSend=0\n\n  if (i != 0)  {\n    if (!(rc522_regRead8(MFRC522_REG_ERROR) &amp; 0x1B)) {\n      status = true;\n      if (n &amp; irqEn &amp; 0x01) {\n        status = false;\n      }\n\n      if (command == PCD_TRANSCEIVE) {\n        n = rc522_regRead8(MFRC522_REG_FIFO_LEVEL);\n        uint8_t l = n;\n        lastBits = rc522_regRead8(MFRC522_REG_CONTROL) &amp; 0x07;\n        if (lastBits) {\n          *backLen = (n - 1) * 8 + lastBits;\n        } else {\n          *backLen = n * 8;\n        }\n\n        if (n == 0) {\n          n = 1;\n        }\n        if (n &gt; MFRC522_MAX_LEN) {\n          n = MFRC522_MAX_LEN;\n        }\n\n        \/\/Reading the received data in FIFO\n        for (i = 0; i &lt; n; i++) {\n          uint8_t d = rc522_regRead8(MFRC522_REG_FIFO_DATA);\n          if (l == 4)\n            printf(&quot;%02x &quot;, d);\n          backData[i] = d;\n        }\n        if (l==4)\n          printf(&quot;\\r\\n&quot;);\n        return status;\n      }\n    } else {\n      printf(&quot;error\\r\\n&quot;);\n      status = false;\n    }\n  }\n\n  return status;\n}\n\nbool rc522_antiColl(uint8_t* serNum)\n{\n  bool status;\n  uint8_t i;\n  uint8_t serNumCheck = 0;\n  uint16_t unLen;\n  \/\/for (i = 0; i &lt; 4; i++)\n\/\/    printf(&quot;Anticoll In %d: 0x%02x\\r\\n&quot;, i, serNum[i]);\n\n\n  rc522_regWrite8(MFRC522_REG_BIT_FRAMING, 0x00);    \/\/TxLastBists = BitFramingReg[2..0]\n\n  serNum[0] = PICC_ANTICOLL;\n  serNum[1] = 0x20;\n  status = rc522_toCard(PCD_TRANSCEIVE, serNum, 2, serNum, &amp;unLen);\n\n  \/\/for (i = 0; i &lt; 4; i++)\n\/\/      printf(&quot;Anticoll ToCard %d: 0x%02x\\r\\n&quot;, i, serNum[i]);\n\n  if (status == true) {\n    \/\/Check card serial number\n    for (i = 0; i &lt; 4; i++) {\n      serNumCheck ^= serNum[i];\n    }\n    if (serNumCheck != serNum[i]) {\n      status = false;\n    }\n  }\n  return status;\n}\n\nvoid rc522_halt(void)\n{\n  uint16_t unLen;\n  uint8_t buff[4];\n\n  buff[0] = PICC_HALT;\n  buff[1] = 0;\n  rc522_calculateCRC(buff, 2, &amp;buff[2]);\n\n  rc522_toCard(PCD_TRANSCEIVE, buff, 4, buff, &amp;unLen);\n}\n\nvoid rc522_calculateCRC(uint8_t*  pIndata, uint8_t len, uint8_t* pOutData)\n{\n  uint8_t i, n;\n\n  rc522_clearBit(MFRC522_REG_DIV_IRQ, 0x04);     \/\/CRCIrq = 0\n  rc522_setBit(MFRC522_REG_FIFO_LEVEL, 0x80);      \/\/Clear the FIFO pointer\n  \/\/Write_MFRC522(CommandReg, PCD_IDLE);\n\n  \/\/Writing data to the FIFO\n  for (i = 0; i &lt; len; i++) {\n    rc522_regWrite8(MFRC522_REG_FIFO_DATA, *(pIndata+i));\n  }\n  rc522_regWrite8(MFRC522_REG_COMMAND, PCD_CALCCRC);\n\n  \/\/Wait CRC calculation is complete\n  i = 0xFF;\n  do {\n    n = rc522_regRead8(MFRC522_REG_DIV_IRQ);\n    i--;\n  } while ((i!=0) &amp;&amp; !(n&amp;0x04));      \/\/CRCIrq = 1\n\n  \/\/Read CRC calculation result\n  pOutData[0] = rc522_regRead8(MFRC522_REG_CRC_RESULT_L);\n  pOutData[1] = rc522_regRead8(MFRC522_REG_CRC_RESULT_M);\n}\n\n\/**\n * @brief compare IDs\n *\/\nbool rc522_compareIds(uint8_t *idCurrent, uint8_t *idReference)\n{\n  uint8_t i;\n  for(i=0; i&lt;4;i++)\n  {\n    if(idCurrent[i] != idReference[i])\n    {\n      return false;\n    }\n  }\n  return true;\n}\n<\/pre><\/div>\n\n\n\n<p>In main.c file, we start by including the following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#include &quot;LiquidCrystal_PCF8574.h&quot;\n#include &quot;delay.h&quot;\n#include &quot;stdio.h&quot;\n#include &quot;rfid.h&quot;<\/pre><\/div>\n\n\n\n<p>delay is based on systick (from <a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=246\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=246\" target=\"_blank\">here<\/a>) and the lcd is i2c based one (<a href=\"https:\/\/blog.embeddedexpert.io\/?p=655\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=655\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>).<\/p>\n\n\n\n<p>variable to hold RFID code<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint8_t rfid_id[4];<\/pre><\/div>\n\n\n\n<p>hence main function and while loop as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">int main(void)\n\t\t{\n\t\t\/\/SysClockConfig();\n\t\tsystick_init_ms(16000000);\n\t\trc522_init();\n\t\tlcd_init();\n\t\tsetCursor(0,0);\n\t\tlcd_send_string(&quot;RFID RC522 with&quot;);\n\t\tsetCursor(7,1);\n\t\tlcd_send_string(&quot;STM32F4&quot;);\n\t\tsetCursor(0,2);\n\t\tlcd_send_string(&quot;EmbeddedExperIO&quot;);\n\t\tdelay(2000);\n\t\tlcd_clear();\n\t\twhile(1)\n\t\t\t\t{\n\t\t\t\tif(rc522_checkCard(rfid_id))\n\t\t\t\t\t\t\t{\n\n\t\t\t\t\t\t\tlcd_clear();\n\t\t\t\t\t\t\tchar data[20];\n\t\t\t\t\t\t\tsetCursor(0,0);\n\t\t\t\t\t\t\tlcd_send_string(&quot;RFID code is&quot;);\n\t\t\t\t\t\t\tsetCursor(0,1);\n\t\t\t\t\t\t\tsprintf(data,&quot;0x%x 0x%x 0x%x 0x%x&quot;,rfid_id[0],rfid_id[1],rfid_id[2],rfid_id[3]);\n\t\t\t\t\t\t\tlcd_send_string(data);\n\t\t\t\t\t\t\tdelay(1000);\n\t\t\t\t\t\t\t}\n\t\t\t\tdelay(100);\n\t\t\t\t}\n\n\t\t}\n<\/pre><\/div>\n\n\n\n<p>you may download the code from here<\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/RFID.zip\">RFID<\/a><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/RFID.zip\" class=\"wp-block-file__button\" download>Download<\/a><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">5. Results:<\/h2>\n\n\n\n<p>Once the code is compiled and uploaded to MCU, place a card on the module and the result shall appear as following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/IMG_7905-1024x768.jpg\" alt=\"\" class=\"wp-image-772\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/IMG_7905-1024x768.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/IMG_7905-300x225.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/IMG_7905-768x576.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/IMG_7905-1536x1152.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/IMG_7905-2048x1536.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/IMG_7905-1150x863.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/IMG_7905-750x563.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/IMG_7905-400x300.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/02\/IMG_7905-250x188.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding \ud83d\ude42 <\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this article, we will took at the RFID and how it does work and use RC522 to read RFID tag and display the tag ID on I2C LCD. In this article, we will cover the following: What is RFID. RC522 RFID module. Connection with STM32. Code. Demo. 1. What is RFID: RFID (radio frequency [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,19,11,12],"tags":[],"class_list":["post-768","post","type-post","status-publish","format-standard","hentry","category-embedded-systems","category-lcd","category-peripheral-drivers","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/768"}],"collection":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=768"}],"version-history":[{"count":2,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/768\/revisions"}],"predecessor-version":[{"id":773,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/768\/revisions\/773"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=768"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=768"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=768"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}