当前位置: 首页 > article >正文

FPM383C指纹模块超详解 附驱动

0. 本人使用环境介绍

0.1 硬件环境

  • ESP32-C3
  • FPM383C指纹模块
  • 一根破旧的usb数据线

0.2 软件环境

  • Clion2024.2.2
  • ESP-IDF5.3.1
  • Clion插件ESP-IDF

1. 硬件接口说明

1.1  UART

  •  UART 缺省波特率为 57.6Kbps,数据格式:8 位数据位,2 位停止位,无校验位;

  • UART 波特率可以通过指令进行设置,范围从 9600 至 115200;

  • 如果主控是 MCU(3.3V),则直接与 UART_TD 和 UART_RD 连接;如果主控是 PC,则需要挂接RS232 电平转换设备。

1.2  USB

  • 标准 USB 接口,内嵌 USB 通讯协议;

  • 兼容 USB2.0,工作在 Full Speed;

  • 默认 VID=0x2109;默认 PID=0x7638;

1.3 UART 与 USB 协同工作

  • 主控即可通过 UART 或 USB 与指纹模组通讯;

  • 两个接口只能单独工作,不支持同时工作;

  • 两个接口执行相同的协议和命令;

  • 两个接口共享同一个数据缓冲区;

2. 业务类指令集

2.1 通用指令集

2.1.1 验证用获取图像PS_GetImage

2.1.1 代码实现


/**
 * 从指纹传感器获取图像
 *
 * 该函数通过UART向指纹传感器发送指令,请求获取当前图像,并接收传感器的响应
 * 根据响应中的状态码判断图像获取是否成功,以及图像质量是否符合要求
 *
 * @return uint8_t 返回状态码:
 *         - 0: 获取图像成功
 *         - 1: 图像不清晰,请重新采集
 *         - 2: 获取图像失败或其他错误
 */


uint8_t Finger_GetImage() {
    // 准备发送给指纹传感器的数据包
    uint8_t sent_data[13] = {
            0xEF, 0x01,             // 包头
            0xFF, 0xFF, 0xFF, 0xFF, // 默认设备地址
            0x01,                   // 包标识
            0x00, 0x03,             // 包长度
            0x01,                   // 指令码
            0x00,                   // 参数
            0x00, 0x5              // 校验和
    };
    // 通过UART发送数据包
    uart_write_bytes(UART_NUM_0, sent_data, 13);
    // 准备接收指纹传感器的响应数据
    uint8_t get_data[64];
    // 读取UART接收到的数据,等待最多100ms
    int st = uart_read_bytes(UART_NUM_0, get_data, 64, 100 / portTICK_PERIOD_MS);
    // 检查读取状态
    if (st >= 0) {
        // 根据响应数据中的状态码判断图像获取结果
        if (get_data[6] == 0x07 && get_data[10] == 0x00) {
            printf("获取图像成功\r\n");
            return 0;
        } else if (get_data[6] == 0x07 && get_data[10] == 0x01) {
            printf("图像不清晰,请重新采集\r\n");
            return 1;
        }
    }
    // 如果读取失败或响应数据不符合预期,则返回错误码
    return 2;
}

2.1.2 生成特征PS_GenChar

2.1.2 代码实现


/**
 * 生成指纹特征
 *
 * 本函数通过UART向指纹模块发送指令,生成指纹特征
 *
 * @param buffer 指纹数据缓冲区
 * @return uint8_t
 *         - 0: 特征生成成功
 *         - 1: 特征生成失败
 *         - 2: UART读写错误
 */
uint8_t Finger_GenChar(uint8_t buffer) {
    // 构造发送数据包
    uint8_t sent_data[13] = {
            0xEF, 0x01,             // 包头
            0xFF, 0xFF, 0xFF, 0xFF, // 默认设备地址
            0x01,                   // 包标识
            0x00, 0x04,             // 包长度
            0x02,                   // 指令码
            '\0',                   // 参数
            '\0', '\0'              // 校验和
    };
    // 将缓冲区数据放入发送数据包中
    sent_data[10] = buffer;
    // 计算校验和
    uint16_t sum = sent_data[6] + sent_data[7] + sent_data[8] + sent_data[9] + sent_data[10];
    // 将校验和放入发送数据包中
    sent_data[11] = sum >> 8;
    sent_data[12] = sum;

    // 通过UART发送数据包
    uart_write_bytes(UART_NUM_0, sent_data, 13);
    // 接收指纹模块返回的数据
    uint8_t get_data[64];
    int st = uart_read_bytes(UART_NUM_0, get_data, 64, 100 / portTICK_PERIOD_MS);
    // 根据返回数据判断特征生成结果
    if (st >= 0) {
        if (get_data[6] == 0x07 && get_data[10] == 0x00) {
            printf("生成特征成功\r\n");
            return 0;
        } else if (get_data[6] == 0x07 && get_data[10] == 0x01) {
            printf("生成特征失败\r\n");
            return 1;
        }
    }
    // 如果读写错误,返回2
    return 2;
}

2.1.3 搜索指纹PS_Search

2.1.3 代码实现

/**
 * 搜索指纹指令
 * 
 * 本函数通过UART向指纹模块发送搜索指令,并接收搜索结果
 * 搜索指令是一个固定格式的字节序列,通过UART发送给指纹模块
 * 接收到的数据显示搜索结果,包括成功、收包错误或搜索失败
 * 
 * @return uint8_t 返回0表示搜索成功,返回1表示搜索失败或通信错误
 */
uint8_t FINGER_Search(void)
{
    // 搜索指纹的指令序列,包含必要的指令码和参数
    uint8_t command[17]={
            0xEF,0x01,
            0xFF,0xFF,0xFF,0xFF,
            0x01,
            0x00,0x08,
            0x04,
            0x01,
            0x00,0x00,
            0xFF,0xFF,
            0x02,0x0C
    };
    
    // 通过UART发送搜索指令
    uart_write_bytes(UART_NUM_1,command,17);
    
    // 接收指纹模块返回的数据
    uint8_t recv_data[64]={0};
    int len=uart_read_bytes(UART_NUM_1,recv_data,64,500/portTICK_PERIOD_MS);
    
    // 检查接收到的数据长度
    if(len>0)
    {
        // 根据接收数据的内容判断搜索结果
        if(recv_data[6]==0x07 && recv_data[9]==0x00)
        {
            printf("搜索成功\r\n");
            return 0;
        }
        else if(recv_data[6]==0x07 && recv_data[9]==0x01)
        {
            printf("收包错误\r\n");
        }
        else if(recv_data[6]==0x07 && recv_data[9]==0x09)
        {
            printf("搜索失败\r\n");
        }
    }
    
    // 如果没有接收到数据或接收到的数据不匹配任何条件,则返回1
    return 1;
}

2.1.4 合并特征 PS_RegModel

2.1.4 代码实现

/**
 * 注册指纹模型
 *
 * 本函数通过串口发送指令以注册指纹模型,并根据返回结果判断注册是否成功
 *
 * @return uint8_t 返回注册状态码:
 *         0 - 合并成功
 *         1 - 收包错误
 *         2 - 合并失败
 *         3 - 通信失败或其他错误
 */
uint8_t Finger_RegModel() {
    // 准备发送的数据包,包含包头、设备地址、包标识、包长度、指令码、参数和校验和
    uint8_t sent_data[13] = {
            0xEF, 0x01,             // 包头
            0xFF, 0xFF, 0xFF, 0xFF, // 默认设备地址
            0x01,                   // 包标识
            0x00, 0x03,             // 包长度
            0x05,                   // 指令码
            0x00,                   // 参数
            0x00, 0x09              // 校验和
    };

    // 通过UART发送数据包
    uart_write_bytes(UART_NUM_0, sent_data, 13);

    // 准备接收数据缓冲区
    uint8_t get_data[64];

    // 通过UART读取返回数据,设置超时时间为100ms
    int st = uart_read_bytes(UART_NUM_0, get_data, 64, 100 / portTICK_PERIOD_MS);

    // 检查读取状态
    if (st >= 0) {
        // 根据返回数据判断注册结果
        if (get_data[6] == 0x07 && get_data[10] == 0x00) {
            printf("合并成功\r\n");
            return 0;
        } else if (get_data[6] == 0x07 && get_data[10] == 0x01) {
            printf("收包错误\r\n");
            return 1;
        } else if (get_data[6] == 0x07 && get_data[10] == 0x01) {
            printf("合并失败\r\n");
            return 2;
        }
    }

    // 如果通信失败或其他错误,返回3
    return 3;
}

2.1.5 储存模板PS_StoreChar

2.1.5 代码实现


/**
 * 函数: Finger_StoreChar
 *
 * 描述: 将一个字符的数据存储到指定的页面ID中。
 *
 * 参数:
 * - buffer: 要存储的字符数据。
 * - pageID: 目标页面的ID。
 *
 * 返回值:
 * - 0: 存储成功。
 * - 1: 收包错误。
 * - 2: 超出指纹库范围。
 * - 3: 通信失败或其他错误。
 */
uint8_t Finger_StoreChar(uint8_t buffer, uint16_t pageID) {
    // 构造要发送的数据包
    uint8_t sent_data[15] = {
            0xEF, 0x01,             // 包头
            0xFF, 0xFF, 0xFF, 0xFF, // 默认设备地址
            0x01,                   // 包标识
            0x00, 0x03,             // 包长度
            0x06,                   // 指令码
            '\0',                   // 缓冲区
            '\0', '\0',                   //位置号
            '\0', '\0'             // 校验和
    };

    // 将要存储的字符数据放入数据包中
    sent_data[10] = buffer;

    // 计算数据包的校验和
    uint16_t sum =
            sent_data[6] + sent_data[7] + sent_data[8] + sent_data[9] + sent_data[10] + sent_data[11] + sent_data[12];
    sent_data[11] = pageID >> 8;
    sent_data[12] = pageID;
    sent_data[13] = sum >> 8;
    sent_data[14] = sum;

    // 通过UART发送数据包
    uart_write_bytes(UART_NUM_0, sent_data, 15);

    // 接收响应数据
    uint8_t get_data[64];
    int st = uart_read_bytes(UART_NUM_0, get_data, 64, 100 / portTICK_PERIOD_MS);

    // 根据响应数据判断存储结果
    if (st >= 0) {
        if (get_data[6] == 0x07 && get_data[10] == 0x00) {
            printf("储存成功\r\n");
            return 0;
        } else if (get_data[6] == 0x07 && get_data[10] == 0x01) {
            printf("收包错误\r\n");
            return 1;
        } else if (get_data[6] == 0x07 && get_data[10] == 0x01) {
            printf("超出指纹库范围\r\n");
            return 2;
        }
    }
    return 3;
}

2.1.6 搜索指纹PS_Search

2.1.6 代码实现


/**
 * 搜索指纹指令
 *
 * 本函数通过UART向指纹模块发送搜索指令,并接收搜索结果
 * 搜索指令是一个固定格式的字节序列,通过UART发送给指纹模块
 * 接收到的数据显示搜索结果,包括成功、收包错误或搜索失败
 *
 * @return uint8_t 返回0表示搜索成功,返回1表示搜索失败或通信错误
 */
uint8_t FINGER_Search(void)
{
    // 搜索指纹的指令序列,包含必要的指令码和参数
    uint8_t command[17]={
            0xEF,0x01,
            0xFF,0xFF,0xFF,0xFF,
            0x01,
            0x00,0x08,
            0x04,
            0x01,
            0x00,0x00,
            0xFF,0xFF,
            0x02,0x0C
    };

    // 通过UART发送搜索指令
    uart_write_bytes(UART_NUM_1,command,17);

    // 接收指纹模块返回的数据
    uint8_t recv_data[64]={0};
    int len=uart_read_bytes(UART_NUM_1,recv_data,64,500/portTICK_PERIOD_MS);

    // 检查接收到的数据长度
    if(len>0)
    {
        // 根据接收数据的内容判断搜索结果
        if(recv_data[6]==0x07 && recv_data[9]==0x00)
        {
            printf("搜索成功\r\n");
            return 0;
        }
        else if(recv_data[6]==0x07 && recv_data[9]==0x01)
        {
            printf("收包错误\r\n");
        }
        else if(recv_data[6]==0x07 && recv_data[9]==0x09)
        {
            printf("搜索失败\r\n");
        }
    }

    // 如果没有接收到数据或接收到的数据不匹配任何条件,则返回1
    return 1;
}

2.1.7 休眠指令PS_Sleep

2.1.7 代码实现

/**
 * @brief 控制指纹模块进入休眠模式
 * 
 * 该函数通过UART向指纹模块发送休眠指令,使模块进入低功耗状态。
 * 主要包括以下几个步骤:
 * 1. 组装休眠指令的数据包。
 * 2. 通过UART发送指令包。
 * 3. 等待并接收指纹模块的响应。
 * 4. 解析响应,判断休眠指令是否执行成功。
 * 
 * @return uint8_t 
 *         - 0: 指纹模块休眠成功
 *         - 1: 指纹模块休眠失败
 */
uint8_t Driver_Finger_Sleep()
{
    // 组装发送给指纹模块的休眠指令包
    uint8_t command[12] = {
        0xEF, 0x01,             // 包头
        0xFF, 0xFF, 0xFF, 0xFF, // 默认设备地址
        0x01,                   // 包标识
        0x00, 0x03,             // 包长度
        0x33,                   // 指令码
        0x00, 0x37              // 校验和
    };

    // 通过UART发送休眠指令包
    uart_write_bytes(UART_NUM_1, command, 12);

    // 初始化接收缓冲区
    uint8_t recv_data[64] = {0};

    // 等待并接收指纹模块的响应
    int len =
        uart_read_bytes(UART_NUM_1, recv_data, 64, 100 / portTICK_PERIOD_MS);

    // 判断接收到的响应长度是否大于0
    if (len > 0)
    {
        // 检查响应中的特定字段,判断休眠指令是否执行成功
        if (recv_data[6] == 0x07 && recv_data[9] == 0x00)
        {
            // 休眠成功
            printf("指纹模块休眠成功\r\n");
            return 0;
        }
    }

    // 休眠失败
    printf("指纹模块休眠失败\r\n");
    return 1;
}

通用指令更到这  待更新后续!!!

原文地址:https://blog.csdn.net/m0_60824353/article/details/143311392
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.kler.cn/a/369565.html

相关文章:

  • MPP音视频总结
  • Matlab 疲劳驾驶检测
  • 麒麟V10、UOS系统实现在线合并多个Word文件
  • MySQL 之 索引
  • Claude Financial Data Analyst:基于Claude的金融数据分析工具!免费开源!
  • 关于git上传文件冲突
  • 从docker中导出已经存在的容器
  • 【设计模式系列】适配器模式(九)
  • MySQL 8 下载与安装攻略
  • 第十届文荣奖华丽开幕,郁葱以青春与努力绽放青年演员光芒
  • 新手铲屎官提问,有哪几款噪音低的宠物空气净化器推荐
  • TypeScript-类型注解知识点详解
  • 驾校管理系统|基于java和小程序的驾校管理系统设计与实现(源码+数据库+文档)
  • ubuntu服务器离线安装pytorch(cpu版本)
  • Go Web开发登录功能实现
  • 【C++】哈希冲突的解决办法:闭散列 与 开散列
  • 学 Python 还是学 Java?——来自程序员的世纪困惑!
  • 求解亥姆霍兹方程
  • llama.cpp基础知识与原理导读
  • CSP/信奥赛C++刷题训练:经典二分例题(2):洛谷P1678:烦恼的高考志愿