发帖
37 0 2

【外设移植】FPM383C指纹模块+Ai-M61-32S

WT_0213
论坛元老

132

主题

1983

回帖

1万

积分

论坛元老

勤劳的打工人

积分
19892
Ai-M61-Kit外设移植教程 14184 37 2023-12-30 13:01:37
──── 0人觉得很赞 ────

使用道具 举报

2023-12-30 13:22:29
2023-12-30 13:47:23
本帖最后由 WT_0213 于 2024-4-22 21:49 编辑


gitee 地址: https://gitee.com/lazy-ai/ai-m61-32s-fpm383c.git
上传的附件: fpm383c.zip (5.44 KB, 下载次数: 53)



2024-4-19 13:58:21


接线方式:
Ai-M61-32s FPM383C
3v3 Pin3
GND PIN6
IO23 PIN5
IO24 PIN4


2023-12-30 13:05:35
本帖最后由 WT_0213 于 2024-4-22 21:54 编辑

接下来上干货,之所以放在二楼是因为怕编辑太多发布失败丢失数据。
FPM383C.h
  1. #ifndef __FPM383C_H
  2. #define __FPM383C_H

  3. #include "stdint.h"

  4. void FPM383C_Init(void);
  5. void FPM383C_SendData(int length, uint8_t buffer[]);
  6. void FPM383C_Sleep(void);

  7. uint8_t FPM383C_GetImage(uint32_t timeout);
  8. uint8_t FPM383C_GenChar(uint32_t timeout);
  9. uint8_t FPM383C_Search(uint32_t timeout);
  10. uint8_t FPM383C_Empty(uint32_t timeout);
  11. uint8_t FPM383C_Delete(uint16_t pageID,uint32_t timeout);
  12. uint8_t FPM383C_ControlLED(uint8_t PS_ControlLEDBuf[],uint32_t timeout);
  13. void FPM383C_Identify(void);
  14. void FPM383C_Enroll(uint16_t pageID,uint16_t timeout);

  15. #endif
复制代码
FPM383C.c
  1. #include "FPM383C.h"
  2. #include "stdio.h"
  3. #include "stdlib.h"
  4. #include "string.h"
  5. #include "bflb_mtimer.h"
  6. #include "bflb_dma.h"
  7. #include "bflb_uart.h"
  8. #include "bflb_gpio.h"
  9. #include "log.h"

  10. //控制模块LED灯颜色
  11. uint8_t PS_BlueLEDBuf[16] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x07,0x3C,0x03,0x01,0x01,0x00,0x00,0x49};
  12. uint8_t PS_RedLEDBuf[16] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x07,0x3C,0x02,0x04,0x04,0x02,0x00,0x50};
  13. uint8_t PS_GreenLEDBuf[16] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x07,0x3C,0x02,0x02,0x02,0x02,0x00,0x4C};

  14. //休眠指令-设置传感器进入休眠模式
  15. uint8_t PS_SleepBuf[12] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x03,0x33,0x00,0x37};

  16. //清空指纹库-删除 flash 数据库中所有指纹模板。
  17. uint8_t PS_EmptyBuf[12] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x03,0x0D,0x00,0x11};

  18. //取消指令-取消自动注册模板和自动验证指纹。如表 2-1 中加密等级设置为 0 或 1 情况下支持此功能
  19. uint8_t PS_CancelBuf[12] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x03,0x30,0x00,0x34};

  20. //自动注册模板-一站式注册指纹,包含采集指纹、生成特征、组合模板、存储模板等功能。加密等级设置为 0 或 1 情况下支持此功能。
  21. uint8_t PS_AutoEnrollBuf[17] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x08,0x31,'\0','\0',0x04,0x00,0x16,'\0','\0'};

  22. // 验证用获取图像-验证指纹时,探测手指,探测到后录入指纹图像存于图像缓冲区。返回确认码表示:录入成功、无手指等。
  23. uint8_t PS_GetImageBuf[12] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x03,0x01,0x00,0x05};

  24. //生成特征值-将图像缓冲区中的原始图像生成指纹特征文件存于模板缓冲区
  25. uint8_t PS_GetCharBuf[13] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x04,0x02,0x01,0x00,0x08};

  26. //搜索指纹-以模板缓冲区中的特征文件搜索整个或部分指纹库。若搜索到,则返回页码。加密等级设置为 0 或 1 情况下支持
  27. uint8_t PS_SearchBuf[17] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x08,0x04,0x01,0x00,0x00,0xFF,0xFF,0x02,0x0C};

  28. //删除模板-删除 flash 数据库中指定 ID 号开始的N 个指纹模板
  29. uint8_t PS_DeleteBuf[16] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x07,0x0C,'\0','\0',0x00,0x01,'\0','\0'};

  30. //设置名为fpm383c_uart的外设句柄,用来执行串口指令的发送
  31. struct bflb_device_s *fpm383c_uart;

  32. //指纹ID和验证指纹的分数
  33. uint16_t pageID,score;

  34. //USART串口接收缓冲数组
  35. uint8_t USART_ReceiveBuf[20];

  36. //主循环状态标志位
  37. uint8_t ScanStatus = 0;

  38. /**
  39. * @brief 获取状态
  40. *
  41. * @param Timeout
  42. */
  43. void FPM383C_ReceiveData(uint16_t Timeout)
  44. {
  45.   uint8_t i = 0;
  46.   // 检测缓冲区是否有数据
  47.   while(bflb_uart_rxavailable(fpm383c_uart) == 0 && (--Timeout))
  48.   {
  49.     bflb_mtimer_delay_ms(1);
  50.   }
  51.   // 轮询fpm383c_uart接收到的字符
  52.   while(bflb_uart_rxavailable(fpm383c_uart) > 0)
  53.   {
  54.     bflb_mtimer_delay_ms(2);
  55.         // 获取数据并放入缓冲数组
  56.     USART_ReceiveBuf[i++] = bflb_uart_getchar(fpm383c_uart);
  57.     if(i > 15) break;
  58.   }
  59. }

  60. /// @brief 初始化FPM383C指纹模块
  61. void FPM383C_Init(){
  62.         // 声明 gpio句柄
  63.     struct bflb_device_s* gpio;
  64.         // FPM383C 模块默认波特率为 57600
  65.     struct bflb_uart_config_s cfg = {
  66.         .baudrate = 57600,
  67.         .data_bits = UART_DATA_BITS_8,
  68.         .stop_bits = UART_STOP_BITS_1,
  69.         .parity = UART_PARITY_NONE,
  70.                .flow_ctrl = UART_FLOWCTRL_NONE,
  71.         .rx_fifo_threshold = 7,
  72.         .tx_fifo_threshold = 7
  73.     };

  74.         // 初始化FPM383C指纹模块UART
  75.     gpio = bflb_device_get_by_name("gpio");
  76.     fpm383c_uart = bflb_device_get_by_name("uart1");

  77.     //将GPIO_23和GPIO_24设置为TX和RX
  78.     bflb_gpio_uart_init(gpio, GPIO_PIN_23, GPIO_UART_FUNC_UART1_TX);
  79.     bflb_gpio_uart_init(gpio, GPIO_PIN_24, GPIO_UART_FUNC_UART1_RX);

  80.     bflb_uart_init(fpm383c_uart, &cfg);
  81. }

  82. /// @brief USART串口发送数据
  83. /// @param length 发送数组长度
  84. /// @param FPM383C_DataBuf 需要发送的功能数组
  85. void FPM383C_SendData(int length,uint8_t FPM383C_DataBuf[])
  86. {

  87.         for(int i = 0;i<length;i++)
  88.         {
  89.         bflb_uart_put(fpm383c_uart,(uint8_t *)&FPM383C_DataBuf[i], 1);
  90.         }
  91. }

  92. /// @brief 发送休眠指令 确认码=00H 表示休眠设置成功。确认码=01H 表示休眠设置失败。
  93. /// @param  
  94. void FPM383C_Sleep(void)
  95. {
  96.         FPM383C_SendData(12,PS_SleepBuf);
  97. }

  98. /// @brief 验证用获取图像
  99. /// @param timeout 接收数据的超时时间
  100. /// @return 确认码
  101. uint8_t FPM383C_GetImage(uint32_t timeout)
  102. {
  103.         uint8_t tmp;
  104.         FPM383C_SendData(12,PS_GetImageBuf);
  105.         FPM383C_ReceiveData(timeout);
  106.         tmp = (USART_ReceiveBuf[6] == 0x07 ? USART_ReceiveBuf[9] : 0xFF);
  107.         memset(USART_ReceiveBuf,0xFF,sizeof(USART_ReceiveBuf));
  108.         return tmp;
  109. }

  110. /// @brief 将图像缓冲区中的原始图像生成指纹特征文件存于模板缓冲区。
  111. /// @param timeout 接收数据的超时时间
  112. /// @return 确认码
  113. uint8_t FPM383C_GenChar(uint32_t timeout)
  114. {
  115.         uint8_t tmp;
  116.         FPM383C_SendData(13,PS_GetCharBuf);
  117.         FPM383C_ReceiveData(timeout);
  118.         tmp = (USART_ReceiveBuf[6] == 0x07 ? USART_ReceiveBuf[9] : 0xFF);
  119.         memset(USART_ReceiveBuf,0xFF,sizeof(USART_ReceiveBuf));
  120.         return tmp;
  121. }

  122. /// @brief 发送搜索指纹指令
  123. /// @param timeout 接收数据的超时时间
  124. /// @return 确认码
  125. uint8_t FPM383C_Search(uint32_t timeout)
  126. {
  127.         FPM383C_SendData(17,PS_SearchBuf);
  128.         FPM383C_ReceiveData(timeout);
  129.         return (USART_ReceiveBuf[6] == 0x07 ? USART_ReceiveBuf[9] : 0xFF);
  130. }

  131. /// @brief 删除指定指纹指令
  132. /// @param pageID 需要删除的指纹ID号
  133. /// @param timeout 接收数据的超时时间
  134. /// @return 确认码
  135. uint8_t FPM383C_Delete(uint16_t pageID,uint32_t timeout)
  136. {
  137.         uint8_t tmp;
  138.         PS_DeleteBuf[10] = (pageID>>8);
  139.         PS_DeleteBuf[11] = (pageID);
  140.         PS_DeleteBuf[14] = (0x15+PS_DeleteBuf[10]+PS_DeleteBuf[11])>>8;
  141.         PS_DeleteBuf[15] = (0x15+PS_DeleteBuf[10]+PS_DeleteBuf[11]);
  142.         FPM383C_SendData(16,PS_DeleteBuf);
  143.         FPM383C_ReceiveData(timeout);
  144.         tmp = (USART_ReceiveBuf[6] == 0x07 ? USART_ReceiveBuf[9] : 0xFF);
  145.         memset(USART_ReceiveBuf,0xFF,sizeof(USART_ReceiveBuf));
  146.         return tmp;
  147. }

  148. /// @brief 清空指纹库
  149. /// @param timeout 接收数据的超时时间
  150. /// @return 确认码
  151. uint8_t FPM383C_Empty(uint32_t timeout)
  152. {
  153.         uint8_t tmp;
  154.         FPM383C_SendData(12,PS_EmptyBuf);
  155.         FPM383C_ReceiveData(timeout);
  156.         tmp = (USART_ReceiveBuf[6] == 0x07 ? USART_ReceiveBuf[9] : 0xFF);
  157.         memset(USART_ReceiveBuf,0xFF,sizeof(USART_ReceiveBuf));
  158.         return tmp;
  159. }

  160. /// @brief 发送控制灯光指令
  161. /// @param PS_ControlLEDBuf 不同颜色的协议数据
  162. /// @param timeout 接收数据的超时时间
  163. /// @return 确认码
  164. uint8_t FPM383C_ControlLED(uint8_t PS_ControlLEDBuf[],uint32_t timeout)
  165. {
  166.         uint8_t tmp;
  167.         FPM383C_SendData(16,PS_ControlLEDBuf);
  168.         FPM383C_ReceiveData(timeout);
  169.         tmp = (USART_ReceiveBuf[6] == 0x07 ? USART_ReceiveBuf[9] : 0xFF);
  170.         memset(USART_ReceiveBuf,0xFF,sizeof(USART_ReceiveBuf));
  171.         return tmp;
  172. }

  173. /// @brief 验证指纹是否注册
  174. /// @param  
  175. void FPM383C_Identify(void)
  176. {
  177.         if(FPM383C_GetImage(2000) == 0x00)
  178.         {
  179.                 if(FPM383C_GenChar(2000) == 0x00)
  180.                 {
  181.                         struct bflb_device_s *led = bflb_device_get_by_name("gpio");
  182.                         if(FPM383C_Search(2000) == 0x00)
  183.                         {
  184.                                 score = (int)((USART_ReceiveBuf[10] << 8) + USART_ReceiveBuf[11]);
  185.                                 LOG_E("解锁成功 指纹ID:%d\r\n",(int)score);
  186.                                 FPM383C_ControlLED(PS_GreenLEDBuf,1000);
  187.                
  188.                                 bflb_gpio_init(led, GPIO_PIN_14, GPIO_OUTPUT);
  189.                                 bflb_gpio_set(led, GPIO_PIN_14);
  190.                                 bflb_mtimer_delay_ms(1000);
  191.                                 bflb_gpio_reset(led, GPIO_PIN_14);
  192.                                 // 重置接收数据缓存
  193.                                 memset(USART_ReceiveBuf,0xFF,sizeof(USART_ReceiveBuf));
  194.                                 return;
  195.                         }else{
  196.                                 LOG_E("解锁失败\r\n");
  197.                                 bflb_gpio_init(led, GPIO_PIN_12, GPIO_OUTPUT);
  198.                                 bflb_gpio_set(led, GPIO_PIN_12);
  199.                                 bflb_mtimer_delay_ms(1000);
  200.                                 bflb_gpio_reset(led, GPIO_PIN_12);
  201.                                 // 重置接收数据缓存
  202.                                 memset(USART_ReceiveBuf,0xFF,sizeof(USART_ReceiveBuf));
  203.                                 return;
  204.                         }
  205.                 }
  206.         }
  207. }

  208. /// @brief 自动注册
  209. /// @param pageID 输入需要注册的指纹ID号,取值范围0—59
  210. /// @param timeout 设置注册指纹超时时间,因为需要按压四次手指,建议大于10000(即10s)
  211. void FPM383C_Enroll(uint16_t pageID,uint16_t timeout)
  212. {
  213.         LOG_E("注册指纹ID: %d\r\n", pageID);
  214.         PS_AutoEnrollBuf[10] = (pageID>>8);
  215.         PS_AutoEnrollBuf[11] = (pageID);
  216.         PS_AutoEnrollBuf[15] = (0x54+PS_AutoEnrollBuf[10]+PS_AutoEnrollBuf[11])>>8;
  217.         PS_AutoEnrollBuf[16] = (0x54+PS_AutoEnrollBuf[10]+PS_AutoEnrollBuf[11]);
  218.         FPM383C_SendData(17,PS_AutoEnrollBuf);
  219.         FPM383C_ReceiveData(timeout);
  220.         if(USART_ReceiveBuf[9] == 0x00)
  221.         {
  222.                 LOG_E("指纹注册完成\r\n");
  223.                 // 亮绿灯2秒
  224.                 FPM383C_ControlLED(PS_GreenLEDBuf,2000);
  225.                 // 重置接收数据缓存
  226.                 memset(USART_ReceiveBuf,0xFF,sizeof(USART_ReceiveBuf));
  227.                 return;
  228.         }
  229.         else if(timeout == 0)
  230.         {
  231.                 // 超时取消注册
  232.                 FPM383C_SendData(12,PS_CancelBuf);
  233.                 bflb_mtimer_delay_ms(50);
  234.                 // 重置接收数据缓存
  235.                 memset(USART_ReceiveBuf,0xFF,sizeof(USART_ReceiveBuf));
  236.         }
  237.         // 亮红灯2秒
  238.         FPM383C_ControlLED(PS_RedLEDBuf,2000);
  239. }
复制代码
main.c
  1. #include "bflb_mtimer.h"
  2. #include "bflb_dma.h"
  3. #include "bflb_uart.h"
  4. #include "bflb_l1c.h"
  5. #include "board.h"
  6. #include "time.h"
  7. #include "FPM383C.h"

  8. //主要用来控制注册和识别
  9. int ISRegister = 1;

  10. int main(void)
  11. {
  12.     board_init();
  13.    
  14.     // 初始化FPM383C指纹模块
  15.     FPM383C_Init();

  16.     // 清空指纹库
  17.     FPM383C_Empty(2000);

  18.     // 随机id
  19.     srand((unsigned int)time(NULL));
  20.     int fpm383cPageId = rand() % 59 + 1;

  21.     while (1) {
  22.         if(ISRegister){
  23.             // 开启注册指纹,指纹ID:0—59, 超时时间尽量在 10秒左右,需要录入四次
  24.             FPM383C_Enroll(fpm383cPageId, 10000);
  25.             // 休息600毫秒进行下次注册
  26.             bflb_mtimer_delay_ms(600);
  27.             // 模块休眠一下
  28.             FPM383C_Sleep();
  29.             ISRegister = 0;
  30.         }else{
  31.             // 开启自动识别
  32.             FPM383C_Identify();
  33.         }

  34.         bflb_mtimer_delay_ms(10);
  35.     }
  36. }
复制代码

CMakeLists.txt
  1. cmake_minimum_required(VERSION 3.15)

  2. include(proj.conf)

  3. find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
  4. # User
  5. sdk_add_compile_definitions(-DCONFIG_CLI_CMD_ENABLE)
  6. #sdk_add_compile_definitions(-DBL616_DHCP_DEBUG)
  7. target_sources(app PRIVATE
  8.                 FPM383C.c)

  9. sdk_add_include_directories(.)

  10. sdk_set_main_file(main.c)

  11. project(fpm383c)
复制代码

其他文件都是通用的,就不放了。



2023-12-30 13:08:45
指纹模块测试工具:

https://r0.hlktech.com/download/HLK-FPM383C/3/指纹测试工具.zip
串口测试工具:
上传的附件: 串口测试工具.zip (411.02 KB, 下载次数: 16)

2023-12-30 13:24:23
本帖最后由 lazy 于 2023-12-30 13:48 编辑

很详细,厉害
2023-12-30 14:45:24
学到了
2023-12-30 23:46:04
学到了
2023-12-31 10:44:01
要是都能够统一放到一个仓库就好了,测试完成都pr一下
2024-1-2 08:57:12
优秀啊!
您需要登录后才可以回帖 立即登录
高级模式
1234下一页
统计信息
  • 会员数: 30702 个
  • 话题数: 44755 篇