cancel
Showing results for 
Search instead for 
Did you mean: 

Cr95hf card emulation help me plz

DJeon.4
Associate II

Hello, I tried to implement the card emulator using CR95HF to refer to the datasheet, but it failed. Could you provide the sample code data for the cmd read write cmd procedure in the form of Hex value? I'd appreciate your help.

Ex)

Write cmd 0x 02 04 68 41

Read cne 0x 01. . .

Card emulator write cmd 0x02008. Etc

16 REPLIES 16

Perhaps don't print data as you're sending and receiving it. ie​ do the CS, SPI interaction quickly and quietly, printing the whole transaction subsequently

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Brian TIDAL
ST Employee

Hi,

make sure to follow the SPI communication protocol as described in §4.1 of the ST25R95 datasheet. In particular, before reading the response to a command, "the application software needs to wait for the ST25R95 to be ready to send the response. Not following this procedure may cause unpredictable behavior". This can be done by:

  • Polling the ST25R95 until it is ready (0x03 poll control byte)
  • waiting for IRQ_OUT: this is what I usually recommend (very simple to use)

So, after sending "0x00 0x02 0x02 0x12 0x0A" (CE mode ProtocolSelect), make sure to poll the ST25R95 or to wait for the IRQ_OUT before reading the response to the command.

The  RFID_CR95HF::readCmd() looks erroneous:

// Poll the CR95HF
void RFID_CR95HF::readCmd() {
  unsigned short i = 0;
 
  while (1)
  {
    digitalWrite(CS, LOW);
    SPI.beginTransaction(SETTINGS);
    SPI.transfer(0x03);
    res = SPI.transfer(0);
    SPI.endTransaction();
    digitalWrite(CS, HIGH);
 
      //Serial.printf("==== Read cmd :");
      for (i = 0; i < dataNum; i++) {  <----!! Use of unitialized value !!
        rdata[i] = SPI.transfer(0);    <---- !! Icorrect SPI read while CS is high !!
      //  Serial.printf("0x%x ", rdata[i]);
      }    
 
    if ((res & 0x08) >> 3) {
      digitalWrite(CS, LOW);
      SPI.beginTransaction(SETTINGS);
      SPI.transfer(0x02);
      res = SPI.transfer(0); <---- !! please print the res value !!
      dataNum = SPI.transfer(0); <---- !! please print the dataNum value !!
      Serial.printf("Read cmd :");
      for (i = 0; i < dataNum; i++) {
        rdata[i] = SPI.transfer(0);
        Serial.printf("0x%x ", rdata[i]);
      }
      Serial.println("");
      SPI.endTransaction();
      digitalWrite(CS, HIGH);
      break;
    }
 
    SPI.endTransaction();
    digitalWrite(CS, HIGH);
    delay(10);
  }
}

After sending the protocolSelect, the res value should be 0x00 (meaning response OK) and the dataNum should be 0 (no payload). Same for the AC filter command and for the listen command.

See examples from logic analyzer:

0693W00000QOEOsQAP.jpg 

0693W00000QOEOYQA5.jpg 

Rgds

BT

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
DJeon.4
Associate II

Hello.

Brian TIDAL

We proceeded according to the sequence you told us but failed to implement the card emulation mode.

Please check if the cmd I entered is correct.

  1. spi setting
  2. cr95hf wake up ( echo Response)
  • irq_in : high , irq_out : high , ss:low set
  • packet tx : 0x00, 0x55,0x00 -> ss:high , spi endTransaction
  • packet rx : 0x02, 0x00 -> ss:high, spi endTransaction

  1. card emulation mode setup protocol select (14443a)
  • irq_in : high , irq_out : high , ss:low set
  • packet tx : 0x00, 0x02, 0x02, 0.x12, 0x0A -> ss:high, spi endTransaction
  • irq_in : high , irq_out : low , ss:low set
  • packet rx start cmd packet tx : 0x02 ,0x00
  • packet rx : 0x00, 0x00 -> ss:high, irq_OUT: high, spi endTransaction

2.card emulation mode ATQA and User Tag UID defind

  • irq_in : high , irq_out : high , ss:low set
  • packet tx : 0x00, 0x0D, 0x07, 0x02, 0x00, 0x20, 0x5f, 0x53, 0x54, 0x4D(user Tag UID) -> ss:high, spi endTransaction
  • irq_in : high , irq_out : low , ss:low set
  • packet rx start cmd packet tx : 0x02 ,0x00
  • packet rx : 0x00, 0x00 -> ss:high, irq_OUT: high, spi endTransaction

3.Listen

  • irq_in : high , irq_out : high , ss:low set
  • packet tx :0x05, 0x00 -> ss:high, spi endTransaction
  • irq_in : high , irq_out : low , ss:low set
  • packet rx start cmd packet tx : 0x02 ,0x00
  • packet rx : 0x00, 0x00 -> ss:high, irq_OUT: high, spi endTransaction

That's all I've done

​Brian TIDAL's sequence changes from 4. to the mobile phone Tag reader mode and recognizes CR95HF, but it doesn't work. I'm not sure where it went wrong.

​Help me

====================================

<​Before contacting the CR95HF in Samsung mobile NFC reader mode...>

0693W00000SuHZWQA3.png<after...>

0693W00000SuHaUQAV.png 

==================================

<card emulation mode code>

void card_Emulation_14443A(void)
{
  Serial.println("Caed Emulation Mode Set up");
  sdata[0] = 0x12;
  sdata[1] = 0x0A;
  writeCmd(ProtocolSelect, 2); // Card Emulation Mode Tag type select 14443A
  delay(10);
  CardEmulate_readCmd();
 
  
  
  sdata[0] = 0x02; //ATQA
  sdata[1] = 0x00;
  sdata[2] = 0x20; // sak
  sdata[3] = 0x5F; // User Tag UID
  sdata[4] = 0x53; // User Tag UID
  sdata[5] = 0x54; // User Tag UID
  sdata[6] = 0x4D; // User Tag UID
  writeCmd(AC_filter ,7); 
  delay(10);
  CardEmulate_readCmd();  
 
  writeCmd(Listen ,0);
  delay(100);
  CardEmulate_readCmd();
  delay(100);
   
  sdata[0] = 0x05;
  sdata[1] = 0x78;
  sdata[2] = 0x80;
  sdata[3] = 0x80;
  sdata[4] = 0x00;
  sdata[5] = 0x28;
  writeCmd(Tag_Send ,6); 
  delay(10);  
  CardEmulate_readCmd();
 
  writeCmd(Listen ,0);
  delay(10);
  CardEmulate_readCmd();
   
}
 
void CardEmulate_readCmd(void) 
{
  unsigned short i = 0;
  while (1) 
  {
    digitalWrite(IRQ_IN, HIGH);
    digitalWrite(IRQ_OUT, LOW);
    digitalWrite(CS, LOW);
    SPI.beginTransaction(SETTINGS);
    SPI.transfer(0x02); // read data
    res = SPI.transfer(0);
    dataNum = 10;
    Serial.printf("Read cmd :");
    for (i = 0; i < dataNum; i++) {
        rdata[i] = SPI.transfer(0);
        Serial.printf("0x%x ", rdata[i]);
      }
      Serial.println("");
      SPI.endTransaction();
      digitalWrite(CS, HIGH);
      digitalWrite(IRQ_OUT, HIGH);
      break;
    delay(10);
  }
}
 
void writeCmd(unsigned short cmd, unsigned short dataLen) 
{
  unsigned short i = 0;
  digitalWrite(IRQ_IN, HIGH);
  digitalWrite(IRQ_OUT, HIGH);
  digitalWrite(CS, LOW);
  SPI.beginTransaction(SETTINGS);
  SPI.transfer(0x00);  // contol byte  :
  SPI.transfer(cmd);   // command
  SPI.transfer(dataLen); // length
  while (dataLen == 0) {
    digitalWrite(CS, HIGH); 
    Serial.println(" data len 0 ");
    break;
  }
  Serial.printf("write cmd :");
  for (i = 0; i < dataLen; i++) {
   SPI.transfer(sdata[i]);
   Serial.printf("0x%x ", sdata[i]);
  }
  Serial.println("");
  SPI.endTransaction();
  digitalWrite(CS, HIGH);
  delay(10);
}

Brian TIDAL
ST Employee

Hi,

can you confirm that the protocolSelect (CE mode) command properly returns 0x00 0x00 and that AC Filter command also returns 0x00 0x00?

Can you provide a LogicAnalyzer trace of SPI CLK/MOSI/MISO/SS + IRQ_OUT?

Thanks

Rgds

BT

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

There is no logic analyzer. So I can't provide itten thousand

I will check the AC filter

​I will modify the code and get packet data including control byte, command, and length. Please wait a moment

4. When the wait for IRQ recognizes the mobile phone, it returns the value as follows.

0x00, 0x80, 0x05, 0xe0, 0x80, 0x31, 0x73, 0x08, 0x00, 0x00

0693W00000SuMLPQA3.png

Brian TIDAL
ST Employee

Hi

this is a great achievement:

0x00, 0x80, 0x05, 0xe0, 0x80, 0x31, 0x73, 0x08, 0x00, 0x00 is basically the E0 80 RATS frame (Request for Answer To Select) that is sent by the Android Phone after the anti collision and the activation. This means the anti collision (AC Filter) is properly working and the Android Phone is now trying to move to ISO14443-4 layer (aka ISO-DEP) with the RATS command. I see that you send the ATS answer (05 78 80 80 00), then make sure to then send the Listen command to trigger the reception of the next command. Note that the logging of the various exchanges may have an impact on the real time: for example the phone is waiting for the ATS within a certain timeout, if the logging through UART is delaying too much the sending of the ATS, the waiting time on phone side may elapse and this can cause a communication failure.

Rgds

BT

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.