NFC Module
这个模块从当前 custom_app 中抽取 DP1312EA + NTAG213 UID 读取功能,目标是后续可以直接移植到别的业务项目。
核心原则:
- NFC 模块不依赖业务层。
- 业务层通过回调接入 NFC 事件。
- I2C/GPIO/中断/RTOS/sleep/log 全部走平台适配层。
- Quectel SDK 调用只允许出现在
platform/quectel/。
目录结构
portable_modules/nfc/
include/
nfc_service.h
nfc_platform.h
src/
nfc_service.c
nfc_dp1312ea.c
nfc_ntag213.c
platform/quectel/
nfc_platform_ql.c
vendor/dp1312ea/
TypeA.c
LPCD.c
reg.h
...
examples/
banban_adapter.c
module.mk
分层说明
include/nfc_service.h: 业务层接口。业务只需要关心初始化、启动、UID 回调。include/nfc_platform.h: 平台适配接口。移植到新 SDK 时实现这里的函数。src/nfc_service.c: NFC 服务状态机,包含 LPCD 等待、中断唤醒、轮询读卡、失败回退。src/nfc_dp1312ea.c: DP1312EA 寄存器、reset、transceive 等芯片封装。src/nfc_ntag213.c: NTAG213 兼容 UID 读取。platform/quectel/nfc_platform_ql.c: 当前移远 SDK 适配。vendor/dp1312ea/: 原 DP1312EA TypeA/LPCD/寄存器等底层代码。examples/banban_adapter.c: 当前 Banban 业务接入示例。
当前能力
- 初始化 DP1312EA。
- 进入 LPCD 低功耗检卡。
- IRQ 唤醒后轮询读卡。
- 读取 NTAG213/Ultralight 兼容标签 UID。
- 将 UID 以二进制和十六进制字符串形式回调给业务层。
暂未实现完整写 NFC 标签功能。vendor 中保留了 MIFARE 风格的 16 字节块写底层函数,但 NTAG213 页写入和 NDEF 写入需要后续单独补。
业务层怎么使用
业务层只包含:
#include "nfc_service.h"
然后实现两个核心回调:
static int app_can_poll(void *ctx)
{
// 返回 1 表示当前允许读卡,返回 0 表示暂时不读。
return 1;
}
static void app_on_uid(const nfc_uid_t *uid, void *ctx)
{
// uid->value 是十六进制字符串,例如 "04A1B2C3D4E5F6"。
// 业务层在这里决定绑定、触发 MQTT、播放提示音等。
}
启动 NFC:
nfc_service_config_t config;
nfc_service_callbacks_t callbacks = {
.can_poll = app_can_poll,
.on_uid = app_on_uid,
.on_error = 0,
.ctx = 0,
};
nfc_service_default_config(&config);
nfc_service_init(&config, &callbacks);
nfc_service_start();
can_poll 可以为空;为空时模块默认一直允许读卡。on_uid 必须提供。
当前 Banban 项目接入方式
参考:
examples/banban_adapter.c
这个示例把原项目中的业务判断放回业务层:
- FOTA 中不读卡。
- 休眠中不读卡。
- MQTT 未连接不读卡。
- 录音/TTS/播放队列忙时不读卡。
- 测试模式允许读卡。
- 读到 UID 后,根据
g_nfc_bind_status决定调用绑定还是触发上报。
在当前项目中正式切换时,应用层可以把原来的:
DP1312EA_Init();
替换为:
banban_nfc_start();
并把 examples/banban_adapter.c 加入业务工程源码。
Quectel SDK 工程怎么接入
如果工程的 Makefile 支持 include 片段,可以引入:
include ../portable_modules/nfc/module.mk
或者手动加入这些源码:
SRC_FILES += \
../portable_modules/nfc/src/nfc_service.c \
../portable_modules/nfc/src/nfc_dp1312ea.c \
../portable_modules/nfc/src/nfc_ntag213.c \
../portable_modules/nfc/platform/quectel/nfc_platform_ql.c \
../portable_modules/nfc/vendor/dp1312ea/LPCD.c \
../portable_modules/nfc/vendor/dp1312ea/TypeA.c
INC_DIRS += \
-I../portable_modules/nfc/include \
-I../portable_modules/nfc/src \
-I../portable_modules/nfc/vendor/dp1312ea
如果要使用 Banban 示例,还需要加入:
SRC_FILES += ../portable_modules/nfc/examples/banban_adapter.c
默认硬件配置
- I2C bus:
1 - DP1312EA I2C slave address:
0x50 >> 1 - Reset pin:
86 - IRQ pin:
87
如硬件不同,在初始化前修改 nfc_service_config_t:
nfc_service_default_config(&config);
config.i2c_bus = 1;
config.reset_pin = 86;
config.irq_pin = 87;
nfc_service_init(&config, &callbacks);
移植到其他平台
移植新平台时,不需要改 src/ 和 vendor/。只需要新增一个平台实现,例如:
platform/my_sdk/nfc_platform_my_sdk.c
实现 include/nfc_platform.h 中的函数:
nfc_platform_i2c_initnfc_platform_i2c_readnfc_platform_i2c_writenfc_platform_gpio_initnfc_platform_gpio_set_levelnfc_platform_gpio_get_levelnfc_platform_irq_registernfc_platform_irq_enable_wakeupnfc_platform_irq_disable_wakeupnfc_platform_sem_createnfc_platform_sem_waitnfc_platform_sem_releasenfc_platform_task_createnfc_platform_sleep_msnfc_platform_log
分层约束
维护时请保持这些边界:
src/和vendor/不能 includeql_*.h。src/和vendor/不能 includeapp_inc.h。src/和vendor/不能调用 MQTT、绑定、播放、录音、FOTA 等业务函数。- 业务判断必须放在
can_poll回调。 - UID 后续动作必须放在
on_uid回调。