实现RFID逻辑

This commit is contained in:
2026-04-14 23:40:46 +08:00
parent 65478d9f02
commit a6359364fd
7 changed files with 970 additions and 1 deletions

160
Core/Bsp/bsp_rc522.h Normal file
View File

@@ -0,0 +1,160 @@
#ifndef __BSP_RC522_H
#define __BSP_RC522_H
#include "main.h"
#ifdef __cplusplus
extern "C" {
#endif
/* RC522 典型 UID 最大长度为 10 字节 */
#define RC522_UID_MAX_LEN 10U
// ================== 站点UID白名单用户可根据实际卡片填写 ==================
// 站点1A卡片 UID: 29 AF 22 07
#define STATION_1_UID {0x29, 0xAF, 0x22, 0x07}
// 站点2B卡片 UID: 1B 45 F3 06
#define STATION_2_UID {0x1B, 0x45, 0xF3, 0x06}
// 站点枚举(可扩展)
typedef enum {
STATION_NONE = 0,
STATION_1 = 1, // 29 AF 22 07
STATION_2 = 2, // 1B 45 F3 06
// 可继续添加更多站点
} station_id_t;
/**
* @brief 根据UID判断属于哪个站点
* @param uid UID字节数组
* @param uid_len UID长度
* @return station_id_t 站点编号
*/
station_id_t rc522_match_station(const uint8_t *uid, uint8_t uid_len);
/*
* RUN 提示灯策略:
* 1) 轮询到卡片后点亮一段时间 (RC522_RUN_LED_HOLD_MS)
* 2) 超时自动熄灭
* 如需关闭该功能,设置 RC522_RUN_LED_ENABLE 为 0
*/
#ifndef RC522_RUN_LED_ENABLE
#define RC522_RUN_LED_ENABLE 1U
#endif
#ifndef RC522_RUN_LED_HOLD_MS
#define RC522_RUN_LED_HOLD_MS 300U
#endif
/* 按当前板卡默认 RUN_LED 低电平点亮 */
#ifndef RC522_RUN_LED_ON_LEVEL
#define RC522_RUN_LED_ON_LEVEL GPIO_PIN_RESET
#endif
/* 最近卡缓存超时时间:超过该时间认为缓存失效 */
#ifndef RC522_CACHE_EXPIRE_MS
#define RC522_CACHE_EXPIRE_MS 1500U
#endif
/*
* 是否使用 IRQ 触发后再读卡:
* 0 = 纯轮询(推荐先用)
* 1 = 依赖 IOR 中断触发(需要在 EXTI 回调中调用 rc522_irq_callback
*/
#ifndef RC522_USE_IRQ_TRIGGER
#define RC522_USE_IRQ_TRIGGER 0U
#endif
/**
* @brief RC522 读卡状态
*/
typedef enum {
RC522_OK = 0,
RC522_NO_CARD,
RC522_ERR_TIMEOUT,
RC522_ERR_CRC,
RC522_ERR_BCC,
RC522_ERR_SPI,
RC522_ERR_PARAM,
RC522_ERR_INTERNAL
} rc522_status_t;
/**
* @brief 最近一次读到的卡片信息
*/
typedef struct {
uint8_t valid; // 1: 有效卡信息, 0: 无效
uint8_t uid[RC522_UID_MAX_LEN]; // UID 原始字节
uint8_t uid_len; // UID 长度 (支持 4/7/10)
uint8_t sak; // Select Acknowledge
uint16_t atqa; // Answer To Request, 高字节在前
uint32_t last_seen_tick_ms; // 最近一次读到该卡的系统毫秒时间
} rc522_card_info_t;
/**
* @brief 初始化 RC522 模块 (SPI + 寄存器)
* @note SPI1 已由 CubeMX 初始化,本函数只做 RC522 芯片侧初始化。
*/
rc522_status_t rc522_init(void);
/**
* @brief 轮询一次读卡,并缓存结果
* @param out_card 可选输出,为 NULL 时仅更新内部缓存
* @return rc522_status_t
*/
rc522_status_t rc522_poll(rc522_card_info_t *out_card);
/**
* @brief RC522 周期服务函数(推荐在任务中调用)
* @param out_card 可选输出,为 NULL 时仅更新内部状态
* @return RC522_OK: 本次成功读到卡; RC522_NO_CARD: 当前无卡; 其他: 读卡异常
*/
rc522_status_t rc522_service(rc522_card_info_t *out_card);
/**
* @brief 获取最近一次成功读到的卡片信息
* @param out_card 输出参数
* @return 1: 成功复制, 0: 当前无有效卡信息
*/
uint8_t rc522_get_last_card(rc522_card_info_t *out_card);
/**
* @brief 当前是否存在有效缓存卡
* @return 1: 有效, 0: 无效
*/
uint8_t rc522_has_valid_card(void);
/**
* @brief 判断当前卡是否“新卡事件”(与上次输出不同)
* @param out_card 输出参数
* @return 1: 新卡, 0: 非新卡或无卡
*/
uint8_t rc522_get_new_card(rc522_card_info_t *out_card);
/**
* @brief 清除内部缓存的最近卡片信息
*/
void rc522_clear_last_card(void);
/**
* @brief 将 UID 格式化为 HEX 字符串 (例如 "DE AD BE EF")
* @param card 卡片信息
* @param out_str 输出缓冲区
* @param out_len 输出缓冲区长度
* @return 1: 成功, 0: 参数错误或缓冲区不足
*/
uint8_t rc522_uid_to_string(const rc522_card_info_t *card, char *out_str, uint16_t out_len);
/**
* @brief EXTI 回调入口(可选)
* @param GPIO_Pin EXTI 引脚号
*/
void rc522_irq_callback(uint16_t GPIO_Pin);
#ifdef __cplusplus
}
#endif
#endif /* __BSP_RC522_H */