Files
portable_modules/nfc/vendor/dp1312ea/Antcoll.c
2026-07-20 10:48:38 +08:00

329 lines
9.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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); // 延时后再检测
}
}