1 NFC抗干扰特性测试
这个测试原本的设计原则是NFC标签对应周围电磁屏蔽和铁磁屏蔽影响的效果评测,对比不同的材质和尺寸,如大平面的屏蔽测试以及隔着金属层的测量。
但是实际上这个测试的初始设计是不成功的,最主要的原因是这个ST25R200读卡器的设计具有很强的抗干扰能力,而且敏感性非常强。
所以,无论NFC标签是在木材,塑料,钢铁,铜板表面,当读卡器Reader状态读取时,都可以很轻松读取数据,而且都可以在20-50mm的范围内感知到并正确读取ID号。这个结果是比较出乎意料的,因为,几年前也测试过类似的产品,这个铁磁效应的屏蔽效果是比较明显的,即使贴近了也不能读取。初步分析,是因为NFC检测距离近,发射器信号弱,在大面积铁磁材料上感应出的反向屏蔽信号源强度弱,不能干扰正常的读取。具体检测的过程和前面正常是读取是完全一致的,因此就不重复上图了。
这个不成功的测试,其实也证明了这个芯片的性能优秀。原来设想不确定是否可以用于在机械设备表面的铭牌内嵌,这次测试证明这个过程是成功的,具有更广大的应用场景,用于设备追踪。不过,NFC的感应距离还是受限,没有找到提高射频频率的设计方法,这样可以使得读卡器同时读取更多的数据,从更远的距离读取数据。
2 总结
本次评测按照计划完成以下内容
STEVAL-25R200SA开箱 - ST NFC团队
STEVAL-25R200SA功耗测试 - ST NFC团队
STEVAL-25R200SA不同模式下距离读写 - ST NFC团队
STEVAL-25R200A的低功耗检卡功能测试 - ST NFC团队
【STEVAL-25R200SA评测】DPO动态功率输出的性能 - ST NFC团队
基本上按照评测计划完成了任务。
官方提供的软件界面清晰易用,易于安装,功能丰富,覆盖了评测的全部内容,因此使得本次评测进行得很顺利。
通过评测,熟悉了这个新型的芯片ST25R200,测试了在工业资产追踪,身份验证等场景有很好的应用机会,在继续加强设计,补充一些适应的功率调整等工作,应该有更好的设计方案。
对于非官方开发板的设计,也就不不带STM32G芯片的设计,其实是采用一个低功耗主控芯片,具有SPI接口,可以对于ST25R200的寄存器直接读取和写入,实现这样的底层管理功能,芯片手册页提供了这样的详细内容,可以实现底层的寄存器级别的开发。
对于评测而言,这些底层的寄存器读写都被EVAL GUI这个工具图形化了,评测的效果是完全相同的。
最后,感谢这样的机会,能够深入学习和理解NFC的基本原理和应用。
3 辅助配置代码生成
在使用EVAL GUI可以自动生成analog config的配置代码,具体生成一个范例如下
/* Generated by ST25R200 Eval GUI 1.1.0.0 */
/*! \file rfal_analog_config_custom.c
*
* Please set RFAL_ANALOG_CONFIG_CUSTOM in platform.h and include
* this file to your project to become active and overwrite the default analog
* configs coming with RFAL
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_analogConfig.h"
#ifndef RFAL_ANALOG_CONFIG_CUSTOM
#warning "Custom analog configs are compiled but not being used. Please define RFAL_ANALOG_CONFIG_CUSTOM."
#endif
/*
******************************************************************************
* GLOBAL VARIABLES
******************************************************************************
*/
/*! Macro for Configuration Setting with only 1 register-mask-value set:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1] */
#define MODE_ENTRY_1_REG(MODE, R0, M0, V0) \
(MODE >> 8), (MODE & 0xFF), 1, (R0 >> 8), (R0 & 0xFF), (M0), (V0)
/*! Macro for Configuration Setting with only 2 register-mask-value set:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1] */
#define MODE_ENTRY_2_REG(MODE, R0, M0, V0, R1, M1, V1) \
(MODE >> 8), (MODE & 0xFF), 2, (R0 >> 8), (R0 & 0xFF), (M0), (V0) \
, (R1 >> 8), (R1 & 0xFF), (M1), (V1)
/*! Macro for Configuration Setting with only 3 register-mask-value set:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_3_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2) \
(MODE >> 8), (MODE & 0xFF), 3, (R0 >> 8), (R0 & 0xFF), (M0), (V0) \
, (R1 >> 8), (R1 & 0xFF), (M1), (V1) \
, (R2 >> 8), (R2 & 0xFF), (M2), (V2) \
/*! Macro for Configuration Setting with only 4 register-mask-value set:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_4_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3) \
(MODE >> 8), (MODE & 0xFF), 4, (R0 >> 8), (R0 & 0xFF), (M0), (V0) \
, (R1 >> 8), (R1 & 0xFF), (M1), (V1) \
, (R2 >> 8), (R2 & 0xFF), (M2), (V2) \
, (R3 >> 8), (R3 & 0xFF), (M3), (V3) \
/*! Macro for Configuration Setting with only 5 register-mask-value set:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_5_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4) \
(MODE >> 8), (MODE & 0xFF), 5, (R0 >> 8), (R0 & 0xFF), (M0), (V0) \
, (R1 >> 8), (R1 & 0xFF), (M1), (V1) \
, (R2 >> 8), (R2 & 0xFF), (M2), (V2) \
, (R3 >> 8), (R3 & 0xFF), (M3), (V3) \
, (R4 >> 8), (R4 & 0xFF), (M4), (V4) \
/*! Macro for Configuration Setting with only 6 register-mask-value set:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_6_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5) \
(MODE >> 8), (MODE & 0xFF), 6, (R0 >> 8), (R0 & 0xFF), (M0), (V0) \
, (R1 >> 8), (R1 & 0xFF), (M1), (V1) \
, (R2 >> 8), (R2 & 0xFF), (M2), (V2) \
, (R3 >> 8), (R3 & 0xFF), (M3), (V3) \
, (R4 >> 8), (R4 & 0xFF), (M4), (V4) \
, (R5 >> 8), (R5 & 0xFF), (M5), (V5) \
/*! Macro for Configuration Setting with only 7 register-mask-value set:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_7_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6) \
(MODE >> 8), (MODE & 0xFF), 7, (R0 >> 8), (R0 & 0xFF), (M0), (V0) \
, (R1 >> 8), (R1 & 0xFF), (M1), (V1) \
, (R2 >> 8), (R2 & 0xFF), (M2), (V2) \
, (R3 >> 8), (R3 & 0xFF), (M3), (V3) \
, (R4 >> 8), (R4 & 0xFF), (M4), (V4) \
, (R5 >> 8), (R5 & 0xFF), (M5), (V5) \
, (R6 >> 8), (R6 & 0xFF), (M6), (V6) \
/*
******************************************************************************
* GLOBAL DATA TYPES
******************************************************************************
*/
const uint8_t rfalAnalogConfigCustomSettings[] = {
/* Mode Name: CHIP_INIT, Mode ID: 0x0000 */
MODE_ENTRY_7_REG(0x0000,
0x0001,0x0c,0x0c, /* Pull down on MISO 1 + 2 */
0x0000,0x08,0x08, /* auto: User Defined */
0x0004,0x01,0x01, /* Regulator AM enable */
0x0004,0xf0,0x40, /* TX Modulation1: am_mod */
0x0003,0x0f,0x00, /* d_res */
0x000d,0x10,0x10, /* en_subc_end */
0x0007,0x0f,0x06 /* Gain in WU mode/measurements (afe_gain_td) */
),
/* Mode Name: POLL_A_106_TX, Mode ID: 0x0111 */
MODE_ENTRY_1_REG(0x0111,
0x0013,0x10,0x00 /* tr_am */
),
/* Mode Name: POLL_A_106_RX, Mode ID: 0x0112 */
MODE_ENTRY_4_REG(0x0112,
0x0008,0x7c,0x4c, /* auto: User Defined */
0x0009,0xff,0xc3, /* auto: User Defined */
0x000d,0x07,0x02, /* Decimation factor for IIR filters (dec_f) */
0x000c,0xff,0xaa /* auto: User Defined */
),
/* Mode Name: POLL_A_ANTICOL, Mode ID: 0x0103 */
MODE_ENTRY_1_REG(0x0103,
0x000c,0xf0,0x70 /* Manchester: collision level ratio (coll_lvl) */
),
/* Mode Name: POLL_B_106_TX, Mode ID: 0x0211 */
MODE_ENTRY_1_REG(0x0211,
0x0013,0x10,0x10 /* tr_am */
),
/* Mode Name: POLL_B_106_RX, Mode ID: 0x0212 */
MODE_ENTRY_4_REG(0x0212,
0x0008,0x7c,0x4c, /* auto: User Defined */
0x0009,0xff,0xc1, /* auto: User Defined */
0x000d,0x07,0x03, /* Decimation factor for IIR filters (dec_f) */
0x000c,0x0f,0x07 /* Manchester: data level ratio (data_lvl) */
),
/* Mode Name: POLL_V_COMMON_TX, Mode ID: 0x1001 */
MODE_ENTRY_1_REG(0x1001,
0x0013,0x10,0x00 /* tr_am */
),
/* Mode Name: POLL_V_COMMON_RX, Mode ID: 0x1002 */
MODE_ENTRY_2_REG(0x1002,
0x0008,0x7c,0x08, /* auto: User Defined */
0x0009,0xff,0xc0 /* auto: User Defined */
),
/* Mode Name: POLL_V_COMMON_ANTICOL, Mode ID: 0x1003 */
MODE_ENTRY_1_REG(0x1003,
0x000c,0xf0,0x70 /* Manchester: collision level ratio (coll_lvl) */
),
/* Mode Name: POLL_V_26_RX, Mode ID: 0x10c2 */
MODE_ENTRY_2_REG(0x10c2,
0x000d,0x07,0x04, /* Decimation factor for IIR filters (dec_f) */
0x000c,0xff,0xaa /* auto: User Defined */
),
/* Mode Name: POLL_V_53_RX, Mode ID: 0x10b2 */
MODE_ENTRY_2_REG(0x10b2,
0x000d,0x07,0x03, /* Decimation factor for IIR filters (dec_f) */
0x000c,0xff,0xaa /* auto: User Defined */
),
/* Mode Name: WAKEUP_ON, Mode ID: 0x0004 */
MODE_ENTRY_1_REG(0x0004,
0x0089,0x01,0x01 /* auto: User Defined */
),
/* Mode Name: WAKEUP_OFF, Mode ID: 0x0005 */
MODE_ENTRY_2_REG(0x0005,
0x0000,0x08,0x08, /* auto: User Defined */
0x0089,0x01,0x00 /* auto: User Defined */
),
/* Mode Name: LOWPOWER_OFF, Mode ID: 0x000b */
MODE_ENTRY_1_REG(0x000b,
0x0000,0x08,0x08 /* auto: User Defined */
)
};
const uint16_t rfalAnalogConfigCustomSettingsLength = sizeof(rfalAnalogConfigCustomSettings);