├── 蓝牙锁通信命令测试.txt ├── R301T指纹模块测试指令.txt ├── Application ├── my_time.h ├── moto.h ├── beep.h ├── battery.h ├── my_time.c ├── set_params.h ├── wt5700.h ├── beep.c ├── sm4_dpwd.h ├── rtc_chip.h ├── led_button.h ├── fm260b.h ├── sm4_mcu.h ├── touch_tsm12.h ├── moto.c ├── operate_code.h ├── set_params.c ├── battery.c ├── ble_init.h ├── wt5700.c ├── sm4_dpwd.c ├── inter_flash.h ├── main.c ├── touch_tsm12.c ├── r301t.h ├── rtc_chip.c ├── fm260b.c ├── inter_flash.c ├── sm4_mcu.c ├── led_button.c ├── r301t.c ├── ble_init.c └── operate_code.c ├── README.md ├── config ├── readme ├── custom_board.h └── uicr_config.h └── FM260B指纹模块测试命令.txt /蓝牙锁通信命令测试.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startpot/ble_door_nrf52832/HEAD/蓝牙锁通信命令测试.txt -------------------------------------------------------------------------------- /R301T指纹模块测试指令.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startpot/ble_door_nrf52832/HEAD/R301T指纹模块测试指令.txt -------------------------------------------------------------------------------- /Application/my_time.h: -------------------------------------------------------------------------------- 1 | #ifndef MY_TIME_H__ 2 | #define MY_TIME_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | time_t my_mktime(struct tm *time); 9 | double my_difftime(time_t time1,time_t time2); 10 | 11 | #endif //MY_TIME_H__ 12 | -------------------------------------------------------------------------------- /Application/moto.h: -------------------------------------------------------------------------------- 1 | #ifndef MOTO_H__ 2 | #define MOTO_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void moto_init(void); 9 | 10 | void moto_open(uint32_t open_time); 11 | void moto_close(uint32_t close_time); 12 | 13 | #endif //MOTO_H__ 14 | -------------------------------------------------------------------------------- /Application/beep.h: -------------------------------------------------------------------------------- 1 | #ifndef BEEP_H__ 2 | #define BEEP_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define BEEP_OPEN 50 //蜂鸣器打开时间(ms) 9 | #define BEEP_DELAY 100 //每次蜂鸣器响完等待的时间 10 | 11 | void beep_init(void); 12 | void beep_didi(uint8_t number); 13 | 14 | #endif //BEEP_H__ 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # ble_door_nrf52832 3 | 基于nRF52832控制的蓝牙门锁
4 | 主要有触摸按键、LED显示、RTC时钟、指纹模块、蜂鸣器、电机6个部分。
5 | 6 | ## 2017.9.28 test 7 | 指纹模块已测试注册和搜索功能 8 | ## 2017.9.30 9 | 内部flash存储的相关程序,必须设置若干pstorage_handle_t,
10 | 保证读取的flash的handle是全局变量.
11 | ## 2017.10.12 12 | 程序中存储的数据结构体以及数据应该是4字节对齐的,
13 | 在程序中,应该在定义要存储的数据结构体时用#pragram pack(n)强制对齐和#pragram pack()取消强制对齐。 -------------------------------------------------------------------------------- /Application/battery.h: -------------------------------------------------------------------------------- 1 | #ifndef BATTERY_H__ 2 | #define BATTERY_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "nrf.h" 10 | #include "nrf_drv_saadc.h" 11 | #include "nrf_drv_ppi.h" 12 | #include "nrf_drv_timer.h" 13 | #include "nrf_delay.h" 14 | #include "boards.h" 15 | 16 | #include "app_error.h" 17 | #include "app_util_platform.h" 18 | 19 | #define SAMPLES_IN_BUFFER 5 20 | 21 | extern nrf_saadc_value_t battery_level_buffer[2][SAMPLES_IN_BUFFER]; 22 | extern uint16_t battery_level_value; 23 | 24 | void saadc_sampling_event_init(void); 25 | void saadc_sampling_event_enable(void); 26 | void saadc_init(void); 27 | void battery_level_init(void); 28 | 29 | #endif //BATTERY_H__ 30 | -------------------------------------------------------------------------------- /Application/my_time.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "my_time.h" 6 | 7 | 8 | time_t my_mktime(struct tm *time) { 9 | time->tm_mon =time->tm_mon +1; 10 | if((int)(time->tm_mon -= 2)<=0) { 11 | //1....12->11,12,1,....10 12 | time->tm_mon +=12; 13 | time->tm_year -=1; 14 | } 15 | 16 | return ( ( ( 17 | (unsigned long) ((time->tm_year +1990)/4 - (time->tm_year+1990)/100 + (time->tm_year+1990)/400 + 367*time->tm_mon/12 + time->tm_mday) +\ 18 | (time->tm_year +1990)*365 - 719499)*24 + time->tm_hour /**//* now have hours */ 19 | )*60 + time->tm_min /**//* now have minutes */ 20 | )*60 + time->tm_sec - 8*3600; /**//* finally seconds */ 21 | 22 | } 23 | 24 | double my_difftime(time_t time1,time_t time2) { 25 | return (double)(time1 - time2); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Application/set_params.h: -------------------------------------------------------------------------------- 1 | #ifndef SET_PARAMS_H__ 2 | #define SET_PARAMS_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include "pstorage.h" 8 | #include "ble_gap.h" 9 | 10 | #define SET_KEY_CHECK_NUMBER 3 11 | #define PARAMS_LEN 7 12 | 13 | 14 | //与动态口令相关的参量 15 | #define SM4_INTERVAL 60 16 | #define SM4_COUNTER 1234 17 | extern uint8_t SM4_challenge[4]; 18 | extern uint8_t key_store_tmp[6]; 19 | //种子的数组 20 | extern uint8_t seed[16]; 21 | 22 | extern pstorage_handle_t block_id_params; 23 | extern uint8_t flash_store_params[PARAMS_LEN + 1]; 24 | 25 | extern uint8_t KEY_CHECK_NUMBER; 26 | extern uint8_t LED_LIGHT_TIME; 27 | 28 | extern uint32_t OPEN_TIME; 29 | extern uint8_t DOOR_OPEN_HOLD_TIME; 30 | extern uint8_t BEEP_DIDI_NUMBER; 31 | extern uint8_t VOL_VALUE; 32 | extern uint8_t KEY_INPUT_USE_TIME; 33 | extern uint8_t MOTO_DIR; 34 | extern uint8_t TOUCH_DELAY; 35 | 36 | extern ble_gap_addr_t addr; 37 | 38 | void set_default_params(void); 39 | 40 | #endif //SET_PARAMS_H__ 41 | -------------------------------------------------------------------------------- /config/readme: -------------------------------------------------------------------------------- 1 | readme 2 | 3 | 4 | 5 | //工程移植---修改说明 6 | 1.添加nRF_Drivers后,必须修改nrf_drv_config.h中的相应端口define 7 | 如uart使能 8 | twi(iic)使能 9 | 10 | 2.要使用pstorage进行内部flash的存储,必须修改nRF_Drivers下的pstorage_platform.h的 11 | 43行 12 | #define PSTORAGE_NUM_OF_PAGES 1 13 | 修改为 14 | #define PSTORAGE_NUM_OF_PAGES 3 15 | 16 | 3使用device_manager后,相应的修改nRF_BLE下的device_manager_cnfg.h的 17 | 78行 18 | #define DM_GATT_CCCD_COUNT 2 19 | 修改为 20 | #define DM_GATT_CCCD_COUNT 4 21 | 22 | 92行 23 | #define DEVICE_MANAGER_APP_CONTEXT_SIZE 0 24 | 修改为 25 | #define DEVICE_MANAGER_APP_CONTEXT_SIZE 16 26 | 27 | 28 | 4使用saadc功能后,需要修改nrf_drv_config.h中369行 29 | #define SAADC_ENABLED 1 30 | 同时,由于使用了协议栈,在battery.c中 31 | static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(1) 32 | m_timer 不能使用timer0 33 | 34 | 35 | 36 | -----2017.8.23 37 | 完成增加配对密码,未完成的是uart不能指定相应的pin28 29 38 | 39 | ----2017.8.30 40 | 完成蓝牙串口和uart的初始化,同时完成部分指纹模块的调试 41 | ----2017.9.13 42 | 完成电池电量服务的功能 43 | ----2017.10.17 44 | 修改了蓝牙开锁和触摸屏输入密码的功能代码 45 | ----2017.10.23 46 | 低功耗模式:在蓝牙芯片停止广播进入低功耗后,主要的耗电芯片是触摸按键芯片 47 | 触摸按键的芯片设置为slow down 模式,可以减少功耗 -------------------------------------------------------------------------------- /Application/wt5700.h: -------------------------------------------------------------------------------- 1 | #ifndef WT_5700_H__ 2 | #define WT_5700_H__ 3 | 4 | #include 5 | #include "custom_board.h" 6 | #include "nrf_drv_gpiote.h" 7 | #include "nrf_gpiote.h" 8 | #include "nrf_drv_twi.h" 9 | 10 | /****************WT5700芯片的iic地址************/ 11 | #define WT5700_DEVICE_ADDR 0xE0 12 | #define WT5700_IIC_REAL_ADDR (WT5700_DEVICE_ADDR>>1) 13 | 14 | //实际板子的引脚 15 | #define WT5700_INT_PIN TOUCH_IIC_INT_PIN 16 | #define WT5700_IIC_SCL_PIN TOUCH_IIC_SCL_PIN 17 | #define WT5700_IIC_SDA_PIN TOUCH_IIC_SDA_PIN 18 | #define WT5700_IIC_EN_PIN TOUCH_IIC_EN_PIN 19 | 20 | /****************WT5700寄存器地址****************/ 21 | #define WT5700_SYS_CTL 0x00 22 | #define WT5700_SYS_CTL02 0x02 23 | #define WT5700_SYS_CTL03 0x03 24 | 25 | #define WT5700_SENSOR_DATA0 0x08 26 | #define WT5700_SENSOR_DATA1 0x09 27 | 28 | /********************************************/ 29 | ret_code_t wt5700_i2c_write_byte(uint8_t address, uint8_t data); 30 | ret_code_t wt5700_i2c_read_byte(uint8_t address, uint8_t *p_read_byte, uint8_t length); 31 | 32 | void wt5700_init(void); 33 | uint8_t wt5700_key_read(void); 34 | 35 | #endif //WT_5700_H__ 36 | -------------------------------------------------------------------------------- /Application/beep.c: -------------------------------------------------------------------------------- 1 | /********************** 2 | *四脚蜂鸣器 3 | **********************/ 4 | #include 5 | #include 6 | #include 7 | #include "nrf_delay.h" 8 | #include "nrf_gpio.h" 9 | #include "custom_board.h" 10 | #include "boards.h" 11 | 12 | #include "beep.h" 13 | 14 | /************************************* 15 | * 初始化蜂鸣器 16 | **************************************/ 17 | void beep_init(void) { 18 | nrf_gpio_cfg_output(BEEP_IN_PIN); 19 | //设置高 20 | nrf_gpio_pin_clear(BEEP_IN_PIN); 21 | #if defined(BLE_DOOR_DEBUG) 22 | printf("beep status set low\r\n"); 23 | #endif 24 | 25 | } 26 | 27 | /********************* 28 | * 蜂鸣器响一次 29 | *********************/ 30 | static void beep_didi_once(void) { 31 | nrf_gpio_pin_set(BEEP_IN_PIN); 32 | nrf_delay_ms(BEEP_OPEN); 33 | nrf_gpio_pin_clear(BEEP_IN_PIN); 34 | 35 | } 36 | 37 | /******************************************** 38 | *蜂鸣器响几次 39 | *in: number 蜂鸣器响的次数 40 | ********************************************/ 41 | void beep_didi(uint8_t number) { 42 | //蜂鸣器响 43 | for(int i = 0; i < number; i++) { 44 | beep_didi_once(); 45 | nrf_delay_ms(BEEP_DELAY); 46 | } 47 | //恢复蜂鸣器状态 48 | nrf_gpio_pin_clear(BEEP_IN_PIN); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /Application/sm4_dpwd.h: -------------------------------------------------------------------------------- 1 | #ifndef SM4_DPWD_H__ 2 | #define SM4_DPWD_H__ 3 | 4 | #include 5 | 6 | #define SM_DPWD_KEY_LEN_MIN (128/8) 7 | #define SM_DPWD_CHALLENGE_LEN_MIN (4) 8 | #define SM_DPWD_LEN_MAX (10) 9 | #define SM_HASH_OUT_LEN (32) 10 | 11 | #define SM_DPDW_KEY_LEN (16) // uint8_ts 12 | #define SM_DPDW_T_LEN (16) // uint8_ts 13 | 14 | 15 | int SM4_DPasswd(uint8_t * pKey, uint64_t Time, uint16_t Interval, uint32_t Counter, \ 16 | uint8_t* pChallenge, uint8_t* pDynPwd); 17 | 18 | // SM4的动态口令生成算法输入、输出用例 19 | // K T C Q P(SM4) 20 | // 1234567890abcdef1234567890abcdef 1340783053 1234 5678 446720 21 | // 1234567890abcdefabcdef1234567890 1340783416 5621 3698 049845 22 | // 1234567890abcdef0987654321abcdef 1340783476 2584 2105 717777 23 | // 87524138025adcfeabfedc2584376195 1340783509 2053 6984 037000 24 | // 87524138025adcfe2584376195abfedc 1340783588 2058 3024 502206 25 | // 1234567890abcdefabcdef0987654321 1340783624 2056 2018 692843 26 | // adcfe87524138025abfedc2584376195 1340783652 2358 1036 902690 27 | // 58ade3698fe28dcb6925010dd236caef 1340783829 2547 2058 499811 28 | // 58ade365201d80cbdd236caef6925010 1340783771 6031 2058 565180 29 | // 65201d80cb58ade3dd236caef6925010 1340783815 6580 1047 724654 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /Application/rtc_chip.h: -------------------------------------------------------------------------------- 1 | #ifndef RTC_CHIP_H__ 2 | #define RTC_CHIP_H__ 3 | 4 | #include 5 | #include 6 | #include "sdk_errors.h" 7 | 8 | /*************************RTC-CHIP的地址****************************/ 9 | #define RTC_CHIP_DEVICE_ADDR 0xA2 10 | #define RTC_CHIP_REAL_ADDR (RTC_CHIP_DEVICE_ADDR>>1) 11 | 12 | /*************************IIC-pins*********************************/ 13 | #define RTC_CHIP_IIC_SCL_PIN RTC_IIC_SCL_PIN 14 | #define RTC_CHIP_IIC_SDA_PIN RTC_IIC_SDA_PIN 15 | 16 | /**************RTC PF85163 REGISTER MAP****************/ 17 | #define PCF85163_Control_1_ADDR 0x00 18 | #define PCF85163_Control_2_ADDR 0x01 19 | #define PCF85163_VL_seconds_ADDR 0x02 20 | #define PCF85163_Minutes_ADDR 0x03 21 | #define PCF85163_Hours_ADDR 0x04 22 | #define PCF85163_Days_ADDR 0x05 23 | #define PCF85163_Weekdays_ADDR 0x06 24 | #define PCF85163_Century_months_ADDR 0x07 25 | #define PCF85163_Years_ADDR 0x08 26 | #define PCF85163_Minute_alarm_ADDR 0x09 27 | #define PCF85163_Hour_alarm_ADDR 0x0a 28 | #define PCF85163_Day_alarm_ADDR 0x0b 29 | #define PCF85163_Weekday_alarm_ADDR 0x0c 30 | #define PCF85163_CLKOUT_control_ADDR 0x0d 31 | #define PCF85163_Timer_control_ADDR 0x0e 32 | #define PCF85163_Timer_ADDR 0x0f 33 | 34 | 35 | void rtc_init(void); 36 | uint8_t rtc_time_write(struct tm *time_write); 37 | uint8_t rtc_time_read(struct tm *time_read); 38 | 39 | #endif //RTC_CHIP_H__ 40 | -------------------------------------------------------------------------------- /Application/led_button.h: -------------------------------------------------------------------------------- 1 | #ifndef LED_BUTTON_H__ 2 | #define LED_BUTTON_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "app_timer.h" 9 | 10 | #include "inter_flash.h" 11 | 12 | enum keys_type { 13 | super_keys= 0x00, 14 | normal_keys, 15 | unkown_keys 16 | }; 17 | 18 | extern bool is_key_value_get;//是否是正在获取键盘按键 19 | 20 | extern char key_express_value; 21 | 22 | #define KEY_INPUT_CHECKED_MAX_NUMBER 5 23 | 24 | #define KEY_MAX_NUMBER 12 25 | extern char key_input[KEY_MAX_NUMBER]; 26 | extern uint8_t key_input_site; 27 | 28 | extern char key_marry[KEY_LENGTH]; 29 | 30 | //输入的密码的时间 31 | extern struct tm key_input_time_tm; 32 | extern time_t key_input_time_t; 33 | 34 | //检测密码的次数 35 | extern uint8_t key_input_checked_number; 36 | extern time_t key_input_checked_locked_time_t; 37 | extern bool key_input_checked_locked; 38 | 39 | extern struct door_open_record open_record_now; 40 | 41 | extern bool is_background_lit; 42 | 43 | #define BUTTON_DETECTION_DELAY APP_TIMER_TICKS(50, APP_TIMER_PRESCALER) 44 | 45 | void leds_init(void); 46 | void leds_on(uint8_t led_pin, uint32_t ms); 47 | 48 | int ble_door_open(void); 49 | 50 | bool keys_input_check_super_keys(char *keys_input_p, uint8_t keys_input_length); 51 | bool keys_input_check_normal_keys(char *keys_input_p, uint8_t keys_input_length, time_t keys_input_time_t); 52 | bool keys_input_check_sm4_keys(char *keys_input_p, uint8_t keys_input_length, time_t keys_input_time_t); 53 | 54 | void door_open_record_flash(char *keys_input_p, uint8_t keys_input_length,time_t keys_input_time_t); 55 | void touch_finger_int_init(void); 56 | 57 | #endif //LED_BUTTON_H__ 58 | -------------------------------------------------------------------------------- /Application/fm260b.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * FM260B是一个指纹模块0x100个,采用uart通讯,默认波特率 57600bps 3 | * 模块端:3--TXD 4--RXD 6---touch(手指探测信号) 4 | * 5 | * 模块上电后,在100ms内完成系统引导和初始化,向上位机发送 6 | * 0x55 0x55,表示ready 7 | * 通讯协议 8 | * 命令包格式:包头(1byte:0x1B) 9 | * 地址码(1byte:0xFF) 10 | * 指令码(1byte:) 11 | * 参数1(2byte:命令附加第一参数,若无,为0x0000)高字节 12 | * 参数2(2byte:命令附加第二参数,若无,为0x0000)高字节 13 | * 校验和(1byte:从包头到参数2的所有字节的算术累计的低字节) 14 | * 应答包格式:包头(1byte:0x1B) 15 | * 指令码(1byte:原操作码) 16 | * 结果码(1byte:执行结果码) 17 | * 参数长度(1byte:返回参数字节数n,若无,则为0x00) 18 | * 参数1(1byte:) 19 | * 参数2(1byte:) 20 | * ........ 21 | * 参数n(1byte:) 22 | * 校验和(1byte:从包头到参数n的所有字节的算术累计和的低字节) 23 | * 24 | * 25 | ************************************************************************************/ 26 | #ifndef FM260B_H__ 27 | #define FM260B_H__ 28 | 29 | #include 30 | #include 31 | 32 | 33 | //上电后,系统发送准备好的码 DR:导纳电子 34 | #define DR_READY_CODE 0x55 35 | 36 | 37 | //包头、地址 38 | #define DR_FIG_START 0x1B 39 | #define DR_FIG_ADDER 0xFF 40 | //命令包指令码 41 | #define DR_FIG_CMD_SETSYS 0x00 42 | #define DR_FIG_CMD_READINFO 0x01 43 | #define DR_FIG_CMD_AUTOENROLL 0x20 44 | #define DR_FIG_CMD_AUTOSEARCH 0x22 45 | #define DR_FIG_CMD_DELETE 0x1C 46 | 47 | //应答包的数据位置 48 | #define DR_FIG_R_CMD_CODE_SITE 1 //bit1 49 | #define DR_FIG_R_RESULT_CODE_SITE 2 //bit2 50 | #define DR_FIG_R_PARAM_LEN_SITE 3 //bit3 51 | 52 | //正确命令包的应答结果码 53 | #define DR_FIG_R_EXE 0x00 54 | 55 | #define DR_FIG_R_FINISH_TRUE 0x01 56 | #define DR_FIG_R_FINISH_FALSE 0x02 57 | 58 | #define DR_FIG_R_FIG_MOVE 0x05 59 | #define DR_FIG_R_FIG_TOUCH 0x06 60 | 61 | //错误命令包的应答结果码 62 | #define DR_FIG_R_CMD_WRONG 0x40 63 | #define DR_FIG_R_PARAM_WRONG 0x41 64 | #define DR_FIG_R_SUM_WRONG 0x42 65 | 66 | 67 | extern bool fig_status; 68 | extern bool exe_result; 69 | extern bool is_fm260b_autoenroll; 70 | 71 | extern uint16_t dr_fig_param_first ; 72 | extern uint16_t dr_fig_param_second ; 73 | 74 | void fig_fm260b_send_autosearch(void); 75 | void fig_fm260b_reply_check(void); 76 | 77 | #endif //FM260B_H__ 78 | -------------------------------------------------------------------------------- /Application/sm4_mcu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file SM4_MCU.h 3 | */ 4 | #ifndef SM4_MCU_H__ 5 | #define SM4_MCU_H__ 6 | 7 | 8 | #include 9 | 10 | #define SM4_ENCRYPT 1 11 | #define SM4_DECRYPT 0 12 | 13 | /** 14 | * \brief SM4 context structure 15 | * // 用于保存加密模式和各轮子密钥的结构体 16 | */ 17 | struct sm4_context { 18 | uint32_t mode; /*!< encrypt/decrypt */ 19 | uint32_t sk[32]; /*!< SM4 subkeys */ 20 | }; 21 | 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | /** 28 | * \brief SM4 key schedule (128-bit, encryption) 29 | * 30 | * \param ctx SM4 context to be initialized 31 | * \param key 16-byte secret key 32 | */ 33 | void sm4_setkey_enc( struct sm4_context *ctx, unsigned char *key); 34 | 35 | /** 36 | * \brief SM4 key schedule (128-bit, decryption) 37 | * 38 | * \param ctx SM4 context to be initialized 39 | * \param key 16-byte secret key 40 | */ 41 | void sm4_setkey_dec(struct sm4_context *ctx, unsigned char *key); 42 | 43 | /** 44 | * \brief SM4-ECB block encryption/decryption 45 | * \param ctx SM4 context 46 | * \param mode SM4_ENCRYPT or SM4_DECRYPT 47 | * \param length length of the input data 48 | * \param input input block 49 | * \param output output block 50 | */ 51 | void sm4_crypt_ecb( struct sm4_context *ctx, \ 52 | int mode, 53 | int length, 54 | unsigned char *input, 55 | unsigned char *output); 56 | 57 | /** 58 | * \brief SM4-CBC buffer encryption/decryption 59 | * \param ctx SM4 context 60 | * \param mode SM4_ENCRYPT or SM4_DECRYPT 61 | * \param length length of the input data 62 | * \param iv initialization vector (updated after use) 63 | * \param input buffer holding the input data 64 | * \param output buffer holding the output data 65 | */ 66 | void sm4_crypt_cbc( struct sm4_context *ctx, 67 | int mode, 68 | int length, 69 | unsigned char *iv, 70 | unsigned char *input, 71 | unsigned char *output ); 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif /* sm4.h */ 78 | 79 | -------------------------------------------------------------------------------- /Application/touch_tsm12.h: -------------------------------------------------------------------------------- 1 | #ifndef TOUCH_TSM12_H__ 2 | #define TOUCH_TSM12_H__ 3 | 4 | #include 5 | #include "custom_board.h" 6 | #include "nrf_drv_gpiote.h" 7 | #include "nrf_gpiote.h" 8 | #include "nrf_drv_twi.h" 9 | 10 | 11 | /*************TSM12M的地址和引脚*********/ 12 | 13 | #define TSM12_DEVICE_ADDR 0xD0 14 | #define TSM12_IIC_REAL_ADDR (TSM12_DEVICE_ADDR>>1) 15 | 16 | #define TSM12_INT_PIN TOUCH_IIC_INT_PIN 17 | #define TSM12_IIC_SCL_PIN TOUCH_IIC_SCL_PIN 18 | #define TSM12_IIC_SDA_PIN TOUCH_IIC_SDA_PIN 19 | #define TSM12_IIC_EN_PIN TOUCH_IIC_EN_PIN 20 | 21 | 22 | /**************TSM12_TOUCH 寄存器地址****************/ 23 | 24 | #define TSM12_Sensitivity1 0x02 25 | #define TSM12_Sensitivity2 0x03 26 | #define TSM12_Sensitivity3 0x04 27 | #define TSM12_Sensitivity4 0x05 28 | #define TSM12_Sensitivity5 0x06 29 | #define TSM12_Sensitivity6 0x07 30 | #define TSM12_Sensitivityx_rst_val 10111011b 31 | 32 | #define TSM12_CTRL1 0x08 33 | #define TSM12_CTRL2 0x09 34 | #define TSM12_CTRL1_rst_val 00100010b 35 | //#define TSM12_CTRL2_rst_val 000001xx 36 | 37 | #define TSM12_Ref_rst1 0x0A 38 | #define TSM12_Ref_rst2 0x0B 39 | #define TSM12_Ref_rst1_rst_val 11111110b 40 | #define TSM12_Ref_rst2_rst_val 00001111b 41 | 42 | #define TSM12_Ch_hold1 0x0C 43 | #define TSM12_Ch_hold2 0x0D 44 | #define TSM12_Ch_hold1_rst_val 11111110b 45 | #define TSM12_Ch_hold2_rst_val 00001111b 46 | 47 | #define TSM12_Cal_hold1 0x0E 48 | #define TSM12_Cal_hold2 0x0F 49 | #define TSM12_Cal_hold1_rst_val 00000000b 50 | #define TSM12_Cal_hold2_rst_val 00000000b 51 | 52 | #define TSM12_Output1 0x10 53 | #define TSM12_Output2 0x11 54 | #define TSM12_Output3 0x12 55 | #define TSM12_Output1_rst_val 00000000b 56 | #define TSM12_Output2_rst_val 00000000b 57 | #define TSM12_Output3_rst_val 00000000b 58 | 59 | /*********************************************/ 60 | 61 | ret_code_t touch_iic_init(void); 62 | 63 | void tsm12_en_start(void); 64 | void tsm12_en_stop(void); 65 | 66 | ret_code_t touch_i2c_device_write_byte(uint8_t address, uint8_t data); 67 | ret_code_t touch_i2c_device_read_byte(uint8_t address, uint8_t *p_read_byte, uint8_t length); 68 | 69 | void tsm12_init(void); 70 | uint8_t tsm12_key_read(void); 71 | 72 | 73 | #endif //TOUCH_TSM12M_H 74 | -------------------------------------------------------------------------------- /Application/moto.c: -------------------------------------------------------------------------------- 1 | /***************************************** 2 | * FI BI fo bo fun 3 | * H L H L forward 4 | * L H L H backward 5 | * H H L L brake 6 | * L L open open standby(stop) 7 | *******************************************/ 8 | 9 | #include "moto.h" 10 | #include 11 | #include 12 | #include 13 | #include "nrf_gpio.h" 14 | #include "nrf_delay.h" 15 | 16 | #include "custom_board.h" 17 | 18 | #include "moto.h" 19 | #include "set_params.h" 20 | 21 | /*********************** 22 | *初始化电机 23 | ************************/ 24 | void moto_init(void) { 25 | //配置P.2(fi) P.3(bi) 26 | nrf_gpio_cfg_output(MOTO_FI); 27 | nrf_gpio_cfg_output(MOTO_BI); 28 | 29 | //设置为stand-by状态 30 | nrf_gpio_pin_clear(MOTO_FI); 31 | nrf_gpio_pin_clear(MOTO_BI); 32 | #if defined(BLE_DOOR_DEBUG) 33 | printf("moto stand_by\r\n"); 34 | #endif 35 | 36 | } 37 | 38 | /************************************************** 39 | *moto向前动ms 40 | *in ms 电机向前转动的时间,单位ms 41 | **************************************************/ 42 | static void moto_forward_ms(uint32_t ms) { 43 | //HB设置为HL 44 | nrf_gpio_pin_set(MOTO_FI); 45 | nrf_gpio_pin_clear(MOTO_BI); 46 | //延迟ms 47 | nrf_delay_ms(ms); 48 | nrf_gpio_pin_set(MOTO_BI); 49 | 50 | //延迟5ms 51 | nrf_delay_ms(5); 52 | //设置为stand-by状态 53 | nrf_gpio_pin_clear(MOTO_FI); 54 | nrf_gpio_pin_clear(MOTO_BI); 55 | 56 | } 57 | 58 | /*************************************************** 59 | *moto向后动ms 60 | *in:ms 电机向后转动的时间,单位ms 61 | ****************************************************/ 62 | static void moto_backward_ms(uint32_t ms) { 63 | //HB设置为LH 64 | nrf_gpio_pin_set(MOTO_BI); 65 | nrf_gpio_pin_clear(MOTO_FI); 66 | //延迟ms 67 | nrf_delay_ms(ms); 68 | nrf_gpio_pin_set(MOTO_FI); 69 | 70 | //延迟5ms 71 | nrf_delay_ms(5); 72 | //设置为stand-by状态 73 | nrf_gpio_pin_clear(MOTO_FI); 74 | nrf_gpio_pin_clear(MOTO_BI); 75 | 76 | } 77 | 78 | /************************************************************ 79 | *门打开 80 | *in: open_time 门打开的时间,单位0.1s 81 | *************************************************************/ 82 | void moto_open(uint32_t open_time) { 83 | moto_forward_ms(open_time*100); 84 | 85 | } 86 | 87 | /************************************************************ 88 | *门关闭 89 | *in: close_time 门关闭的时间,单位0.1s 90 | *************************************************************/ 91 | void moto_close(uint32_t close_time) { 92 | moto_backward_ms(close_time*100); 93 | 94 | } 95 | -------------------------------------------------------------------------------- /FM260B指纹模块测试命令.txt: -------------------------------------------------------------------------------- 1 | 系统设置 SetSys 2 | 空闲: 发送 1BFF00 0000 0000 1A 3 | 成功 1B00 01 00 1C 4 | 失败 1B00 02 00 1D 5 | 6 | 更新模板 发送 1BFF00 0002 0001 1D (允许更新) 7 | 1BFF00 0002 0002 1E (禁止更新) 8 | 成功 1B00 01 00 1C 9 | 失败 1B00 02 00 1D 10 | 11 | 照明灯状态 发送 1BFF00 0008 0001 23 (打开照明灯) 12 | 1BFF00 0008 0002 24 (关闭照明灯) 13 | 成功 1B00 01 00 1C 14 | 失败 1B00 02 00 1D 15 | 16 | 17 | 读取模块信息 ReadInfo 18 | 检查单个指纹模板 发送 1BFF01 0001 ID号 SUM(1C+ID号的算术和) 19 | TestID 有模板 1B01 01 00 1D 20 | 无模板 1B01 02 00 1E 21 | 22 | 读取指纹库索引表 发送 1BFF01 0010 起始ID号 SUM(2B+起始ID号的算术和) 23 | ReadIndex(连续64个) 完成 1B01 01 08 返回8字节,用bit表示有无 SUM(所有的算术和) 24 | 25 | 读取系统信息 发送 读取产品型号 1BFF01 0002 0001 1E 26 | ReadInfo 返回 产品型号 1B01 01 0A (FM-260S256的ASCII)46 4D 2D 32 36 30 53 32 35 36 6F(SUM) 27 | 发送 读取软件版本号和日期 1BFF01 0002 0002 1F 28 | 返回 12字节软件版本 1B01 01 0C (12字节的ASCII,如1.3 20170725) 31 2E 33 20 32 30 31 37 30 37 32 35 73(SUM) 29 | 发送 读取指纹库容量 1BFF01 0002 0003 20 30 | 返回 容量 1B01 01 02 01 00 20 31 | 发送 读取模块序列号SN 1BFF01 0002 0004 21 32 | 返回 SN号 1B01 01 04 54 C8 C4 86 87 33 | 探测手指 发送 1BFF01 0008 0001 24 34 | TestFinger 返回 有手指 1B01 01 00 1D 35 | 返回 无手指 1B01 02 00 1E 36 | 37 | 38 | 自动注册模板 AutoEnroll 39 | 发送 1BFF20 0001 ID号 SUM(3B+ID号的算术和) 40 | 返回 1 1B20 00 00 3B 41 | 2 录入第一个指纹 42 | 3 1B20 05 00 40 拿开手指数据包 43 | 4 1B20 06 00 41 2S内拿开手指后,发出方上手指数据包,若未拿开,2S后直接到第5步 44 | 5 录入第二个指纹 45 | 6 1B20 01 00 3C 两个指纹合成完成,发送此包,命令结束。失败的话,进入第7步 46 | 7 1B20 05 00 40 拿开手指数据包 47 | 8 1B20 06 00 41 2S内拿开手指后,发出方上手指数据包,若未拿开,2S后直接到第9步 48 | 9 再次执行2-5步 49 | 10 再次进行模板合成 50 | 1B20 01 00 3C 成功,命令结束 51 | 1B20 02 00 3D 失败,命令结束 52 | //注释:一般情况下,只需按两次手指,执行步骤:1-2-3-4-5-6 53 | // 不顺利的话,可能需要按4次手指(即第一次注册不成功,再次注册一次),执行步骤:1-2-3-4-5-6-7-8-2-3-4-5-10 54 | 55 | 56 | 自动搜索模板 AutoSearch 57 | 发送 1BFF22 0000 00FF(255) 3B 58 | 返回 1 1B22 00 00 3D 59 | 2 1B22 05 00 42 录好图像可以拿开手指 60 | 3.1 1B22 01 04 ID号(两字节) SCOLE(两字节) SUM 61 | 3.2 1B22 02 01 00 40 搜索区间无指纹模板 62 | 1B22 02 01 FF 3F 搜素区间内有指纹模板,但未搜索到 63 | 64 | 65 | 删除指纹模板 Delete 66 | 发送 1BFF1C 起始ID号(两字节) 结束ID号(两字节) SUM 67 | 返回 1B1C 01 00 38 删除指纹成功 68 | 1B1C 02 00 39 删除指纹失败 69 | 70 | 71 | 命令错误的应答包 72 | 指令错误 1B 指令码 40 00 SUM 73 | 参数错误 1B 指令码 41 00 SUM 74 | 校验和错误 1B 指令码 42 00 SUM -------------------------------------------------------------------------------- /Application/operate_code.h: -------------------------------------------------------------------------------- 1 | #ifndef OPERATE_CODE_H__ 2 | #define OPERATE_CODE_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "inter_flash.h" 10 | #include "ble_nus.h" 11 | 12 | 13 | 14 | extern bool is_ble_cmd_exe;//ble命令是否在执行 15 | 16 | extern struct tm time_record; 17 | extern time_t time_record_t; 18 | extern struct tm time_record_compare; 19 | extern time_t time_record_compare_t; 20 | 21 | 22 | //与获取和设置时间相关的变量 23 | extern struct tm time_set; 24 | extern struct tm time_get; 25 | extern time_t time_get_t; 26 | 27 | //设置触摸屏密码 28 | extern struct key_store_struct key_store_set; 29 | extern struct key_store_struct key_store_get; 30 | 31 | extern uint32_t record_length_get; 32 | 33 | extern uint8_t ble_operate_code; 34 | 35 | extern uint8_t fig_cmd_code; 36 | extern bool is_superkey_checked; 37 | 38 | extern uint8_t r301t_autoenroll_step; 39 | 40 | extern uint8_t enroll_fig_id[2]; 41 | extern uint8_t delete_fig_id[2]; 42 | 43 | /********************************** 44 | * 数据包的分析 45 | ***********************************/ 46 | #define OPERATE_CODE_BIT 0 //命令位,除去用户设置密码的命令 47 | 48 | //系统设置相关 49 | #define SET_SUPER_KEY 0x80 //设置管理员密码 50 | #define CHECK_SUPER_KEY 0x81 //验证超级密码 51 | 52 | #define SYNC_TIME 0x82 //对时 53 | #define SET_KEY_SEED 0x83 //设置种子 54 | 55 | #define SET_MAC 0x84 //设置mac 56 | #define GET_MAC 0x85 //获取mac 57 | 58 | #define SET_PARAMS 0x86 //设置工作参数 59 | 60 | #define GET_KEY_NOW 0x87 //TODO 后期移除 61 | 62 | #define GET_TIME 0x88 //获取时间 63 | 64 | #define GET_BATTERY_LEVEL 0x8C //返回电池电量 65 | 66 | #define USER_UNBIND_CMD 0x8F //用户解除绑定 67 | 68 | 69 | //触摸按键相关 70 | #define SET_TOUCH_KEY 0x90 //设置触摸屏密码 71 | #define DELETE_TOUCH_KEY 0x91 //删除触摸屏密码 72 | #define GET_TOUCH_KEY_STORE 0x92 //查询设置的键盘密码 73 | 74 | //开门记录相关 75 | #define GET_RECORD_NUMBER 0x9A //获取记录数量 76 | #define GET_RECENT_RECORD 0x9B //获取最近的记录 77 | 78 | 79 | //指纹模块相关 80 | #define ENROLL_FIG 0xA0 //注册指纹 81 | #define DELETE_FIG 0xA1 //删除指纹 82 | #define SEARCH_FIG 0xA2 //搜素指纹 83 | #define GET_FIG_INFO 0xA3 //获取指纹信息 84 | #define STOP_FIG 0xA4 //停止指纹模块 85 | #define DELETE_ALL_FIG 0xA5 //删除所有指纹 86 | #define GET_FIG_NUMBER 0xA6 //读取指纹个数 87 | #define GET_FIG_INDEXTABLE 0xA7 //读取指纹模块存储的指纹信息 88 | 89 | void ble_reply(uint8_t operate_code, uint8_t *reply_code, uint16_t reply_code_length); 90 | void open_fig(void); 91 | void close_fig(void); 92 | void operate_code_check(uint8_t *p_data, uint16_t length); 93 | 94 | #endif //OPERATE_CODE_H__ 95 | -------------------------------------------------------------------------------- /Application/set_params.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "pstorage.h" 5 | #include "ble_gap.h" 6 | #include "app_error.h" 7 | #include "inter_flash.h" 8 | 9 | #include "set_params.h" 10 | #include "moto.h" 11 | 12 | pstorage_handle_t block_id_params; 13 | uint8_t flash_store_params[PARAMS_LEN + 1]; 14 | 15 | //对比动态密码的变量 16 | uint8_t SM4_challenge[4] = {0x31,0x30,0x33,0x36}; 17 | uint8_t key_store_tmp[6]; 18 | 19 | //种子的数组 20 | uint8_t seed[16]; 21 | 22 | uint8_t KEY_CHECK_NUMBER; 23 | uint8_t LED_LIGHT_TIME; 24 | 25 | uint32_t OPEN_TIME; 26 | uint8_t DOOR_OPEN_HOLD_TIME; 27 | uint8_t BEEP_DIDI_NUMBER; 28 | uint8_t VOL_VALUE; //实际值<<4位 29 | uint8_t KEY_INPUT_USE_TIME; 30 | uint8_t MOTO_DIR; 31 | uint8_t TOUCH_DELAY;//按键的延迟 32 | 33 | 34 | //与设置mac有关的变量 35 | ble_gap_addr_t addr; 36 | 37 | /******************************************* 38 | * 初始化参数 39 | * in: none 40 | ******************************************/ 41 | void set_default_params(void) { 42 | uint32_t err_code; 43 | 44 | //设置动态密码的长度为6位ASCII 45 | KEY_CHECK_NUMBER = 5; 46 | LED_LIGHT_TIME = 5; 47 | 48 | //读出设置的参数(判读是否是后期设置的,如果不是,设定参数) 49 | //初始化参数 50 | //([0x77(w,如果为w则已经设置参数,如果不是则初始化参数), 51 | // 25(OPEN_TIME *0.1s),10(DOOR_OPEN_HOLD_TIME *0.1s), 52 | // 5(BEEP_DIDI_NUMBER 次数),5(LED_LIGHT_TIME *0.1s), 53 | // 5(KEY_CHECK_NUMBER) 次数]后面补0) 54 | err_code = pstorage_block_identifier_get(&block_id_flash_store, \ 55 | (pstorage_size_t)DEFAULT_PARAMS_OFFSET, &block_id_params); 56 | APP_ERROR_CHECK(err_code); 57 | pstorage_load(flash_store_params, &block_id_params, 16, 0); 58 | if(flash_store_params[0] == 'w') { 59 | OPEN_TIME = flash_store_params[1];//电机转动时间 60 | DOOR_OPEN_HOLD_TIME = flash_store_params[2];//开门保持时间 61 | BEEP_DIDI_NUMBER = flash_store_params[3];//蜂鸣器响次数 62 | VOL_VALUE = flash_store_params[4];//电池电压报警 63 | KEY_INPUT_USE_TIME = flash_store_params[5];//键盘密码输入密码有效时间,以10min为单位 64 | MOTO_DIR = flash_store_params[6];//电机的方向 65 | TOUCH_DELAY = flash_store_params[7];//按键的延迟 66 | } else { 67 | OPEN_TIME = 0x03;//电机转动时间 68 | DOOR_OPEN_HOLD_TIME = 0x32;//开门保持时间 50*0.1s=5s 69 | BEEP_DIDI_NUMBER = 0x05;//蜂鸣器响次数 70 | VOL_VALUE = 0x2C;//电池电压报警,左移4位,大致是5.0V(设定的欠压值) 71 | KEY_INPUT_USE_TIME = 0x05;//键盘密码输入密码有效时间,以10min为单位 72 | MOTO_DIR = 0;//电机方向 73 | TOUCH_DELAY = 10; 74 | } 75 | 76 | #if defined(BLE_DOOR_DEBUG) 77 | printf("params set:\r\n"); 78 | printf("moto time:%d\r\n", OPEN_TIME); 79 | printf("door open time:%d\r\n", DOOR_OPEN_HOLD_TIME); 80 | printf("beep didi number:%d\r\n", BEEP_DIDI_NUMBER); 81 | printf("led ligth time:%d\r\n", LED_LIGHT_TIME); 82 | printf("key check number:%d\r\n", KEY_CHECK_NUMBER); 83 | #endif 84 | 85 | } 86 | -------------------------------------------------------------------------------- /config/custom_board.h: -------------------------------------------------------------------------------- 1 | #ifndef CUSTOM_BOARD_H 2 | #define CUSTOM_BOARD_H 3 | 4 | /******************************************* 5 | -----13 LEDS--------- 6 | LED nRF52832 7 | 1 p0.1 8 | 2 p0.19 9 | 3 p0.28 10 | 4 p0.8 11 | 5 p0.25 12 | 6 p0.2 13 | 7 p0.20 14 | 8 p0.12 15 | 9 p0.11 16 | 10 p0.6 17 | 11 p0.31 18 | 12 p0.7 19 | 13 p0.3 20 | 21 | --------BEEP---------- 22 | beep_in nRF52832 23 | 2 p0.13 24 | 25 | --------touch button TSM12---------- 26 | touch ic nRF52832 27 | TOUCH_IIC_EN_PIN 29 28 | TOUCH_IIC_INT_PIN 30 29 | TOUCH_IIC_SCL_PIN 27 30 | TOUCH_IIC_SDA_PIN 26 31 | 32 | ---------rtc ic pcf85163t--------- 33 | rtc ic nRF52832 34 | RTC_IIC_SCL_PIN 27 35 | RTC_IIC_SDA_PIN 26 36 | 37 | ---------moto ic hg7881c---------- 38 | moto ic nRF52832 39 | MOTO_FI 15 40 | MOTO_BI 14 41 | 42 | ----------uart figprint ic r301t------------ 43 | 控制小板 nRF52832 指纹模块r301t 44 | J4-1(vt 3.3v) --- 6(touch_power) 45 | J4-2(vcc 5v) --- 1(vcc 5v) 46 | J4-3(rxd) 18 3(txd) 47 | J4-4(txd) 17 4(rxd) 48 | J4-5(gnd) --- 2(gnd) 49 | J4-6(touch_in) 16 5(touch_in) 50 | 51 | ********************************************/ 52 | //LEDs 53 | #define LED_1 23 54 | #define LED_2 19 55 | #define LED_3 28 56 | #define LED_4 8 57 | #define LED_5 25 58 | #define LED_6 2 59 | #define LED_7 20 60 | #define LED_8 12 61 | #define LED_9 11 62 | #define LED_10 6 63 | #define LED_11 31 64 | #define LED_12 7 65 | #define LED_13 3 66 | 67 | #define BSP_LED_0 LED_1 68 | #define BSP_LED_1 LED_2 69 | #define BSP_LED_2 LED_3 70 | #define BSP_LED_3 LED_4 71 | #define BSP_LED_4 LED_5 72 | #define BSP_LED_5 LED_6 73 | #define BSP_LED_6 LED_7 74 | #define BSP_LED_7 LED_8 75 | #define BSP_LED_8 LED_9 76 | #define BSP_LED_9 LED_10 77 | #define BSP_LED_10 LED_11 78 | #define BSP_LED_11 LED_12 79 | #define BSP_LED_12 LED_13 80 | 81 | #define LEDS_NUMBER 13 82 | 83 | #define LEDS_LIST { LED_1, LED_2, LED_3, LED_4, LED_5, LED_6, LED_7, \ 84 | LED_8, LED_9, LED_10, LED_11, LED_12, LED_13} 85 | 86 | #define BSP_LED_0_MASK (1< 2 | #include 3 | #include 4 | #include 5 | 6 | #include "nrf.h" 7 | #include "nrf_drv_saadc.h" 8 | #include "nrf_drv_ppi.h" 9 | #include "nrf_drv_timer.h" 10 | #include "nrf_delay.h" 11 | #include "boards.h" 12 | 13 | #include "app_error.h" 14 | #include "app_util_platform.h" 15 | 16 | #include "battery.h" 17 | #include "set_params.h" 18 | 19 | volatile uint8_t state = 1; 20 | static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(3); //因为使用了协议栈,不能使用定时器0 21 | static nrf_ppi_channel_t m_ppi_channel; 22 | static uint32_t m_adc_evt_counter; 23 | 24 | nrf_saadc_value_t battery_level_buffer[2][SAMPLES_IN_BUFFER]; 25 | uint16_t battery_level_value; 26 | 27 | static void timer_handler(nrf_timer_event_t event_type, void* p_context) { 28 | 29 | } 30 | 31 | void saadc_sampling_event_init(void) { 32 | ret_code_t err_code; 33 | 34 | err_code = nrf_drv_ppi_init(); 35 | APP_ERROR_CHECK(err_code); 36 | 37 | 38 | //初始化定时器 39 | err_code = nrf_drv_timer_init(&m_timer,NULL, timer_handler); 40 | APP_ERROR_CHECK(err_code); 41 | 42 | //setup m_timer for compare event every 4ms 43 | uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, 4); 44 | nrf_drv_timer_extended_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, \ 45 | ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false); 46 | nrf_drv_timer_enable(&m_timer); 47 | 48 | uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer, NRF_TIMER_CC_CHANNEL0); 49 | uint32_t saadc_sample_event_addr = nrf_drv_saadc_task_address_get(NRF_SAADC_TASK_SAMPLE); 50 | 51 | //setup ppi channel so that timer compare event is triggering sample task in SAADC 52 | err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel); 53 | APP_ERROR_CHECK(err_code); 54 | 55 | err_code = nrf_drv_ppi_channel_assign(m_ppi_channel, timer_compare_event_addr, saadc_sample_event_addr); 56 | APP_ERROR_CHECK(err_code); 57 | 58 | } 59 | 60 | void saadc_sampling_event_enable(void) { 61 | ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel); 62 | APP_ERROR_CHECK(err_code); 63 | 64 | } 65 | 66 | static void saadc_callback(nrf_drv_saadc_evt_t const * p_event) { 67 | 68 | if (p_event->type == NRF_DRV_SAADC_EVT_DONE) { 69 | ret_code_t err_code; 70 | 71 | err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER); 72 | APP_ERROR_CHECK(err_code); 73 | 74 | // int i; 75 | /* printf("ADC event number: %d\r\n",(int)m_adc_evt_counter); 76 | for (i = 0; i < SAMPLES_IN_BUFFER; i++) 77 | { 78 | printf("%d\r\n", p_event->data.done.p_buffer[i]); 79 | } 80 | m_adc_evt_counter++; 81 | */ 82 | battery_level_value = battery_level_buffer[0][0]; 83 | 84 | if(battery_level_value <= (uint16_t)(VOL_VALUE)<<4) { //0x02c0 大致为5.0V 85 | //亮起*灯 86 | // nrf_gpio_pin_clear(LED_8); 87 | } else { 88 | //否则灭*灯 89 | // nrf_gpio_pin_set(LED_8); 90 | } 91 | } 92 | 93 | } 94 | 95 | void saadc_init(void) { 96 | ret_code_t err_code; 97 | 98 | nrf_saadc_channel_config_t channel_config = 99 | NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);//电压输入到AIN2 100 | err_code = nrf_drv_saadc_init(NULL, saadc_callback); 101 | APP_ERROR_CHECK(err_code); 102 | 103 | err_code = nrf_drv_saadc_channel_init(0, &channel_config); 104 | APP_ERROR_CHECK(err_code); 105 | 106 | err_code = nrf_drv_saadc_buffer_convert(battery_level_buffer[0],SAMPLES_IN_BUFFER); 107 | APP_ERROR_CHECK(err_code); 108 | 109 | err_code = nrf_drv_saadc_buffer_convert(battery_level_buffer[1],SAMPLES_IN_BUFFER); 110 | APP_ERROR_CHECK(err_code); 111 | 112 | } 113 | 114 | static void battery_level_en(void) { 115 | //设置引脚为输出,置低 116 | nrf_gpio_cfg_output( BATTERY_LEVEL_EN ); 117 | nrf_gpio_pin_clear( BATTERY_LEVEL_EN ); 118 | // nrf_gpio_pin_set( BATTERY_LEVEL_EN ); 119 | 120 | //设置电压测量引脚为输入 121 | nrf_gpio_cfg_input(BATTERY_LEVEL_IN, NRF_GPIO_PIN_NOPULL); 122 | 123 | } 124 | 125 | 126 | 127 | void battery_level_init(void) { 128 | //使能电池电压输出端 129 | battery_level_en(); 130 | //初始化saadc sample event 131 | saadc_sampling_event_init(); 132 | //初始化saadc 133 | saadc_init(); 134 | //使能saadc sample event 135 | // saadc_sampling_event_enable(); 136 | 137 | } 138 | 139 | 140 | -------------------------------------------------------------------------------- /Application/ble_init.h: -------------------------------------------------------------------------------- 1 | #ifndef BLE_INIT_H__ 2 | #define BLE_INIT_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "app_timer.h" 11 | #include "ble_nus.h" 12 | 13 | 14 | #define IS_SRVC_CHANGED_CHARACT_PRESENT 0 15 | 16 | //以下2个变量会决定SD的运行空间(app_ram_base.h有定义),从而决定编译的时候,APP的运行空间设置 17 | #define CENTRAL_LINK_COUNT 0 18 | #define PERIPHERAL_LINK_COUNT 1 19 | 20 | #define APP_COMPANY_ID 0x5a5a //自定义厂商ID 21 | 22 | #define DEVICE_NAME "tecsheild_door"//蓝牙设备名称,蓝牙广播给其他设备的名字 23 | #define DEVICE_NAME_SIZE 31 //名称最长20 -2字节,设备规定最长31 24 | //#define MANUFACTURER_NAME "NordicSemiconductor" //设备制造商,Will be passed to Device Information Service 25 | //#define MODEL_NUMBER "nRF52"// 型号字符串. Will be passed to Device Information Service. 26 | //#define MANUFACTURER_ID 0x55AA55AA55 //设备制造商ID(可修改为自己的). Will be passed to Device Information Service. 27 | //#define ORG_UNIQUE_ID 0xEEBBEE //BLE组织联盟中唯一的ID. Will be passed to Device Information Service 28 | 29 | // UUID type for the Nordic UART Service (vendor specific),主要是可以用官方的APP测试 30 | #define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN 31 | 32 | #define APP_ADV_FAST_INTERVAL 64 //快速广播间隔(0.625 ms * 64 = 40 ms),广播间隔越大,越省电 33 | #define APP_ADV_FAST_TIMEOUT_IN_SECONDS 30//30 //快速广播超时,单位s 34 | #define APP_ADV_SLOW_INTERVAL 8000 //慢速广播间隔(0.625 ms * 8000 = 5 s),广播间隔越大,越省电 35 | #define APP_ADV_SLOW_TIMEOUT_IN_SECONDS 0//0//慢速广播超时,单位s 36 | 37 | 38 | #define APP_TIMER_PRESCALER 0 // Value of the RTC1 PRESCALER register 39 | #define APP_TIMER_MAX_TIMERS 4 40 | #define APP_TIMER_OP_QUEUE_SIZE 4 //Size of timer operation queues 41 | 42 | #define SECURITY_REQUEST_DELAY APP_TIMER_TICKS(4000, APP_TIMER_PRESCALER) //配对定时器时间间隔:4000MS 43 | #define BACKGROUND_LIT_DELAY APP_TIMER_TICKS(1000,APP_TIMER_PRESCALER) //重复背景灯时间间隔:1000MS 44 | 45 | 46 | #define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) 47 | #define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) 48 | #define SLAVE_LATENCY 0 49 | #define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) 50 | #define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000, APP_TIMER_PRESCALER) 51 | #define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000, APP_TIMER_PRESCALER) 52 | #define MAX_CONN_PARAMS_UPDATE_COUNT 3 53 | 54 | #define SEC_PARAM_BOND 0 55 | #define SEC_PARAM_MITM 1 56 | 57 | //如果下面的属性换成BLE_GAP_IO_CAPS_NONE,则无需输出配对密码,就可以配对 58 | #define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_DISPLAY_ONLY//BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */ 59 | #define SEC_PARAM_OOB 0 60 | #define SEC_PARAM_MIN_KEY_SIZE 7 61 | #define SEC_PARAM_MAX_KEY_SIZE 16 62 | 63 | //配对定时器 64 | //APP_TIMER_DEF(m_sec_req_timer_id); 65 | //开启背景灯的定时器 66 | APP_TIMER_DEF(m_backlit_timer_id); 67 | 68 | #define DEAD_BEEF 0xDEADBEEF 69 | 70 | //广播设备类型(外设种类) 71 | #define BIT_TOUCH BIT_0 72 | #define BIT_FIG BIT_1 73 | 74 | 75 | 76 | //#define APP_FEATURE_NOT_SUPPORTED BLE_GATT_STATUS_ATTERR_APP_BEGIN + 2 77 | 78 | #define UART_TX_BUF_SIZE 512 79 | #define UART_RX_BUF_SIZE 512 80 | 81 | 82 | extern ble_nus_t m_nus; /*Nordic UART Service*/ 83 | extern uint16_t m_conn_handle; 84 | //extern app_timer_id_t m_backlit_timer_id; 85 | 86 | extern uint8_t mac[8];//第一位:标志位,第二位:长度 87 | 88 | //以下3个变量是在uart service中保存的全局变量,交给operate_code_check函数去处理,蓝牙串口接收的数据 89 | extern bool operate_code_setted; 90 | extern uint8_t nus_data_recieve[BLE_NUS_MAX_DATA_LEN]; 91 | extern uint16_t nus_data_recieve_length; 92 | 93 | extern uint8_t nus_data_send[BLE_NUS_MAX_DATA_LEN];//20位,发送给蓝牙串口的数据 94 | extern uint32_t nus_data_send_length;//测试数据存储时,长度的全局变量 95 | 96 | //指纹模块发送给蓝牙芯片的数据 97 | extern uint8_t fig_recieve_data[UART_RX_BUF_SIZE]; 98 | extern uint16_t fig_recieve_data_length; 99 | 100 | //在编译的时候,代替弱连接,做ble的回调函数 101 | void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name); 102 | 103 | void timers_init(void); 104 | void application_timers_start(void); 105 | //BLE启动的设置函数 106 | void gap_params_init(void); 107 | void services_init(void); 108 | void conn_params_init(void); 109 | void ble_stack_init(void); 110 | void advertising_init(void); 111 | void adverts_start(void); 112 | void power_manage(void); 113 | void device_manager_init(bool erase_bonds); 114 | void buttons_leds_init(bool * p_erase_bonds); 115 | 116 | //与BLE有部分分离,接收板子UART0的数据,通过蓝牙进行传输出去 117 | //初始化uart,供给板子上的application使用,(工程的编译选项有NRF_LOG_USES_UART=1 ) 118 | void uart_init(void); 119 | 120 | #endif //BLE_INIT_H__ 121 | -------------------------------------------------------------------------------- /Application/wt5700.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "bsp.h" 6 | #include "nrf_delay.h" 7 | #include "nrf_drv_gpiote.h" 8 | #include "nrf_drv_twi.h" 9 | #include "nrf_gpiote.h" 10 | #include "nrf_gpio.h" 11 | #include "app_util_platform.h" 12 | #include "nrf_drv_config.h" 13 | 14 | #include "wt5700.h" 15 | #include "led_button.h" 16 | 17 | 18 | nrf_drv_twi_t m_twi_master_wt5700 = NRF_DRV_TWI_INSTANCE(1); //指定TWI1 19 | 20 | /*********************************************** 21 | *初始化触摸屏 22 | *in: none 23 | ************************************************/ 24 | static ret_code_t touch_iic_init(void) { 25 | ret_code_t ret; 26 | const nrf_drv_twi_config_t config = { 27 | .scl = WT5700_IIC_SCL_PIN, 28 | .sda = WT5700_IIC_SDA_PIN, 29 | .frequency = NRF_TWI_FREQ_100K, 30 | .interrupt_priority = APP_IRQ_PRIORITY_HIGH 31 | }; 32 | 33 | do { 34 | ret = nrf_drv_twi_init(&m_twi_master_wt5700, &config, NULL, NULL); 35 | if(NRF_SUCCESS != ret) { 36 | break; 37 | } 38 | nrf_drv_twi_enable(&m_twi_master_wt5700); 39 | } while(0); 40 | 41 | return ret; 42 | } 43 | 44 | /************************************** 45 | *往触摸屏的写某个地址的数据 46 | *in:address 地址 47 | data 数据 48 | *out: ret 0成功 49 | ****************************************/ 50 | ret_code_t wt5700_i2c_write_byte(uint8_t address, uint8_t data) { 51 | ret_code_t ret; 52 | uint8_t buffer[3] = {0x00,address,data}; 53 | ret = nrf_drv_twi_tx(&m_twi_master_wt5700, WT5700_IIC_REAL_ADDR, buffer, 3, false); 54 | 55 | return ret; 56 | } 57 | 58 | /************************************************************* 59 | *从触摸屏的某个地址开始读数据 60 | *in: address 地址 61 | *p_read_byte 读出数据的地址指针 62 | length 读出数据的长度 63 | *out: ret 0成功 64 | **************************************************************/ 65 | ret_code_t wt5700_i2c_read_byte(uint8_t address, uint8_t *p_read_byte, uint8_t length) { 66 | ret_code_t ret; 67 | 68 | do { 69 | //写地址 70 | uint8_t set_address[2] = {0x00,address}; 71 | 72 | ret = nrf_drv_twi_tx(&m_twi_master_wt5700, WT5700_IIC_REAL_ADDR, set_address, 2, true); 73 | if(ret !=NRF_SUCCESS) { 74 | break; 75 | } 76 | //读数据 77 | ret = nrf_drv_twi_rx(&m_twi_master_wt5700, WT5700_IIC_REAL_ADDR, p_read_byte, length); 78 | } while(0); 79 | 80 | return ret; 81 | } 82 | 83 | /****************************************** 84 | *初始化触摸屏芯片 85 | *in none 86 | *******************************************/ 87 | void wt5700_init(void) { 88 | uint8_t set_data; 89 | 90 | touch_iic_init(); 91 | 92 | //设置为slow down model 93 | set_data = 0x72;//62 94 | wt5700_i2c_write_byte(WT5700_SYS_CTL, set_data); 95 | 96 | //将芯片设置成单触摸模式,1/2win sense 97 | set_data = 0xc2; //c2 98 | wt5700_i2c_write_byte(WT5700_SYS_CTL02, set_data); 99 | 100 | // 101 | set_data = 0x02; //02 102 | wt5700_i2c_write_byte(WT5700_SYS_CTL03, set_data); 103 | 104 | #if defined(BLE_DOOR_DEBUG) 105 | printf("touch button init success\r\n"); 106 | #endif 107 | 108 | } 109 | 110 | /*************************************************** 111 | *读取触摸屏键值 112 | *in: none 113 | *out: key_value 触摸屏的键值 114 | ***************************************************/ 115 | uint8_t wt5700_key_read(void) { 116 | 117 | uint8_t wt5700_key_value = 0; 118 | uint8_t wt5700_temp[2]; 119 | uint8_t *p; 120 | 121 | p = wt5700_temp; 122 | 123 | if(is_key_value_get == true) { 124 | //读取通道8-11 125 | wt5700_i2c_read_byte(WT5700_SENSOR_DATA0, p, 0x01); 126 | //读取通道0-7 127 | wt5700_i2c_read_byte(WT5700_SENSOR_DATA1, (p+1), 0x01); 128 | 129 | if(*p !=0) { 130 | switch(*p) { 131 | case 0x01://SI8 132 | wt5700_key_value = '3'; 133 | break; 134 | case 0x02://SI9 135 | wt5700_key_value = '6'; 136 | break; 137 | case 0x04://SI10 138 | wt5700_key_value = '9'; 139 | break; 140 | case 0x08://SI11 141 | wt5700_key_value = 'b'; 142 | break; 143 | default: 144 | wt5700_key_value = 0; 145 | break; 146 | } 147 | } else if(*(p+1) !=0) { 148 | switch(*(p + 1)) { 149 | case 0x01://SI0 150 | wt5700_key_value = 'a'; 151 | break; 152 | case 0x02://SI1 153 | wt5700_key_value = '7'; 154 | break; 155 | case 0x04://SI2 156 | wt5700_key_value = '4'; 157 | break; 158 | case 0x08://SI3 159 | wt5700_key_value = '1'; 160 | break; 161 | case 0x10://SI4 162 | wt5700_key_value = '2'; 163 | break; 164 | case 0x20://SI5 165 | wt5700_key_value = '5'; 166 | break; 167 | case 0x40://SI6 168 | wt5700_key_value = '0'; 169 | break; 170 | case 0x80://SI7 171 | wt5700_key_value = '8'; 172 | break; 173 | default: 174 | wt5700_key_value = 0; 175 | break; 176 | } 177 | } 178 | } 179 | 180 | return wt5700_key_value; 181 | 182 | } 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /Application/sm4_dpwd.c: -------------------------------------------------------------------------------- 1 | // SM4 2 | #include 3 | #include 4 | #include "stdio.h" 5 | #include "string.h" 6 | #include "math.h" 7 | #include "sm4_mcu.h" 8 | #include "sm4_dpwd.h" 9 | 10 | #ifdef __cpluseplus 11 | #define INLINE INLINE 12 | #else 13 | #define INLINE 14 | #endif 15 | 16 | #define sm_word uint32_t 17 | 18 | /*********************************** 19 | *32位大小端变换 20 | ************************************/ 21 | INLINE uint32_t Reverse32(uint32_t x) { 22 | uint32_t tmp; 23 | tmp = (x & 0x000000ff) << 24; 24 | tmp |= (x & 0x0000ff00) << 8; 25 | tmp |= (x & 0x00ff0000) >> 8; 26 | tmp |= (x & 0xff000000) >> 24; 27 | return tmp; 28 | } 29 | 30 | /******************************************* 31 | *64位大小端变换 32 | ********************************************/ 33 | INLINE uint64_t Reverse64(uint64_t x) { 34 | uint32_t nTemp[3] = {0}; 35 | memcpy(nTemp + 1, &x, sizeof(uint64_t)); 36 | nTemp[0] = Reverse32(nTemp[2]); 37 | nTemp[1] = Reverse32(nTemp[1]); 38 | return *(uint64_t *)nTemp; 39 | } 40 | 41 | INLINE sm_word ML(uint8_t X, uint8_t j) { 42 | return Reverse32((sm_word)(X << (j % 32))); 43 | } 44 | 45 | INLINE sm_word SUM(sm_word X, sm_word Y) { 46 | return Reverse32(Reverse32(X) + Reverse32(Y)); 47 | } 48 | 49 | int TruncateSM4(uint8_t pSrc[16], uint16_t nSrcLen, uint8_t pDst[4], uint16_t nDstSize) { 50 | if(nSrcLen != 16 || nDstSize < 4) { 51 | return -1; 52 | } 53 | 54 | memset(pDst, 0, nDstSize); 55 | 56 | uint8_t* S = (uint8_t *)pSrc; 57 | sm_word S1 = ML(S[ 0], 24) | ML(S[ 1], 16) | ML(S[ 2], 8) | ML(S[ 3], 0); 58 | sm_word S2 = ML(S[ 4], 24) | ML(S[ 5], 16) | ML(S[ 6], 8) | ML(S[ 7], 0); 59 | sm_word S3 = ML(S[ 8], 24) | ML(S[ 9], 16) | ML(S[10], 8) | ML(S[11], 0); 60 | sm_word S4 = ML(S[12], 24) | ML(S[13], 16) | ML(S[14], 8) | ML(S[15], 0); 61 | 62 | sm_word OD = SUM(SUM(SUM(S1, S2), S3), S4); 63 | memcpy(pDst, &OD, sizeof(sm_word)); 64 | 65 | return 0; 66 | } 67 | 68 | // pKey:种子数组,128位,16uint8_t;不足128bits,自动填充‘0’补足长度 69 | // pTime:时间因子,UTC或自定义时间,8uint8_t,单位秒 70 | // pInterval:时间间隔,最大为60秒 71 | // pCounter:事件因子,4uint8_t 72 | // pChallenge:挑战因子或其他需要参与运算的因子,最小4uint8_t 73 | // pDynPwd:输出的动态口令,可配置位数nDynPwdSize 74 | // nGenLen: 输出的10进制的位数 75 | // nDynPwdSize: 用于存储十进制动态密码的uint8_t个数 76 | // 77 | #define DPWD_KEY_LEN 16 78 | #define DPWD_UTC_TIME_LEN 8 79 | #define DPWD_TIME_INTERVAL_LEN 2 80 | #define DPWD_COUNTER_LEN 4 81 | #define DPWD_CHALLENGE_LEN 4 82 | #define DPWD_GEN_DPWD_DEC_LEN 6 83 | #define DPWD_GEN_DPWD_HEX_LEN 6 84 | 85 | #define DPWD_ERROR_OK 0 86 | #define DPWD_ERROR_INTERVAL_ZERO 1 87 | #define DPWD_ERROR_INTERVAL_TOO_LARGE 2 88 | #define DPWD_ERROR_OTHER 3 89 | // Key:种子,16字节 90 | // Time:UTC或其他格式的时间,8uint8_t,单位秒,Littel-endian 91 | // Interval:时间间隔,2uint8_t,单位秒,Little-endian 92 | // Counter:计数值,4uint8_t,Littel-endian 93 | // Challenge:挑战数,4uint8_t, 自定义 94 | // Dynpwd:输出的动态口令,ASIIC,十进制数值 95 | // 种子和时间是必须的;Interval最大为60秒;Counter和Challenge填写固定值,或者用户定义 96 | // DPWD_UTC_TIME_LEN + DPWD_COUNTER_LEN + DPWD_CHALLENGE_LEN == 16 97 | // 若DPWD_KEY_LEN 和 (DPWD_UTC_TIME_LEN + DPWD_COUNTER_LEN + DPWD_CHALLENGE_LEN)不等于16,应补充0到16uint8_t 98 | // 如果种子和ID的长度大于16uint8_t,应按标准做多次处理。以下仅仅针对16uint8_t 99 | int SM4_DPasswd(uint8_t * pKey, uint64_t Time, uint16_t Interval, uint32_t Counter, \ 100 | uint8_t* pChallenge, uint8_t* pDynPwd) { 101 | // T = T0/Tc 102 | if(Interval == 0) 103 | return DPWD_ERROR_INTERVAL_ZERO; 104 | if(Interval > 60) 105 | return DPWD_ERROR_INTERVAL_TOO_LARGE; 106 | 107 | uint64_t tTime; 108 | tTime = Time / Interval; 109 | 110 | uint8_t sm_k[DPWD_KEY_LEN] = {0}; 111 | uint8_t sm_i[DPWD_UTC_TIME_LEN + DPWD_COUNTER_LEN + DPWD_CHALLENGE_LEN] = {0}; 112 | uint8_t sm_o[DPWD_KEY_LEN] = {0}; 113 | 114 | int i, offset; 115 | uint32_t pwd = 0; 116 | 117 | // copy key 118 | for(i = 0; i < DPWD_KEY_LEN; i ++) { 119 | sm_k[i] = pKey[i]; 120 | } 121 | 122 | // assemble ID 123 | // ID = T|C|Q 124 | // ID 由T C Q构成;T C最少必须有一个存在;Q为可选项;若ID不足128bits,则自动补充‘0’填充满 125 | // 将T、C、Q copy到sm_buf中;不足部分自动补充'0' 126 | uint8_t* tBuf; 127 | tTime = Reverse64(tTime); 128 | tBuf = (uint8_t *)&tTime; 129 | for(i = 0, offset = 0; i < DPWD_UTC_TIME_LEN; i ++) { 130 | sm_i[offset ++] = tBuf[i]; 131 | } 132 | 133 | uint32_t tCounter; 134 | tCounter = Reverse32(Counter); 135 | tBuf = (uint8_t *)&tCounter; 136 | for(i = 0; i < DPWD_COUNTER_LEN; i ++) { 137 | sm_i[offset ++] = tBuf[i]; 138 | } 139 | for(i = 0; i < DPWD_CHALLENGE_LEN; i ++) { 140 | sm_i[offset ++] = pChallenge[i]; 141 | } 142 | 143 | struct sm4_context ctx; 144 | sm4_setkey_enc(&ctx, sm_k); 145 | sm4_crypt_ecb(&ctx, SM4_ENCRYPT, 16, sm_i, sm_o); 146 | 147 | TruncateSM4(sm_o, DPWD_KEY_LEN, (uint8_t*) &pwd, sizeof(pwd)); 148 | 149 | pwd = Reverse32(pwd); 150 | 151 | pwd = pwd % (int)pow(10, DPWD_GEN_DPWD_DEC_LEN); 152 | 153 | for(i = DPWD_GEN_DPWD_DEC_LEN - 1; i >= 0; i --) 154 | 155 | { 156 | uint32_t tmp; 157 | tmp = pow(10, i); 158 | offset = pwd / tmp; 159 | pwd %= tmp; 160 | //pDynPwd [i] = offset + 0x30;//小端情况 161 | pDynPwd [DPWD_GEN_DPWD_DEC_LEN-1-i] = offset + 0x30;//大端情况 162 | } 163 | 164 | return DPWD_ERROR_OK; 165 | 166 | } 167 | -------------------------------------------------------------------------------- /Application/inter_flash.h: -------------------------------------------------------------------------------- 1 | #ifndef INTER_FLASH_H__ 2 | #define INTER_FLASH_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include "pstorage.h" 8 | 9 | #define SUPER_KEY_LENGTH 12 10 | #define KEY_LENGTH 6 11 | 12 | 13 | #pragma pack(4) 14 | 15 | //存储的键盘钥匙 16 | struct key_store_struct { 17 | uint8_t is_store;//'w' 18 | uint8_t key_store[KEY_LENGTH]; 19 | uint16_t key_use_time;//有效时间,以10分钟为单位 20 | time_t key_store_time; 21 | }; 22 | 23 | 24 | //超级管理员秘钥 25 | 26 | 27 | //开门记录的长度 28 | struct record_length_struct { 29 | uint32_t record_length; 30 | uint32_t record_full; 31 | }; 32 | 33 | //开门记录 34 | struct door_open_record { 35 | uint8_t key_store[6]; 36 | time_t door_open_time;//门打开的时间s,(从1970.1.1到现在的时间的s) 37 | }; 38 | 39 | //指纹存储信息 40 | struct fig_info { 41 | uint8_t is_store; //是否存储 42 | uint32_t fig_info_id;//指纹信息的ID 43 | char fig_info_data[16];//指纹的描述信息16B 44 | }; 45 | #pragma pack() 46 | 47 | extern char super_key[SUPER_KEY_LENGTH]; 48 | 49 | extern struct key_store_struct key_store_struct_set; 50 | extern struct door_open_record door_open_record_get; 51 | 52 | 53 | extern struct fig_info fig_info_set; 54 | extern struct fig_info fig_info_get; 55 | /********************************************************************************* 56 | *flash存储空间整个一个block_id 57 | *[0]存储参数+[1]钥匙个数+钥匙记录(10)+[12]长度+开门记录[30] 58 | * flash中各个存储量的偏移地址和长度 59 | ---------------------------------------------------------------------------------- 60 | 内部flash存储结构图 61 | ---------------------------------------------------------------------------------- 62 | -block_id_flash_store BLOCK_STORE_SIZE * BLOCK_STORE_COUNT-- 63 | ---------------------------------------------------------------------------------- 64 | block_offset -|- size 65 | ---------------------------------------------------------------------------------- 66 | DEFAULT_PARAMS_OFFSET (0) -|- DEFAULT_PARAMS_NUMBER (1) 67 | MAC_OFFSET (1) -|- MAC_NUMBER (1) 68 | SPUER_KEY_OFFSET (2) -|- SUPER_KEY_NUMBER (1) 69 | SEED_OFFSET (3) -|- SEED_NUMBER (1) 70 | DEVICE_NAME_OFFSET (4) -|- DEVICE_NAME_NUMBER (1) 71 | KEY_STORE_OFFSET (5) -|- KEY_STORE_NUMBER (10) 72 | RECORD_OFFSET (16) -|- RECORD_LENGTH (1) + RECORD_NUMBER(30) 73 | FIG_INFO_OFFSET (47) -|- FP_STORE_NUMBER (32) 74 | **********************************************************************************/ 75 | 76 | /********************************************************* 77 | *默认的参数:(1byte) 78 | * 电机转动时间(OPEN_TIME) 79 | * 开门后等待时间(DOOR_OPEN_HOLD_TIME) 80 | * 蜂鸣器响动次数(BEEP_DIDI_NUMBER) 81 | * 亮灯时间(LED_LIGHT_TIME) 82 | * 密码校对次数(KEY_CHECK_NUMBER) 83 | **********************************************************/ 84 | #define DEFAULT_PARAMS_OFFSET 0 85 | #define DEFAULT_PARAMS_NUMBER 1 86 | 87 | #define MAC_OFFSET DEFAULT_PARAMS_OFFSET + DEFAULT_PARAMS_NUMBER 88 | #define MAC_NUMBER 1 89 | 90 | #define SUPER_KEY_OFFSET MAC_OFFSET + MAC_NUMBER 91 | #define SUPER_KEY_NUMBER 1 92 | 93 | #define SEED_OFFSET SUPER_KEY_OFFSET + SUPER_KEY_NUMBER 94 | #define SEED_NUMBER 1 95 | 96 | #define DEVICE_NAME_OFFSET SEED_OFFSET + SEED_NUMBER 97 | #define DEVICE_NAME_NUMBER 1 98 | 99 | #define KEY_STORE_OFFSET DEVICE_NAME_OFFSET + DEVICE_NAME_NUMBER 100 | #define KEY_STORE_NUMBER 10 101 | 102 | #define RECORD_OFFSET KEY_STORE_OFFSET + KEY_STORE_NUMBER 103 | #define RECORD_LENGTH 1 //第一个4字节表示条数,第二个字节表示是否满 104 | #define RECORD_NUMBER 30 105 | 106 | #define FIG_INFO_OFFSET RECORD_OFFSET + RECORD_LENGTH + RECORD_NUMBER 107 | #define FIG_INFO_NUMBER 32 108 | 109 | 110 | #define BLOCK_STORE_COUNT DEFAULT_PARAMS_NUMBER +MAC_NUMBER + SUPER_KEY_NUMBER + \ 111 | SEED_NUMBER + DEVICE_NAME_NUMBER + \ 112 | KEY_STORE_NUMBER + \ 113 | RECORD_LENGTH + RECORD_NUMBER + \ 114 | FIG_INFO_NUMBER 115 | 116 | #define BLOCK_STORE_SIZE 32 117 | 118 | #define SEED_LENGTH 16 119 | 120 | 121 | extern pstorage_handle_t block_id_flash_store; 122 | 123 | extern pstorage_handle_t block_id_default_params; 124 | extern pstorage_handle_t block_id_mac; 125 | extern pstorage_handle_t block_id_super_key; 126 | extern pstorage_handle_t block_id_seed; 127 | extern pstorage_handle_t block_id_device_name; 128 | extern pstorage_handle_t block_id_key_store; 129 | extern pstorage_handle_t block_id_record; 130 | extern pstorage_handle_t block_id_fig_info; 131 | 132 | 133 | extern struct record_length_struct record_length; 134 | 135 | //内部flash读取和存储 136 | extern uint8_t interflash_write_data[BLOCK_STORE_SIZE]; 137 | extern uint8_t interflash_read_data[BLOCK_STORE_SIZE]; 138 | 139 | 140 | extern pstorage_handle_t block_id_write; 141 | extern pstorage_handle_t block_id_read; 142 | //从flash中读出的数据 143 | extern uint8_t flash_write_data[BLOCK_STORE_SIZE]; 144 | extern uint8_t flash_read_data[BLOCK_STORE_SIZE]; 145 | extern uint8_t flash_read_key_store_data[BLOCK_STORE_SIZE]; 146 | extern uint8_t flash_write_key_store_data[BLOCK_STORE_SIZE]; 147 | extern uint8_t flash_read_record_data[BLOCK_STORE_SIZE]; 148 | extern uint8_t flash_write_record_data[BLOCK_STORE_SIZE]; 149 | extern uint8_t flash_read_temp[BLOCK_STORE_SIZE]; 150 | 151 | void flash_init(void); 152 | 153 | int interflash_write(uint8_t *p_data, uint32_t data_len, \ 154 | pstorage_size_t block_id_offset); 155 | 156 | int interflash_read(uint8_t *p_data, uint32_t data_len, \ 157 | pstorage_size_t block_id_offset); 158 | 159 | int write_super_key(uint8_t *p_data, uint32_t data_len); 160 | void key_store_write(struct key_store_struct *key_store_input, uint16_t key_store_site); 161 | void record_write(struct door_open_record *open_record); 162 | int fig_info_write(struct fig_info *fp_info_set_p); 163 | int fig_info_read(struct fig_info *fp_info_get_p); 164 | 165 | #endif //INTER_FLASH_H__ 166 | -------------------------------------------------------------------------------- /Application/main.c: -------------------------------------------------------------------------------- 1 | /******************************************************** 2 | *-------------------------------------------------------- 3 | * bluetooth-door 4 | * ------------------------------- ----------------------- 5 | * 13 LEDs ; iic(sda,scl,en,int) 6 | *-------------------------------------------------------- 7 | * 2-wire moto ; 1-wire beer;uart(fig) 8 | *-------------------------------------------------------- 9 | * ble-softdevice-s132_nrf52_2.0.0-7.alpha 10 | *-------------------------------------------------------- 11 | * nrf52832-P.x define in 12 | * custom_board.h 13 | ********************************************************/ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "nordic_common.h" 22 | #include "bsp.h" 23 | #include "nrf.h" 24 | #include "nrf_delay.h" 25 | #include "nrf_gpio.h" 26 | #include "nrf_drv_config.h" 27 | 28 | #include "ble_hci.h" 29 | #include "ble_dis.h" 30 | #include "ble_advdata.h" 31 | #include "ble_advertising.h" 32 | #include "ble_conn_params.h" 33 | #include "softdevice_handler.h" 34 | #include "app_timer.h" 35 | #include "ble_nus.h" 36 | #include "app_uart.h" 37 | #include "pstorage.h" 38 | #include "device_manager.h" 39 | #include "app_trace.h" 40 | #include "app_util_platform.h" 41 | #include "uicr_config.h" 42 | 43 | //设置nfc引脚为gpio 44 | #define CONFIG_NFCT_PINS_AS_GPIOS 45 | #include "nrf52.h" 46 | #include "system_nrf52.h" 47 | 48 | 49 | #include "led_button.h" 50 | //#include "touch_tsm12.h" 51 | #include "wt5700.h" 52 | #include "moto.h" 53 | #include "beep.h" 54 | #include "rtc_chip.h" 55 | #include "inter_flash.h" 56 | #include "operate_code.h" 57 | #include "set_params.h" 58 | #include "ble_init.h" 59 | #include "sm4_mcu.h" 60 | #include "sm4_dpwd.h" 61 | #include "my_time.h" 62 | #include "battery.h" 63 | 64 | /*************************** 65 | * 动态口令算法测试程序 66 | ***************************/ 67 | void sm4_test(void) { 68 | struct sm4_context sm4_ctx; 69 | uint8_t output[16]; 70 | uint8_t key[16] = { 0x01, 0x23, 0x45, 0x67, \ 71 | 0x89, 0xab, 0xcd, 0xef, \ 72 | 0xfe, 0xdc, 0xba, 0x98, \ 73 | 0x76, 0x54, 0x32, 0x10 74 | }; 75 | uint8_t data[16] = { 0x01, 0x23, 0x45, 0x67, \ 76 | 0x89, 0xab, 0xcd, 0xef, \ 77 | 0xfe, 0xdc, 0xba, 0x98, \ 78 | 0x76, 0x54, 0x32, 0x10 79 | }; 80 | 81 | sm4_ctx.mode = SM4_ENCRYPT; 82 | sm4_ctx.sk[0] = 0x00; 83 | 84 | sm4_setkey_enc(&sm4_ctx, key); 85 | 86 | // output = 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e 87 | // 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46 88 | sm4_crypt_ecb( &sm4_ctx, SM4_ENCRYPT, 16, data, output); 89 | 90 | uint8_t DynPwd[6]; 91 | 92 | // DPasswd 93 | key[0] = 0x12; 94 | key[1] = 0x34; 95 | key[2] = 0x56; 96 | key[3] = 0x78; 97 | key[4] = 0x90; 98 | key[5] = 0xab; 99 | key[6] = 0xcd; 100 | key[7] = 0xef; 101 | key[8] = 0x12; 102 | key[9] = 0x34; 103 | key[10] = 0x56; 104 | key[11] = 0x78; 105 | key[12] = 0x90; 106 | key[13] = 0xab; 107 | key[14] = 0xcd; 108 | key[15] = 0xef; 109 | uint16_t Interval = 0x01; 110 | uint64_t time = 0x4feab9cd; 111 | uint32_t counter = 0x000004d2; 112 | uint8_t Challenge[4] = {0x35, 0x36, 0x37, 0x38}; 113 | 114 | // SM4 encoder output is 115 | // 88 0d 6a e7 7e cf 8e e5 23 5c 71 98 e1 3f 15 9c 116 | // TruncateSM4 output is 117 | // 0b 78 81 00 118 | // DPasswd is : 446720 119 | SM4_DPasswd(key, time, Interval, counter, Challenge, DynPwd); 120 | } 121 | 122 | static void set_mac_from_interflash(void) { 123 | uint32_t err_code; 124 | //如果配置了mac,则使用配置的mac 125 | if(mac[0] =='w') { 126 | memset(addr.addr, 0, 6); 127 | //拷贝设置的mac 128 | memcpy(addr.addr, &mac[2], 6); 129 | err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE,&addr); 130 | if(err_code == NRF_SUCCESS) { 131 | #if defined(BLE_DOOR_DEBUG) 132 | printf(" use mac setted by user:"); 133 | for(int i=0; i<6; i++) { 134 | printf("%x ",mac[2+i]); 135 | } 136 | printf("\r\n"); 137 | #endif 138 | } 139 | } 140 | } 141 | 142 | static void set_peer_password(void) { 143 | uint32_t err_code; 144 | //添加配对密码 145 | char *passcode = "123456"; 146 | ble_opt_t static_option; 147 | 148 | static_option.gap_opt.passkey.p_passkey = (uint8_t *)passcode; 149 | err_code = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &static_option); 150 | APP_ERROR_CHECK(err_code); 151 | 152 | #if defined(BLE_DOOR_DEBUG) 153 | printf("ble pair pin set:%s \n",passcode); 154 | printf("\r\n"); 155 | #endif 156 | } 157 | 158 | /***************************** 159 | *Application main function. 160 | *****************************/ 161 | int main(void) { 162 | uint32_t err_code; 163 | bool erase_bonds; 164 | 165 | 166 | NRF_UICR->NFCPINS = 0; 167 | 168 | //Initialize 169 | timers_init(); 170 | uart_init(); 171 | // buttons_leds_init(&erase_bonds); 172 | ble_stack_init(); 173 | device_manager_init(erase_bonds); 174 | //初始化内部flash,和各个存储变量,紧跟在device_manager_init后面,读取mac和蓝牙名称 175 | flash_init(); 176 | 177 | //从内部flash中读取mac,设置 178 | set_mac_from_interflash(); 179 | 180 | 181 | gap_params_init(); 182 | services_init(); 183 | advertising_init(); 184 | conn_params_init(); 185 | 186 | //初始化所有参数 187 | set_default_params(); 188 | //初始化灯,拉高,灭 189 | leds_init(); 190 | // led test 191 | // leds_on(LED_13,5); 192 | 193 | 194 | 195 | //初始化电机 196 | moto_init(); 197 | //初始化蜂鸣器 198 | beep_init(); 199 | //beep test 200 | // beep_didi(5); 201 | //初始化触摸屏 202 | // tsm12_init(); 203 | wt5700_init(); 204 | //初始化RTC 205 | rtc_init(); 206 | //初始化触摸屏和指纹的中断函数 207 | touch_finger_int_init(); 208 | 209 | //设置配对密码 210 | // set_peer_password(); 211 | 212 | application_timers_start(); 213 | err_code = ble_advertising_start(BLE_ADV_MODE_FAST); 214 | APP_ERROR_CHECK(err_code); 215 | // adverts_start(); 216 | 217 | //使能电池服务 218 | battery_level_init(); 219 | 220 | //Enter main loop. 221 | for (;;) { 222 | power_manage(); 223 | 224 | //判断命令 225 | if(operate_code_setted ==true) { 226 | operate_code_check(nus_data_recieve, nus_data_recieve_length); 227 | operate_code_setted = false; 228 | } 229 | if(is_background_lit == true){ 230 | nrf_delay_ms(3000); 231 | nrf_gpio_pin_clear( BATTERY_LEVEL_EN ); 232 | is_background_lit = false; 233 | } 234 | } 235 | 236 | } 237 | -------------------------------------------------------------------------------- /Application/touch_tsm12.c: -------------------------------------------------------------------------------- 1 | /************************************************** 2 | * 触摸按键分布 3 | * T8---1 T9---2 T10--3 4 | * T7---4 T12--5 T11--6 5 | * T6---7 T1---8 T2---9 6 | * T5---* T4---0 T3---# 7 | *(#就是开锁键) 8 | **************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "bsp.h" 15 | #include "nrf_delay.h" 16 | #include "nrf_drv_gpiote.h" 17 | #include "nrf_drv_twi.h" 18 | #include "nrf_gpiote.h" 19 | #include "nrf_gpio.h" 20 | #include "app_util_platform.h" 21 | #include "nrf_drv_config.h" 22 | 23 | #include "touch_tsm12.h" 24 | 25 | uint8_t key_value; 26 | 27 | nrf_drv_twi_t m_twi_master_touch = NRF_DRV_TWI_INSTANCE(1); //指定TWI1 28 | 29 | /*********************************************** 30 | *初始化触摸屏 31 | *in: none 32 | ************************************************/ 33 | ret_code_t touch_iic_init(void) { 34 | ret_code_t ret; 35 | const nrf_drv_twi_config_t config = { 36 | .scl = TSM12_IIC_SCL_PIN, 37 | .sda = TSM12_IIC_SDA_PIN, 38 | .frequency = NRF_TWI_FREQ_100K, 39 | .interrupt_priority = APP_IRQ_PRIORITY_HIGH 40 | }; 41 | 42 | do { 43 | ret = nrf_drv_twi_init(&m_twi_master_touch, &config, NULL, NULL); 44 | if(NRF_SUCCESS != ret) { 45 | break; 46 | } 47 | nrf_drv_twi_enable(&m_twi_master_touch); 48 | } while(0); 49 | 50 | return ret; 51 | } 52 | 53 | /********************** 54 | *触摸屏使能 55 | *********************/ 56 | void tsm12_en_start(void) { 57 | //设置使能端为输出 58 | nrf_gpio_cfg_output(TSM12_IIC_EN_PIN); 59 | nrf_gpio_pin_clear(TSM12_IIC_EN_PIN); 60 | } 61 | 62 | /************************* 63 | *触摸屏停止 64 | *************************/ 65 | void tsm12_en_stop(void) { 66 | //设置使能端为输出 67 | nrf_gpio_cfg_output(TSM12_IIC_EN_PIN); 68 | nrf_gpio_pin_set(TSM12_IIC_EN_PIN); 69 | } 70 | 71 | /************************************** 72 | *往触摸屏的写某个地址的数据 73 | *in:address 地址 74 | data 数据 75 | *out: ret 0成功 76 | ****************************************/ 77 | ret_code_t touch_i2c_device_write_byte(uint8_t address, uint8_t data) { 78 | ret_code_t ret; 79 | uint8_t buffer[2] = {address,data}; 80 | ret = nrf_drv_twi_tx(&m_twi_master_touch, TSM12_IIC_REAL_ADDR, buffer, 2, false); 81 | 82 | return ret; 83 | } 84 | 85 | /************************************************************* 86 | *从触摸屏的某个地址开始读数据 87 | *in: address 地址 88 | *p_read_byte 读出数据的地址指针 89 | length 读出数据的长度 90 | *out: ret 0成功 91 | **************************************************************/ 92 | ret_code_t touch_i2c_device_read_byte(uint8_t address, uint8_t *p_read_byte, uint8_t length) { 93 | ret_code_t ret; 94 | 95 | do { 96 | //写地址 97 | uint8_t set_address; 98 | set_address = address; 99 | 100 | ret = nrf_drv_twi_tx(&m_twi_master_touch, TSM12_IIC_REAL_ADDR, &set_address, 1, true); 101 | if(ret !=NRF_SUCCESS) { 102 | break; 103 | } 104 | //读数据 105 | ret = nrf_drv_twi_rx(&m_twi_master_touch, TSM12_IIC_REAL_ADDR, p_read_byte, length); 106 | } while(0); 107 | 108 | return ret; 109 | } 110 | 111 | /****************************************** 112 | *初始化触摸屏芯片 113 | *in none 114 | *******************************************/ 115 | void tsm12_init(void) { 116 | uint8_t set_data; 117 | //使能IIC管脚 118 | tsm12_en_start(); 119 | 120 | touch_iic_init(); 121 | 122 | //软件复位,睡眠模式开 123 | set_data = 0x0F; 124 | touch_i2c_device_write_byte(TSM12_CTRL2, set_data); 125 | //使能软件复位,睡眠模式关 126 | set_data = 0x07; 127 | touch_i2c_device_write_byte(TSM12_CTRL2, set_data); 128 | //设置通道1-2的灵敏度 129 | set_data = 0xBB; 130 | touch_i2c_device_write_byte(TSM12_Sensitivity1, set_data); 131 | //设置通道3-4的灵敏度 132 | touch_i2c_device_write_byte(TSM12_Sensitivity2, set_data); 133 | //设置通道5-6的灵敏度 134 | touch_i2c_device_write_byte(TSM12_Sensitivity3, set_data); 135 | //设置通道7-8的灵敏度 136 | touch_i2c_device_write_byte(TSM12_Sensitivity4, set_data); 137 | //设置通道9-10的灵敏度 138 | touch_i2c_device_write_byte(TSM12_Sensitivity5, set_data); 139 | //设置通道11-12的灵敏度 140 | touch_i2c_device_write_byte(TSM12_Sensitivity6, set_data); 141 | 142 | //基本设置 143 | // set_data = 0x22; 144 | // i2c_device_write_byte(TSM12_CTRL1, set_data); 145 | 146 | 147 | //不复位通道1-8的参考 148 | set_data = 0x00; 149 | touch_i2c_device_write_byte(TSM12_Ref_rst1, set_data); 150 | //不复位通道9-12的参考 151 | set_data = 0x00; 152 | touch_i2c_device_write_byte(TSM12_Ref_rst2, set_data); 153 | 154 | /* 155 | //使能通道1-8复位 156 | set_data = 0x00; 157 | i2c_device_write_byte(TSM12_Cal_hold1, set_data); 158 | //使能通道9-12复位 159 | set_data = 0x00; 160 | i2c_device_write_byte(TSM12_Cal_hold2, set_data); 161 | */ 162 | 163 | //打开1-8所有通道 164 | set_data = 0x00; 165 | touch_i2c_device_write_byte(TSM12_Ch_hold1, set_data); 166 | //打开9-12所有通道 167 | set_data = 0x00; 168 | touch_i2c_device_write_byte(TSM12_Ch_hold2, set_data); 169 | #if defined(BLE_DOOR_DEBUG) 170 | printf("touch button init success\r\n"); 171 | #endif 172 | } 173 | 174 | /*************************************************** 175 | *读取触摸屏键值 176 | *in: none 177 | *out: key_value 触摸屏的键值 178 | ***************************************************/ 179 | uint8_t tsm12_key_read(void) { 180 | uint8_t temp[3]; 181 | uint8_t *p; 182 | 183 | p = temp; 184 | 185 | //读取通道1-4 186 | touch_i2c_device_read_byte(TSM12_Output1, p, 0x01); 187 | //读取通道5-8 188 | touch_i2c_device_read_byte(TSM12_Output2, (p+1), 0x01); 189 | //读取通道9-12 190 | touch_i2c_device_read_byte(TSM12_Output3, (p+2), 0x01); 191 | 192 | if(*p > 2) { 193 | switch(*p) { 194 | case 0x03://00000011 195 | key_value = '8'; 196 | break; 197 | case 0x0c://00001100 198 | key_value = '9'; 199 | break; 200 | case 0x30://00110000 201 | key_value = 'b'; 202 | break; 203 | case 0xc0://11000000 204 | key_value = '0'; 205 | break; 206 | default: 207 | key_value = 0; 208 | break; 209 | } 210 | } else if(*(p + 1) > 2) { 211 | switch(*(p + 1)) { 212 | case 0x03: 213 | key_value = 'a'; 214 | break; 215 | case 0x0c: 216 | key_value = '7'; 217 | break; 218 | case 0x30: 219 | key_value = '4'; 220 | break; 221 | case 0xc0: 222 | key_value = '1'; 223 | break; 224 | default: 225 | key_value = 0; 226 | break; 227 | } 228 | } else { 229 | switch(*(p + 2)) { 230 | case 0x03: 231 | key_value = '2'; 232 | break; 233 | case 0x0c: 234 | key_value = '3'; 235 | break; 236 | case 0x30: 237 | key_value = '6'; 238 | break; 239 | case 0xc0: 240 | key_value = '5'; 241 | break; 242 | default: 243 | key_value = 0; 244 | break; 245 | } 246 | } 247 | return key_value; 248 | 249 | } 250 | -------------------------------------------------------------------------------- /Application/r301t.h: -------------------------------------------------------------------------------- 1 | #ifndef R301T_H__ 2 | #define R301T_H__ 3 | 4 | 5 | #include 6 | #include 7 | 8 | #include "inter_flash.h" 9 | 10 | 11 | /********************************************************** 12 | *r301t是一个指纹模块,容量0x0bb8 (3000) 13 | * pin1------5v 14 | * pin2------GND 15 | * pin3------TXD 16 | * pin4------RXD 17 | * pin5------TOUCH 18 | * pin6------Touch Power 19 | * UART波特率(N*9600) N默认是6,即57600bps 20 | * 21 | * 命令包格式 22 | * 包头(2bytes,0xEF01)--模块地址(4bytes,0xFFFFFFFF)--包标识(1byte,0x01)--包长度(2bytes)--指令(1byte)--参数(Nbytes)--校验和(2bytes) 23 | * 24 | * 数据包格式 25 | * 包头(2bytes,0xEF01)--模块地址(4bytes,0xFFFFFFFF)--包标识(1byte,0x02)---包长度(2bytes)--数据(Nbytes)---校验和(2bytes) 26 | * 27 | * 结束包格式 28 | * 包头(2bytes,0xEF01)--模块地址(4bytes,0xFFFFFFFF)--包标识(1byte,0x08)---包长度(2bytes)--数据(Nbytes)---校验和(2bytes) 29 | * 30 | * 应答包格式 31 | * 包头(2bytes,0xEF01)--模块地址(4bytes,0xFFFFFFFF)--包标识(1byte,0x07)---包长度(2bytes)--确认码(1byte)--数据(Nbytes)---校验和(2bytes) 32 | * 33 | ************************************************************/ 34 | 35 | #define R301T_MAX_FIG_NUMBER 32 36 | 37 | 38 | //状态寄存器 GR:杭州城章 39 | #define GR_SYS_PARAM_BUSY_BIT 0 //1表示系统正在执行命令,0表示空闲 40 | #define GR_SYS_PARAM_PASS_BIT 1 //1表示指纹验证通过 41 | #define GR_SYS_PARAM_PWD_BIT 2 //1表示设备握手口令通过验证。 42 | #define GR_SYS_PARAM_IBS_BIT 3 //IBS ImgBufStat 1表示指纹图像缓冲区存在有效指纹图像 43 | 44 | #define GR_FIG_HEADER_SITE 0 45 | #define GR_FIG_HEADER 0xEF01 //包头 46 | #define GR_FIG_ADDR_SITE 2 47 | #define GR_FIG_ADDR 0xFFFFFFFF //模块地址 48 | 49 | #define GR_FIG_DATA_ID_SITE 6 50 | #define GR_FIG_DATA_ID_CMD 0x01 //命令包标识 51 | #define GR_FIG_DATA_ID_DATA 0x02 //数据包标识 52 | #define GR_FIG_DATA_ID_END 0x08 //结束包标识 53 | //应答是将有关命令执行情况与结果上报给上位机,应答包含有参数, 54 | //并可跟后续数据包。上位机只有在收到模块的应答包后才能确认模块 55 | //收包情况与指令执行情况 56 | #define GR_FIG_DATA_ID_REPLY 0x07 //应答包标识 57 | 58 | #define GR_FIG_REPLY_ACK_OK 0x00 //应答包中确认码,表示指令执行完毕或OK 59 | #define GR_FIG_REPLY_ACK_ER1 0x01 //应答包中确认码,表示数据包接收错误 60 | #define GR_FIG_REPLY_ACK_ER2 0x02 //应答包中确认码,表示传感器上没手指 61 | #define GR_FIG_REPLY_ACK_ER3 0x03 //应答包中确认码,表示录入指纹失败(IFPFAIL input fingerprint fail) 62 | #define GR_FIG_REPLY_ACK_ER4 0x04 //应答包中确认码,表示指纹图像太干、太淡而生不成特征 63 | #define GR_FIG_REPLY_ACK_ER5 0x05 //应答包中确认码,表示指纹图像太湿、太糊而生不成特征 64 | #define GR_FIG_REPLY_ACK_ER6 0x06 //应答包中确认码,表示指纹图像太乱而生不成特征 65 | #define GR_FIG_REPLY_ACK_ER7 0x07 //应答包中确认码,表示指纹图像正常,但是特征点太少(或面积太小)而生不成特征 66 | #define GR_FIG_REPLY_ACK_ER8 0x08 //应答包中确认码,表示指纹不匹配 67 | #define GR_FIG_REPLY_ACK_ER9 0x09 //应答包中确认码,没有搜索到指纹 68 | #define GR_FIG_REPLY_ACK_ER10 0x0A //应答包中确认码,表示特征合并失败 69 | #define GR_FIG_REPLY_ACK_ER11 0x0B //应答包中确认码,表示访问指纹库时地址序号超出指纹库范围 70 | #define GR_FIG_REPLY_ACK_ER12 0x0C //应答包中确认码,表示从指纹库读模板出错或者无效 71 | #define GR_FIG_REPLY_ACK_ER13 0x0D //应答包中确认码,表示上传特征失败 72 | #define GR_FIG_REPLY_ACK_ER14 0x0E //应答包中确认码,表示模块不能接受后续数据包 73 | #define GR_FIG_REPLY_ACK_ER15 0x0F //应答包中确认码,表示上传图像失败 74 | #define GR_FIG_REPLY_ACK_ER16 0x10 //应答包中确认码,表示删除模板失败 75 | #define GR_FIG_REPLY_ACK_ER17 0x11 //应答包中确认码,表示清空指纹库失败 76 | #define GR_FIG_REPLY_ACK_ER18 0x12 //应答包中确认码,表示口令不正确 77 | 78 | #define GR_FIG_REPLY_ACK_ER21 0x15 //应答包中确认码,表示缓冲区内没有有效原始图而生不成图像 79 | #define GR_FIG_REPLY_ACK_ER24 0x18 //应答包中确认码,表示读写FLASH 出错 80 | #define GR_FIG_REPLY_ACK_ER25 0x19 //应答包中确认码,表示未定义错误 81 | #define GR_FIG_REPLY_ACK_ER26 0x1A //应答包中确认码,表示无效寄存器号 82 | #define GR_FIG_REPLY_ACK_ER27 0x1B //应答包中确认码,表示寄存器设定内容错误号 83 | #define GR_FIG_REPLY_ACK_ER28 0x1C //应答包中确认码,表示记事本页码指定错误 84 | #define GR_FIG_REPLY_ACK_ER29 0x1D //应答包中确认码,表示端口操作失败 85 | #define GR_FIG_REPLY_ACK_ER30 0x1E //应答包中确认码,表示自动注册(enroll)失败 86 | #define GR_FIG_REPLY_ACK_ER31 0x1F //应答包中确认码,表示指纹库满 87 | //20-efH:Reserved 88 | 89 | #define GR_FIG_DATA_LEN_SITE 7 //包长度,占2bytes 90 | 91 | 92 | //系统默认口令为0,若默认口令未被修改,则系统不要求验证口令,上位机可以直接与芯片通讯; 93 | //若口令被修改,则上位机与芯片通讯的第一个指令必须是验证口令,只有口令验证通过后,芯片才接收其它指令。 94 | 95 | #define GR_FIG_CMD_SITE 9 //命令的位置 96 | 97 | #define GR_FIG_CMD_GETIMG 0x01 //从传感器上读入图像存于图像缓冲区 98 | #define GR_FIG_CMD_GENCHAR 0x02 //根据原始图像生成指纹特征存于CharBuffer1 或CharBuffer2 99 | #define GR_FIG_CMD_MATCH 0x03 //精确比对CharBuffer1 与CharBuffer2 中的特征文件 100 | #define GR_FIG_CMD_SEARCH 0x04 //以CharBuffer1 或CharBuffer2 中的特征文件搜索整个或部分指纹库 101 | #define GR_FIG_CMD_REGMODEL 0x05 //将CharBuffer1 与CharBuffer2 中的特征文件合并生成模板存于CharBuffer1与CharBuffer2 102 | #define GR_FIG_CMD_STORECHAR 0x06 //将特征缓冲区中的文件储存到flash 指纹库中 103 | #define GR_FIG_CMD_LOADCHAR 0x07 //从flash 指纹库中读取一个模板到特征缓冲区 104 | #define GR_FIG_CMD_UPCHAR 0x08 //将特征缓冲区中的文件上传给上位机 105 | #define GR_FIG_CMD_DOWNCHAR 0x09 //从上位机下载一个特征文件到特征缓冲区 106 | #define GR_FIG_CMD_UPIMG 0x0A //上传原始图像 107 | #define GR_FIG_CMD_DOWNIMG 0x0B //下载原始图像 108 | #define GR_FIG_CMD_DELCHAR 0x0C //删除flash 指纹库中的一个特征文件 109 | #define GR_FIG_CMD_EMPTY 0x0D //清空flash 指纹库 110 | #define GR_FIG_CMD_WRREG 0x0E //设置系统参数 111 | #define GR_FIG_CMD_RDSYSPARA 0x0F //读系统基本参数 112 | #define GR_FIG_CMD_SETPWD 0x12 //设置设备握手口令 113 | #define GR_FIG_CMD_VFYPWD 0x13 //验证设备握手口令 114 | #define GR_FIG_CMD_GETRDC 0x14 //采样随机数 115 | #define GR_FIG_CMD_SETADDR 0x15 //设置模块地址 116 | #define GR_FIG_CMD_POETCTRL 0x17 //通讯端口(UART/USB)开关控制 117 | #define GR_FIG_CMD_WRNOTPAD 0x18 //写记事本 118 | #define GR_FIG_CMD_RDNOTPAD 0x19 //读记事本 119 | #define GR_FIG_CMD_GENBINIMG 0x1C //生成二值化指纹图像 120 | #define GR_FIG_CMD_VTNUM 0x1D //读有效模板个数 121 | #define GR_FIG_CMD_RDINDEXTB 0x1F //读索引表 122 | 123 | 124 | extern bool is_r301t_autoenroll; 125 | extern uint8_t r301t_autosearch_step; 126 | 127 | extern uint8_t r301t_indextable_data[32]; 128 | extern bool is_get_r301t_indextable; 129 | extern uint8_t fig_info_get_site; 130 | 131 | 132 | /************************************** 133 | *r301t指纹模块相关指令 134 | **************************************/ 135 | //发送获取指纹图像命令 136 | extern uint8_t r301t_send_getimg_cmd[1]; 137 | //将生成的图像生成到charbuff1 138 | extern uint8_t r301t_send_genchar1_cmd[2]; 139 | //将生成的图像生成到charbuff2 140 | extern uint8_t r301t_send_genchar2_cmd[2]; 141 | //发送搜索指纹模式,一共有32个指纹 142 | extern uint8_t r301t_send_search_cmd[6]; 143 | //将charbuff1与charbuffer2中的特征文件合并生成模板存于charbuff1与charbuff2 144 | extern uint8_t r301t_send_regmodel_cmd[1]; 145 | //将特征缓冲区的文件储存在flash指纹库这里是ID0 146 | extern uint8_t r301t_send_storechar_id0_cmd[4]; 147 | extern uint8_t r301t_send_storechar_idx_cmd[4]; 148 | //删除指纹命令 149 | extern uint8_t r301t_send_deletechar_id0_cmd[5]; 150 | extern uint8_t r301t_send_deletechar_idx_cmd[5]; 151 | //清空指纹库命令 152 | extern uint8_t r301t_send_empty_cmd[1]; 153 | //获取有效模板个数 154 | extern uint8_t r301t_send_get_vtnum_cmd[1]; 155 | //读取索引列表 156 | extern uint8_t r301t_send_get_indextb0_cmd[2]; 157 | extern uint8_t r301t_send_get_indextbx_cmd[2]; 158 | 159 | void fig_r301t_send_cmd(uint8_t data_id, uint16_t data_len, uint8_t *data_code); 160 | int fig_r301t_reply_check(void); 161 | 162 | #endif //R301T_H__ 163 | -------------------------------------------------------------------------------- /Application/rtc_chip.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * RTC芯片 IIC接口 3 | *---------------------------------------------------------------------------- 4 | * tm RTC 5 | * tm_sec(int:0-60) 02H(BCD:0-59:[6:0]) 6 | * tm_min(int:0-59) 03H(BCD:0-59:[6:0]) 7 | * tm_hour(int:0-23) 04H(BCD:0-23:[5:0]) 8 | * tm_mday(int:1-31) 05H(BCD:1-31:[5:0]) 9 | * tm_mon(int:0-11) 07H(BCD:1-12:[4:0],7表示世纪) 10 | * tm_year(int:Year-1990) 08H(BCD:0-99) 11 | * tm_wday(int:0-6) 06H(int:0-6) sun-sat 12 | * tm_yday(0-365) 13 | * tm_isdst(夏令时) 14 | ****************************************************************************/ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "bsp.h" 22 | #include "nrf_delay.h" 23 | #include "nrf_drv_gpiote.h" 24 | #include "nrf_drv_twi.h" 25 | #include "nrf_gpiote.h" 26 | #include "nrf_gpio.h" 27 | #include "app_util_platform.h" 28 | #include "nrf_drv_config.h" 29 | 30 | #include "rtc_chip.h" 31 | 32 | nrf_drv_twi_t m_twi_master_rtc = NRF_DRV_TWI_INSTANCE(1); //指定TWI1 33 | 34 | /*********************** 35 | *初始化RTC芯片 36 | *in: none 37 | ************************/ 38 | static ret_code_t rtc_iic_init(void) { 39 | ret_code_t ret; 40 | const nrf_drv_twi_config_t config = { 41 | .scl = RTC_CHIP_IIC_SCL_PIN, 42 | .sda = RTC_CHIP_IIC_SDA_PIN, 43 | .frequency = NRF_TWI_FREQ_100K, 44 | .interrupt_priority = APP_IRQ_PRIORITY_LOW 45 | }; 46 | 47 | do { 48 | ret = nrf_drv_twi_init(&m_twi_master_rtc, &config, NULL, NULL); 49 | if(NRF_SUCCESS != ret) { 50 | break; 51 | } 52 | nrf_drv_twi_enable(&m_twi_master_rtc); 53 | } while(0); 54 | return ret; 55 | 56 | } 57 | 58 | /********************************************************** 59 | *RTC芯片写入1个byte 60 | *in: address 要写入RTC芯片的地址 61 | data 写入RTC芯片的数据 62 | *out: ret 0成功 63 | **********************************************************/ 64 | static ret_code_t rtc_i2c_device_write_byte(uint8_t address, uint8_t data) { 65 | ret_code_t ret; 66 | uint8_t buffer[2] = {address,data}; 67 | ret = nrf_drv_twi_tx(&m_twi_master_rtc, RTC_CHIP_REAL_ADDR, buffer, 2, false); 68 | return ret; 69 | 70 | } 71 | 72 | /**************************************************************** 73 | *RTC芯片读出length个byte 74 | *in: address 要读出的地址 75 | *p_read_byte 读出数据的指针 76 | length 读出数据的长度 77 | *out ret 0成功 78 | ****************************************************************/ 79 | static ret_code_t rtc_i2c_device_read_byte(uint8_t address, uint8_t *p_read_byte, uint8_t length) { 80 | ret_code_t ret; 81 | 82 | do { 83 | //写地址 84 | uint8_t set_address; 85 | set_address = address; 86 | ret = nrf_drv_twi_tx(&m_twi_master_rtc, RTC_CHIP_REAL_ADDR, &set_address, 1, true); 87 | if(ret !=NRF_SUCCESS) { 88 | break; 89 | } 90 | //读数据 91 | ret = nrf_drv_twi_rx(&m_twi_master_rtc, RTC_CHIP_REAL_ADDR, p_read_byte, length); 92 | } while(0); 93 | return ret; 94 | 95 | } 96 | 97 | /******************************************************* 98 | * 初始化RTC芯片 99 | *in: none 100 | *******************************************************/ 101 | void rtc_init(void) { 102 | //初始化RTC的IIC 103 | rtc_iic_init(); 104 | 105 | //使能RTC芯片 106 | rtc_i2c_device_write_byte(PCF85163_Timer_control_ADDR, 0x83); 107 | rtc_i2c_device_write_byte(PCF85163_Timer_ADDR, 0xff); 108 | #if defined(BLE_DOOR_DEBUG) 109 | printf("rtc:pcf85163 init success\r\n"); 110 | #endif 111 | 112 | } 113 | 114 | /***************************************** 115 | *hex变换为BCD 116 | *in: value 要变换的hex 117 | *out: 变换后的BCD 118 | *****************************************/ 119 | static uint8_t hex_2_bcd(uint8_t value) { 120 | return (((value/10)<<4) | (value%10)); 121 | 122 | } 123 | 124 | /**************************************************** 125 | *BCD变换为hex 126 | *in: value 要变换的BCD 127 | *out: 变换后的hex 128 | *****************************************************/ 129 | static uint8_t bcd_2_hex(uint8_t value) { 130 | return (((value & 0xf0)>>4)*10 + (value & 0x0f)); 131 | 132 | } 133 | 134 | /****************************************************** 135 | *设置RTC芯片的时间 136 | *in: *time_write 要写入的时间 137 | *out: 0成功 138 | *******************************************************/ 139 | uint8_t rtc_time_write(struct tm *time_write) { 140 | uint8_t byte_write; 141 | //停止RTC 142 | rtc_i2c_device_write_byte(PCF85163_Timer_control_ADDR, 0x03); 143 | //写秒 144 | byte_write = 0x7f & hex_2_bcd(time_write->tm_sec); 145 | rtc_i2c_device_write_byte(PCF85163_VL_seconds_ADDR, byte_write); 146 | //写分 147 | byte_write = 0x7f & hex_2_bcd(time_write->tm_min); 148 | rtc_i2c_device_write_byte(PCF85163_Minutes_ADDR, byte_write); 149 | //写小时 150 | byte_write = 0x3f & hex_2_bcd(time_write->tm_hour); 151 | rtc_i2c_device_write_byte(PCF85163_Hours_ADDR, byte_write); 152 | //写天 153 | byte_write = 0x3f & hex_2_bcd(time_write->tm_mday); 154 | rtc_i2c_device_write_byte(PCF85163_Days_ADDR, byte_write); 155 | //写周 156 | byte_write = 0x07 & hex_2_bcd(time_write->tm_wday); 157 | rtc_i2c_device_write_byte(PCF85163_Weekdays_ADDR, byte_write); 158 | //写月 2xxx年 159 | byte_write = (0x1f & hex_2_bcd(time_write->tm_mon + 1)) + 0x80; 160 | rtc_i2c_device_write_byte(PCF85163_Century_months_ADDR, byte_write); 161 | //写年 162 | byte_write = 0xff & hex_2_bcd(time_write->tm_year - 10); 163 | rtc_i2c_device_write_byte(PCF85163_Years_ADDR, byte_write); 164 | //使能RTC 165 | rtc_i2c_device_write_byte(PCF85163_Timer_control_ADDR, 0x83); 166 | /* 167 | #if defined(BLE_DOOR_DEBUG) 168 | printf("rtc time set:%4d-%2d-%2d %2d:%2d:%2d\r\n",\ 169 | time_write->tm_year +1990, time_write->tm_mon + 1, \ 170 | time_write->tm_mday, time_write->tm_hour, \ 171 | time_write->tm_min, time_write->tm_sec); 172 | #endif 173 | */ 174 | return 0; 175 | 176 | } 177 | 178 | /******************************************************** 179 | *读出RTC芯片的时间 180 | *in: *time_read 读出的时间 181 | *out: 0成功 182 | ********************************************************/ 183 | uint8_t rtc_time_read(struct tm *time_read) { 184 | uint8_t byte_read[7]; 185 | //读时间 186 | rtc_i2c_device_read_byte(PCF85163_VL_seconds_ADDR, byte_read, 7); 187 | 188 | //写入秒 189 | time_read->tm_sec = bcd_2_hex(0x7f & byte_read[0]); 190 | //写入分 191 | time_read->tm_min = bcd_2_hex(0x7f & byte_read[1]); 192 | //写入时 193 | time_read->tm_hour = bcd_2_hex(0x3f & byte_read[2]); 194 | //写入天 195 | time_read->tm_mday = bcd_2_hex(0x3f & byte_read[3]); 196 | //写入周 197 | time_read->tm_wday = bcd_2_hex(0x07 & byte_read[4]); 198 | //写入月 199 | time_read->tm_mon = bcd_2_hex(0x1f & byte_read[5]) - 1; 200 | //写入年 201 | time_read->tm_year = bcd_2_hex(0xff & byte_read[6]) + 10; 202 | /* 203 | #if defined(BLE_DOOR_DEBUG) 204 | printf("rtc time read:%4d-%2d-%2d %2d:%2d:%2d\r\n",\ 205 | time_read->tm_year +1990, time_read->tm_mon + 1, \ 206 | time_read->tm_mday, time_read->tm_hour, \ 207 | time_read->tm_min, time_read->tm_sec); 208 | #endif 209 | */ 210 | return 0; 211 | 212 | } 213 | -------------------------------------------------------------------------------- /config/uicr_config.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Nordic Semiconductor ASA 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * * Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 10 | * * Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * * Neither the name of Nordic Semiconductor ASA nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | /* Template files (including this one) are application specific and therefore expected to 32 | be copied into the application project folder prior to its use! */ 33 | 34 | #ifndef _UICR_CONFIG_H 35 | #define _UICR_CONFIG_H 36 | 37 | /*lint ++flb "Enter library region" */ 38 | 39 | #include 40 | 41 | /* 42 | * Include this file in your project if you want to include in your compiled code files data 43 | * for the User Information Configuration Registers (UICR) area; see nRF51 Series Reference 44 | * Manual chapter User Information Configuration Registers. This file declares one variable 45 | * per register of the UICR area and informs the linker where to place them. To include 46 | * the desired value in the desired address, uncomment the variable with the proper address 47 | * at the target area and update the assignment value. 48 | * 49 | * Please note that UICR values are stored in a reserved area of the flash and should only be 50 | * stored into when downloading a hex file. Do not use these defined variables to store data 51 | * at run time. 52 | * 53 | * Note as well that this file uses one non-standard attribute ("at"). It will only function 54 | * with the ARMCC compiler toolset. 55 | * 56 | * Note that the hex file generated when this file is included will fail to download when using 57 | * the standard download algorithm provided by Nordic. See example project "uicr_config_example" 58 | * in any of the board example folders for an example of the recommended download method as well 59 | * as the documentation that follows with the SDK. nrfjprog can be used as normal. 60 | * 61 | */ 62 | 63 | // const uint32_t UICR_CLENR0 __attribute__((at(0x10001000))) __attribute__((used)) = 0xFFFFFFFF; 64 | // const uint32_t UICR_RBPCONF __attribute__((at(0x10001004))) __attribute__((used)) = 0xFFFFFFFF; 65 | // const uint32_t UICR_XTALFREQ __attribute__((at(0x10001008))) __attribute__((used)) = 0xFFFFFFFF; 66 | 67 | const uint32_t UICR_ADDR_0x80 __attribute__((at(0x10001080))) __attribute__((used)) = 0x12345678; 68 | // const uint32_t UICR_ADDR_0x84 __attribute__((at(0x10001084))) __attribute__((used)) = 0xFFFFFFFF; 69 | // const uint32_t UICR_ADDR_0x88 __attribute__((at(0x10001088))) __attribute__((used)) = 0xFFFFFFFF; 70 | // const uint32_t UICR_ADDR_0x8C __attribute__((at(0x1000108C))) __attribute__((used)) = 0xFFFFFFFF; 71 | // const uint32_t UICR_ADDR_0x90 __attribute__((at(0x10001090))) __attribute__((used)) = 0xFFFFFFFF; 72 | // const uint32_t UICR_ADDR_0x94 __attribute__((at(0x10001094))) __attribute__((used)) = 0xFFFFFFFF; 73 | // const uint32_t UICR_ADDR_0x98 __attribute__((at(0x10001098))) __attribute__((used)) = 0xFFFFFFFF; 74 | // const uint32_t UICR_ADDR_0x9C __attribute__((at(0x1000109C))) __attribute__((used)) = 0xFFFFFFFF; 75 | // const uint32_t UICR_ADDR_0xA0 __attribute__((at(0x100010A0))) __attribute__((used)) = 0xFFFFFFFF; 76 | // const uint32_t UICR_ADDR_0xA4 __attribute__((at(0x100010A4))) __attribute__((used)) = 0xFFFFFFFF; 77 | // const uint32_t UICR_ADDR_0xA8 __attribute__((at(0x100010A8))) __attribute__((used)) = 0xFFFFFFFF; 78 | // const uint32_t UICR_ADDR_0xAC __attribute__((at(0x100010AC))) __attribute__((used)) = 0xFFFFFFFF; 79 | // const uint32_t UICR_ADDR_0xB0 __attribute__((at(0x100010B0))) __attribute__((used)) = 0xFFFFFFFF; 80 | // const uint32_t UICR_ADDR_0xB4 __attribute__((at(0x100010B4))) __attribute__((used)) = 0xFFFFFFFF; 81 | // const uint32_t UICR_ADDR_0xB8 __attribute__((at(0x100010B8))) __attribute__((used)) = 0xFFFFFFFF; 82 | // const uint32_t UICR_ADDR_0xBC __attribute__((at(0x100010BC))) __attribute__((used)) = 0xFFFFFFFF; 83 | // const uint32_t UICR_ADDR_0xC0 __attribute__((at(0x100010C0))) __attribute__((used)) = 0xFFFFFFFF; 84 | // const uint32_t UICR_ADDR_0xC4 __attribute__((at(0x100010C4))) __attribute__((used)) = 0xFFFFFFFF; 85 | // const uint32_t UICR_ADDR_0xC8 __attribute__((at(0x100010C8))) __attribute__((used)) = 0xFFFFFFFF; 86 | // const uint32_t UICR_ADDR_0xCC __attribute__((at(0x100010CC))) __attribute__((used)) = 0xFFFFFFFF; 87 | // const uint32_t UICR_ADDR_0xD0 __attribute__((at(0x100010D0))) __attribute__((used)) = 0xFFFFFFFF; 88 | // const uint32_t UICR_ADDR_0xD4 __attribute__((at(0x100010D4))) __attribute__((used)) = 0xFFFFFFFF; 89 | // const uint32_t UICR_ADDR_0xD8 __attribute__((at(0x100010D8))) __attribute__((used)) = 0xFFFFFFFF; 90 | // const uint32_t UICR_ADDR_0xDC __attribute__((at(0x100010DC))) __attribute__((used)) = 0xFFFFFFFF; 91 | // const uint32_t UICR_ADDR_0xE0 __attribute__((at(0x100010E0))) __attribute__((used)) = 0xFFFFFFFF; 92 | // const uint32_t UICR_ADDR_0xE4 __attribute__((at(0x100010E4))) __attribute__((used)) = 0xFFFFFFFF; 93 | // const uint32_t UICR_ADDR_0xE8 __attribute__((at(0x100010E8))) __attribute__((used)) = 0xFFFFFFFF; 94 | // const uint32_t UICR_ADDR_0xEC __attribute__((at(0x100010EC))) __attribute__((used)) = 0xFFFFFFFF; 95 | // const uint32_t UICR_ADDR_0xF0 __attribute__((at(0x100010F0))) __attribute__((used)) = 0xFFFFFFFF; 96 | // const uint32_t UICR_ADDR_0xF4 __attribute__((at(0x100010F4))) __attribute__((used)) = 0xFFFFFFFF; 97 | // const uint32_t UICR_ADDR_0xF8 __attribute__((at(0x100010F8))) __attribute__((used)) = 0xFFFFFFFF; 98 | // const uint32_t UICR_ADDR_0xFC __attribute__((at(0x100010FC))) __attribute__((used)) = 0xFFFFFFFF; 99 | 100 | const uint32_t UICR_NFCPINS __attribute__((at(0x1000120C))) __attribute__((used)) = 0xFFFFFFFE; 101 | /*lint --flb "Leave library region" */ 102 | 103 | #endif //_UICR_CONFIG_H 104 | -------------------------------------------------------------------------------- /Application/fm260b.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "nordic_common.h" 6 | 7 | #include "app_uart.h" 8 | 9 | #include "fm260b.h" 10 | #include "beep.h" 11 | #include "led_button.h" 12 | #include "ble_init.h" 13 | 14 | 15 | bool fig_status = false; 16 | bool exe_result = false; 17 | bool is_fm260b_autoenroll = false; 18 | 19 | //与指纹模块有关的参数 20 | uint16_t dr_fig_param_first = 0x0000; 21 | uint16_t dr_fig_param_second =0x0000; 22 | 23 | 24 | /********************************** 25 | *发送自动搜索模板 26 | ***********************************/ 27 | void fig_fm260b_send_autosearch(void) { 28 | static uint8_t fig_cmd_autosearch[8]= { 0x1B, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, 0x3B}; 29 | for (uint32_t i = 0; i < 8; i++) { 30 | while(app_uart_put(fig_cmd_autosearch[i]) != NRF_SUCCESS); 31 | } 32 | } 33 | 34 | 35 | 36 | static void ble_set_fig_free(void) { 37 | static uint8_t fig_cmd_free[8]= {0x1B,0xFF,0x00, 0x00,0x00, 0x00,0x00, 0x1A}; 38 | //发送free指令,使模块进入低功耗 39 | for (uint32_t i = 0; i < sizeof(fig_cmd_free); i++) { 40 | while(app_uart_put(fig_cmd_free[i]) != NRF_SUCCESS); 41 | } 42 | } 43 | 44 | /********************************* 45 | *指纹模块应答包处理模块 46 | *********************************/ 47 | void fig_fm260b_reply_check(void) { 48 | //------------- 初始化上电后 --------接收到准备命令 49 | //返回包长2 50 | if( (fig_recieve_data_length==2) &&\ 51 | (fig_recieve_data[0]==DR_READY_CODE) && (fig_recieve_data[1]==DR_READY_CODE ) ) { 52 | //设置指纹模块的状态位ture 53 | fig_status = true; 54 | fig_recieve_data_length = 0; 55 | } 56 | 57 | //----------------ERROR CMD REPLY----------错误的指令包 58 | //返回包长5 59 | if( (fig_recieve_data_length==5) &&\ 60 | ( (fig_recieve_data[DR_FIG_R_RESULT_CODE_SITE] == DR_FIG_R_CMD_WRONG) ||\ 61 | (fig_recieve_data[DR_FIG_R_RESULT_CODE_SITE] == DR_FIG_R_PARAM_WRONG) ||\ 62 | (fig_recieve_data[DR_FIG_R_RESULT_CODE_SITE] == DR_FIG_R_SUM_WRONG) ) ) { 63 | //将结果返回上位机 64 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 65 | fig_recieve_data_length = 0; 66 | //set fig free 67 | ble_set_fig_free(); 68 | } 69 | 70 | //-------CMD 1-1 REPLY-----------------SetSys命令的应答包 71 | //返回包长5 72 | if( (fig_recieve_data_length==5)&&\ 73 | (fig_recieve_data[DR_FIG_R_CMD_CODE_SITE]== DR_FIG_CMD_SETSYS) ) { 74 | //将结果返回上位机 75 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 76 | fig_recieve_data_length =0; 77 | } 78 | 79 | //---------CMD 2-1 REPLY--------------ReadInfo命令的应答包 80 | //检查单个指纹模板,返回包长5 81 | if( (fig_recieve_data_length==5) &&\ 82 | (fig_recieve_data[DR_FIG_R_CMD_CODE_SITE] == DR_FIG_CMD_READINFO) &&\ 83 | (dr_fig_param_first == 0x0001) ) { 84 | //将结果返回上位机 85 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 86 | fig_recieve_data_length = 0; 87 | //set fig free 88 | ble_set_fig_free(); 89 | } 90 | //-----------CMD 2-2 REPLY--------------ReadInfo命令的应该包 91 | //读取指纹库连续64个ID号对应位置是否有指纹,返回包长13 92 | if( (fig_recieve_data_length==13) &&\ 93 | (fig_recieve_data[DR_FIG_R_CMD_CODE_SITE] == DR_FIG_CMD_READINFO) &&\ 94 | (dr_fig_param_first == 0x0010) ) { 95 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 96 | fig_recieve_data_length = 0; 97 | //set fig free 98 | ble_set_fig_free(); 99 | } 100 | //-------------CMD 2-3 REPLY -------------ReadInfo命令的应答包 101 | //读取产品型号,返回包长15 102 | if( fig_recieve_data_length == 15 &&\ 103 | dr_fig_param_first == 0x0002 && dr_fig_param_second == 0x0001 &&\ 104 | fig_recieve_data[DR_FIG_R_CMD_CODE_SITE] == DR_FIG_CMD_READINFO) { 105 | //将结果返回上位机 106 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 107 | fig_recieve_data_length = 0; 108 | //set fig free 109 | ble_set_fig_free(); 110 | } 111 | //-------------CMD 2-4 REPLY -------------ReadInfo命令的应答包 112 | //读取软件版本号和日期,返回包长17 113 | if( fig_recieve_data_length == 17 &&\ 114 | dr_fig_param_first == 0x0002 && dr_fig_param_second == 0x0002 &&\ 115 | fig_recieve_data[DR_FIG_R_CMD_CODE_SITE] == DR_FIG_CMD_READINFO) { 116 | //将结果返回上位机 117 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 118 | fig_recieve_data_length = 0; 119 | //set fig free 120 | ble_set_fig_free(); 121 | } 122 | //-------------CMD 2-5 REPLY -------------ReadInfo命令的应答包 123 | //读取指纹库容量,返回包长7 124 | if( fig_recieve_data_length == 7 &&\ 125 | dr_fig_param_first == 0x0002 && dr_fig_param_second == 0x0003 &&\ 126 | fig_recieve_data[DR_FIG_R_CMD_CODE_SITE] == DR_FIG_CMD_READINFO) { 127 | //将结果返回上位机 128 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 129 | fig_recieve_data_length = 0; 130 | //set fig free 131 | ble_set_fig_free(); 132 | } 133 | //-------------CMD 2-6 REPLY -------------ReadInfo命令的应答包 134 | //读取SN号,返回包长9 135 | if( fig_recieve_data_length == 9 &&\ 136 | dr_fig_param_first == 0x0002 && dr_fig_param_second == 0x0004 &&\ 137 | fig_recieve_data[DR_FIG_R_CMD_CODE_SITE] == DR_FIG_CMD_READINFO) { 138 | //将结果返回上位机 139 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 140 | fig_recieve_data_length = 0; 141 | //set fig free 142 | ble_set_fig_free(); 143 | } 144 | 145 | //-------------CMD 2-7 REPLY-----------ReadInfo命令的应答包 146 | //探测手指,返回包长5 147 | if( (fig_recieve_data_length == 5) && \ 148 | (dr_fig_param_first==0x0008) && (dr_fig_param_second == 0x0001) && \ 149 | fig_recieve_data[DR_FIG_R_CMD_CODE_SITE] == DR_FIG_CMD_READINFO ) { 150 | //将结果返回上位机 151 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 152 | fig_recieve_data_length = 0; 153 | } 154 | 155 | //-------CMD 3-1 REPLY ----自动注册模板AutoEnroll 156 | //注释:直接上传结果给上位机,蓝牙芯片不做控制,其实手指一直放到上面即可 157 | //返回包长5 158 | if( (fig_recieve_data_length == 5) && \ 159 | (fig_recieve_data[DR_FIG_R_CMD_CODE_SITE]== DR_FIG_CMD_AUTOENROLL) ) { 160 | //将结果返回上位机 161 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 162 | fig_recieve_data_length = 0; 163 | //判断自动注册是否完成 164 | if( (fig_recieve_data[DR_FIG_R_RESULT_CODE_SITE] == DR_FIG_R_FINISH_TRUE) || \ 165 | (fig_recieve_data[DR_FIG_R_RESULT_CODE_SITE] == DR_FIG_R_FINISH_FALSE) ) { 166 | is_fm260b_autoenroll = false; 167 | //注册指纹完成,蜂鸣器响5次 168 | beep_didi(5); 169 | } 170 | } 171 | 172 | //-----------CMD 4-1 REPLY----------自动搜索模块AutoSearch,按下手指发,发送的前两步的指令 173 | //返回包长5 174 | if( (fig_recieve_data_length == 5) && \ 175 | (fig_recieve_data[DR_FIG_R_CMD_CODE_SITE] == DR_FIG_CMD_AUTOSEARCH) ) { 176 | //判断结果码 177 | switch(fig_recieve_data[DR_FIG_R_RESULT_CODE_SITE]) { 178 | case 0x00://第一个应答包,之后连续连续探测手指,将结果返回给上位机 179 | //蜂鸣器滴滴一声 180 | //beep_didi(1); 181 | //将结果返回上位机 182 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 183 | fig_recieve_data_length = 0; 184 | break; 185 | case 0x05://第二个应答包,提示已录好要比对的指纹,将结果返回给上位机 186 | //蜂鸣器滴滴二声 187 | //beep_didi(2); 188 | //将结果返回上位机 189 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 190 | fig_recieve_data_length = 0; 191 | break; 192 | 193 | default: 194 | break; 195 | } 196 | } 197 | 198 | //-----------CMD 4-2 REPLY------自动搜索模板AutoSearch,第三步,如果检索到指纹,发送结果 199 | //返回包长9 200 | if( (fig_recieve_data_length == 9) && \ 201 | (fig_recieve_data[DR_FIG_R_CMD_CODE_SITE] == DR_FIG_CMD_AUTOSEARCH) && \ 202 | (fig_recieve_data[DR_FIG_R_RESULT_CODE_SITE] ==DR_FIG_R_FINISH_TRUE) ) { 203 | //蜂鸣器滴滴三声 204 | beep_didi(3); 205 | //开门 206 | ble_door_open(); 207 | //将结果返回上位机 208 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 209 | fig_recieve_data_length = 0; 210 | //发送free指令,使模块进入低功耗 211 | ble_set_fig_free(); 212 | } 213 | 214 | //------------CMD 4-3 REPLY--------自动搜索模板AutoSearch,第三步,如果无比对的指纹 215 | //返回包长6 216 | if( (fig_recieve_data_length == 6) && \ 217 | (fig_recieve_data[DR_FIG_R_CMD_CODE_SITE] == DR_FIG_CMD_AUTOSEARCH) && \ 218 | (fig_recieve_data[DR_FIG_R_RESULT_CODE_SITE] == DR_FIG_R_FINISH_FALSE) ) { 219 | //搜索指纹失败,不开门,将结果返回给上位机 220 | //蜂鸣器滴滴四声 221 | beep_didi(4); 222 | //将结果返回上位机 223 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 224 | fig_recieve_data_length = 0; 225 | //发送free指令,使模块进入低功耗 226 | ble_set_fig_free(); 227 | } 228 | 229 | //--------CMD 5-1 REPLY -------------删除指纹模块Delete 230 | //返回包长5 231 | if( (fig_recieve_data_length == 5) && \ 232 | (fig_recieve_data[DR_FIG_R_CMD_CODE_SITE] == DR_FIG_CMD_DELETE) ) { 233 | //将结果返回上位机 234 | ble_nus_string_send(&m_nus,fig_recieve_data,fig_recieve_data_length); 235 | fig_recieve_data_length = 0; 236 | //发送free指令,使模块进入低功耗 237 | ble_set_fig_free(); 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /Application/inter_flash.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "bsp.h" 5 | #include "pstorage.h" 6 | #include "app_error.h" 7 | 8 | #include "inter_flash.h" 9 | #include "ble_init.h" 10 | #include "set_params.h" 11 | 12 | char super_key[SUPER_KEY_LENGTH]; 13 | 14 | pstorage_handle_t block_id_flash_store; 15 | 16 | pstorage_handle_t block_id_default_params; 17 | pstorage_handle_t block_id_mac; 18 | pstorage_handle_t block_id_super_key; 19 | pstorage_handle_t block_id_seed; 20 | pstorage_handle_t block_id_device_name; 21 | pstorage_handle_t block_id_key_store; 22 | pstorage_handle_t block_id_record; 23 | pstorage_handle_t block_id_fig_info; 24 | 25 | struct record_length_struct record_length; 26 | 27 | struct key_store_struct key_store_struct_set; 28 | struct door_open_record door_open_record_get; 29 | 30 | struct fig_info fig_info_set; //设置的指纹信息 31 | struct fig_info fig_info_get; //获取的指纹信息 32 | 33 | uint8_t interflash_write_data[BLOCK_STORE_SIZE]; 34 | uint8_t interflash_read_data[BLOCK_STORE_SIZE]; 35 | 36 | pstorage_handle_t block_id_write; 37 | pstorage_handle_t block_id_read; 38 | 39 | uint8_t flash_write_data[BLOCK_STORE_SIZE]; 40 | uint8_t flash_read_data[BLOCK_STORE_SIZE]; 41 | uint8_t flash_read_key_store_data[BLOCK_STORE_SIZE]; 42 | uint8_t flash_write_key_store_data[BLOCK_STORE_SIZE]; 43 | uint8_t flash_read_record_data[BLOCK_STORE_SIZE]; 44 | uint8_t flash_write_record_data[BLOCK_STORE_SIZE]; 45 | 46 | uint8_t flash_read_temp[BLOCK_STORE_SIZE]; 47 | 48 | /************************************************************************ 49 | *flash操作的回调函数 50 | *in: *handle 操作的flash的block_id 51 | op_code 操作码,具体定义参照pstorage.h 52 | result 执行结果 53 | *p_data 操作的数据的指针 54 | len 数据的长度 55 | ************************************************************************/ 56 | static void my_cb(pstorage_block_t *handle, uint8_t op_code, \ 57 | uint32_t result, uint8_t *p_data, uint32_t data_len) { 58 | switch(op_code) { 59 | case PSTORAGE_LOAD_OP_CODE: 60 | if (result != NRF_SUCCESS) { 61 | printf("pstorage LOAD ERROR callback received \r\n"); 62 | } 63 | break; 64 | case PSTORAGE_STORE_OP_CODE: 65 | if (result != NRF_SUCCESS) { 66 | printf("pstorage STORE ERROR callback received \r\n"); 67 | } 68 | break; 69 | case PSTORAGE_UPDATE_OP_CODE: 70 | if (result != NRF_SUCCESS) { 71 | printf("pstorage UPDATE ERROR callback received \r\n"); 72 | } 73 | break; 74 | case PSTORAGE_CLEAR_OP_CODE: 75 | if (result != NRF_SUCCESS) { 76 | printf("pstorage CLEAR ERROR callback received \r\n"); 77 | } 78 | break; 79 | default: 80 | break; 81 | } 82 | 83 | } 84 | 85 | /******************************************* 86 | *初始化内部flash空间 87 | *in: none 88 | *******************************************/ 89 | void flash_init(void) { 90 | uint32_t err_code; 91 | 92 | // pstorage_init(); //初始化flash操作,在device_manager_init中初始化了,这里就不用了 93 | 94 | //初始化key_store的空间 95 | pstorage_module_param_t module_param_key_store; 96 | module_param_key_store.block_count = BLOCK_STORE_COUNT;//申请 BLOCK_STORE_COUNT 个块 97 | module_param_key_store.block_size = BLOCK_STORE_SIZE; //每块大小 BLOCK_STORE_SIZE bytes 98 | module_param_key_store.cb = (pstorage_ntf_cb_t)my_cb; 99 | 100 | err_code = pstorage_register(&module_param_key_store, &block_id_flash_store); 101 | APP_ERROR_CHECK(err_code); 102 | #if defined(BLE_DOOR_DEBUG) 103 | printf("flash name:block_id_flash_store.\r\n"); 104 | printf("it has %i blocks and block size is %i \r\n",\ 105 | module_param_key_store.block_count, module_param_key_store.block_size); 106 | #endif 107 | 108 | //取设置的mac 109 | err_code =pstorage_block_identifier_get(&block_id_flash_store, \ 110 | (pstorage_size_t)MAC_OFFSET, &block_id_mac); 111 | APP_ERROR_CHECK(err_code); 112 | err_code = pstorage_load(mac, &block_id_mac, 8, 0); 113 | APP_ERROR_CHECK(err_code); 114 | 115 | //取设置的device_name 116 | /* err_code =pstorage_block_identifier_get(&block_id_flash_store, \ 117 | (pstorage_size_t)DEVICE_NAME_OFFSET, &block_id_device_name); 118 | APP_ERROR_CHECK(err_code); 119 | err_code = pstorage_load(device_name,&block_id_device_name,DEVICE_NAME_SIZE,0); 120 | APP_ERROR_CHECK(err_code); 121 | */ 122 | //如果开门记录的条数为全f,写开门记录条数为0 123 | err_code = pstorage_block_identifier_get(&block_id_flash_store, \ 124 | (pstorage_size_t)RECORD_OFFSET, &block_id_record); 125 | APP_ERROR_CHECK(err_code); 126 | err_code = pstorage_load((uint8_t *)&record_length, &block_id_record, sizeof(struct record_length_struct), 0); 127 | if(err_code == NRF_SUCCESS) { 128 | if(record_length.record_length == 0xffffffff) { 129 | record_length.record_length = 0x0; 130 | record_length.record_full = 0x0; 131 | err_code = pstorage_clear(&block_id_record,BLOCK_STORE_SIZE); 132 | APP_ERROR_CHECK(err_code); 133 | err_code = pstorage_store(&block_id_record, (uint8_t *)&record_length, sizeof(struct record_length_struct), 0); 134 | APP_ERROR_CHECK(err_code); 135 | } 136 | #if defined(BLE_DOOR_DEBUG) 137 | printf("record length set %d\r\n", record_length.record_length); 138 | #endif 139 | } 140 | #if defined(BLE_DOOR_DEBUG) 141 | printf("flash init success \r\n"); 142 | #endif 143 | 144 | } 145 | 146 | 147 | /********************************************************** 148 | *存储到flash 149 | *in: *p_data 写入数据的指针 150 | data_len 数据长度 151 | block_id_offset 写入的block偏移量 152 | *block_di_write 写入的block_id 153 | **********************************************************/ 154 | int interflash_write(uint8_t *p_data, uint32_t data_len,\ 155 | pstorage_size_t block_id_offset ) { 156 | uint32_t err_code; 157 | uint8_t data_len_4_left; 158 | uint32_t data_len_write; 159 | if(data_len <= BLOCK_STORE_SIZE) { 160 | //1、判断数据的长度是否是4的倍数,获取要写入的实际字节数 161 | data_len_4_left = data_len%4; 162 | if(data_len_4_left ==0) { 163 | //字节数是4的倍数 164 | data_len_write = data_len; 165 | } else { 166 | //字节数不是4的倍数 167 | data_len_write = (data_len +4 - data_len_4_left); 168 | } 169 | 170 | //2、组织要写入的数据数组 171 | memset(interflash_write_data, 0, BLOCK_STORE_SIZE); 172 | memcpy(interflash_write_data, p_data, data_len); 173 | 174 | //3、将数据存储到指定的位置 175 | //获取需要存储的位置 176 | pstorage_block_identifier_get(&block_id_flash_store, block_id_offset, &block_id_write); 177 | //清除当前存储区域 178 | pstorage_clear(&block_id_write, BLOCK_STORE_SIZE); 179 | err_code = pstorage_store(&block_id_write, interflash_write_data, (pstorage_size_t)data_len_write, 0); 180 | if(err_code ==NRF_SUCCESS) { 181 | #if defined(BLE_DOOR_DEBUG) 182 | printf("%2d bytes store in flash offset:%i\r\n", data_len, block_id_offset); 183 | #endif 184 | } 185 | return 0; 186 | } else { 187 | return 1; 188 | } 189 | 190 | } 191 | 192 | /********************************************************** 193 | *将flash中的数据读出来 194 | *in: *p_data 写入数据的指针 195 | data_len 数据长度 196 | block_id_offset 写入的block偏移量 197 | *block_di_read 写入的block_id 198 | **********************************************************/ 199 | int interflash_read(uint8_t *p_data, uint32_t data_len, \ 200 | pstorage_size_t block_id_offset) { 201 | uint32_t err_code; 202 | uint8_t data_len_4_left; 203 | uint32_t data_len_read; 204 | if(data_len <= BLOCK_STORE_SIZE) { 205 | //1、判断数据的长度是否是4的倍数,获取要写入的实际字节数 206 | data_len_4_left = data_len%4; 207 | if(data_len_4_left ==0) { 208 | //字节数是4的倍数 209 | data_len_read = data_len; 210 | } else { 211 | //字节数不是4的倍数 212 | data_len_read = (data_len +4 - data_len_4_left); 213 | } 214 | memset(interflash_read_data, 0, BLOCK_STORE_SIZE); 215 | pstorage_block_identifier_get(&block_id_flash_store, (pstorage_size_t)block_id_offset, &block_id_read); 216 | err_code = pstorage_load(interflash_read_data, &block_id_read, (pstorage_size_t)data_len_read, 0); 217 | if(err_code ==NRF_SUCCESS) { 218 | memset(p_data, 0, data_len); 219 | memcpy(p_data, interflash_read_data, data_len); 220 | #ifdef BLE_DOOR_DEBUG 221 | printf("%2d bytes read in flash offset:%i\r\n", data_len, block_id_offset); 222 | #endif 223 | } 224 | return 0; 225 | } else { 226 | return 1; 227 | } 228 | 229 | } 230 | 231 | /************************************************************************* 232 | *写入管理员秘钥(12位ASCII) 233 | *in: *p_data 超级密码的指针 234 | data_len 数据的长度 235 | ************************************************************************/ 236 | int write_super_key(uint8_t *p_data, uint32_t data_len) { 237 | uint8_t data_len_4_left; 238 | uint32_t data_len_write; 239 | if(data_len <= BLOCK_STORE_SIZE) { 240 | //1、判断数据的长度是否是4的倍数,获取要写入的实际字节数 241 | data_len_4_left = data_len%4; 242 | if(data_len_4_left ==0) { 243 | //字节数是4的倍数 244 | data_len_write = data_len; 245 | } else { 246 | //字节数不是4的倍数 247 | data_len_write = (data_len +4 - data_len_4_left); 248 | } 249 | //2、组织要写入的数据数组 250 | memset(interflash_write_data, 0, BLOCK_STORE_SIZE); 251 | memcpy(interflash_write_data, p_data, data_len); 252 | 253 | //3、将数据存储到指定的位置 254 | pstorage_block_identifier_get(&block_id_flash_store, (pstorage_size_t)SUPER_KEY_OFFSET, &block_id_super_key); 255 | pstorage_clear(&block_id_super_key,BLOCK_STORE_SIZE); 256 | pstorage_store(&block_id_super_key, interflash_write_data, data_len_write, 0); 257 | #ifdef BLE_DOOR_DEBUG 258 | printf("super key write:"); 259 | for(int i=0; icontrol_bits =0x01,以前的记录清除 276 | *记录达到上限KEY_STORE_NUMBER,则循环记录 277 | **********************************************************************/ 278 | void key_store_write(struct key_store_struct *key_store_input, uint16_t key_store_site) { 279 | 280 | memset(flash_write_key_store_data, 0, BLOCK_STORE_SIZE); 281 | memcpy(flash_write_key_store_data,key_store_input, sizeof(struct key_store_struct)); 282 | interflash_write(flash_write_key_store_data, BLOCK_STORE_SIZE, \ 283 | (pstorage_size_t)(KEY_STORE_OFFSET + key_store_site)); 284 | 285 | #if defined(BLE_DOOR_DEBUG) 286 | printf("key set success:"); 287 | for(int j=0; jkey_store[j]); 289 | } 290 | printf("\r\n"); 291 | #endif 292 | 293 | } 294 | 295 | /******************************************************************** 296 | *将记录存储在flash中 297 | *in: *open_record 写入的记录结构体 298 | *********************************************************************/ 299 | void record_write(struct door_open_record *open_record) { 300 | //写记录条数 301 | pstorage_block_identifier_get(&block_id_flash_store, (pstorage_size_t)RECORD_OFFSET, &block_id_record); 302 | pstorage_load((uint8_t *)&record_length, &block_id_record, sizeof(struct record_length_struct), 0); 303 | if(record_length.record_length >= RECORD_NUMBER) { 304 | //达到记录上限 305 | record_length.record_length = 0x1; 306 | record_length.record_full= 0x01; 307 | } else { 308 | //未达到记录上限 309 | record_length.record_length++; 310 | } 311 | pstorage_clear(&block_id_record, BLOCK_STORE_SIZE); 312 | pstorage_store(&block_id_record, (uint8_t *)&record_length, 4, 0); 313 | 314 | memset(flash_write_record_data, 0, BLOCK_STORE_SIZE); 315 | memcpy(flash_write_record_data, open_record, sizeof(struct door_open_record)); 316 | interflash_write(flash_write_record_data, BLOCK_STORE_SIZE,\ 317 | (pstorage_size_t)(RECORD_OFFSET + record_length.record_length)); 318 | 319 | } 320 | 321 | /************************************************ 322 | *将指纹信息存储到内部flash 323 | ************************************************/ 324 | int fig_info_write(struct fig_info *fp_info_set_p) { 325 | int err_code; 326 | // err_code = interflash_write((uint8_t *) fp_info_set_p, sizeof(struct fig_info), \ 327 | (pstorage_size_t)(FIG_INFO_OFFSET + fp_info_set_p->fig_info_id)); 328 | //1、获取label 329 | pstorage_block_identifier_get(&block_id_flash_store, \ 330 | (pstorage_size_t)(FIG_INFO_OFFSET+fp_info_set_p->fig_info_id), &block_id_fig_info); 331 | //2、清除区域 332 | pstorage_clear(&block_id_fig_info, BLOCK_STORE_SIZE); 333 | //3、存储信息 334 | memset(interflash_write_data, 0, BLOCK_STORE_SIZE); 335 | memcpy(interflash_write_data, fp_info_set_p, sizeof(struct fig_info)); 336 | err_code = pstorage_store(&block_id_fig_info, interflash_write_data, BLOCK_STORE_SIZE, 0); 337 | 338 | return err_code; 339 | } 340 | 341 | /************************************************* 342 | *读取内部flash中指定位置的 343 | *************************************************/ 344 | int fig_info_read(struct fig_info *fp_info_get_p) { 345 | int err_code; 346 | err_code = interflash_write((uint8_t *) fp_info_get_p, sizeof(struct fig_info), \ 347 | (pstorage_size_t)(FIG_INFO_OFFSET + fp_info_get_p->fig_info_id)); 348 | return err_code; 349 | } 350 | -------------------------------------------------------------------------------- /Application/sm4_mcu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SM4 Encryption alogrithm (SMS4 algorithm) 3 | * GM/T 0002-2012 Chinese National Standard ref:http://www.oscca.gov.cn/ 4 | * thanks to Xyssl 5 | * thnaks and refers to http://hi.baidu.com/numax/blog/item/80addfefddfb93e4cf1b3e61.html 6 | * author:goldboar 7 | * email:goldboar@163.com 8 | * 2012-4-20 9 | */ 10 | 11 | // 采用嵌入式MCU的加/解密 SM4算法,C 12 | 13 | // Test vector 1 14 | // plain: 01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10 15 | // key: 01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10 16 | // round key and temp computing result: 17 | // rk[ 0] = f12186f9 X[ 0] = 27fad345 18 | // rk[ 1] = 41662b61 X[ 1] = a18b4cb2 19 | // rk[ 2] = 5a6ab19a X[ 2] = 11c1e22a 20 | // rk[ 3] = 7ba92077 X[ 3] = cc13e2ee 21 | // rk[ 4] = 367360f4 X[ 4] = f87c5bd5 22 | // rk[ 5] = 776a0c61 X[ 5] = 33220757 23 | // rk[ 6] = b6bb89b3 X[ 6] = 77f4c297 24 | // rk[ 7] = 24763151 X[ 7] = 7a96f2eb 25 | // rk[ 8] = a520307c X[ 8] = 27dac07f 26 | // rk[ 9] = b7584dbd X[ 9] = 42dd0f19 27 | // rk[10] = c30753ed X[10] = b8a5da02 28 | // rk[11] = 7ee55b57 X[11] = 907127fa 29 | // rk[12] = 6988608c X[12] = 8b952b83 30 | // rk[13] = 30d895b7 X[13] = d42b7c59 31 | // rk[14] = 44ba14af X[14] = 2ffc5831 32 | // rk[15] = 104495a1 X[15] = f69e6888 33 | // rk[16] = d120b428 X[16] = af2432c4 34 | // rk[17] = 73b55fa3 X[17] = ed1ec85e 35 | // rk[18] = cc874966 X[18] = 55a3ba22 36 | // rk[19] = 92244439 X[19] = 124b18aa 37 | // rk[20] = e89e641f X[20] = 6ae7725f 38 | // rk[21] = 98ca015a X[21] = f4cba1f9 39 | // rk[22] = c7159060 X[22] = 1dcdfa10 40 | // rk[23] = 99e1fd2e X[23] = 2ff60603 41 | // rk[24] = b79bd80c X[24] = eff24fdc 42 | // rk[25] = 1d2115b0 X[25] = 6fe46b75 43 | // rk[26] = 0e228aeb X[26] = 893450ad 44 | // rk[27] = f1780c81 X[27] = 7b938f4c 45 | // rk[28] = 428d3654 X[28] = 536e4246 46 | // rk[29] = 62293496 X[29] = 86b3e94f 47 | // rk[30] = 01cf72e5 X[30] = d206965e 48 | // rk[31] = 9124a012 X[31] = 681edf34 49 | // cypher: 68 1e df 34 d2 06 96 5e 86 b3 e9 4f 53 6e 42 46 50 | // 51 | // test vector 2 52 | // the same key and plain 1000000 times coumpting 53 | // plain: 01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10 54 | // key: 01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10 55 | // cypher: 59 52 98 c7 c6 fd 27 1f 04 02 f8 04 c3 3d 3f 66 56 | 57 | #include 58 | #include 59 | #include 60 | #include "sm4_mcu.h" 61 | 62 | /* 63 | * 32-bit integer manipulation macros (big endian) 64 | * // 将一个32位的Little-Endian的长字转换成Big-Endian格式 65 | * // n:输出结果 66 | * // b: 输入数组地址 67 | * // i: 起始对齐字节 68 | */ 69 | #ifndef GET_ULONG_BE 70 | #define GET_ULONG_BE(n,b,i) \ 71 | { \ 72 | (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ 73 | | ( (unsigned long) (b)[(i) + 1] << 16 ) \ 74 | | ( (unsigned long) (b)[(i) + 2] << 8 ) \ 75 | | ( (unsigned long) (b)[(i) + 3] ); \ 76 | } 77 | #endif 78 | 79 | /* 80 | * // 将一个32位的Big-Endian的长字转换成Little-Endian格式 81 | * // n:输入数值 82 | * // b: 输出数组地址 83 | * // i: 起始对齐字节 84 | */ 85 | #ifndef PUT_ULONG_BE 86 | #define PUT_ULONG_BE(n,b,i) \ 87 | { \ 88 | (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ 89 | (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ 90 | (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ 91 | (b)[(i) + 3] = (unsigned char) ( (n) ); \ 92 | } 93 | #endif 94 | 95 | /* 96 | * rotate shift left marco definition 97 | * // 左移 98 | */ 99 | #define SHL(x,n) (((x) & 0xFFFFFFFF) << n) 100 | 101 | /* 102 | * rotate shift left marco definition 103 | * // 将(x)的高位的 n bits向右移动到低位位置 104 | */ 105 | #define ROTL(x,n) (SHL((x),n) | ((x) >> (32 - n))) 106 | 107 | /* 108 | * swap marco definition 109 | * // a 和 b 进行数值交换 110 | */ 111 | #define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; } 112 | 113 | /**************************************************** 114 | * Expanded SM4 S-boxes 115 | * Sbox table: 8bits input convert to 8 bits output 116 | ***************************************************/ 117 | 118 | static const unsigned char SboxTable[16][16] = { 119 | {0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05}, 120 | {0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99}, 121 | {0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62}, 122 | {0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6}, 123 | {0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8}, 124 | {0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35}, 125 | {0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87}, 126 | {0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e}, 127 | {0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1}, 128 | {0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3}, 129 | {0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f}, 130 | {0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51}, 131 | {0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8}, 132 | {0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0}, 133 | {0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84}, 134 | {0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48} 135 | }; 136 | 137 | /* System parameter 系统参数 */ 138 | static const unsigned long FK[4] = {0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc}; 139 | 140 | /* fixed parameter 固定参数 */ 141 | static const unsigned long CK[32] = { 142 | 0x00070e15,0x1c232a31,0x383f464d,0x545b6269, 143 | 0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9, 144 | 0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249, 145 | 0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9, 146 | 0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229, 147 | 0x30373e45,0x4c535a61,0x686f767d,0x848b9299, 148 | 0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209, 149 | 0x10171e25,0x2c333a41,0x484f565d,0x646b7279 150 | }; 151 | 152 | 153 | /* 154 | * private function: 155 | * look up in SboxTable and get the related value. 156 | * args: [in] inch: 0x00~0xFF (8 bits unsigned value). 157 | * 查找S盒子参数 158 | */ 159 | static unsigned char sm4Sbox(unsigned char inch) { 160 | unsigned char *pTable = (unsigned char *)SboxTable; 161 | unsigned char retVal = (unsigned char)(pTable[inch]); 162 | return retVal; 163 | } 164 | 165 | /* 166 | * private F(Lt) function: 167 | * "T algorithm" == "L algorithm" + "t algorithm". 168 | * args: [in] a: a is a 32 bits unsigned value; 169 | * return: c: c is calculated with line algorithm "L" and nonline algorithm "t" 170 | * 查表并进行T算数运算 171 | */ 172 | static unsigned long sm4Lt(unsigned long ka) { 173 | unsigned long bb = 0; 174 | unsigned long c = 0; 175 | unsigned char a[4]; 176 | unsigned char b[4]; 177 | 178 | // 将ka转成Little-endian 没必要吧? 179 | PUT_ULONG_BE(ka,a,0) 180 | b[0] = sm4Sbox(a[0]); 181 | b[1] = sm4Sbox(a[1]); 182 | b[2] = sm4Sbox(a[2]); 183 | b[3] = sm4Sbox(a[3]); 184 | 185 | // 将S盒子变换后的值转为Big-endian 186 | GET_ULONG_BE(bb,b,0) 187 | c =bb^(ROTL(bb, 2))^(ROTL(bb, 10))^(ROTL(bb, 18))^(ROTL(bb, 24)); 188 | return c; 189 | } 190 | 191 | /* 192 | * private F function: 193 | * Calculating and getting encryption/decryption contents. 194 | * args: [in] x0: original contents; 195 | * args: [in] x1: original contents; 196 | * args: [in] x2: original contents; 197 | * args: [in] x3: original contents; 198 | * args: [in] rk: encryption/decryption key; 199 | * return the contents of encryption/decryption contents. 200 | * 轮函数 201 | */ 202 | static unsigned long sm4F(unsigned long x0, unsigned long x1, unsigned long x2, unsigned long x3, unsigned long rk) { 203 | return (x0^sm4Lt(x1^x2^x3^rk)); 204 | } 205 | 206 | 207 | /* private function: 208 | * Calculating round encryption key. 209 | * args: [in] a: a is a 32 bits unsigned value; 210 | * return: sk[i]: i{0,1,2,3,...31}. 211 | * 对秘钥进行循环扩展处理 212 | */ 213 | static unsigned long sm4CalciRK(unsigned long ka) { 214 | unsigned long bb = 0; 215 | unsigned long rk = 0; 216 | unsigned char a[4]; 217 | unsigned char b[4]; 218 | 219 | // 将ka转成Little-endian 没必要吧? 220 | PUT_ULONG_BE(ka,a,0) 221 | b[0] = sm4Sbox(a[0]); 222 | b[1] = sm4Sbox(a[1]); 223 | b[2] = sm4Sbox(a[2]); 224 | b[3] = sm4Sbox(a[3]); 225 | 226 | // 将S盒子变换后的值转为Big-endian 227 | GET_ULONG_BE(bb,b,0) 228 | rk = bb^(ROTL(bb, 13))^(ROTL(bb, 23)); 229 | return rk; 230 | } 231 | 232 | /* 233 | * // 设置秘钥函数 234 | * // SK[]:输出的秘钥数组,Big-endian 235 | * // key[]:输入的秘钥数组,16字节,128bits,Little-endian 236 | */ 237 | static void sm4_setkey( uint32_t *SK, unsigned char *key) { 238 | uint32_t MK[4]; 239 | uint32_t k[36]; 240 | uint32_t i; 241 | 242 | // 将key转成Big-endian 243 | GET_ULONG_BE( MK[0], key, 0 ); 244 | GET_ULONG_BE( MK[1], key, 4 ); 245 | GET_ULONG_BE( MK[2], key, 8 ); 246 | GET_ULONG_BE( MK[3], key, 12 ); 247 | 248 | k[0] = MK[0] ^ FK[0]; 249 | k[1] = MK[1] ^ FK[1]; 250 | k[2] = MK[2] ^ FK[2]; 251 | k[3] = MK[3] ^ FK[3]; 252 | 253 | for(i = 0; i < 32; i++) { 254 | k[i+4] = k[i] ^ (sm4CalciRK(k[i+1]^k[i+2]^k[i+3]^CK[i])); 255 | SK[i] = k[i+4]; 256 | } 257 | 258 | } 259 | 260 | /* 261 | * SM4 standard one round processing 262 | * // sk[] 扩展后的轮秘钥,big-endian 263 | * // input 输入加密内容,little-endian 264 | * // output 输出的加密结果,little-endian 265 | * 对输入的16字节 128bits内容进行一次加解密 266 | */ 267 | static void sm4_one_round( uint32_t *sk, 268 | unsigned char *input, 269 | unsigned char *output) { 270 | uint32_t i = 0; 271 | uint32_t ulbuf[36]; 272 | 273 | memset(ulbuf, 0, sizeof(ulbuf)); 274 | 275 | // 将输入的加密内容,转换为big-endian 276 | GET_ULONG_BE( ulbuf[0], input, 0 ) 277 | GET_ULONG_BE( ulbuf[1], input, 4 ) 278 | GET_ULONG_BE( ulbuf[2], input, 8 ) 279 | GET_ULONG_BE( ulbuf[3], input, 12 ) 280 | while(i<32) { 281 | ulbuf[i+4] = sm4F(ulbuf[i], ulbuf[i+1], ulbuf[i+2], ulbuf[i+3], sk[i]); 282 | // #ifdef _DEBUG 283 | // printf("rk(%02d) = 0x%08x, X(%02d) = 0x%08x \n",i,sk[i], i, ulbuf[i+4] ); 284 | // #endif 285 | i++; 286 | } 287 | 288 | // 将输出的加密内容转换为little-endian 289 | PUT_ULONG_BE(ulbuf[35],output,0); 290 | PUT_ULONG_BE(ulbuf[34],output,4); 291 | PUT_ULONG_BE(ulbuf[33],output,8); 292 | PUT_ULONG_BE(ulbuf[32],output,12); 293 | } 294 | 295 | /* 296 | * SM4 key schedule (128-bit, encryption) 297 | * // ctx-mode:加密模式,标识秘钥的用途 298 | * // ctx-sk:输出的轮秘钥 big-endian 299 | * // key:输入秘钥 littel-endian 300 | */ 301 | void sm4_setkey_enc( struct sm4_context *ctx, unsigned char *key) { 302 | ctx->mode = SM4_ENCRYPT; 303 | sm4_setkey( ctx->sk, key ); 304 | } 305 | 306 | /* 307 | * SM4 key schedule (128-bit, decryption) 308 | */ 309 | void sm4_setkey_dec( struct sm4_context *ctx, unsigned char *key) { 310 | int i; 311 | ctx->mode = SM4_DECRYPT; 312 | sm4_setkey( ctx->sk, key ); 313 | for( i = 0; i < 16; i ++ ) { 314 | SWAP( ctx->sk[ i ], ctx->sk[ 31-i] ); 315 | } 316 | } 317 | 318 | 319 | /* 320 | * SM4-ECB block encryption/decryption 321 | * 电码本加解密方式 322 | * // ctx:加密方式及扩展后的轮秘钥,big-endian 323 | * // length:输入的加密内容的长度 324 | * // input:输入的内容指针,little-endian 325 | * // output:输出的加密后的内容,little-endian 326 | */ 327 | 328 | void sm4_crypt_ecb( struct sm4_context *ctx, 329 | int mode, 330 | int length, 331 | unsigned char *input, 332 | unsigned char *output) { 333 | while( length > 0 ) { 334 | sm4_one_round( ctx->sk, input, output ); 335 | input += 16; 336 | output += 16; 337 | length -= 16; 338 | } 339 | 340 | } 341 | 342 | /* 343 | * SM4-CBC buffer encryption/decryption 344 | * 分组链接加解密方式 345 | * // ctx:加密方式及扩展后的轮秘钥 346 | * // length:输入的加密内容的长度 347 | * // iv[]:初始化值或上一组加密结果 348 | * // input:输入的内容指针 349 | * // output:输出的加密后的内容 350 | */ 351 | void sm4_crypt_cbc( struct sm4_context *ctx, 352 | int mode, 353 | int length, 354 | unsigned char *iv, 355 | unsigned char *input, 356 | unsigned char *output ) { 357 | int i; 358 | unsigned char temp[16]; 359 | 360 | if( mode == SM4_ENCRYPT ) { 361 | while( length > 0 ) { 362 | for( i = 0; i < 16; i++ ) 363 | output[i] = (unsigned char)( input[i] ^ iv[i] ); 364 | 365 | sm4_one_round( ctx->sk, output, output ); 366 | memcpy( iv, output, 16 ); 367 | 368 | input += 16; 369 | output += 16; 370 | length -= 16; 371 | } 372 | } else { /* SM4_DECRYPT */ 373 | while( length > 0 ) { 374 | memcpy( temp, input, 16 ); 375 | sm4_one_round( ctx->sk, input, output ); 376 | 377 | for( i = 0; i < 16; i++ ) 378 | output[i] = (unsigned char)( output[i] ^ iv[i] ); 379 | 380 | memcpy( iv, temp, 16 ); 381 | 382 | input += 16; 383 | output += 16; 384 | length -= 16; 385 | } 386 | } 387 | } 388 | -------------------------------------------------------------------------------- /Application/led_button.c: -------------------------------------------------------------------------------- 1 | /******************************** 2 | *初始化LEDs 3 | *初始化I2C的int_pin和中断处理函数 4 | *********************************/ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "nrf_delay.h" 13 | #include "nrf_gpio.h" 14 | #include "boards.h" 15 | #include "custom_board.h" 16 | #include "boards.h" 17 | #include "app_gpiote.h" 18 | #include "app_uart.h" 19 | 20 | #include "led_button.h" 21 | #include "ble_init.h" 22 | //#include "touch_tsm12.h" 23 | #include "wt5700.h" 24 | #include "moto.h" 25 | #include "beep.h" 26 | #include "set_params.h" 27 | #include "inter_flash.h" 28 | #include "rtc_chip.h" 29 | #include "sm4_mcu.h" 30 | #include "sm4_dpwd.h" 31 | #include "my_time.h" 32 | #include "operate_code.h" 33 | //#include "fm260b.h" 34 | #include "r301t.h" 35 | 36 | #define APP_GPIOTE_MAX_USERS 1 37 | 38 | app_gpiote_user_id_t m_app_gpiote_id; 39 | 40 | bool is_key_value_get = false; 41 | 42 | char key_express_value; 43 | 44 | //输入按键值,当作输入密码 45 | char key_input[KEY_MAX_NUMBER]; 46 | uint8_t key_input_site; 47 | 48 | char key_marry[KEY_LENGTH];//匹配的密码 49 | 50 | //输入的密码的时间 51 | struct tm key_input_time_tm; 52 | time_t key_input_time_t; 53 | 54 | //检测密码的次数 55 | uint8_t key_input_checked_number = 0; 56 | time_t key_input_checked_locked_time_t; 57 | bool key_input_checked_locked = false; 58 | 59 | ///开锁记录全局变量 60 | struct door_open_record open_record_now; 61 | 62 | bool is_background_lit = false; 63 | 64 | /*********************************************** 65 | *初始化LED pins 66 | * 设置LED PINS high(led light when pin is low) 67 | **********************************************/ 68 | void leds_init(void) { 69 | uint32_t led_list[LEDS_NUMBER] = LEDS_LIST; 70 | 71 | //set output set high //led lit when set low 72 | for(int pin = 0; pin = (10*60) ) { 334 | //大于10分钟,则解除验证锁定 335 | is_check_locked = false; 336 | } else { //1.2 337 | //小于10分钟,锁定验证 338 | is_check_locked = true; 339 | } 340 | } else { //2 341 | is_check_locked = false; 342 | } 343 | 344 | 345 | //3.如果验证没锁定 346 | if(is_check_locked == false) { 347 | //判断输入的按键值 348 | if(touch_keys_input_check(key_input, key_input_site, key_input_time_t)) { 349 | ble_door_open(); 350 | key_input_checked_number = 0; 351 | key_input_checked_locked_time_t = 0; 352 | key_input_checked_locked = false; 353 | #ifdef BLE_DOOR_DEBUG 354 | printf("door open\r\n"); 355 | #endif 356 | 357 | //记录开门 358 | door_open_record_flash(key_input, key_input_site, key_input_time_t); 359 | } else { 360 | key_input_checked_number++; 361 | if(key_input_checked_number == KEY_INPUT_CHECKED_MAX_NUMBER) { 362 | //记录第5次验证失败的时间 363 | key_input_checked_locked_time_t = key_input_time_t; 364 | key_input_checked_locked = true; 365 | } 366 | #ifdef BLE_DOOR_DEBUG 367 | printf("input keys check fail\r\n"); 368 | #endif 369 | } 370 | } 371 | 372 | //判断完输入的按键序列后,删除所有按键值 373 | clear_key_expressed(); 374 | #if defined(BLE_DOOR_DEBUG) 375 | printf("clear all express button\r\n"); 376 | #endif 377 | 378 | } 379 | 380 | /***************************************** 381 | *检验按下的键值,并记录, 382 | *如果是开锁键(b)进行密码校验 383 | *in: express_value 按下的键值 384 | ******************************************/ 385 | 386 | static void check_key_express(char express_value) { 387 | static uint8_t board_leds[LEDS_NUMBER-1] = {LED_1, LED_3, LED_5,\ 388 | LED_7, LED_10, LED_11,\ 389 | LED_2, LED_4, LED_6,\ 390 | LED_8, LED_9, LED_12 391 | }; 392 | static char board_buttons[LEDS_NUMBER-1] = {'1', '2', '3',\ 393 | '4', '5', '6',\ 394 | '7', '8', '9',\ 395 | 'a', '0', 'b' 396 | }; 397 | 398 | //判断按键,亮相应的灯 399 | for(int i=0; i< (LEDS_NUMBER-1); i++) { 400 | if(board_buttons[i] == express_value) { 401 | // leds_on(board_leds[i], LED_LIGHT_TIME); 402 | //蜂鸣器响1声 403 | beep_didi(1); 404 | //3、闪一下背光 405 | // nrf_gpio_pin_clear( BATTERY_LEVEL_EN ); 406 | nrf_delay_ms(TOUCH_DELAY*10); 407 | // nrf_gpio_pin_set( BATTERY_LEVEL_EN ); 408 | write_key_expressed(); 409 | } 410 | } 411 | //如果按键是'b',检验所有按键,其他键则记录下来 412 | if(express_value == 'b') { 413 | if(key_input_site >=6) { 414 | //蜂鸣器响1声 415 | beep_didi(1); 416 | check_keys(); 417 | } else { 418 | //蜂鸣器响1声 419 | beep_didi(1); 420 | clear_key_expressed(); 421 | } 422 | } 423 | 424 | } 425 | 426 | /************************************ 427 | *用户解绑操作 428 | ************************************/ 429 | static void nrst_all(void) { 430 | 431 | //1、清除内部flash所有数据 432 | for(int j=0; j < BLOCK_STORE_COUNT; j++) { 433 | pstorage_block_identifier_get(&block_id_flash_store, \ 434 | (pstorage_size_t)j, &block_id_write); 435 | 436 | pstorage_clear(&block_id_write, BLOCK_STORE_SIZE); 437 | 438 | } 439 | 440 | //2、清除指纹内所有存储指纹 441 | //2.1、打开指纹模 442 | open_fig(); 443 | //2.2、发送删除指令 444 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_empty_cmd), r301t_send_empty_cmd); 445 | //2.3、获取指令码,此指令码需要在回复命令处理中使用 446 | fig_cmd_code = r301t_send_empty_cmd[0]; 447 | //3、获取指令码 448 | ble_operate_code = USER_UNBIND_CMD; 449 | 450 | } 451 | 452 | /************************************************************** 453 | *触摸屏中断和指纹中断处理函数 454 | *in: event_pins_low_to_high 状态由低到高的引脚 455 | * event_pins_high_to_low 状态由高到低的引脚 456 | **************************************************************/ 457 | static void touch_finger_int_handler(uint32_t event_pins_low_to_high, uint32_t event_pins_high_to_low) { 458 | //触摸按键中断响应 459 | if (event_pins_high_to_low & (1 << TOUCH_IIC_INT_PIN)) { 460 | //触摸中断由高变低 461 | //1、开启背景灯 462 | if(is_background_lit == false) { 463 | nrf_gpio_pin_set( BATTERY_LEVEL_EN ); 464 | is_background_lit = true; 465 | // app_timer_start(m_backlit_timer_id, BACKGROUND_LIT_DELAY, NULL); 466 | } 467 | //2、读取触摸按键 468 | is_key_value_get = true; 469 | key_express_value = (char)wt5700_key_read(); 470 | is_key_value_get = false; 471 | if(key_express_value != 0) { 472 | check_key_express(key_express_value); 473 | } 474 | 475 | } 476 | //指纹中断响应 477 | if (event_pins_high_to_low & (1 << FIG_WAKE_N_PIN)) { 478 | /*//指纹中断由高变低,自动化过程,判断如果不是上位机设置的注册模式,发送自动搜索 479 | if( is_fm260b_autoenroll == false ) 480 | { 481 | //未处在自动注册状态,发送自动搜索模板功能 482 | fig_fm260b_send_autosearch(); 483 | }*/ 484 | 485 | if(r301t_autosearch_step == 0 && is_r301t_autoenroll == false) { 486 | //打开模块芯片 487 | open_fig(); 488 | //设置步骤为1,设置命令码为getimg 489 | r301t_autosearch_step = 1; 490 | ble_operate_code = SEARCH_FIG; 491 | //指纹模块r301t 492 | //发送获取图像命令 493 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_getimg_cmd), \ 494 | r301t_send_getimg_cmd); 495 | } 496 | } 497 | //初始化按键中断响应 498 | if (event_pins_high_to_low & (1 << NRST_IN)) { 499 | nrst_all(); 500 | } 501 | 502 | } 503 | 504 | /*************************************************************** 505 | * 初始化触摸屏中断引脚和指纹中断引脚 506 | *in: none 507 | ***************************************************************/ 508 | void touch_finger_int_init(void) { 509 | uint32_t err_code; 510 | 511 | //初始化键值,变量 512 | key_express_value = 0x0; 513 | //初始化按键记录,及按键值保存位置 514 | clear_key_expressed(); 515 | 516 | uint32_t low_to_high_bitmask = 0x00000000; 517 | uint32_t high_to_low_bitmask = (1 << TOUCH_IIC_INT_PIN) | (1 << FIG_WAKE_N_PIN) | (1 < 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "nordic_common.h" 8 | #include "nrf_gpio.h" 9 | #include "nrf_delay.h" 10 | 11 | #include "app_uart.h" 12 | 13 | #include "r301t.h" 14 | #include "beep.h" 15 | #include "led_button.h" 16 | #include "ble_init.h" 17 | #include "rtc_chip.h" 18 | #include "my_time.h" 19 | #include "custom_board.h" 20 | #include "operate_code.h" 21 | 22 | 23 | bool is_r301t_autoenroll = false; 24 | uint8_t r301t_autosearch_step = 0; 25 | 26 | uint8_t r301t_indextable_data[32]; 27 | bool is_get_r301t_indextable = false; 28 | uint8_t fig_info_get_site; 29 | 30 | 31 | //发送获取指纹图像命令 32 | uint8_t r301t_send_getimg_cmd[1] = {0x01}; 33 | //将生成的图像生成到charbuff1 34 | uint8_t r301t_send_genchar1_cmd[2] = {0x02, 0x01}; 35 | //将生成的图像生成到charbuff2 36 | uint8_t r301t_send_genchar2_cmd[2] = {0x02, 0x02}; 37 | //发送搜索指纹模式,一共有32个指纹 38 | uint8_t r301t_send_search_cmd[6] = {0x04, 0x01, 0x00, 0x00, 0x00, 0x20}; 39 | //将charbuff1与charbuffer2中的特征文件合并生成模板存于charbuff1与charbuff2 40 | uint8_t r301t_send_regmodel_cmd[1] = {0x05}; 41 | //将特征缓冲区的文件储存在flash指纹库这里是ID0 42 | uint8_t r301t_send_storechar_id0_cmd[4] = {0x06, 0x02, 0x00, 0x00}; 43 | uint8_t r301t_send_storechar_idx_cmd[4]; 44 | //删除指纹命令,这里是ID0 45 | uint8_t r301t_send_deletechar_id0_cmd[5] = {0x0c, 0x00, 0x00, 0x00, 0x01}; 46 | uint8_t r301t_send_deletechar_idx_cmd[5]; 47 | //清空指纹库命令 48 | uint8_t r301t_send_empty_cmd[1] = {0x0d}; 49 | //获取有效模板个数 50 | uint8_t r301t_send_get_vtnum_cmd[1] = {0x1d}; 51 | //读取索引列表 52 | uint8_t r301t_send_get_indextb_cmd[2] = {0x1f, 0x00}; 53 | uint8_t r301t_send_get_indextbx_cmd[2] = {0x1f, 0x00}; 54 | 55 | 56 | /********************************************************** 57 | * 向指纹模块发送指令 58 | * data_id 包标识 bit6 59 | * data_len 包长度-2 bit7-8 60 | * data_code 包内容 bit9-...(共data_len-2个) 61 | ************************************************************/ 62 | void fig_r301t_send_cmd(uint8_t data_id, uint16_t data_len, uint8_t *data_code) { 63 | uint8_t send_data[UART_TX_BUF_SIZE]; 64 | uint16_t sum = 0; 65 | //包头 66 | send_data[0] = 0xEF; 67 | send_data[1] = 0x01; 68 | //模块地址 69 | for(int i=GR_FIG_ADDR_SITE; i<(GR_FIG_ADDR_SITE+4); i++) { 70 | send_data[i] = (GR_FIG_ADDR>>(8*(i-GR_FIG_ADDR_SITE)) &0xff); 71 | 72 | } 73 | //包标识 74 | send_data[GR_FIG_DATA_ID_SITE] = data_id; 75 | //包长度 76 | send_data[GR_FIG_DATA_LEN_SITE] = ((data_len +2) / 0x100); 77 | send_data[GR_FIG_DATA_LEN_SITE+1] = ((data_len + 2 )&0xFF); 78 | //包内容 79 | if(data_code !=NULL) { 80 | memcpy(&send_data[9], data_code, data_len ); 81 | } 82 | 83 | //校验和,从6位开始计算 84 | for(int j=6; j<(7 +1+ data_len + 2 -1); j++) { 85 | sum = sum+send_data[j]; 86 | } 87 | send_data[GR_FIG_DATA_LEN_SITE +1+data_len + 2 - 1] = (sum/0x100); 88 | send_data[GR_FIG_DATA_LEN_SITE+1+ data_len + 2] = (sum &0xFF); 89 | //将命令通过uart发送给指纹模块 90 | for (uint32_t m = 0; m < (9 + data_len + 2 ); m++) { 91 | while(app_uart_put(send_data[m]) != NRF_SUCCESS); 92 | // printf("%02X ",send_data[m]); 93 | } 94 | 95 | } 96 | /****************************** 97 | *将指纹模块的信息返回给上位机 98 | ******************************/ 99 | static void send_fig_r301t_reply_data(void) { 100 | static uint32_t send_time; 101 | static uint32_t send_left; 102 | //无论如何都会将结果返还给上位机的 103 | //将模块的返回包全部通过蓝牙串口返回给上位机 104 | if(fig_recieve_data_length <=BLE_NUS_MAX_DATA_LEN) { 105 | //数据长度小于20,一次发完 106 | memcpy(nus_data_send,fig_recieve_data, fig_recieve_data_length); 107 | nus_data_send_length = fig_recieve_data_length; 108 | ble_nus_string_send(&m_nus,nus_data_send, nus_data_send_length); 109 | } else { 110 | //计算一共发送几次整的20字节 111 | send_time = fig_recieve_data_length / BLE_NUS_MAX_DATA_LEN; 112 | send_left = fig_recieve_data_length % BLE_NUS_MAX_DATA_LEN; 113 | 114 | //发送整20字节的 115 | for(int i=0; i0) { 122 | memcpy(nus_data_send,&fig_recieve_data[send_time * BLE_NUS_MAX_DATA_LEN], send_left); 123 | nus_data_send_length = send_left; 124 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 125 | } 126 | } 127 | 128 | } 129 | 130 | /*************************************** 131 | *获取指纹模块索引列表的返回包 132 | ***************************************/ 133 | static void send_get_r301t_indextable_reply_data(void) { 134 | static uint32_t send_time; 135 | static uint32_t send_left; 136 | //判断返回索引表的字节数(不带校验和) 137 | if((fig_recieve_data_length - 12)<=(BLE_NUS_MAX_DATA_LEN - 1)) { 138 | //数据长度小于20,一次发完 139 | //命令码+0x40 140 | nus_data_send[0] = ble_operate_code + 0x40; 141 | memcpy(&nus_data_send[1],&fig_recieve_data[10], (fig_recieve_data_length -12)); 142 | nus_data_send_length = (fig_recieve_data_length - 12); 143 | ble_nus_string_send(&m_nus,nus_data_send, (nus_data_send_length -12)); 144 | } else { 145 | //计算一共发送几次整的20字节 146 | send_time = (fig_recieve_data_length - 12)/ (BLE_NUS_MAX_DATA_LEN - 1); 147 | send_left = (fig_recieve_data_length - 12) % (BLE_NUS_MAX_DATA_LEN - 1); 148 | 149 | //发送整20字节的 150 | for(int i=0; i0) { 159 | //命令码+0x40 160 | nus_data_send[0] = ble_operate_code + 0x40; 161 | memcpy(&nus_data_send[1],&fig_recieve_data[10 + send_time * (BLE_NUS_MAX_DATA_LEN - 1)], send_left); 162 | nus_data_send_length = send_left + 1; 163 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 164 | } 165 | } 166 | 167 | } 168 | 169 | /*********************************************** 170 | *获取指纹信息索引列表 171 | ***********************************************/ 172 | static void get_r301t_indextable_data(void) { 173 | //1获取指纹模块返回信息 174 | memset(r301t_indextable_data, 0, sizeof(r301t_indextable_data)); 175 | memcpy(r301t_indextable_data, &fig_recieve_data[10],sizeof(r301t_indextable_data)); 176 | //2设置标志量 177 | is_get_r301t_indextable = true; 178 | 179 | } 180 | 181 | /******************************************* 182 | *同步指纹模块 183 | ********************************************/ 184 | static void updata_fig_info(void) { 185 | for(int i=0; i < (FIG_INFO_NUMBER/8); i++) { 186 | for(int j=0; j < 8; j++) { 187 | //1、如果指纹ID号有指纹则写信息 188 | if( ((r301t_indextable_data[i] &(uint8_t)(0x01 <> j) == 1) { 189 | //1.1、获取查询的ID号 190 | fig_info_get_site = i*8 + j; 191 | 192 | //1.2、获取内部flash存储区的信息 193 | pstorage_block_identifier_get(&block_id_flash_store, \ 194 | (pstorage_size_t)(FIG_INFO_OFFSET + fig_info_get_site), &block_id_fig_info); 195 | pstorage_load(interflash_read_data, &block_id_fig_info, BLOCK_STORE_SIZE, 0); 196 | memset(&fig_info_get, 0, sizeof(struct fig_info)); 197 | memcpy(&fig_info_get, interflash_read_data, sizeof(struct fig_info)); 198 | 199 | if(fig_info_get.is_store != 'w') { 200 | //1.3、如果没有记录,则写入记录信息 201 | //1.3.1、设置信息 202 | memset(&fig_info_set, 0, sizeof(struct fig_info)); 203 | fig_info_set.is_store = 'w'; 204 | fig_info_set.fig_info_id = fig_info_get_site; 205 | //1.3.2、清除区域 206 | pstorage_clear(&block_id_fig_info, BLOCK_STORE_SIZE); 207 | //1.3.3、存储信息 208 | memset(interflash_write_data, 0, BLOCK_STORE_SIZE); 209 | memcpy(interflash_write_data, &fig_info_set, sizeof(struct fig_info)); 210 | pstorage_store(&block_id_fig_info, interflash_write_data, BLOCK_STORE_SIZE, 0); 211 | //拷贝设置的信息 212 | memcpy(&fig_info_get, &fig_info_set, sizeof(struct fig_info)); 213 | } 214 | //写了指纹信息,将指令码+40,再把指纹信息返回给上位机 215 | nus_data_send[0] = ble_operate_code + 0x40; 216 | nus_data_send[1] = fig_info_get.fig_info_id / 0x100; 217 | nus_data_send[2] = fig_info_get.fig_info_id &0xff; 218 | memcpy(&nus_data_send[3], fig_info_get.fig_info_data, sizeof(fig_info_get.fig_info_data)); 219 | nus_data_send_length = 3+sizeof(fig_info_get.fig_info_data); 220 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 221 | } 222 | } 223 | } 224 | fig_info_get_site = 0; 225 | } 226 | 227 | /********************************************* 228 | *指纹模块的应答处理 229 | *********************************************/ 230 | int fig_r301t_reply_check(void) { 231 | int err_code; 232 | uint8_t fig_input[6]; 233 | 234 | uint8_t end_reply[4] = {0, 0, 0, 0}; 235 | 236 | //send_fig_r301t_reply_data(); 237 | //判断发送包的指令码 238 | switch(fig_cmd_code) { 239 | case GR_FIG_CMD_DELCHAR: 240 | //关闭指纹芯片 241 | close_fig(); 242 | 243 | //将命令加上0x40,返回给app 244 | nus_data_send[0] = ble_operate_code + 0x40; 245 | //判断结果码 246 | if(fig_recieve_data[9] ==0x00) { 247 | nus_data_send[1] = 0x00; 248 | nus_data_send_length = 2; 249 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 250 | //删除记录的指纹信息 251 | //1.1、获取内部flash存储区的信息 252 | redelete_fig_info: 253 | pstorage_block_identifier_get(&block_id_flash_store, \ 254 | (pstorage_size_t)(FIG_INFO_OFFSET+(delete_fig_id[0]*0x100 + delete_fig_id[1])), &block_id_fig_info); 255 | err_code = pstorage_clear(&block_id_fig_info, BLOCK_STORE_SIZE); 256 | if(err_code !=0) { 257 | goto redelete_fig_info; 258 | } 259 | } else { 260 | nus_data_send[1] = 0x01; 261 | nus_data_send_length = 2; 262 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 263 | } 264 | 265 | break; 266 | 267 | case GR_FIG_CMD_EMPTY: 268 | //1、关闭指纹芯片 269 | close_fig(); 270 | 271 | //2、清除所有指纹库信息 272 | for(int i = 0; i 0) { 340 | //手指按下设置的自动搜索模式, 341 | //应答包失败 342 | if(fig_recieve_data[9] !=0x00) {//失败的话,关闭电源模块,将步骤和错误码发送给上位机 343 | //失败情况,如果是第一步则重复发GR_GetImage 344 | /* if(r301t_autosearch_step == 1) { 345 | //第一步执行失败,继续发送getimage命令 346 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_getimg_cmd), \ 347 | r301t_send_getimg_cmd); 348 | fig_recieve_data_length =0; 349 | } else {*/ 350 | //关闭指纹模块 351 | close_fig(); 352 | 353 | //返回第几步 354 | //将命令加上0x40,返回给app 355 | nus_data_send[0] = ble_operate_code; 356 | //第几步 357 | nus_data_send[1] = r301t_autosearch_step; 358 | nus_data_send[2] = fig_recieve_data[9]; 359 | nus_data_send_length = 3; 360 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 361 | //应答失败,鸣笛4次 362 | beep_didi(4); 363 | //如果不是第一步,则直接退出 364 | r301t_autosearch_step = 0; 365 | // } 366 | fig_recieve_data_length =0; 367 | } else { 368 | //判断自动搜索的步骤 369 | switch(r301t_autosearch_step) { 370 | case 1://第一步的应答包的话,发送第2个指令,设置步骤为2,发送genchar生成特征值命令 371 | r301t_autosearch_step =2; 372 | fig_recieve_data_length = 0; 373 | fig_cmd_code = GR_FIG_CMD_GENCHAR; 374 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_genchar1_cmd), \ 375 | r301t_send_genchar1_cmd); 376 | break; 377 | 378 | case 2://第二步的应答包的话,发送第3个指令,设置步骤为3,发送搜索指纹命令 379 | r301t_autosearch_step =3; 380 | fig_recieve_data_length = 0; 381 | fig_cmd_code = GR_FIG_CMD_SEARCH; 382 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_search_cmd), \ 383 | r301t_send_search_cmd); 384 | break; 385 | 386 | case 3://第三步,判断结果码 387 | //最后一步,判断结果 388 | if(fig_recieve_data[9] == 0) { 389 | //返回搜索到了指纹 390 | //向上位机发送匹配的ID号和匹配得分 391 | nus_data_send[0] = SEARCH_FIG + 0x40; 392 | nus_data_send[1] = fig_recieve_data[10]; 393 | nus_data_send[2] = fig_recieve_data[11]; 394 | nus_data_send[3] = fig_recieve_data[12]; 395 | nus_data_send[4] = fig_recieve_data[13]; 396 | nus_data_send_length = 5; 397 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 398 | //打开门 399 | ble_door_open(); 400 | //TODO记录指纹开锁 401 | //获取按下开锁键的时间 402 | rtc_time_read(&key_input_time_tm); 403 | key_input_time_t = my_mktime(&key_input_time_tm); 404 | memset(fig_input, 0, sizeof(fig_input)); 405 | fig_input[0] = 'f'; 406 | fig_input[1] = 'g'; 407 | memcpy(&fig_input[2], &fig_recieve_data[10], 4); 408 | door_open_record_flash((char *)fig_input,6, key_input_time_t); 409 | } 410 | //设置步骤为0,状态为false 411 | r301t_autosearch_step = 0; 412 | fig_recieve_data_length = 0; 413 | //关闭指纹芯片 414 | close_fig(); 415 | break; 416 | 417 | default: 418 | 419 | break; 420 | } 421 | } 422 | } else { //自动注册模式 423 | if(r301t_autoenroll_step > 0) { 424 | //上位机设置自动注册模式 425 | if(fig_recieve_data[9] != 0x00) { 426 | if(r301t_autoenroll_step == 1) { 427 | //第二步继续发送getimg 428 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_getimg_cmd), \ 429 | r301t_send_getimg_cmd); 430 | } else { 431 | //注册失败,将命令加上0x40,+01,返回给app 432 | nus_data_send[0] = ble_operate_code + 0x40; 433 | //第几步 434 | nus_data_send[1] = 0x01; 435 | nus_data_send_length = 2; 436 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 437 | 438 | //应答包,失败 439 | //设置步骤为0,接收数据长度清零 440 | r301t_autoenroll_step = 0x00; 441 | fig_recieve_data_length = 0; 442 | is_r301t_autoenroll = false; 443 | //关闭指纹模块 444 | close_fig(); 445 | return 0; 446 | } 447 | } else { 448 | switch(r301t_autoenroll_step) { 449 | case 1://第1步,发送Genchar1命令,设置步骤为2 450 | r301t_autoenroll_step = 2; 451 | fig_recieve_data_length = 0; 452 | fig_cmd_code = GR_FIG_CMD_GENCHAR; 453 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_genchar1_cmd), \ 454 | r301t_send_genchar1_cmd); 455 | break; 456 | 457 | case 2://第2步,发送getimg命令,设置步骤为3 458 | r301t_autoenroll_step = 3; 459 | fig_recieve_data_length = 0; 460 | fig_cmd_code = GR_FIG_CMD_GETIMG; 461 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_getimg_cmd), \ 462 | r301t_send_getimg_cmd); 463 | break; 464 | 465 | case 3://第3步,发送genchar2命令,设置步骤为4 466 | r301t_autoenroll_step = 4; 467 | fig_recieve_data_length = 0; 468 | fig_cmd_code = GR_FIG_CMD_GENCHAR; 469 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_genchar2_cmd), \ 470 | r301t_send_genchar2_cmd); 471 | break; 472 | 473 | case 4://第4步,发送regmodel命令,设置步骤为5 474 | r301t_autoenroll_step = 5; 475 | fig_recieve_data_length = 0; 476 | fig_cmd_code = GR_FIG_CMD_REGMODEL; 477 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_regmodel_cmd), \ 478 | r301t_send_regmodel_cmd); 479 | break; 480 | 481 | case 5://第5步,发送储storechar命令,完成,设置步骤为0,设置标志位为false 482 | r301t_autoenroll_step = 6; 483 | fig_recieve_data_length = 0; 484 | //设置命令码为storechar 485 | fig_cmd_code = GR_FIG_CMD_STORECHAR; 486 | //组织发送存储命令 487 | memset(r301t_send_storechar_idx_cmd, 0, 4); 488 | memcpy(r301t_send_storechar_idx_cmd, \ 489 | r301t_send_storechar_id0_cmd, 4); 490 | //设置ID号 491 | r301t_send_storechar_idx_cmd[2] = enroll_fig_id[0]; 492 | r301t_send_storechar_idx_cmd[3] = enroll_fig_id[1]; 493 | 494 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_storechar_idx_cmd), \ 495 | r301t_send_storechar_idx_cmd); 496 | break; 497 | case 6://第6步,判断结果 498 | //关闭指纹芯片 499 | close_fig(); 500 | r301t_autoenroll_step = 0; 501 | fig_recieve_data_length = 0; 502 | //将命令加上0x40,返回给app 503 | nus_data_send[0] = ble_operate_code + 0x40; 504 | //判断结果码 505 | if(fig_recieve_data[9] ==0x00) { 506 | nus_data_send[1] = 0x00; 507 | nus_data_send[2] = enroll_fig_id[0]; 508 | nus_data_send[3] = enroll_fig_id[1]; 509 | nus_data_send_length = 4; 510 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 511 | //成功将设置指纹信息函数存储在内部flash 512 | restore_fig_info: 513 | err_code = fig_info_write(&fig_info_set); 514 | if(err_code != 0) { 515 | goto restore_fig_info; 516 | } 517 | // nrf_delay_ms(2000); 518 | } else { 519 | nus_data_send[1] = 0x01; 520 | nus_data_send_length = 2; 521 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 522 | } 523 | is_r301t_autoenroll = false; 524 | break; 525 | default: 526 | 527 | break; 528 | } 529 | } 530 | } 531 | } 532 | 533 | //收到数据长度清零 534 | fig_recieve_data_length = 0; 535 | return 0; 536 | } 537 | -------------------------------------------------------------------------------- /Application/ble_init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "nordic_common.h" 7 | #include "bsp.h" 8 | #include "nrf.h" 9 | #include "nrf_delay.h" 10 | #include "nrf_gpio.h" 11 | #include "nrf_drv_config.h" 12 | #include "nrf_drv_timer.h" 13 | 14 | #include "ble_hci.h" 15 | #include "ble_dis.h" 16 | #include "ble_advdata.h" 17 | #include "ble_advertising.h" 18 | #include "ble_conn_params.h" 19 | #include "softdevice_handler.h" 20 | #include "app_timer.h" 21 | #include "ble_nus.h" 22 | #include "app_uart.h" 23 | #include "pstorage.h" 24 | #include "device_manager.h" 25 | #include "app_trace.h" 26 | #include "app_util_platform.h" 27 | #include "bsp_btn_ble.h" 28 | 29 | #include "ble_init.h" 30 | #include "inter_flash.h" 31 | //#include "fm260b.h" 32 | #include "r301t.h" 33 | #include "beep.h" 34 | #include "led_button.h" 35 | #include "operate_code.h" 36 | 37 | dm_application_instance_t m_app_handle; 38 | dm_handle_t m_dm_handle; 39 | //app_timer_id_t m_backlit_timer_id; 40 | 41 | ble_uuid_t m_adv_uuids[] = {{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}}; 42 | 43 | ble_nus_t m_nus;//ble 服务注册的nus服务 44 | uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; 45 | 46 | uint8_t mac[8];//第一位:标志位,第二位:长度 47 | 48 | //自定义的nus服务中data_handle函数中暂存的数据,需要交给check命令 49 | bool operate_code_setted = false; 50 | uint8_t nus_data_recieve[BLE_NUS_MAX_DATA_LEN]; 51 | uint16_t nus_data_recieve_length; 52 | 53 | uint8_t nus_data_send[BLE_NUS_MAX_DATA_LEN];//20位,发送给上位机的 54 | uint32_t nus_data_send_length = 0; 55 | 56 | //指纹模块发送给蓝牙芯片的数据 57 | uint8_t fig_recieve_data[UART_RX_BUF_SIZE]; 58 | uint16_t fig_recieve_data_length = 0; 59 | 60 | /******************** 61 | *回调函数 62 | *******************/ 63 | void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name) { 64 | app_error_handler(DEAD_BEEF, line_num, p_file_name); 65 | } 66 | 67 | /************************************************** 68 | *配对超时处理函数 69 | *in: p_context 超时描述 70 | **************************************************/ 71 | static void sec_req_timeout_handler(void * p_context) { 72 | uint32_t err_code; 73 | dm_security_status_t status; 74 | 75 | if (m_conn_handle != BLE_CONN_HANDLE_INVALID) { 76 | err_code = dm_security_status_req(&m_dm_handle, &status); 77 | APP_ERROR_CHECK(err_code); 78 | 79 | // In case the link is secured by the peer during timeout, the request is not sent. 80 | if (status == NOT_ENCRYPTED) { 81 | err_code = dm_security_setup_req(&m_dm_handle); 82 | APP_ERROR_CHECK(err_code); 83 | } 84 | } 85 | 86 | } 87 | 88 | /*************************************** 89 | *背景灯定时器任务处理函数 90 | ****************************************/ 91 | static void backlit_timeout_handler(void * p_context) { 92 | //UNUSED_PARAMETER(p_context); 93 | if(is_background_lit == true) { 94 | //关闭背景灯 95 | nrf_gpio_pin_clear( BATTERY_LEVEL_EN ); 96 | //设置标识位 97 | is_background_lit = false; 98 | } 99 | 100 | } 101 | 102 | /********************************* 103 | *初始化timers 104 | *********************************/ 105 | void timers_init(void) { 106 | uint32_t err_code; 107 | 108 | // Initialize timer module. 109 | APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false); 110 | 111 | // Create timers. 112 | // Create Security Request timer. 113 | /* err_code = app_timer_create(&m_sec_req_timer_id, 114 | APP_TIMER_MODE_SINGLE_SHOT, 115 | sec_req_timeout_handler); 116 | APP_ERROR_CHECK(err_code); 117 | */ 118 | //初始化背景灯定时器 119 | err_code = app_timer_create(&m_backlit_timer_id, 120 | APP_TIMER_MODE_SINGLE_SHOT, 121 | backlit_timeout_handler); 122 | APP_ERROR_CHECK(err_code); 123 | 124 | } 125 | 126 | void application_timers_start(void) { 127 | /* YOUR_JOB: Start your timers. below is an example of how to start a timer. 128 | uint32_t err_code; 129 | err_code = app_timer_start(m_app_timer_id, TIMER_INTERVAL, NULL); 130 | APP_ERROR_CHECK(err_code); 131 | uint32_t err_code; 132 | err_code = app_timer_start(m_ad_repeat_timer_id, AD_REPEAT_DELAY, NULL); 133 | APP_ERROR_CHECK(err_code);*/ 134 | 135 | } 136 | 137 | void gap_params_init(void) { 138 | uint32_t err_code; 139 | ble_gap_conn_params_t gap_conn_params; 140 | ble_gap_conn_sec_mode_t sec_mode; 141 | 142 | BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); 143 | 144 | err_code = sd_ble_gap_device_name_set(&sec_mode, 145 | (const uint8_t *) DEVICE_NAME, 146 | strlen(DEVICE_NAME)); 147 | 148 | APP_ERROR_CHECK(err_code); 149 | 150 | memset(&gap_conn_params, 0, sizeof(gap_conn_params)); 151 | 152 | gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; 153 | gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; 154 | gap_conn_params.slave_latency = SLAVE_LATENCY; 155 | gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; 156 | 157 | err_code = sd_ble_gap_ppcp_set(&gap_conn_params); 158 | APP_ERROR_CHECK(err_code); 159 | 160 | } 161 | 162 | /************************************************* 163 | *蓝牙串口服务的处理函数 164 | *************************************************/ 165 | static void nus_data_handler(ble_nus_t * p_nus, uint8_t * p_data, uint16_t length) { 166 | /* 167 | for (uint32_t i = 0; i < length; i++) 168 | { 169 | while(app_uart_put(p_data[i]) != NRF_SUCCESS); 170 | } 171 | while(app_uart_put('\n') != NRF_SUCCESS); 172 | */ 173 | //将获取的数据存到全局变量,供operate_code_check函数用 174 | if(operate_code_setted == false && is_ble_cmd_exe == false) { 175 | //不在执行上位机发送的命令 176 | for(int i = 0; i evt_type == BLE_CONN_PARAMS_EVT_FAILED) { 209 | err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); 210 | APP_ERROR_CHECK(err_code); 211 | } 212 | 213 | } 214 | 215 | static void conn_params_error_handler(uint32_t nrf_error) { 216 | APP_ERROR_HANDLER(nrf_error); 217 | } 218 | 219 | 220 | /********************************* 221 | *连接参数初始化 222 | *********************************/ 223 | void conn_params_init(void) { 224 | uint32_t err_code; 225 | ble_conn_params_init_t cp_init; 226 | 227 | memset(&cp_init, 0, sizeof(cp_init)); 228 | 229 | cp_init.p_conn_params = NULL; 230 | cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; 231 | cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; 232 | cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; 233 | cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; 234 | cp_init.disconnect_on_fail = false; 235 | cp_init.evt_handler = on_conn_params_evt; 236 | cp_init.error_handler = conn_params_error_handler; 237 | 238 | err_code = ble_conn_params_init(&cp_init); 239 | APP_ERROR_CHECK(err_code); 240 | 241 | } 242 | 243 | /*********************************** 244 | *进入低功耗 245 | ***********************************/ 246 | static void sleep_mode_enter(void) { 247 | uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE); 248 | APP_ERROR_CHECK(err_code); 249 | 250 | // Prepare wakeup buttons. 251 | /* err_code = bsp_btn_ble_sleep_mode_prepare(); 252 | APP_ERROR_CHECK(err_code); 253 | */ 254 | // Go to system-off mode (this function will not return; wakeup will cause a reset). 255 | err_code = sd_power_system_off(); 256 | APP_ERROR_CHECK(err_code); 257 | 258 | } 259 | 260 | /************************************************ 261 | *广播事件处理函数 262 | *************************************************/ 263 | static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { 264 | switch (ble_adv_evt) { 265 | case BLE_ADV_EVT_FAST: 266 | // err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); 267 | // APP_ERROR_CHECK(err_code); 268 | break; 269 | case BLE_ADV_EVT_IDLE: 270 | sleep_mode_enter(); 271 | break; 272 | default: 273 | break; 274 | } 275 | 276 | } 277 | 278 | 279 | /****************************** 280 | *BLE事件处理函数 281 | ******************************/ 282 | static void on_ble_evt(ble_evt_t * p_ble_evt) { 283 | uint32_t err_code; 284 | 285 | switch (p_ble_evt->header.evt_id) { 286 | case BLE_GAP_EVT_CONNECTED: 287 | // err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); 288 | // APP_ERROR_CHECK(err_code); 289 | m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; 290 | break; 291 | 292 | case BLE_GAP_EVT_DISCONNECTED: 293 | // err_code = bsp_indication_set(BSP_INDICATE_IDLE); 294 | // APP_ERROR_CHECK(err_code); 295 | m_conn_handle = BLE_CONN_HANDLE_INVALID; 296 | //增加处理 297 | dm_device_delete_all(&m_app_handle); 298 | //断开时,设置超级密码验证状态为失败 299 | is_superkey_checked = false; 300 | //继续广播 301 | ble_advertising_start(BLE_ADV_MODE_FAST); 302 | break; 303 | 304 | case BLE_GAP_EVT_AUTH_STATUS: 305 | //判断配对是否成功,如果不成功断开连接,从而阻止其他人任意连接 306 | /* if(p_ble_evt->evt.gap_evt.params.auth_status.auth_status != BLE_GAP_SEC_STATUS_SUCCESS) { 307 | sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); 308 | } else { 309 | #if defined(BLE_DOOR_DEBUG) 310 | printf("pair success\r\n"); 311 | #endif 312 | }*/ 313 | break; 314 | 315 | /* 316 | case BLE_GAP_EVT_SEC_PARAMS_REQUEST: 317 | // Pairing not supported 318 | err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); 319 | APP_ERROR_CHECK(err_code); 320 | break; 321 | */ 322 | case BLE_GATTS_EVT_SYS_ATTR_MISSING: 323 | // No system attributes have been stored. 324 | err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); 325 | APP_ERROR_CHECK(err_code); 326 | break; 327 | 328 | default: 329 | // No implementation needed. 330 | break; 331 | } 332 | 333 | } 334 | 335 | /************************ 336 | *BLE事件分发 337 | ************************/ 338 | //因为广播函数是在后面定义的,使用的话,先定义 339 | void advertising_init(void); 340 | 341 | static void ble_evt_dispatch(ble_evt_t * p_ble_evt) { 342 | 343 | //在断开连接事件后,初始化广播数据 344 | if(p_ble_evt->header.evt_id == BLE_GAP_EVT_DISCONNECTED) { 345 | advertising_init(); 346 | } 347 | 348 | ble_conn_params_on_ble_evt(p_ble_evt); 349 | ble_nus_on_ble_evt(&m_nus, p_ble_evt); 350 | 351 | dm_ble_evt_handler(p_ble_evt); 352 | 353 | on_ble_evt(p_ble_evt); 354 | ble_advertising_on_ble_evt(p_ble_evt); 355 | bsp_btn_ble_on_ble_evt(p_ble_evt); 356 | 357 | } 358 | 359 | /********************************* 360 | *系统事件分发 361 | ********************************/ 362 | static void sys_evt_dispatch(uint32_t sys_evt) { 363 | pstorage_sys_event_handler(sys_evt); 364 | ble_advertising_on_sys_evt(sys_evt); 365 | } 366 | 367 | /************************************ 368 | *BLE协议栈初始化 369 | ***********************************/ 370 | void ble_stack_init(void) { 371 | uint32_t err_code; 372 | 373 | // Initialize SoftDevice. 374 | SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, NULL); 375 | 376 | ble_enable_params_t ble_enable_params; 377 | err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT, 378 | PERIPHERAL_LINK_COUNT, 379 | &ble_enable_params); 380 | APP_ERROR_CHECK(err_code); 381 | 382 | //Check the ram settings against the used number of links 383 | CHECK_RAM_START_ADDR(CENTRAL_LINK_COUNT,PERIPHERAL_LINK_COUNT); 384 | // Enable BLE stack. 385 | err_code = softdevice_enable(&ble_enable_params); 386 | APP_ERROR_CHECK(err_code); 387 | 388 | // Register with the SoftDevice handler module for BLE events. 389 | err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch); 390 | APP_ERROR_CHECK(err_code); 391 | 392 | // Register with the SoftDevice handler module for BLE events. 393 | err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch); 394 | APP_ERROR_CHECK(err_code); 395 | 396 | } 397 | 398 | /*********************************************************** 399 | *芯片uart接收处理函数 400 | *最长数据为20,将指纹模块返回的数据进行处理 401 | ***********************************************************/ 402 | static void uart_event_handle(app_uart_evt_t * p_event) { 403 | //由于指纹模块是一个自动化的模块,只需将返回结果直接通过蓝牙串口返还给上位机即可 404 | 405 | switch (p_event->evt_type) { 406 | case APP_UART_DATA_READY: 407 | UNUSED_VARIABLE(app_uart_get(&fig_recieve_data[fig_recieve_data_length])); 408 | fig_recieve_data_length++; 409 | //指纹模板的应答包分析 410 | // fig_fm260b_reply_check(); //指纹模块fm260b 411 | 412 | //收到的数据包长度至少12位 413 | if(fig_recieve_data_length >11) { 414 | //接收长度完毕 415 | if(fig_recieve_data_length == \ 416 | (9 + (fig_recieve_data[GR_FIG_DATA_LEN_SITE]*0x100) + fig_recieve_data[GR_FIG_DATA_LEN_SITE + 1])) { 417 | //指纹模块r301t 418 | fig_r301t_reply_check(); 419 | } 420 | } 421 | break; 422 | 423 | case APP_UART_COMMUNICATION_ERROR: 424 | APP_ERROR_HANDLER(p_event->data.error_communication); 425 | break; 426 | 427 | case APP_UART_FIFO_ERROR: 428 | APP_ERROR_HANDLER(p_event->data.error_code); 429 | break; 430 | 431 | default: 432 | break; 433 | } 434 | 435 | } 436 | 437 | /***************************** 438 | * UART INIT 439 | ******************************/ 440 | void uart_init(void) { 441 | uint32_t err_code; 442 | const app_uart_comm_params_t comm_params = { 443 | RX_PIN_NUMBER, 444 | TX_PIN_NUMBER, 445 | RTS_PIN_NUMBER, 446 | CTS_PIN_NUMBER, 447 | APP_UART_FLOW_CONTROL_DISABLED, 448 | false, 449 | UART_BAUDRATE_BAUDRATE_Baud57600 450 | }; 451 | 452 | APP_UART_FIFO_INIT( &comm_params, 453 | UART_RX_BUF_SIZE, 454 | UART_TX_BUF_SIZE, 455 | uart_event_handle, 456 | APP_IRQ_PRIORITY_LOW, 457 | err_code); 458 | APP_ERROR_CHECK(err_code); 459 | 460 | } 461 | 462 | void advertising_init(void) { 463 | uint32_t err_code; 464 | ble_advdata_t advdata; 465 | ble_advdata_manuf_data_t manuf_data; //自定义厂商数据,这里为mac 466 | 467 | uint8_t device_hard_info = BIT_TOUCH | BIT_FIG; 468 | uint8_t device_info[BLE_GAP_ADDR_LEN + 1];//设备信息6位mac地址+硬件版本号 469 | 470 | memset(&advdata, 0, sizeof(advdata)); 471 | 472 | //广播数据内厂商ID 473 | manuf_data.company_identifier = APP_COMPANY_ID; 474 | //添加厂商自定义数据(其实就时mac地址) 475 | ble_gap_addr_t device_addr; 476 | sd_ble_gap_address_get(&device_addr); 477 | //添加mac 478 | memcpy(device_info, device_addr.addr, 6); 479 | //添加硬件版本号 480 | memcpy(&device_info[6], &device_hard_info, 1); 481 | manuf_data.data.p_data = device_info; 482 | manuf_data.data.size = 7; 483 | 484 | // Build advertising data struct to pass into @ref ble_advertising_init. 485 | advdata.name_type = BLE_ADVDATA_FULL_NAME; 486 | advdata.include_appearance = false; 487 | // advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; 488 | advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; 489 | // advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); 490 | // advdata.uuids_complete.p_uuids = m_adv_uuids; 491 | advdata.p_manuf_specific_data = &manuf_data; 492 | 493 | ble_adv_modes_config_t options = 494 | { 495 | BLE_ADV_WHITELIST_DISABLED, 496 | BLE_ADV_DIRECTED_DISABLED, 497 | BLE_ADV_DIRECTED_SLOW_DISABLED, 0,0, 498 | BLE_ADV_FAST_ENABLED, APP_ADV_FAST_INTERVAL, APP_ADV_FAST_TIMEOUT_IN_SECONDS, 499 | BLE_ADV_SLOW_ENABLED, APP_ADV_SLOW_INTERVAL, APP_ADV_SLOW_TIMEOUT_IN_SECONDS 500 | }; 501 | 502 | 503 | 504 | err_code = ble_advertising_init(&advdata, NULL, &options, on_adv_evt, NULL); 505 | APP_ERROR_CHECK(err_code); 506 | // err_code = ble_advdata_set(&advdata,NULL); 507 | // APP_ERROR_CHECK(err_code); 508 | 509 | 510 | } 511 | 512 | // start advertising 513 | void adverts_start(void) { 514 | uint32_t err_code; 515 | ble_gap_adv_params_t adv_params; 516 | memset(&adv_params, 0, sizeof(adv_params)); 517 | 518 | //设置广播信道是否开启 519 | adv_params.channel_mask.ch_37_off = 0; 520 | adv_params.channel_mask.ch_38_off = 0; 521 | adv_params.channel_mask.ch_39_off = 0; 522 | 523 | adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND; 524 | adv_params.p_peer_addr = NULL; 525 | adv_params.fp = BLE_GAP_ADV_FP_ANY; 526 | adv_params.interval = APP_ADV_FAST_INTERVAL; 527 | adv_params.timeout = APP_ADV_FAST_TIMEOUT_IN_SECONDS; 528 | adv_params.p_whitelist = NULL; 529 | 530 | err_code = sd_ble_gap_adv_start(&adv_params); 531 | APP_ERROR_CHECK(err_code); 532 | } 533 | 534 | static void bsp_event_handler(bsp_event_t event) { 535 | uint32_t err_code; 536 | switch (event) { 537 | case BSP_EVENT_SLEEP: 538 | sleep_mode_enter(); 539 | break; 540 | 541 | case BSP_EVENT_DISCONNECT: 542 | err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); 543 | if (err_code != NRF_ERROR_INVALID_STATE) { 544 | APP_ERROR_CHECK(err_code); 545 | } 546 | break; 547 | 548 | case BSP_EVENT_WHITELIST_OFF: 549 | err_code = ble_advertising_restart_without_whitelist(); 550 | if (err_code != NRF_ERROR_INVALID_STATE) { 551 | APP_ERROR_CHECK(err_code); 552 | } 553 | break; 554 | 555 | default: 556 | break; 557 | } 558 | 559 | } 560 | 561 | void buttons_leds_init(bool * p_erase_bonds) { 562 | bsp_event_t startup_event; 563 | 564 | uint32_t err_code = bsp_init(BSP_INIT_LED | BSP_INIT_BUTTONS, 565 | APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), 566 | bsp_event_handler); 567 | APP_ERROR_CHECK(err_code); 568 | 569 | err_code = bsp_btn_ble_init(NULL, &startup_event); 570 | APP_ERROR_CHECK(err_code); 571 | 572 | *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA); 573 | 574 | } 575 | 576 | 577 | /**@brief Function for placing the application in low power state while waiting for events. 578 | */ 579 | void power_manage(void) { 580 | uint32_t err_code = sd_app_evt_wait(); 581 | APP_ERROR_CHECK(err_code); 582 | } 583 | 584 | /***************************************************** 585 | *DM处理函数 586 | ******************************************************/ 587 | static uint32_t device_manager_evt_handler(dm_handle_t const * p_handle, 588 | dm_event_t const * p_event, 589 | ret_code_t event_result) { 590 | uint32_t err_code; 591 | 592 | APP_ERROR_CHECK(event_result); 593 | 594 | switch (p_event->event_id) { 595 | case DM_EVT_CONNECTION: 596 | m_dm_handle = (*p_handle); 597 | // Start Security Request timer. 598 | // if (m_dm_handle.device_id != DM_INVALID_ID) 599 | { 600 | //在有蓝牙设备请求连接的时候,开启安全请求的timer 601 | // err_code = app_timer_start(m_sec_req_timer_id, SECURITY_REQUEST_DELAY, NULL); 602 | // APP_ERROR_CHECK(err_code); 603 | } 604 | break; 605 | case DM_EVT_DISCONNECTION: 606 | // dm_device_delete_all(&m_app_handle); 607 | break; 608 | case DM_EVT_SECURITY_SETUP: 609 | 610 | break; 611 | case DM_EVT_SECURITY_SETUP_COMPLETE: 612 | 613 | break; 614 | case DM_EVT_SERVICE_CONTEXT_DELETED: 615 | // if(m_conn_handle != BLE_CONN_HANDLE_INVALID) 616 | // { 617 | // sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); 618 | // } 619 | break; 620 | case DM_EVT_LINK_SECURED: 621 | 622 | break; 623 | default: 624 | break; 625 | } 626 | 627 | #ifdef BLE_DFU_APP_SUPPORT 628 | if(p_event->event_id == DM_EVT_LINK_SECURED) { 629 | app_context_load(p_handle); 630 | } 631 | #endif //BLE_DFU_APP_SUPPORT 632 | return NRF_SUCCESS; 633 | 634 | } 635 | 636 | 637 | void device_manager_init(bool erase_bonds) { 638 | uint32_t err_code; 639 | dm_init_param_t init_param = {.clear_persistent_data = erase_bonds}; 640 | dm_application_param_t register_param; 641 | 642 | // Initialize persistent storage module. 643 | err_code = pstorage_init(); 644 | APP_ERROR_CHECK(err_code); 645 | 646 | err_code = dm_init(&init_param); 647 | APP_ERROR_CHECK(err_code); 648 | 649 | memset(®ister_param.sec_param, 0, sizeof(ble_gap_sec_params_t)); 650 | 651 | register_param.sec_param.bond = SEC_PARAM_BOND; 652 | register_param.sec_param.mitm = SEC_PARAM_MITM; 653 | register_param.sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; 654 | register_param.sec_param.oob = SEC_PARAM_OOB; 655 | register_param.sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; 656 | register_param.sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; 657 | register_param.evt_handler = device_manager_evt_handler; 658 | register_param.service_type = DM_PROTOCOL_CNTXT_GATT_SRVR_ID; 659 | 660 | err_code = dm_register(&m_app_handle, ®ister_param); 661 | APP_ERROR_CHECK(err_code); 662 | 663 | } 664 | -------------------------------------------------------------------------------- /Application/operate_code.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "bsp.h" 7 | #include "ble_nus.h" 8 | #include "ble_gap.h" 9 | #include "pstorage.h" 10 | #include "app_uart.h" 11 | 12 | #include "operate_code.h" 13 | #include "ble_init.h" 14 | #include "rtc_chip.h" 15 | #include "inter_flash.h" 16 | #include "set_params.h" 17 | #include "sm4_dpwd.h" 18 | #include "my_time.h" 19 | #include "led_button.h" 20 | #include "fm260b.h" 21 | #include "r301t.h" 22 | #include "battery.h" 23 | 24 | 25 | bool is_ble_cmd_exe = false;//ble命令是否在执行 26 | 27 | struct tm time_record;//读出记录的时间 28 | time_t time_record_t;//读出的时间的int 29 | struct tm time_record_compare;//要对比的时间 30 | time_t time_record_compare_t;//要对比的时间的int 31 | 32 | 33 | //与获取和设置时间相关的变量 34 | struct tm time_set; 35 | struct tm time_get; 36 | time_t time_get_t; 37 | 38 | uint32_t record_length_get; 39 | 40 | //设置触摸屏密码 41 | struct key_store_struct key_store_set; 42 | struct key_store_struct key_store_get; 43 | 44 | uint8_t ble_operate_code; 45 | 46 | uint8_t fig_cmd_code; 47 | 48 | bool is_superkey_checked = false; 49 | uint8_t r301t_autoenroll_step = 0;//自动注册的步骤 50 | 51 | uint8_t enroll_fig_id[2]; //注册指纹的ID号 52 | uint8_t delete_fig_id[2]; //删除指纹的ID号 53 | 54 | 55 | /*********************************** 56 | *设置开锁密码命令 57 | ************************************/ 58 | static int sm4_key_check_open(uint8_t *p_data, uint16_t length) { 59 | uint32_t err_code; 60 | bool is_keys_checked = false; 61 | 62 | //获取收到的时间 63 | err_code = rtc_time_read(&time_get); 64 | if(err_code == NRF_SUCCESS) { 65 | time_get_t = my_mktime(&time_get); 66 | } 67 | 68 | //1、获取种子,进行动态密码对比,对比SET_KEY_CHECK_NUMBER次 69 | is_keys_checked = keys_input_check_sm4_keys((char *)p_data, 6, time_get_t); 70 | if(is_keys_checked == true) { 71 | //返回ff00 72 | nus_data_send[0] = 0xff; 73 | nus_data_send[1] = 0x00; 74 | nus_data_send_length = 2; 75 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 76 | 77 | //开门 78 | ble_door_open(); 79 | //记录开门 80 | door_open_record_flash((char *)p_data, 6, time_get_t); 81 | return 0; 82 | } 83 | 84 | //失败返回ff01 85 | nus_data_send[0] = 0xff; 86 | nus_data_send[1] = 0x01; 87 | nus_data_send_length = 2; 88 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 89 | return 0; 90 | 91 | } 92 | 93 | /********************************************************************** 94 | *设置管理员密码,如果是第一次设置,直接通过,返回设置成功 95 | *如果不是第一次设置,则需要通过管理员密码的验证,通过的话,返回设置成功 96 | *没有通过验证的话,返回设置失败 97 | ***********************************************************************/ 98 | static int set_super_key(uint8_t *p_data, uint16_t length) { 99 | //1读取超级管理员存储区内容 100 | interflash_read(flash_read_data, BLOCK_STORE_SIZE, SUPER_KEY_OFFSET); 101 | 102 | if( flash_read_data[0] != 'w' ) { 103 | //没有有管理员密码,直接存储 104 | memset(flash_write_data, 0, BLOCK_STORE_SIZE); 105 | flash_write_data[0] = 'w';//'w' 106 | memcpy(&flash_write_data[1],&p_data[1], SUPER_KEY_LENGTH); 107 | //超级密码就12位,取写入数据前面16位(16>(1+12)) 108 | write_super_key(flash_write_data,SUPER_KEY_LENGTH +1); 109 | 110 | //将命令加上0x40,返回给app 111 | nus_data_send[0] = p_data[0] + 0x40; 112 | nus_data_send[1] = 0x00; 113 | nus_data_send_length = 2; 114 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 115 | 116 | } else { 117 | //是不是跟原来密码一致 118 | //取存储的超级管理员密码 119 | memset(super_key, 0, sizeof(super_key)); 120 | memcpy(super_key, &flash_read_data[1],sizeof(super_key)); 121 | //1、对比管理员密码是否相同 122 | if(strncasecmp((char *)&p_data[1],super_key, SUPER_KEY_LENGTH) == 0) { 123 | //将命令加上0x40,返回给app 124 | nus_data_send[0] = p_data[0] + 0x40; 125 | nus_data_send[1] = 0x00; 126 | nus_data_send_length = 2; 127 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 128 | return 0; 129 | } 130 | 131 | if(is_superkey_checked == true) { 132 | //存在管理员密码,但是验证了管理员密码,属于修改密码 133 | memset(flash_write_data, 0, BLOCK_STORE_SIZE); 134 | memcpy(&flash_write_data[1],&p_data[1], SUPER_KEY_LENGTH); 135 | flash_write_data[0] = 'w';//'w' 136 | //超级密码就12位,取写入数据前面16位(16>(1+12)) 137 | write_super_key(flash_write_data,SUPER_KEY_LENGTH + 1); 138 | 139 | //将命令加上0x40,返回给app 140 | nus_data_send[0] = p_data[0] + 0x40; 141 | nus_data_send[1] = 0x00; 142 | nus_data_send_length = 2; 143 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 144 | return 0; 145 | } 146 | 147 | //已经有管理员密码了,且没有验证管理员密码或者与原密码不一致 148 | 149 | //将命令加上0x40,返回给app 150 | nus_data_send[0] = p_data[0] + 0x40; 151 | nus_data_send[1] = 0x01; 152 | nus_data_send_length = 2; 153 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 154 | } 155 | return 0; 156 | } 157 | 158 | /******************************************* 159 | *验证超级管理员密码,验证通过则返回 160 | *(命令码+0x40)+超级管理员密码 161 | *验证失败,返回:没有设置管理员密码 162 | * 或者验证失败 163 | *******************************************/ 164 | static void check_super_key(uint8_t *p_data, uint16_t length) { 165 | //1、从flash中读取超级管理员密码 166 | interflash_read(flash_read_data, 16, SUPER_KEY_OFFSET); 167 | if(flash_read_data[0] == 'w') { 168 | //设置了超级管理员密码 169 | memset(super_key, 0, 12); 170 | memcpy(super_key, &flash_read_data[1],12); 171 | //2、对比管理员密码是否相同 172 | if(strncasecmp((char *)&p_data[1],super_key, SUPER_KEY_LENGTH) == 0) { 173 | #if defined(BLE_DOOR_DEBUG) 174 | printf("spuer key checked\r\n"); 175 | #endif 176 | is_superkey_checked = true; 177 | 178 | //将命令加上0x40,返回给app 179 | nus_data_send[0] = p_data[0] + 0x40; 180 | nus_data_send[1] = 0x00; 181 | nus_data_send_length = 2; 182 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 183 | } else { 184 | 185 | //将命令加上0x40,返回给app 186 | nus_data_send[0] = p_data[0] + 0x40; 187 | nus_data_send[1] = 0x01; 188 | nus_data_send_length = 2; 189 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 190 | } 191 | } else { 192 | //未设置管理员密码 193 | 194 | //将命令加上0x40,返回给app 195 | nus_data_send[0] = p_data[0] + 0x40; 196 | nus_data_send[1] = 0x02; 197 | nus_data_send_length = 2; 198 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 199 | } 200 | 201 | } 202 | 203 | /********************************************** 204 | *同步时间命令,成功返回(命令码+0x40)+设置的时间 205 | ***********************************************/ 206 | static void sync_rtc_time(uint8_t *p_data, uint16_t length) { 207 | uint32_t err_code; 208 | if(is_superkey_checked == true) { //如果验证了超级密码 209 | //是对时命令,[year0][year1][mon][day][hour][min][sec] 210 | time_set.tm_sec = (int)p_data[7]; 211 | time_set.tm_min = (int)p_data[6]; 212 | time_set.tm_hour = (int)p_data[5]; 213 | time_set.tm_mday = (int)p_data[4]; 214 | time_set.tm_mon = (int)p_data[3]; 215 | //年小端 216 | time_set.tm_year = (int)((((int)p_data[2])<<8 | (int)p_data[1]) - 1990); 217 | 218 | //将时间写入RTC 219 | err_code = rtc_time_write(&time_set); 220 | if(err_code ==NRF_SUCCESS) { 221 | //将命令加上0x40,返回给app 222 | nus_data_send[0] = p_data[0] + 0x40; 223 | nus_data_send[1] = 0x00; 224 | nus_data_send_length = 2; 225 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 226 | } else { 227 | //将命令加上0x40,返回给app 228 | nus_data_send[0] = p_data[0] + 0x40; 229 | nus_data_send[1] = 0x01; 230 | nus_data_send_length = 2; 231 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 232 | } 233 | } 234 | 235 | } 236 | 237 | /******************************************** 238 | *获取系统时间,返回(命令码+0x40)+系统时间 239 | ********************************************/ 240 | static void get_rtc_time(uint8_t *p_data, uint16_t length) { 241 | uint32_t err_code; 242 | memset(nus_data_send, 0, BLE_NUS_MAX_DATA_LEN); 243 | err_code = rtc_time_read(&time_get); 244 | if(err_code == NRF_SUCCESS) { 245 | //年是小端 246 | nus_data_send[2] = (uint8_t)((time_get.tm_year + 1990)>>8); 247 | nus_data_send[1] = (uint8_t)(time_get.tm_year + 1990); 248 | nus_data_send[3] = (uint8_t)time_get.tm_mon; 249 | nus_data_send[4] = (uint8_t)time_get.tm_mday; 250 | nus_data_send[5] = (uint8_t)time_get.tm_hour; 251 | nus_data_send[6] = (uint8_t)time_get.tm_min; 252 | nus_data_send[7] = (uint8_t)time_get.tm_sec; 253 | 254 | nus_data_send[0] = p_data[0] + 0x40; 255 | nus_data_send_length = 8; 256 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 257 | } 258 | 259 | } 260 | 261 | /************************************************* 262 | *获取现在的动态密码 263 | *************************************************/ 264 | static void get_key_now(uint8_t *p_data, uint16_t length) { 265 | uint32_t err_code; 266 | char no_seed[8] = "no seed"; 267 | memset(nus_data_send, 0, BLE_NUS_MAX_DATA_LEN); 268 | err_code = rtc_time_read(&time_get); 269 | if(err_code == NRF_SUCCESS) { 270 | //将时间变换为64位 271 | time_get_t = my_mktime(&time_get); 272 | //获取种子 273 | interflash_read(flash_read_data, 32, SEED_OFFSET); 274 | if(flash_read_data[0] == 'w') { 275 | //设置了种子 276 | //获取种子 277 | memset(seed, 0, 16); 278 | memcpy(seed, &flash_read_data[1], 16); 279 | //计算动态密码 280 | SM4_DPasswd(seed, time_get_t, SM4_INTERVAL, SM4_COUNTER, SM4_challenge, key_store_tmp); 281 | //整合返回包 282 | nus_data_send[0] = p_data[0] + 0x40; 283 | memcpy(&nus_data_send[1], &key_store_tmp, 6); 284 | nus_data_send_length = KEY_LENGTH + 1; 285 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 286 | } else { 287 | //无种子,则发送no seed 288 | ble_nus_string_send(&m_nus, (uint8_t *)no_seed, strlen(no_seed)); 289 | } 290 | } 291 | 292 | } 293 | 294 | /********************************************* 295 | *设置系统参数,成功返回(命令码+0x40)+设置参数 296 | **********************************************/ 297 | static void set_param(uint8_t *p_data, uint16_t length) { 298 | int ret_code; 299 | //设置电机转动时间 300 | OPEN_TIME = p_data[1]; 301 | //设置开门时间 302 | DOOR_OPEN_HOLD_TIME = p_data[2]; 303 | //设置蜂鸣器响动次数 304 | BEEP_DIDI_NUMBER = p_data[3]; 305 | //设置电池电压报警 306 | VOL_VALUE = p_data[4]; 307 | //键盘设置密码的有效时间(单位 10min) 308 | KEY_CHECK_NUMBER = p_data[5]; 309 | //电机的转动方向 310 | MOTO_DIR = p_data[6]; 311 | //按键延迟 312 | TOUCH_DELAY = p_data[7]; 313 | 314 | memset(flash_write_data, 0, BLOCK_STORE_SIZE); 315 | //写入标记'w' 316 | flash_write_data[0] = 'w'; 317 | memcpy(&flash_write_data[1], &p_data[1], length -1); 318 | 319 | //将参数写入到flash 320 | ret_code = interflash_write(flash_write_data, length, DEFAULT_PARAMS_OFFSET); 321 | 322 | //应答包 323 | //将命令加上0x40,返回给app 324 | nus_data_send[0] = p_data[0] + 0x40; 325 | nus_data_send[1] = ret_code; 326 | nus_data_send_length = 2; 327 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 328 | 329 | } 330 | 331 | /************************************************ 332 | *设置系统的种子,设置成功返回(命令码+0x40)+种子 333 | *************************************************/ 334 | static void set_key_seed(uint8_t *p_data, uint16_t length) { 335 | int ret_code; 336 | //传输的种子应该是小端字节 337 | memset(flash_write_data, 0, BLOCK_STORE_SIZE); 338 | //写入标记'w' 339 | flash_write_data[0] = 'w'; 340 | memcpy(&flash_write_data[1],&p_data[1], SEED_LENGTH); 341 | 342 | //将种子写入到flash 343 | ret_code = interflash_write(flash_write_data, BLOCK_STORE_SIZE, SEED_OFFSET); 344 | 345 | //应答包 346 | 347 | //将命令加上0x40,返回给app 348 | nus_data_send[0] = p_data[0] + 0x40; 349 | nus_data_send[1] = (uint8_t) ret_code; 350 | nus_data_send_length = 2; 351 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 352 | } 353 | 354 | /*********************************************** 355 | *设置mac,成功则返回(命令码+0x40)+mac 356 | * 失败返回设置失败 357 | ***********************************************/ 358 | static void set_mac(uint8_t *p_data, uint16_t length) { 359 | uint32_t err_code; 360 | if((p_data[6] &0xc0) ==0xc0) { 361 | //设置的mac最高2位为11,有效 362 | //存储mac地址 363 | memset(mac, 0, 8); 364 | mac[0] = 'w'; 365 | mac[1] = 0x06; 366 | memcpy(&mac[3], &p_data[1], 6); 367 | interflash_write(mac, 8, MAC_OFFSET); 368 | //配置mac 369 | memset(addr.addr, 0, 6); 370 | //拷贝设置的mac 371 | memcpy(addr.addr, &p_data[1], 6); 372 | err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE,&addr); 373 | if(err_code == NRF_SUCCESS) { 374 | //将命令加上0x40,返回给app 375 | nus_data_send[0] = p_data[0] + 0x40; 376 | nus_data_send[1] = 0x00; 377 | nus_data_send_length = 2; 378 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 379 | } 380 | } else { 381 | //将命令加上0x40,返回给app 382 | nus_data_send[0] = p_data[0] + 0x40; 383 | nus_data_send[1] = 0x01; 384 | nus_data_send_length = 2; 385 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 386 | } 387 | 388 | } 389 | 390 | /******************************************************* 391 | *获取mac地址,成功返回(命令码+0x40)+mac 392 | * 失败返回获取失败 393 | *******************************************************/ 394 | static void get_mac(uint8_t *p_data, uint16_t length) { 395 | uint32_t err_code; 396 | 397 | memset(addr.addr, 0, 6); 398 | err_code = sd_ble_gap_address_get(&addr); 399 | if(err_code == NRF_SUCCESS) { 400 | //将命令加上0x40,返回给app 401 | nus_data_send[0] = p_data[0] + 0x40; 402 | memcpy(&nus_data_send[1], &addr.addr[0], 6); 403 | nus_data_send_length = 7; 404 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 405 | } else { 406 | //将命令加上0x40,返回给app 407 | nus_data_send[0] = p_data[0] + 0x40; 408 | nus_data_send[1] = 0x01; 409 | nus_data_send_length = 2; 410 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 411 | } 412 | 413 | } 414 | 415 | /******************** 416 | *打开电池测量的开关 417 | *********************/ 418 | static void open_battery_source(void) { 419 | nrf_gpio_pin_set(BATTERY_LEVEL_EN); 420 | 421 | } 422 | 423 | /*************************************************** 424 | *获取电池电量,大致1~~~0.1V 425 | ****************************************************/ 426 | static void get_battery_level(uint8_t *p_data, uint16_t length) { 427 | uint8_t tmp; 428 | 429 | //1、开启电源使能 430 | open_battery_source(); 431 | //2、开启AD采集 432 | saadc_sampling_event_enable(); 433 | nrf_delay_ms(1000); 434 | //3、获取电量数据 435 | tmp = (battery_level_value &0x0ff0) >>4; 436 | //4、关闭电源使能 437 | nrf_gpio_pin_clear(BATTERY_LEVEL_EN); 438 | 439 | //将命令加上0x40,返回给app 440 | nus_data_send[0] = p_data[0] + 0x40; 441 | memcpy(&nus_data_send[1], &tmp, 1); 442 | nus_data_send[1] = nus_data_send[1] + 6; 443 | nus_data_send_length = 2; 444 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 445 | 446 | } 447 | 448 | /*************************************** 449 | *获取开锁记录的数量 450 | ****************************************/ 451 | static void get_record_number(uint8_t *p_data, uint16_t length) { 452 | memset(flash_read_data, 0, BLOCK_STORE_SIZE); 453 | memset(nus_data_send, 0, BLE_NUS_MAX_DATA_LEN); 454 | //读取记录的数量,小端字节 455 | interflash_read(flash_read_data, BLOCK_STORE_SIZE, RECORD_OFFSET); 456 | memcpy(&record_length,flash_read_data, sizeof(struct record_length_struct)); 457 | 458 | nus_data_send[0] = p_data[0] + 0x40; 459 | if(record_length.record_full ==0x1) { 460 | //记录满 461 | record_length_get = RECORD_NUMBER; 462 | memcpy(&nus_data_send[1], &record_length_get,4); 463 | } else { 464 | memcpy(&nus_data_send[1], &record_length.record_length,4); 465 | } 466 | //发送应答包 467 | nus_data_send_length = 5; 468 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 469 | 470 | } 471 | 472 | /**************************************** 473 | *获取最近的开锁记录 474 | *****************************************/ 475 | static void get_recent_record(uint8_t *p_data, uint16_t length) { 476 | memset(nus_data_send, 0, BLE_NUS_MAX_DATA_LEN); 477 | time_record_compare.tm_sec = p_data[7]; 478 | time_record_compare.tm_min = p_data[6]; 479 | time_record_compare.tm_hour = p_data[5]; 480 | time_record_compare.tm_mday = p_data[4]; 481 | time_record_compare.tm_mon = p_data[3]; 482 | time_record_compare.tm_year = (int)((((int)p_data[2])<<8 | (int)p_data[1]) -1990); 483 | //计算秒数 484 | time_record_compare_t = my_mktime(&time_record_compare); 485 | //获取记录的数量,小端字节 486 | //读取记录的数量,小端字节 487 | interflash_read(flash_read_data, BLOCK_STORE_SIZE, RECORD_OFFSET); 488 | memcpy(&record_length,flash_read_data, sizeof(struct record_length_struct)); 489 | 490 | if(record_length.record_full ==0x1) { 491 | nus_data_send[1] = (uint8_t)RECORD_NUMBER; 492 | for(int i=0; i0) { 499 | nus_data_send[0] = p_data[0] + 0x40; 500 | nus_data_send[2] = i; 501 | memcpy(&nus_data_send[3], &door_open_record_get, sizeof(struct door_open_record)); 502 | nus_data_send_length = sizeof(struct door_open_record)+3; 503 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 504 | } 505 | } 506 | } else if(record_length.record_length >0) { 507 | nus_data_send[1] = (uint8_t)record_length.record_length; 508 | for(int i=0; i0) { 515 | nus_data_send[0] = p_data[0] + 0x40; 516 | nus_data_send[2] = i; 517 | memcpy(&nus_data_send[3], &door_open_record_get, sizeof(struct door_open_record)); 518 | nus_data_send_length = sizeof(struct door_open_record)+3; 519 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 520 | } 521 | } 522 | } else { 523 | //无记录 524 | nus_data_send[0] = p_data[0] + 0x40; 525 | nus_data_send[2] = 0x00; 526 | nus_data_send_length = 2; 527 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 528 | } 529 | 530 | } 531 | 532 | /************************************** 533 | *设置键盘密码 534 | ***************************************/ 535 | static int set_touch_key(uint8_t *p_data, uint16_t length) { 536 | int err_code; 537 | uint16_t store_site; 538 | //1、设置获取的时间 539 | err_code = rtc_time_read(&time_get); 540 | if(err_code == NRF_SUCCESS) { 541 | time_get_t = my_mktime(&time_get); 542 | } 543 | //2、设置获取的格式 544 | //设置的密码 545 | memset(&key_store_set, 0, sizeof(struct key_store_struct)); 546 | //2.1、写标志位'w' 547 | key_store_set.is_store = 'w'; 548 | memcpy(key_store_set.key_store, &p_data[1], sizeof(key_store_set.key_store)); 549 | memcpy(&key_store_set.key_use_time, &p_data[1 + sizeof(key_store_set.key_store)], \ 550 | sizeof(key_store_set.key_use_time)); 551 | memcpy(&key_store_set.key_store_time,&time_get_t, \ 552 | sizeof(key_store_set.key_store_time)); 553 | //3、存储密码 554 | //3、1寻找存储的位置 555 | for(int i = 0; i < KEY_STORE_NUMBER; i++) { 556 | interflash_read((uint8_t *)&key_store_get, sizeof(struct key_store_struct), (pstorage_size_t)(KEY_STORE_OFFSET + i)); 557 | if(key_store_get.is_store != 'w') { 558 | store_site = i; 559 | goto touch_key_store; 560 | } 561 | } 562 | touch_key_store: 563 | key_store_write(&key_store_set, store_site); 564 | //4、返回包 565 | nus_data_send[0] = p_data[0] + 0x40; 566 | nus_data_send[1] = 0x00; 567 | nus_data_send[2] = store_site/0x100; 568 | nus_data_send[3] = store_site &0xff; 569 | nus_data_send_length = 4; 570 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 571 | return 0; 572 | 573 | //都没有,记录满 574 | nus_data_send[0] = p_data[0] + 0x40; 575 | nus_data_send[1] = 0x01; 576 | nus_data_send[2] = 0xff; 577 | nus_data_send[3] = 0xff; 578 | nus_data_send_length = 4; 579 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 580 | return 0; 581 | } 582 | 583 | /************************************ 584 | *删除键盘密码 585 | ************************************/ 586 | static void delete_touch_key(uint8_t *p_data, uint16_t length) { 587 | uint16_t delete_site;//删除的位置 588 | //1、获取要删除的ID号 589 | delete_site = p_data[1] * 0x100 + p_data[2]; 590 | //2、读取指定的ID号的键盘密码内容 591 | interflash_read((uint8_t *)&key_store_get, sizeof(struct key_store_struct), (pstorage_size_t)(KEY_STORE_OFFSET + delete_site)); 592 | //3、判断密码是否存在,存在的话,删除 593 | if(key_store_get.is_store =='w') { 594 | //获取需要存储的位置 595 | pstorage_block_identifier_get(&block_id_flash_store, (pstorage_size_t)(KEY_STORE_OFFSET + delete_site), &block_id_read); 596 | //清除当前存储区域 597 | pstorage_clear(&block_id_read, BLOCK_STORE_SIZE); 598 | } 599 | //4、返回包 600 | nus_data_send[0] = p_data[0] + 0x40; 601 | nus_data_send[1] = 0x00; 602 | nus_data_send_length = 2; 603 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 604 | } 605 | 606 | /***************************************** 607 | *获取现在存储的密码 608 | ******************************************/ 609 | static void get_touch_key_store(uint8_t *p_data, uint16_t length) { 610 | 611 | memset(nus_data_send, 0, BLE_NUS_MAX_DATA_LEN); 612 | 613 | for(int i = 0; i < KEY_STORE_NUMBER; i++) { 614 | interflash_read((uint8_t *)&key_store_get, sizeof(struct key_store_struct), (pstorage_size_t)(KEY_STORE_OFFSET + i)); 615 | if(key_store_get.is_store == 'w') { 616 | nus_data_send[0] = p_data[0] + 0x40; 617 | nus_data_send[1] = i/0x100; 618 | nus_data_send[2] = i&0xff; 619 | //密码 620 | memcpy(&nus_data_send[3], \ 621 | key_store_get.key_store, sizeof(key_store_get.key_store)); 622 | //有效时间 623 | memcpy(&nus_data_send[3 + sizeof(key_store_get.key_store)], \ 624 | &key_store_get.key_use_time, sizeof(key_store_get.key_use_time)); 625 | //存储时间 626 | memcpy(&nus_data_send[3 + sizeof(key_store_get.key_store) + sizeof(key_store_get.key_use_time)], \ 627 | &key_store_get.key_store_time, sizeof(key_store_get.key_store_time)); 628 | nus_data_send_length = 3 + sizeof(key_store_get.key_store) + \ 629 | sizeof(key_store_get.key_use_time) + \ 630 | sizeof(key_store_get.key_store_time); 631 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 632 | } 633 | } 634 | //结束包 635 | nus_data_send[0] = p_data[0] + 0x40; 636 | nus_data_send[1] = 0x00; 637 | nus_data_send[2] = 0x00; 638 | nus_data_send[3] = 0x00; 639 | nus_data_send[4] = 0x00; 640 | nus_data_send_length = 5; 641 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 642 | 643 | } 644 | 645 | /************************************* 646 | *用户解除绑定命令 647 | **************************************/ 648 | static void user_unbind_cmd(uint8_t *p_data, uint16_t length) { 649 | uint8_t reply_data[1]; 650 | //用户解除绑定 651 | //1、清除内部flash所有数据 652 | 653 | for(int j=0; j < BLOCK_STORE_COUNT; j++) { 654 | pstorage_block_identifier_get(&block_id_flash_store, \ 655 | (pstorage_size_t)j, &block_id_write); 656 | 657 | pstorage_clear(&block_id_write, BLOCK_STORE_SIZE); 658 | 659 | } 660 | 661 | //2、清除指纹内所有存储指纹 662 | //2.1、打开指纹模块电源 663 | nrf_gpio_pin_set(BATTERY_LEVEL_EN); 664 | //上电需要0.5s的准备时间 665 | nrf_delay_ms(1000); 666 | //2.2、发送删除指令 667 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_empty_cmd), r301t_send_empty_cmd); 668 | //2.3、获取指令码,此指令码需要在回复命令处理中使用 669 | fig_cmd_code = r301t_send_empty_cmd[0]; 670 | //3、获取命令包 671 | ble_operate_code = p_data[0]; 672 | 673 | } 674 | 675 | /******************************************************* 676 | *指纹模块fm260b命令处理,主要调用uart端口 677 | *******************************************************/ 678 | static void send_fig_fm260b_cmd(uint8_t *p_data, uint16_t length) { 679 | //获取第一参数和第二参数,两字节,大端 680 | dr_fig_param_first = p_data[3] *256 + p_data[4]; 681 | dr_fig_param_second = p_data[5] *256 + p_data[6]; 682 | //将获取的指令发送给指纹模块 683 | for (uint32_t i = 0; i < length; i++) { 684 | while(app_uart_put(p_data[i]) != NRF_SUCCESS); 685 | } 686 | 687 | if(p_data[2] == DR_FIG_CMD_AUTOSEARCH) { //自动注册模块指令 688 | //设置自动注册状态位 689 | is_fm260b_autoenroll = true; 690 | } 691 | 692 | } 693 | 694 | /************************************** 695 | *注册指纹 696 | **************************************/ 697 | static int enroll_fig(uint8_t *p_data, uint16_t length) { 698 | uint16_t empty_1st_id;//第一个为空的id号 699 | uint8_t reply_full[4];//指纹库满的回复 700 | //1、获取指纹ID号 701 | //读取flash中 702 | for(int i = 0; i < FIG_INFO_NUMBER; i++) { 703 | //1.1、获取内部flash存储区的信息 704 | pstorage_block_identifier_get(&block_id_flash_store, \ 705 | (pstorage_size_t)(FIG_INFO_OFFSET+i), &block_id_fig_info); 706 | memset(&fig_info_get, 0, sizeof(struct fig_info)); 707 | pstorage_load((uint8_t *)&fig_info_get, &block_id_fig_info, sizeof(struct fig_info), 0); 708 | if(fig_info_get.is_store ==0xff) { 709 | //1.1.1、未存储,获取要存储的id号 710 | empty_1st_id = i; 711 | //跳转执行存储 712 | goto exe_enroll_fig; 713 | } 714 | } 715 | //1.1.2、遍历完后,没有空的fig,返回错误 716 | //将命令加上0x40,返回给app 717 | reply_full[0] = 0xff; 718 | reply_full[1] = 0xff; 719 | reply_full[2] = 0xff; 720 | reply_full[3] = 0xff; 721 | ble_reply(p_data[0], reply_full, sizeof(reply_full)); 722 | 723 | return 0; 724 | 725 | exe_enroll_fig: 726 | //2、获取要存储的id号,大端字节 727 | memset(enroll_fig_id, 0, 2); 728 | enroll_fig_id[0] = empty_1st_id / 0x100; 729 | enroll_fig_id[1] = empty_1st_id & 0xff; 730 | //3、获取存储的指纹信息模块 731 | memset(&fig_info_set, 0, sizeof(struct fig_info)); 732 | memcpy(fig_info_set.fig_info_data, &p_data[1], sizeof(fig_info_set.fig_info_data));//指纹描述信息8B 733 | fig_info_set.is_store = 'w'; 734 | fig_info_set.fig_info_id = empty_1st_id; 735 | 736 | //4、打开指纹模 737 | open_fig(); 738 | //5、设置,开始注册,注册步骤为1 739 | is_r301t_autoenroll = true; 740 | r301t_autoenroll_step = 1; 741 | //6、取指令码 742 | ble_operate_code = p_data[0]; 743 | fig_cmd_code = GR_FIG_CMD_GETIMG; 744 | //7、发送指纹模块命令 745 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_getimg_cmd), \ 746 | r301t_send_getimg_cmd); 747 | } 748 | 749 | /************************************** 750 | *删除指纹 751 | **************************************/ 752 | static int delete_fig(uint8_t *p_data, uint16_t length) { 753 | // uint16_t marry_fig_id;//匹配的指纹id 754 | uint8_t reply_data[1]; 755 | // uint8_t r301t_send_deletechar_idx_cmd[5]; 756 | 757 | pstorage_block_identifier_get(&block_id_flash_store, \ 758 | (pstorage_size_t)(FIG_INFO_OFFSET+(p_data[1]*0x100 + p_data[2])), &block_id_fig_info); 759 | memset(&fig_info_get, 0, sizeof(struct fig_info)); 760 | pstorage_load((uint8_t *)&fig_info_get, &block_id_fig_info, sizeof(struct fig_info), 0); 761 | 762 | if(fig_info_get.is_store == 'w') { 763 | //跳转执行存储 764 | goto exe_delete_fig; 765 | } 766 | 767 | //1.1.2、遍历完后,没有空的fig,返回错误 768 | reply_data[0] = 0x01; 769 | ble_reply(p_data[0], reply_data, sizeof(reply_data)); 770 | return 0; 771 | 772 | exe_delete_fig: 773 | 774 | //设置删除的指纹ID,大端字节 775 | memset(delete_fig_id, 0, 2); 776 | memcpy(delete_fig_id, &p_data[1], 2); 777 | 778 | //2、打开指纹模块 779 | open_fig(); 780 | //3、发送删除指纹号命令 781 | memset(r301t_send_deletechar_idx_cmd, 0, sizeof(r301t_send_deletechar_idx_cmd)); 782 | memcpy(r301t_send_deletechar_idx_cmd, r301t_send_deletechar_id0_cmd, sizeof(r301t_send_deletechar_idx_cmd)); 783 | //指定flash指纹ID 784 | r301t_send_deletechar_idx_cmd[1] = delete_fig_id[0]; 785 | r301t_send_deletechar_idx_cmd[2] = delete_fig_id[1]; 786 | //发送命令 787 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_deletechar_idx_cmd), \ 788 | r301t_send_deletechar_idx_cmd); 789 | //设置命令码为删除char 790 | fig_cmd_code = GR_FIG_CMD_DELCHAR; 791 | //4、取指令码 792 | ble_operate_code = p_data[0]; 793 | } 794 | 795 | /**************************** 796 | *获取指纹信息 797 | *****************************/ 798 | static int get_fig_info(uint8_t *p_data, uint16_t length) { 799 | uint8_t end_reply[4] = {0, 0, 0, 0}; 800 | 801 | 802 | //1、获取指纹模块的信息列表 803 | //1、1.设置指令码为GR_FIG_CMD_RDINDEXTB 804 | fig_cmd_code = GR_FIG_CMD_RDINDEXTB; 805 | ble_operate_code = p_data[0]; 806 | //1、2.打开指纹模块 807 | open_fig(); 808 | //1、3.发送获取指纹模快索引表命令 809 | r301t_send_get_indextbx_cmd[1] = 0; 810 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_get_indextbx_cmd), \ 811 | r301t_send_get_indextbx_cmd); 812 | /* 813 | //3、获取flash中的指纹信息 814 | for(int i = 0; i < FIG_INFO_NUMBER; i++) { 815 | //1.1、获取内部flash存储区的信息 816 | pstorage_block_identifier_get(&block_id_flash_store, \ 817 | (pstorage_size_t)(FIG_INFO_OFFSET+i), &block_id_fig_info); 818 | pstorage_load(interflash_read_data, &block_id_fig_info, BLOCK_STORE_SIZE, 0); 819 | memset(&fig_info_get, 0, sizeof(struct fig_info)); 820 | memcpy(&fig_info_get, interflash_read_data, sizeof(struct fig_info)); 821 | 822 | if(fig_info_get.is_store == 'w') { 823 | //写了指纹信息,将指令码+40,再把指纹信息返回给上位机 824 | nus_data_send[0] = p_data[0] + 0x40; 825 | nus_data_send[1] = fig_info_get.fig_info_id / 0x100; 826 | nus_data_send[2] = fig_info_get.fig_info_id &0xff; 827 | memcpy(&nus_data_send[3], fig_info_get.fig_info_data, sizeof(fig_info_get.fig_info_data)); 828 | nus_data_send_length = 3+sizeof(fig_info_get.fig_info_data); 829 | ble_nus_string_send(&m_nus, nus_data_send, nus_data_send_length); 830 | } 831 | } 832 | //4、结束包 833 | ble_reply(p_data[0], end_reply, sizeof(end_reply)); 834 | */ 835 | } 836 | 837 | /*********************** 838 | *停止指纹模块 839 | ***********************/ 840 | static void stop_fig(uint8_t *p_data, uint16_t length) { 841 | uint8_t reply_data[1]; 842 | //1、关闭指纹模块 843 | close_fig(); 844 | //2、初始化指纹模块相关的步骤 845 | r301t_autoenroll_step = 0; 846 | r301t_autosearch_step = 0; 847 | //3、初始化标志量 848 | fig_recieve_data_length = 0; 849 | is_r301t_autoenroll = false; 850 | //4、回复上位机 851 | reply_data[0] = 0x00; 852 | ble_reply(p_data[0], reply_data, sizeof(reply_data)); 853 | 854 | } 855 | 856 | /**************************************** 857 | *删除所有指纹信息 858 | ****************************************/ 859 | static void delete_all_fig(uint8_t *p_data, uint16_t length) { 860 | //1.设置指令码为GR_FIG_CMD_EMPTY 861 | fig_cmd_code = GR_FIG_CMD_EMPTY; 862 | ble_operate_code = p_data[0]; 863 | //2.打开指纹模块 864 | open_fig(); 865 | //3.发送删除所有指纹库命令 866 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_empty_cmd), \ 867 | r301t_send_empty_cmd); 868 | } 869 | 870 | /**************************************** 871 | *获取指纹模块的有效指纹数量 872 | ****************************************/ 873 | static void get_fig_number(uint8_t *p_data, uint16_t length) { 874 | //1.设置指令码为GR_FIG_CMD_VTNUM 875 | fig_cmd_code = GR_FIG_CMD_VTNUM; 876 | ble_operate_code = p_data[0]; 877 | //2.打开指纹模块 878 | open_fig(); 879 | //3.发送获取有效模板个数命令 880 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_get_vtnum_cmd), \ 881 | r301t_send_get_vtnum_cmd); 882 | } 883 | 884 | /**************************************** 885 | *获取指纹模块的索引表 886 | ****************************************/ 887 | static void get_fig_indextable(uint8_t *p_data, uint16_t length) { 888 | //1.设置指令码为GR_FIG_CMD_RDINDEXTB 889 | fig_cmd_code = GR_FIG_CMD_RDINDEXTB; 890 | ble_operate_code = p_data[0]; 891 | //2.打开指纹模块 892 | open_fig(); 893 | //3.发送获取指纹模快索引表命令 894 | r301t_send_get_indextbx_cmd[1] = p_data[1]; 895 | fig_r301t_send_cmd(0x01, sizeof(r301t_send_get_indextbx_cmd), \ 896 | r301t_send_get_indextbx_cmd); 897 | } 898 | 899 | /***************************** 900 | *ble回复函数 901 | ******************************/ 902 | void ble_reply(uint8_t operate_code, uint8_t *reply_code, uint16_t reply_code_length) { 903 | memset(nus_data_send, 0, sizeof(nus_data_send)); 904 | nus_data_send[0] = operate_code + 0x40; 905 | memcpy(&nus_data_send[1], reply_code, reply_code_length); 906 | ble_nus_string_send(&m_nus, nus_data_send, reply_code_length + 1); 907 | 908 | } 909 | 910 | 911 | /********************************* 912 | *打开指纹模块,使能uart 913 | **********************************/ 914 | void open_fig(void) { 915 | //1、打开指纹模块电源 916 | nrf_gpio_cfg_output(BATTERY_LEVEL_EN); 917 | nrf_gpio_pin_set(BATTERY_LEVEL_EN); 918 | //上电需要0.5s的准备时间 919 | nrf_delay_ms(1000); 920 | //初始化uart 921 | // uart_init(); 922 | 923 | } 924 | 925 | 926 | /******************************************* 927 | *关闭指纹模块,未使能uart 928 | ********************************************/ 929 | void close_fig(void) { 930 | //关闭指纹芯片电源电源 931 | nrf_gpio_cfg_output(BATTERY_LEVEL_EN); 932 | nrf_gpio_pin_clear(BATTERY_LEVEL_EN); 933 | //设置uart的引脚 934 | /* nrf_gpio_cfg_output(RX_PIN_NUMBER); 935 | nrf_gpio_pin_clear(RX_PIN_NUMBER); 936 | nrf_gpio_cfg_output(TX_PIN_NUMBER); 937 | nrf_gpio_pin_clear(TX_PIN_NUMBER);*/ 938 | 939 | } 940 | 941 | /************************************************************ 942 | *对nus servvice传来的数据进行分析 943 | *in: *p_data 处理的数据指针 944 | length 数据长度 945 | ***********************************************************/ 946 | void operate_code_check(uint8_t *p_data, uint16_t length) { 947 | static char checked_superkey_false[16] = "skey check fail"; 948 | switch(p_data[0]) { 949 | case '0'...'9'://设置开锁秘钥 950 | if(length ==0x06) { //6字节 951 | is_ble_cmd_exe = true; 952 | sm4_key_check_open(p_data, length); 953 | is_ble_cmd_exe = false; 954 | } 955 | break; 956 | 957 | case SET_SUPER_KEY://设置管理员密码 958 | if(length == 0x0d) { //13字节 959 | is_ble_cmd_exe = true; 960 | set_super_key(p_data, length); 961 | is_ble_cmd_exe = false; 962 | } 963 | break; 964 | 965 | case CHECK_SUPER_KEY://验证超级管理员密码 966 | if(length == 0x0d) { 967 | is_ble_cmd_exe = true; 968 | check_super_key(p_data,length); 969 | is_ble_cmd_exe = false; 970 | } 971 | break; 972 | 973 | case SYNC_TIME://同步时间 974 | if(length ==0x08) { //8字节 975 | if(is_superkey_checked == true) { //如果验证了超级密码 976 | is_ble_cmd_exe = true; 977 | sync_rtc_time(p_data, length); 978 | is_ble_cmd_exe = false; 979 | } else { 980 | //向手机发送失败信息"skey check fail" 981 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 982 | strlen(checked_superkey_false) ); 983 | } 984 | } 985 | break; 986 | 987 | case GET_TIME://获取时间 988 | is_ble_cmd_exe = true; 989 | get_rtc_time(p_data, length); 990 | is_ble_cmd_exe = false; 991 | break; 992 | 993 | case SET_KEY_SEED://写入种子 994 | if(length == 0x11) { //17字节 995 | if(is_superkey_checked == true) { //如果验证了超级密码 996 | is_ble_cmd_exe = true; 997 | set_key_seed(p_data, length); 998 | is_ble_cmd_exe = false; 999 | } else { 1000 | //向手机发送失败信息"skey check fail" 1001 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1002 | strlen(checked_superkey_false) ); 1003 | } 1004 | } 1005 | break; 1006 | 1007 | case GET_KEY_NOW://获取现在的动态密码,后期要注释掉 1008 | is_ble_cmd_exe = true; 1009 | get_key_now(p_data, length); 1010 | is_ble_cmd_exe = false; 1011 | break; 1012 | 1013 | case SET_PARAMS://设置参量 1014 | if(length == PARAMS_LEN + 1) { //6字节 1015 | if(is_superkey_checked == true) { //如果验证了超级密码 1016 | is_ble_cmd_exe = true; 1017 | set_param(p_data, length); 1018 | is_ble_cmd_exe = false; 1019 | } else { 1020 | //向手机发送失败信息"skey check fail" 1021 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1022 | strlen(checked_superkey_false) ); 1023 | } 1024 | } 1025 | break; 1026 | 1027 | case SET_MAC://配置mac,与显示的mac反向 1028 | if(length ==0x07) { //7字节 1029 | is_ble_cmd_exe = true; 1030 | set_mac(p_data, length); 1031 | is_ble_cmd_exe = false; 1032 | } 1033 | break; 1034 | 1035 | case GET_MAC://获取mac地址 1036 | is_ble_cmd_exe = true; 1037 | get_mac(p_data, length); 1038 | is_ble_cmd_exe = false; 1039 | break; 1040 | 1041 | case GET_BATTERY_LEVEL://获取电池电量 1042 | is_ble_cmd_exe = true; 1043 | get_battery_level(p_data, length); 1044 | is_ble_cmd_exe = false; 1045 | break; 1046 | 1047 | case GET_RECORD_NUMBER://查询开门记录数量 1048 | is_ble_cmd_exe = true; 1049 | get_record_number(p_data, length); 1050 | is_ble_cmd_exe = false; 1051 | break; 1052 | 1053 | case GET_RECENT_RECORD://查询指定日期后的记录 1054 | if(length == 0x08) { //8字节 1055 | if(is_superkey_checked == true) { //如果验证了超级密码 1056 | is_ble_cmd_exe = true; 1057 | get_recent_record(p_data, length); 1058 | is_ble_cmd_exe = false; 1059 | } else { 1060 | //向手机发送失败信息"skey check fail" 1061 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1062 | strlen(checked_superkey_false) ); 1063 | } 1064 | } 1065 | break; 1066 | 1067 | case SET_TOUCH_KEY://设置触摸按键密码 1068 | if(length == 9) { //9字节 1069 | if(is_superkey_checked == true) { //如果验证了超级密码 1070 | is_ble_cmd_exe = true; 1071 | set_touch_key(p_data, length); 1072 | is_ble_cmd_exe = false; 1073 | } else { 1074 | //向手机发送失败信息"skey check fail" 1075 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1076 | strlen(checked_superkey_false) ); 1077 | } 1078 | 1079 | } 1080 | break; 1081 | 1082 | case DELETE_TOUCH_KEY://设置触摸按键密码 1083 | if(length == 3) { //11字节 1084 | if(is_superkey_checked == true) { //如果验证了超级密码 1085 | is_ble_cmd_exe = true; 1086 | delete_touch_key(p_data, length); 1087 | is_ble_cmd_exe = false; 1088 | } else { 1089 | //向手机发送失败信息"skey check fail" 1090 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1091 | strlen(checked_superkey_false) ); 1092 | } 1093 | 1094 | } 1095 | break; 1096 | 1097 | case GET_TOUCH_KEY_STORE://查询有效密码 1098 | if(is_superkey_checked == true) { //如果验证了超级密码 1099 | is_ble_cmd_exe = true; 1100 | get_touch_key_store(p_data, length); 1101 | is_ble_cmd_exe = false; 1102 | } else { 1103 | //向手机发送失败信息"skey check fail" 1104 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1105 | strlen(checked_superkey_false) ); 1106 | } 1107 | break; 1108 | 1109 | case USER_UNBIND_CMD: //用户解除绑定 1110 | if(is_superkey_checked == true) { //如果验证了超级密码 1111 | is_ble_cmd_exe = true; 1112 | user_unbind_cmd(p_data, length); 1113 | is_ble_cmd_exe = false; 1114 | } else { 1115 | //向手机发送失败信息"skey check fail" 1116 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1117 | strlen(checked_superkey_false) ); 1118 | } 1119 | break; 1120 | 1121 | case ENROLL_FIG://注册指纹 1122 | if(length == 17) {//指令码+描述信息16B 1123 | if(is_superkey_checked == true) { //如果验证了超级密码 1124 | is_ble_cmd_exe = true; 1125 | enroll_fig(p_data, length); 1126 | is_ble_cmd_exe = false; 1127 | } else { 1128 | //向手机发送失败信息"skey check fail" 1129 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1130 | strlen(checked_superkey_false) ); 1131 | 1132 | } 1133 | } 1134 | break; 1135 | 1136 | case DELETE_FIG://删除指纹 1137 | if(length == 19) {//指令码+描述信息16B 1138 | if(is_superkey_checked == true) { //如果验证了超级密码 1139 | is_ble_cmd_exe = true; 1140 | delete_fig(p_data, length); 1141 | is_ble_cmd_exe = false; 1142 | } else { 1143 | //向手机发送失败信息"skey check fail" 1144 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1145 | strlen(checked_superkey_false) ); 1146 | } 1147 | } 1148 | break; 1149 | 1150 | case GET_FIG_INFO://获取指纹信息 1151 | if(is_superkey_checked == true) { //如果验证了超级密码 1152 | is_ble_cmd_exe = true; 1153 | get_fig_info(p_data, length); 1154 | is_ble_cmd_exe = false; 1155 | } else { 1156 | //向手机发送失败信息"skey check fail" 1157 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1158 | strlen(checked_superkey_false) ); 1159 | } 1160 | break; 1161 | 1162 | case STOP_FIG://停止指纹模块 1163 | if(is_superkey_checked == true) { //如果验证了超级密码 1164 | is_ble_cmd_exe = true; 1165 | stop_fig(p_data, length); 1166 | is_ble_cmd_exe = false; 1167 | } else { 1168 | //向手机发送失败信息"skey check fail" 1169 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1170 | strlen(checked_superkey_false) ); 1171 | } 1172 | break; 1173 | case DELETE_ALL_FIG://删除所有指纹信息 1174 | if(is_superkey_checked == true) { //如果验证了超级密码 1175 | is_ble_cmd_exe = true; 1176 | delete_all_fig(p_data, length); 1177 | is_ble_cmd_exe = false; 1178 | } else { 1179 | //向手机发送失败信息"skey check fail" 1180 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1181 | strlen(checked_superkey_false) ); 1182 | } 1183 | break; 1184 | case GET_FIG_NUMBER://获取指纹数量 1185 | if(is_superkey_checked == true) { //如果验证了超级密码 1186 | is_ble_cmd_exe = true; 1187 | get_fig_number(p_data, length); 1188 | is_ble_cmd_exe = false; 1189 | } else { 1190 | //向手机发送失败信息"skey check fail" 1191 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1192 | strlen(checked_superkey_false) ); 1193 | } 1194 | break; 1195 | /* case GET_FIG_INDEXTABLE://获取指纹的索引码 1196 | if(length == 2){ 1197 | if(is_superkey_checked == true ) { //如果验证了超级密码 1198 | is_ble_cmd_exe = true; 1199 | get_fig_indextable(p_data, length); 1200 | is_ble_cmd_exe = false; 1201 | } else { 1202 | //向手机发送失败信息"skey check fail" 1203 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1204 | strlen(checked_superkey_false) ); 1205 | } 1206 | } 1207 | break;*/ 1208 | 1209 | case 0x1B://指纹模块fm260b指令,长度为8,直接通过串口发送给模块 1210 | if(length == 8) { //长度为8 1211 | if(is_superkey_checked == true) { //如果验证了超级密码 1212 | is_ble_cmd_exe = true; 1213 | send_fig_fm260b_cmd(p_data, length); 1214 | is_ble_cmd_exe = false; 1215 | } else { 1216 | //向手机发送失败信息"skey check fail" 1217 | ble_nus_string_send(&m_nus, (uint8_t *)checked_superkey_false, \ 1218 | strlen(checked_superkey_false) ); 1219 | } 1220 | } 1221 | break; 1222 | 1223 | default: 1224 | 1225 | break; 1226 | } 1227 | 1228 | } 1229 | --------------------------------------------------------------------------------