NTAG I2C Text and URL Record Example

Created by Matthew Bon on Mar 24, 2016

Useful Links:

NTAG I2C Demo Board

NTAG I2C Datasheet
NT3H1101_1201.pdf (1.8 MB)

Description:

The NXP NTAG I2C is a NFC Forum Type 2 tag equipped with an I2C interface which allows for communication with a host device. This article demonstrates how to configure the NTAG I2C, via the I2C interface, to display simple text and URL messages in the NFC data exchange format (NDEF) . These examples were kept fairly generic to ensure they can be easily applied to a wide variety of I2C enabled devices.

NTAG I2C Demo Board:

The NTAG I2C demo board consists of two separate sections connected by a 6 pin header. The first section consists of a NXP LPC812 32 bit Cortex M0+ microcontroller, PCT2075 temperature sensor, three pushbuttons, three LEDs and a 10-pin mini JTAG debug header. The second section consists of the NTAG I2C chip, specifically the NT3H1201, an antenna tuned for the 13.56 MHz band and a breadboard compatible connector that makes it easy to interface the NTAG I2C chip with other devices. Only the second section needs to be used to perform the examples, but feel free to use the other section as well if the LPC812 is your preferred microcontroller.

The demo board comes pre-programmed with a example program, so it might be worth your while to experiment with the board a little before diving in to the following examples. Additional information about the demo program can be found in the following NXP app note: [AN11597.pdf|attachment]

Writing to the Tag using the I2C Bus:

Hardware Setup:

The NTAG I2C uses a standard I2C bus for communication and configuration. thus the only extra components needed are pull up resistors for the SDA and SCL lines. The tag supports both Standard (100Kbps) and Fast (400Kbps) mode operation.

Schematic for 100 Kbps operation

NTAG I2C Demo Board mounted in a breadboard.

Writing to the tag:

The memory of the NTAG I2C is divided into separate blocks, each of which contain 16 bytes. The user memory begins at block 0x01. The procedure to write to these blocks is as follows:

  1. The host sends a start condition to the tag.
  2. The host then sends the I2C address, (default is 0x55), with the R/W bit set to 0.
  3. The host then sends the number of the block to be written to and the tag responds with an acknowledgment.
  4. The host can then write data to the block and the tag will respond to each byte written with an acknowledgement. After each byte is written, the byte index in each block will be automatically incremented, allowing each write to access a new byte of memory.
  5. The transactions ends with the host sending a stop condition.

:exclamation: In addition to the steps above, there are also two other important points to note. First when writing to a block, it is necessary to write to every byte in the block or else the write will not commit. If you do not have enough data to fill the block, you can simply write zeros to the rest of the block. Second, when writing data to multiple blocks, it is necessary to send a stop condition after each block is finished and then restart I2C communication to access the next block. This process is shown in the URL and Multiple records examples below.

I would also highly recommend looking at the memory map of the NTAG I2C. which can be found on page 15 of its datasheet.

:warning: Take care when writing to block 0. It contains the both the tag’s I2C address and capability container. NXP already pre-configured the capability container according to the NFC Forum Type 2 Specification, so there should be no reason to change it unless you want to utilize some sort of proprietary, non-NDEF format. You will not need to modify block zero in any of the examples.

Text Demo PseudoCode:

:warning: Ensure you do not accidentally modify block 0 as it contains both the I2C address and the capability container! If you do modify it, these examples will not work!

#define Write (0)
#define Read  (1)
 
/*globals*/
int i = 0;
int j = 0; 
 
/*Functions */
void Wipe_Tag(); 
  
/*NDEF Message*/
unsigned char NDEF_DATA[] =
{
 
/*NDEF Text Record*/
     
0x03, 0x0E,  //NDEF message, 14 byte message
0xD1,        //NDEF Record header: MB = 1b, ME = 1b, CF = 0b, SR = 1b, IL = 0b, TNF = 001b
0x01, 0x0A,  //type length, payload length
0x54,        //Type = Text
0x02,        //Language code size
0x65, 0x6E,  // Language = English, 'e', 'n',
     
/*Payload data = " EEwiki"*/
' ', 'E', 'E', 'w', 'i', 'k', 'i',
     
};
 
int main()
{
    I2C_Start(); //Start/Initialize I2C Peripheral
   
    Wipe_Tag(); //Erase the tag's contents
     
    //Ensure global counter is reset
     i = 0;
     
     
        //Write to Block 1 
        I2CMasterSendStart()
        I2CMasterSendAddress(0x55,Write);
        I2C_I2CMasterWriteByte(0x01); //Set Block to be written to
        for (i = 0; i < 16; i++)
        {
            I2CMasterWriteByte(NDEF_DATA[i]); //Fill Block with Data
        }
        I2CMasterSendStop();
         
         
     for(;;)
    {  
    }
 
}
 
void Wipe_Tag()
{
    for (i = 1; i < 50; i++)
    {
        I2CMasterSendStart();
        I2CMasterSendAddress(0x55,Write);
        I2CMasterWriteByte(i);//Set Block to be written to 
        for (j = 0; j < 16; j++)
        {
            I2CMasterWriteByte(0x00); //Fill Block with Zeros
        }
        I2CMasterSendStop();
        DelayMs(50); //Delay 50 ms
       
    }
}

Testing the Text Demo Using NXP’s TagInfo App:

If you have an Android smartphone, you can easily test the demo above using NXP’s TagInfo App which can be downloaded from the Google play store. Once the app is installed, you can test the tag using the following procedure:

  1. Ensure that the NTAG I2C board is connected to your microcontroller as shown in the “Writing to the tag using the I2C Bus” section above.
  2. Write the NDEF data to the tag as shown in the pseudocode above. This can take several seconds, so make sure to wait a little while before you try to read from the tag.
  3. Open the TagInfo app on your smartphone and then touch the back of the phone against the antenna of the demo board.The phone should vibrate, indicating that the tag has been read.
  4. Immediately after the tag is read, the app should display the message below indicating that an NXP tag was detected and that the tag contains an NDEF record.

  1. Select the NDEF tab in the app, you should see this record below.

URL Demo PseudoCode:

#define Write (0)
#define Read  (1)
 
/*globals*/
int i = 0;
int j = 0; 
 
/*Functions */ 
void Wipe_Tag(); 
  
unsigned char NDEF_DATA[] =
{
//NDEF URL Record
     
0x03, 0x0F, //NDEF message, 15 byte message
0xD1,       // NDEF Record header: MB = 1b, ME = 1b, CF = 0b, SR = 1b, IL = 0b, TNF - 001b
0x01, 0x0B, //type length, payload length
0x55,       //Type = URI
0x02,       //URI Indentifier = https://www.
     
//Payload data = "eewiki.net"
 'e', 'e', 'w', 'i', 'k', 'i', '.', 'n', 'e', 't',
     
};
 
int main()
{
    I2C_Start(); //Start/Initialize I2C Peripheral
   
    Wipe_Tag(); //Erase the tag's contents
     
    //Ensure counter is reset
    i = 0;
     
     
    //Write to Block 1
    I2CMasterSendStart();
    I2CMasterSendAddress(0x55,Write);
    I2CMasterWriteByte(0x01); 
    for (i = 0; i < 16; i++)
    {
        I2CMasterWriteByte(NDEF_DATA[i]); //Fill Block with Data
    }
    I2CMasterSendStop(); 
         
    Delayms(50); //Delay 50 ms
         
    //Write to Block 2
    I2CMasterSendStart();
    I2CMasterSendAddress(0x55,Write);
    I2CMasterWriteByte(0x02); 
    for (i = 16; i < 32; i++)
    {
        if ( i == 16)
        {
            I2CMasterWriteByte(NDEF_DATA[i]); //Fill Block with Data
        }
        else
        {
            I2CMasterWriteByte(0x00);//Write zeros to the rest of the block
        }
             
    }
    I2CMasterSendStop();
         
    for(;;)
    {     
    }
 
}
 
void Wipe_Tag()
{
    for (i = 1; i < 50; i++)
    {
        I2CMasterSendStart();
        I2CMasterSendAddress(0x55,Write);
        I2CMasterWriteByte(i);//Set Block to be written to 
        for (j = 0; j < 16; j++)
        {
            I2CMasterWriteByte(0x00); //Fill Block with Zeros
        }
        I2CMasterSendStop();
        DelayMs(50); //Delay 50 ms
       
    }
}

Testing the URL Demo Using NXP’s TagInfo App:

The URL example can be tested using the same procedure that was used to test the text record example. The NDEF record should look similar to the picture below:

Multiple Records Demo Pseudocode:

#define Write (0)
#define Read  (1)
 
/*globals*/
int i = 0;
int j = 0; 
  
/*Functions */
void Wipe_Tag(); 
  
unsigned char NDEF_DATA[] =
{
     
0x03, 0x1D,    //NDEF message, 31 byte message
0x91,          //NDEF Record header: MB = 1b, ME = 0b, CF = 0b, SR = 1b, IL = 0b, TNF - 001b
0x01, 0x0B,    //type length, payload length
0x55,          //Type = URI
0x02,          //URI Indentifier = https://www.
     
//Payload data = "eewiki.net"
 'e', 'e', 'w', 'i', 'k', 'i', '.', 'n', 'e', 't', 
     
0x51,        //NDEF Record header: MB = 0b, ME = 1b, CF = 0b, SR = 1b, IL = 0b, TNF - 001b
0x01, 0x0A,  //type length, payload length
0x54,        //Type = Text
0x02,        //Language code size
0x65, 0x6E,  //Language, English, 'e', 'n',
     
//Payload data = " EEwiki"
' ', 'E', 'E', 'w', 'i', 'k', 'i',
     
};
  
int main()
{
    I2C_Start(); //Start/Initialize I2C Peripheral
     
    Wipe_Tag(); //Erase the tag's contents
     
    //Ensure counter is reset
     i = 0;
     
     
        //Write to Block 1
        I2CMasterSendStart(0x55,Write);
        I2CMasterWriteByte(0x01);
        for (i = 0; i < 16; i++)
        {
            I2CMasterWriteByte(NDEF_DATA[i]); //Fill Block with Data
        }
        I2CMasterSendStop();
         
        CyDelay(50);
          
         
        //Write to Block 2
        I2CMasterSendStart(0x55,Write);
        I2CMasterWriteByte(0x02);
        for (i = 16; i < 32; i++)
        {
            if ( i < 31)
            {
            I2CMasterWriteByte(NDEF_DATA[i]); //NDEF_DATA[i]); //Fill Block with Data
            }
            else
            {
            I2CMasterWriteByte(0x00);//Write zeros to the rest of the block
            }
             
        }
        I2CMasterSendStop();
         
     for(;;)
    {  
         
         
    }
}
  
void Wipe_Tag()
{
    for (i = 1; i < 50; i++)
    {
        I2CMasterSendStart();
        I2CMasterSendAddress(0x55,Write);
        I2CMasterWriteByte(i);  //Set Block to be written to 
        for (j = 0; j < 16; j++)
        {
            I2CMasterWriteByte(0x00); //Fill Block with Zeros
        }
        I2CMasterSendStop();
        DelayMs(50); //Delay 50 ms
       
    }
}

Testing the Multiple Records Demo Using NXP’s TagInfo App:

As before, the procedure used to test the text example will also work for testing this example. The NDEF records should look similar to the following: