Add portable NFC module
This commit is contained in:
211
nfc/README.md
Normal file
211
nfc/README.md
Normal file
@@ -0,0 +1,211 @@
|
||||
# NFC Module
|
||||
|
||||
这个模块从当前 `custom_app` 中抽取 DP1312EA + NTAG213 UID 读取功能,目标是后续可以直接移植到别的业务项目。
|
||||
|
||||
核心原则:
|
||||
|
||||
- NFC 模块不依赖业务层。
|
||||
- 业务层通过回调接入 NFC 事件。
|
||||
- I2C/GPIO/中断/RTOS/sleep/log 全部走平台适配层。
|
||||
- Quectel SDK 调用只允许出现在 `platform/quectel/`。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```text
|
||||
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 写入需要后续单独补。
|
||||
|
||||
## 业务层怎么使用
|
||||
|
||||
业务层只包含:
|
||||
|
||||
```c
|
||||
#include "nfc_service.h"
|
||||
```
|
||||
|
||||
然后实现两个核心回调:
|
||||
|
||||
```c
|
||||
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:
|
||||
|
||||
```c
|
||||
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 项目接入方式
|
||||
|
||||
参考:
|
||||
|
||||
```text
|
||||
examples/banban_adapter.c
|
||||
```
|
||||
|
||||
这个示例把原项目中的业务判断放回业务层:
|
||||
|
||||
- FOTA 中不读卡。
|
||||
- 休眠中不读卡。
|
||||
- MQTT 未连接不读卡。
|
||||
- 录音/TTS/播放队列忙时不读卡。
|
||||
- 测试模式允许读卡。
|
||||
- 读到 UID 后,根据 `g_nfc_bind_status` 决定调用绑定还是触发上报。
|
||||
|
||||
在当前项目中正式切换时,应用层可以把原来的:
|
||||
|
||||
```c
|
||||
DP1312EA_Init();
|
||||
```
|
||||
|
||||
替换为:
|
||||
|
||||
```c
|
||||
banban_nfc_start();
|
||||
```
|
||||
|
||||
并把 `examples/banban_adapter.c` 加入业务工程源码。
|
||||
|
||||
## Quectel SDK 工程怎么接入
|
||||
|
||||
如果工程的 Makefile 支持 include 片段,可以引入:
|
||||
|
||||
```make
|
||||
include ../portable_modules/nfc/module.mk
|
||||
```
|
||||
|
||||
或者手动加入这些源码:
|
||||
|
||||
```make
|
||||
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 示例,还需要加入:
|
||||
|
||||
```make
|
||||
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`:
|
||||
|
||||
```c
|
||||
nfc_service_default_config(&config);
|
||||
config.i2c_bus = 1;
|
||||
config.reset_pin = 86;
|
||||
config.irq_pin = 87;
|
||||
nfc_service_init(&config, &callbacks);
|
||||
```
|
||||
|
||||
## 移植到其他平台
|
||||
|
||||
移植新平台时,不需要改 `src/` 和 `vendor/`。只需要新增一个平台实现,例如:
|
||||
|
||||
```text
|
||||
platform/my_sdk/nfc_platform_my_sdk.c
|
||||
```
|
||||
|
||||
实现 `include/nfc_platform.h` 中的函数:
|
||||
|
||||
- `nfc_platform_i2c_init`
|
||||
- `nfc_platform_i2c_read`
|
||||
- `nfc_platform_i2c_write`
|
||||
- `nfc_platform_gpio_init`
|
||||
- `nfc_platform_gpio_set_level`
|
||||
- `nfc_platform_gpio_get_level`
|
||||
- `nfc_platform_irq_register`
|
||||
- `nfc_platform_irq_enable_wakeup`
|
||||
- `nfc_platform_irq_disable_wakeup`
|
||||
- `nfc_platform_sem_create`
|
||||
- `nfc_platform_sem_wait`
|
||||
- `nfc_platform_sem_release`
|
||||
- `nfc_platform_task_create`
|
||||
- `nfc_platform_sleep_ms`
|
||||
- `nfc_platform_log`
|
||||
|
||||
## 分层约束
|
||||
|
||||
维护时请保持这些边界:
|
||||
|
||||
- `src/` 和 `vendor/` 不能 include `ql_*.h`。
|
||||
- `src/` 和 `vendor/` 不能 include `app_inc.h`。
|
||||
- `src/` 和 `vendor/` 不能调用 MQTT、绑定、播放、录音、FOTA 等业务函数。
|
||||
- 业务判断必须放在 `can_poll` 回调。
|
||||
- UID 后续动作必须放在 `on_uid` 回调。
|
||||
Reference in New Issue
Block a user