基于STM32F103的FM1702驱动程序

发布于:2025-07-29 ⋅ 阅读:(13) ⋅ 点赞:(0)

基于STM32F103微控制器与复旦微电子FM1702SL射频读卡芯片的驱动开发方案,整合了硬件配置、寄存器操作和通信协议实现:


一、硬件连接设计

1. 管脚映射表
FM1702SL引脚 STM32F103引脚 功能说明
VDD 3.3V 电源输入
GND GND 地线
SCK PA5(SPI1_SCK) SPI时钟
MISO PA6(SPI1_MISO) 主入从出
MOSI PA7(SPI1_MOSI) 主出从入
CS PA4(GPIO) 片选控制
RST PA3(GPIO) 复位信号
IRQ PA2(GPIO) 中断输入
2. 电路设计要点
  • 电源滤波:在VDD和GND间并联104陶瓷电容+10μF电解电容
  • 天线匹配:采用1.35μH电感+27pF电容的LC谐振电路(参考)
  • ESD防护:在RST和CS引脚串联1kΩ电阻并联TVS管

二、软件架构设计

1. 驱动层结构
// 文件结构
fm1702_driver/
├── hal/
│   ├── spi.c       # SPI底层驱动
│   └── gpio.c      # GPIO控制
├── src/
│   ├── fm1702.c    # 核心驱动
│   └── fm1702.h    # 寄存器定义
└── example/
    └── read_card.c # 示例应用
2. 关键数据结构
typedef struct {
    uint8_t  version;    // 固件版本
    uint16_t atqa;       // ATS响应
    uint8_t  sak;        // SEL_RES
    uint8_t  uid[4];     // UID存储
} FM1702_CardInfo;

typedef enum {
    FM1702_STATE_IDLE,
    FM1702_STATE_SELECTED,
    FM1702_STATE_AUTHENTICATED
} FM1702_State;

三、核心功能实现

1. SPI初始化(HAL库)
void FM1702_SPI_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    // 使能时钟
    __HAL_RCC_SPI1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();

    // 配置SPI引脚
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // SPI参数配置
    SPI_HandleTypeDef hspi1;
    hspi1.Instance = SPI1;
    hspi1.Init.Mode = SPI_MODE_MASTER;
    hspi1.Init.Direction = SPI_DIRECTION_2LINES;
    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
    HAL_SPI_Init(&hspi1);
}
2. 寄存器操作
// 读寄存器函数
uint8_t FM1702_ReadReg(uint8_t addr) {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // CS拉低
    SPI_SendByte(addr & 0x7F); // 发送地址(低电平有效)
    uint8_t data = SPI_ReceiveByte();
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // CS拉高
    return data;
}

// 写寄存器函数
void FM1702_WriteReg(uint8_t addr, uint8_t data) {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    SPI_SendByte(addr | 0x80); // 地址最高位设1表示写操作
    SPI_SendByte(data);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}
3. 射频卡检测流程
FM1702_State FM1702_DetectCard(void) {
    FM1702_WriteReg(0x0D, 0x07); // 设置射频场强度
    
    // 发送请求命令
    FM1702_WriteReg(0x0A, 0x52); // Request命令
    HAL_Delay(10);
    
    if(FM1702_ReadReg(0x0A) & 0x01) { // 检测到卡片
        uint8_t uid[4];
        FM1702_ReadUID(uid); // 读取UID
        return FM1702_STATE_SELECTED;
    }
    return FM1702_STATE_IDLE;
}

四、中断处理机制

1. 中断服务例程
void EXTI0_IRQHandler(void) {
    if(EXTI_GetITStatus(EXTI_LINE0) != RESET) {
        FM1702_ClearIRQFlag(); // 清除中断标志
        // 处理卡片插入/移除事件
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); // LED状态翻转
    }
    EXTI_ClearITPendingBit(EXTI_LINE0);
}
2. 中断配置
void FM1702_EnableIRQ(void) {
    EXTI_InitTypeDef EXTI_InitStruct = {0};
    
    // 配置EXTI0为下降沿触发
    EXTI_InitStruct.Line = EXTI_LINE0;
    EXTI_InitStruct.Trigger = EXTI_TRIGGER_FALLING;
    EXTI_InitStruct.LineCmd = ENABLE;
    HAL_EXTI_SetConfigLine(&EXTI_InitStruct);
}

五、调试与优化

1. 逻辑分析仪捕获
  • 使用Saleae捕获SPI通信波形,验证时序是否符合手册要求(时钟极性CPOL=0,相位CPHA=0)
2. 常见问题解决
现象 可能原因 解决方案
无法检测卡片 天线匹配不良 调整L/C参数至1.35μH+27pF
通信错误 SPI时钟频率过高 降低至1MHz以下
数据校验失败 CRC计算错误 实现ISO14443A CRC算法

六、完整代码示例

// 读卡器初始化
void FM1702_Init(void) {
    FM1702_GPIO_Init();    // 配置GPIO
    FM1702_SPI_Init();     // 初始化SPI
    FM1702_Reset();        // 硬件复位
    FM1702_WriteReg(0x02, 0x8D); // 启动射频场
}

// 主循环处理
int main(void) {
    FM1702_Init();
    while(1) {
        FM1702_State state = FM1702_DetectCard();
        if(state == FM1702_STATE_SELECTED) {
            // 执行读写操作
            uint8_t block_data[16];
            FM1702_ReadBlock(0x08, block_data);
        }
    }
}

七、性能优化建议

  1. 低功耗模式:在IDLE状态下关闭射频场(设置Reg02[3]=0)
  2. DMA传输:使用DMA实现SPI数据传输(配置DMA1_Stream0)
  3. 加密加速:利用STM32硬件加密模块加速DES运算

八、参考资料

  1. 《FM1702SL数据手册》(复旦微电子官网)
  2. 代码 基于STM32F103的FM1702驱动程序 youwenfan.com/contentcsa/72737.html
  3. STM32F103参考手册(ARM Cortex-M3内核)
  4. ISO/IEC 14443-3标准文档(卡片通信协议)

网站公告

今日签到

点亮在社区的每一天
去签到