ST25R3916B no any tag response
Hello.
I am making a custom PCB with a custom antenna and ST25R on the board.
Antenna: single-ended (RF0, RF1).
Bundle: Nucleo-C031C6 with STM32 for communication via I2C with my PCB.
The antenna has a SWR at a frequency of 13.56MHz is about 2.2 (not ideal, but for testing it should work). The spectrum analyzer shows that the field is established by command cmd = 0xC8 and with a fairly strong signal. It seems to me that my problem is somewhere in the configuration or the commands used.
I will briefly describe the steps (the code is presented below):
STEP 1: Reset to default state with a command 0xC0.
STEP 2: Basic interface configuration
Write IO config1 (0x00) = 0x81 (Single antenna, sup3V, No LF clock)
Write IO config2 (0x01) = 0xA6 (sup3V, AAT EN, I2C, VDD_RF)
STEP 3: Automatic regulator adjustment wit ha command 0xD6.
STEP 4: Enable regulators and oscillator
Operation control (0x02) = 0x80 (bit EN = 1)
Delay 100ms
STEP 5: Configure operation mode
Mode definition (0x03) = 0x01 → Initiator ISO14443A
ISO14443A settings (0x05) = 0x01 → enable anticollision
STEP 7: Clear FIFO before new communication wit ha command 0xD8.
STEP 8: Turn on RF field wit ha command 0xC8.
Wait for IRQ I_APON flag
Wait for IRQ I_CAT flag
STEP 9: Send REQA like a command 0xC6.
STEP 10: Wait for RXE
As I understand 0x1D register should return I_wu_a as "1". But I got always "0"
And then STEP 11 Read ATQA from FIFO is also "0"
My code:
#define ST25R_ADDR (0x50 << 1) // HAL expects 8-bit
uint8_t buf[2];
uint8_t rxBuf[512];
uint8_t buttonState = 1;
uint8_t state = 1; //Used for initialization and normal work
uint8_t cmd = 0;
uint8_t irq = 0;
uint8_t regAdr = 0;
while (1)
{
buttonState = HAL_GPIO_ReadPin(User_Button_GPIO_Port, User_Button_Pin);
if (buttonState == 0 && state == 1) {
buttonState=1;
/* === STEP 1. Reset to default state === */
// Direct command: Set Default (0xC0)
cmd = 0xC0;
HAL_I2C_Master_Transmit(&hi2c1, ST25R_ADDR, &cmd, 1, 100);
/* === STEP 2. Basic interface configuration === */
// Write IO config1 (0x00) = 0x81 (Single antenna, sup3V, No LF clock)
buf[0] = 0x00; buf[1] = 0x81;
HAL_I2C_Master_Transmit(&hi2c1, ST25R_ADDR, buf, 2, 100);
// Write IO config2 (0x01) = 0xA6 (sup3V, AAT EN, I2C, VDD_RF)
buf[0] = 0x01; buf[1] = 0xA6;
HAL_I2C_Master_Transmit(&hi2c1, ST25R_ADDR, buf, 2, 100);
/* === STEP 3. Automatic regulator adjustment === */
// Direct command: Adjust regulators (0xD6)
cmd = 0xD6;
HAL_I2C_Master_Transmit(&hi2c1, ST25R_ADDR, &cmd, 1, 100);
/* === STEP 4. Enable regulators and oscillator === */
// Operation control (0x02) = 0x80 (EN bit = 1)
buf[0] = 0x02; buf[1] = 0x80;
HAL_I2C_Master_Transmit(&hi2c1, ST25R_ADDR, buf, 2, 100);
// Wait for IRQ that oscillator is stable (osc_ok)
HAL_Delay(100); Just 100ms delay instead IRQ read
/* === STEP 5. Configure operation mode === */
// Mode definition (0x03) = 0x01 → Initiator ISO14443A
buf[0] = 0x03; buf[1] = 0x01;
HAL_I2C_Master_Transmit(&hi2c1, ST25R_ADDR, buf, 2, 100);
// ISO14443A settings (0x05) = 0x01 → enable anticollision
buf[0] = 0x05; buf[1] = 0x01;
HAL_I2C_Master_Transmit(&hi2c1, ST25R_ADDR, buf, 2, 100);
buf[0] = 0x3F|(1 << 6);
HAL_I2C_Mem_Read(&hi2c1, ST25R_ADDR, buf[0], I2C_MEMADD_SIZE_8BIT, &irq, 1, 100);
/* === STEP 6. Go to the next state === */
state = 2;
regAdr = 0x00 | (1 << 6);
HAL_I2C_Mem_Read(&hi2c1, ST25R_ADDR, regAdr, 1, &irq, 1, 100);
regAdr = 0x01 | (1 << 6);
HAL_I2C_Mem_Read(&hi2c1, ST25R_ADDR, regAdr, 1, &irq, 1, 100);
HAL_Delay(1000);
}
if (buttonState == 0 && state == 2) {
buttonState=1;
/* === STEP 7. Clear FIFO before new communication === */
// Direct command: Clear FIFO (0xDB)
// Ensures no "old" data is left in the queue before sending REQA.
cmd = 0xDB;
HAL_I2C_Master_Transmit(&hi2c1, ST25R_ADDR, &cmd, 1, 100);
/* === STEP 8. Turn on RF field === */
// Direct command: NFC Initial Field ON (0xC8)
// Starts the antenna activation and collision check procedure.
cmd = 0xC8;
HAL_I2C_Master_Transmit(&hi2c1, ST25R_ADDR, &cmd, 1, 100);
// Wait for IRQ I_APON confirming that the field was turned on successfully.
irq = 0;
regAdr = 0x1D|(1 << 6);//0x5D
for (int tries = 0; tries < 20; tries++) {
HAL_Delay(1); // 1 ms пауза
HAL_I2C_Mem_Read(&hi2c1, ST25R_ADDR, regAdr, 1, &irq, 1, 100);
if (irq & (1 << 5)) {
break;
}
}
// Wait for IRQ I_CAT confirming that the field was turned on successfully.
irq = 0;
regAdr = 0x1B|(1 << 6);//0x5B
for (int tries = 0; tries < 20; tries++) {
HAL_Delay(1); // 1 ms пауза
HAL_I2C_Mem_Read(&hi2c1, ST25R_ADDR, regAdr, 1, &irq, 1, 100);
if (irq & (1 << 1)) {
break;
}
}
// === STEP 9. Send REQA ===
cmd = 0xC6;
HAL_I2C_Master_Transmit(&hi2c1, ST25R_ADDR, &cmd, 1, 100);
// up to here it works.
// === STEP 10. Wait for RXE ===
irq = 0;
regAdr = 0x1D | (1 << 6);
for (int tries = 0; tries < 250; tries++) {
HAL_Delay(1);
HAL_I2C_Mem_Read(&hi2c1, ST25R_ADDR, regAdr, 1, &irq, 1, 100);
if (irq != 0) {
break;
}
}
// === STEP 11. Read ATQA from FIFO ===
uint8_t atqa[2] = {0};
regAdr = 0x5F; // FIFO read
HAL_I2C_Mem_Read(&hi2c1, ST25R_ADDR, regAdr, I2C_MEMADD_SIZE_8BIT, atqa, 2, 100);
// Now atqa[0..1] contains the card response
Log from Logic Analyzer:
//Step 1
write to 0x50 nak
//Step 2
write to 0x50 ack data: 0x00 0x81
write to 0x50 ack data: 0x01 0xA6
//Step 3
write to 0x50 ack data: 0xD6
//Step 4
write to 0x50 ack data: 0x02 0x80
//Step 5
write to 0x50 ack data: 0x03 0x01
write to 0x50 ack data: 0x05 0x01
//Just read ID
write to 0x50 ack data: 0x7F
read to 0x50 ack data: 0x31
//Just check configuration registers
write to 0x50 ack data: 0x40
read to 0x50 ack data: 0x81
write to 0x50 ack data: 0x41
read to 0x50 ack data: 0xA6
//Step 7
write to 0x50 ack data: 0xDB
//Step 8
write to 0x50 ack data: 0xC8
//Waiting for I_APON
write to 0x50 ack data: 0x5D
read to 0x50 ack data: 0x20
/Waiting for I_CAT
...
write to 0x50 ack data: 0x5B
read to 0x50 ack data: 0x02
//Step 9
write to 0x50 ack data: 0xC6
//Step 10 - Waiting for I_wu_a*
write to 0x50 ack data: 0x5D
read to 0x50 ack data: 0x00
...
is always 0x00
//Step 11
read to 0x50 ack data: 0x00 0x00