Add portable NFC module

This commit is contained in:
2026-07-20 10:48:38 +08:00
commit 4ed123f87c
25 changed files with 3965 additions and 0 deletions

328
nfc/vendor/dp1312ea/Antcoll.c vendored Normal file
View File

@@ -0,0 +1,328 @@
#include <string.h>
#include <stdio.h>
#include "DP1312EA_Config.h"
#include "DP1312EA.h"
#include "TypeA.h"
#include "nfc_platform.h"
// 定义卡片状态
typedef enum {
CARD_STATE_IDLE,
CARD_STATE_READY,
CARD_STATE_ACTIVE,
CARD_STATE_HALT
} CardState;
// 卡片信息结构
typedef struct {
uint8_t uid[10]; // UID (4,7或10字节)
uint8_t uid_len; // UID长度
CardState state; // 卡片状态
} CardInfo;
// 系统参数
#define MAX_CARDS 10 // 最大检测卡片数量
CardInfo detectedCards[MAX_CARDS];
uint8_t cardCount = 0;
// 函数声明
void DP1312EA_Config(void);
uint8_t DP1312EA_Transceive(uint8_t *send, uint8_t sendLen, uint8_t *recv, uint8_t *recvLen);
uint8_t DP1312EA_Request(uint8_t cmd, uint8_t *atq);
uint8_t DP1312EA_Anticollision(uint8_t level, uint8_t *uid, uint8_t *uid_len);
uint8_t DP1312EA_Select(uint8_t level, uint8_t *uid, uint8_t uid_len, uint8_t *sak);
uint8_t DP1312EA_Halt(void);
void DP1312EA_HandleCollision(uint8_t *uid, uint8_t uid_len, uint8_t level);
void FindAllCards(void);
int TypeA_AntiColl(void);
// DP1312EA初始化
void DP1312EA_Config(void) {
DP1312EA_Reset();
// 配置DP1312EA寄存器
DP1312EA_PcdConfigISOType('A');
DP1312EA_FieldOn();
nfc_platform_sleep_ms(10);
}
// 发送和接收数据
uint8_t DP1312EA_Transceive(uint8_t *send, uint8_t sendLen, uint8_t *recv, uint8_t *recvLen) {
// 清除FIFO
DP1312EA_WriteRawRC(0x01, DP1312EA_IDLE);
DP1312EA_WriteRawRC(0x01, DP1312EA_MEM);
// 写入发送数据
DP1312EA_WriteFIFO(send, sendLen);
// 启动传输
DP1312EA_WriteRawRC(0x01, DP1312EA_TRANSCEIVE);
DP1312EA_WriteRawRC(0x0D, 0x30); // 启用发送和接收
// 等待传输完成
uint16 timeout = 2000; // 超时时间
while (!(DP1312EA_ReadRawRC(0x04) & 0x30) ){ // 等待TxIRq或RxIRq
if (--timeout == 0) {
DP1312EA_WriteRawRC(0x01, DP1312EA_IDLE); // 停止传输
return 1; // 超时错误
}
//nfc_platform_sleep_ms(1);
//Delay_us(100);
}
// 检查错误
if (DP1312EA_ReadRawRC(0x06) & 0x13) { // 检查错误标志
DP1312EA_WriteRawRC(0x01, DP1312EA_IDLE);
return 2; // 通信错误
}
// 读取接收数据
*recvLen = DP1312EA_ReadRawRC(0x0A); // FIFOLevel
if (*recvLen > 0) {
DP1312EA_ReadFIFO(recv, *recvLen);
}
DP1312EA_WriteRawRC(0x01, DP1312EA_IDLE);
return 0; // 成功
}
// 请求阶段
uint8_t DP1312EA_Request(uint8_t cmd, uint8_t *atq) {
uint8_t response[2];
uint8_t resLen = 2;
uint8_t status = DP1312EA_Transceive(&cmd, 1, response, &resLen);
if (status == 0 && resLen == 2) {
atq[0] = response[0];
atq[1] = response[1];
return 1; // 成功
}
return 0; // 失败
}
// 防冲突函数
uint8_t DP1312EA_Anticollision(uint8_t level, uint8_t *uid, uint8_t *uid_len) {
uint8_t anticoll_cmd;
uint8_t nvb;
switch(level) {
case 0:
anticoll_cmd = PICC_ANTICOLL1;
nvb = 0x20; // 32位
break;
case 1:
anticoll_cmd = PICC_ANTICOLL2;
nvb = 0x20; // 32位
break;
case 2:
anticoll_cmd = PICC_ANTICOLL3;
nvb = 0x20; // 32位
break;
default:
return 0;
}
uint8_t sendBuf[2] = {anticoll_cmd, nvb};
uint8_t recvBuf[10]; // 最大UID长度+1
uint8_t recvLen = sizeof(recvBuf);
uint8_t status = DP1312EA_Transceive(sendBuf, 2, recvBuf, &recvLen);
if (status != 0 || recvLen < 5) { // 至少4字节UID+1字节BCC
return 0; // 失败
}
// 检查冲突
if (DP1312EA_ReadRawRC(0x06) & 0x08) { // CollErr标志
return 2; // 冲突
}
// 计算BCC
uint8_t bcc = 0;
for (uint8_t i = 0; i < recvLen - 1; i++) {
bcc ^= recvBuf[i];
}
if (bcc != recvBuf[recvLen-1]) {
return 0; // BCC错误
}
// 复制UID
*uid_len = recvLen - 1;
memcpy(uid, recvBuf, *uid_len);
return 1; // 成功
}
// 选择卡片
uint8_t DP1312EA_Select(uint8_t level, uint8_t *uid, uint8_t uid_len, uint8_t *sak) {
uint8_t select_cmd;
switch(level) {
case 0: select_cmd = SELECT_0; break;
case 1: select_cmd = SELECT_1; break;
case 2: select_cmd = SELECT_2; break;
default: return 0;
}
uint8_t sendBuf[10]; // SEL + NVB + UID + BCC
uint8_t sendLen = 0;
sendBuf[sendLen++] = select_cmd;
sendBuf[sendLen++] = 0x70; // NVB=64位
uint8_t bcc = 0;
for (uint8_t i = 0; i < uid_len; i++) {
sendBuf[sendLen++] = uid[i];
bcc ^= uid[i];
}
sendBuf[sendLen++] = bcc;
uint8_t response[3];
uint8_t resLen = sizeof(response);
if (DP1312EA_Transceive(sendBuf, sendLen, response, &resLen) != 0 || resLen < 1) {
return 0; // 失败
}
*sak = response[0];
return 1; // 成功
}
// 休眠卡片
uint8_t DP1312EA_Halt(void) {
uint8_t halt_cmd[4] = {PICC_HALT, 0, 0, 0}; // CRC由DP1312EA计算
uint8_t resLen = 0;
return (DP1312EA_Transceive(halt_cmd, 4, NULL, &resLen) == 0);
}
// 处理冲突
void DP1312EA_HandleCollision(uint8_t *uid, uint8_t uid_len, uint8_t level) {
uint8_t coll_pos = DP1312EA_ReadRawRC(BitFramingReg) & 0x1F;
uint8_t bit_pos = coll_pos % 8;
uint8_t byte_pos = coll_pos / 8;
// 确定冲突位的位置
// uint8_t collision_byte = uid[byte_pos];
// 尝试两种可能的值 (0和1)
for (uint8_t bit_value = 0; bit_value <= 1; bit_value++) {
// 创建新的UID分支
uint8_t new_uid[10];
memcpy(new_uid, uid, uid_len);
// 设置冲突位的值
if (bit_value) {
new_uid[byte_pos] |= (1 << bit_pos);
} else {
new_uid[byte_pos] &= ~(1 << bit_pos);
}
// 尝试防冲突
uint8_t status = DP1312EA_Anticollision(level, new_uid, &uid_len);
if (status == 1) {
// 成功获取UID
uint8_t sak;
if (DP1312EA_Select(level, new_uid, uid_len, &sak)) {
// 检查SAK的UID完整标志
if (sak & 0x04) {
// UID完整存储卡片
if (cardCount < MAX_CARDS) {
memcpy(detectedCards[cardCount].uid, new_uid, uid_len);
detectedCards[cardCount].uid_len = uid_len;
detectedCards[cardCount].state = CARD_STATE_ACTIVE;
cardCount++;
}
// 使卡片休眠
DP1312EA_Halt();
} else {
// UID不完整进入下一级防冲突
DP1312EA_HandleCollision(new_uid, uid_len, level + 1);
}
}
} else if (status == 2) {
// 仍有冲突,递归处理
DP1312EA_HandleCollision(new_uid, uid_len, level);
}
}
}
// 完整的防冲突流程
void FindAllCards(void) {
cardCount = 0; // 重置卡片计数
// 1. 发送REQA唤醒卡片
uint8_t atq[2];
if (!DP1312EA_Request(PICC_REQIDL, atq)) {
return; // 没有卡片
}
// 2. 初始防冲突循环
uint8_t uid[10];
uint8_t uid_len;
uint8_t status;
while (cardCount < MAX_CARDS) {
status = DP1312EA_Anticollision(0, uid, &uid_len);
if (status == 1) {
// 成功获取UID
uint8_t sak;
if (DP1312EA_Select(0, uid, uid_len, &sak)) {
// 检查SAK的UID完整标志
if (sak & 0x04) {
// UID完整存储卡片
memcpy(detectedCards[cardCount].uid, uid, uid_len);
detectedCards[cardCount].uid_len = uid_len;
detectedCards[cardCount].state = CARD_STATE_ACTIVE;
cardCount++;
// 使卡片休眠
DP1312EA_Halt();
} else {
// UID不完整进入下一级防冲突
DP1312EA_HandleCollision(uid, uid_len, 1);
}
}
} else if (status == 2) {
// 冲突发生,处理冲突
DP1312EA_HandleCollision(uid, uid_len, 0);
} else {
// 没有更多卡片
break;
}
}
}
// 主函数
int TypeA_AntiColl(void) {
DP1312EA_Config();
while (1) {
FindAllCards();
if (cardCount > 0) {
// 处理所有检测到的卡片
for (uint8_t i = 0; i < cardCount; i++) {
// 打印UID
nfc_platform_log("Card %d UID: ", i);
for (uint8_t j = 0; j < detectedCards[i].uid_len; j++) {
nfc_platform_log("%02X ", detectedCards[i].uid[j]);
}
nfc_platform_log("\n");
}
}
//Delay_ms(500); // 延时后再检测
}
}