Pārlūkot izejas kodu

shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2

lwy 2 gadi atpakaļ
vecāks
revīzija
cbc4dde5cd
100 mainītis faili ar 15622 papildinājumiem un 0 dzēšanām
  1. 52 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/.gitignore
  2. 13 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/BUG.txt
  3. BIN
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/Picture/Down.png
  4. BIN
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/Picture/Hotkey.png
  5. BIN
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/Picture/config.png
  6. 26 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/README.md
  7. 137 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_Calibration.c
  8. 19 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_Calibration.h
  9. 488 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_ImuCalibration.c
  10. 13 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_ImuCalibration.h
  11. 171 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_baseinfo.c
  12. 15 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_baseinfo.h
  13. 211 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_charge/app_charge.c
  14. 15 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_charge/app_charge.h
  15. 195 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_client.c
  16. 17 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_client.h
  17. 168 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_client_step.c
  18. 20 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_client_step.h
  19. 208 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_config.c
  20. 12 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_config.h
  21. 215 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_connect_manage.c
  22. 12 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_connect_manage.h
  23. 88 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_data_transfer.c
  24. 55 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_data_transfer.h
  25. 709 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_flash.c
  26. 130 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_flash.h
  27. 149 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_game.c
  28. 13 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_game.h
  29. 90 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_host.c
  30. 26 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_host.h
  31. 39 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_losspack.c
  32. 17 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_losspack.h
  33. 257 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_math.c
  34. 15 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_math.h
  35. 55 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_organ.c
  36. 12 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_organ.h
  37. 197 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_ota.c
  38. 13 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_ota.h
  39. 140 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_overturn.c
  40. 14 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_overturn.h
  41. 315 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_pair.c
  42. 23 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_pair.h
  43. 70 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_power/app_power.c
  44. 13 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_power/app_power.h
  45. 33 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_safe.c
  46. 15 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_safe.h
  47. 398 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_self_checking - 副本.c
  48. 347 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_self_checking.c
  49. 39 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_self_checking.h
  50. 131 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_step.c
  51. 14 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_step.h
  52. 47 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_switchimu.c
  53. 19 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_switchimu.h
  54. 457 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/ble_comm.h
  55. 699 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/cli.c
  56. 100 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/cli.h
  57. 593 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/cli_vt100.h
  58. 289 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/dtalige.c
  59. 678 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/host.c
  60. 46 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/queue.c
  61. 76 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/queue.h
  62. 82 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/ringframe.c
  63. 62 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/ringframe.h
  64. 1614 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/slave.c
  65. 177 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/timeslot.c
  66. 325 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_dfu/ble_dfu.c
  67. 249 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_dfu/ble_dfu.h
  68. 367 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_dfu/ble_dfu_bonded.c
  69. 299 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_dfu/ble_dfu_unbonded.c
  70. 256 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_adc.c
  71. 60 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_adc.h
  72. 190 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_esb.c
  73. 20 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_esb.h
  74. 523 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_flash.c
  75. 75 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_flash.h
  76. 16 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_gpio.c
  77. 12 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_gpio.h
  78. 230 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_interface.c
  79. 10 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_interface.h
  80. 84 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_mpu9250.c
  81. 143 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_mpu9250.h
  82. 91 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_ms5611.c
  83. 10 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_ms5611.h
  84. 32 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_protocol.c
  85. 32 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_protocol.h
  86. 467 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_pwm.c
  87. 88 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_pwm.h
  88. 13 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_pwm/bsp_pwm.h
  89. 92 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_pwm/bsp_pwm_led_gpio.c
  90. 65 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_pwm/bsp_pwm_led_ws2812.c
  91. 144 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_rtc.c
  92. 19 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_rtc.h
  93. 685 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_spi.c
  94. 112 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_spi.h
  95. 285 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_time.c
  96. 18 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_time.h
  97. 149 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_uart.c
  98. 20 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_uart.h
  99. 65 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_wdt.c
  100. 13 0
      shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_wdt.h

+ 52 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/.gitignore

@@ -0,0 +1,52 @@
+# Prerequisites
+*.d
+
+# Object files
+*.o
+*.crf
+*.ko
+*.obj
+*.elf
+
+# Linker output
+*.ilk
+*.map
+*.exp
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Kernel Module Compile Results
+*.mod*
+*.cmd
+.tmp_versions/
+modules.order
+Module.symvers
+Mkfile.old
+dkms.conf

+ 13 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/BUG.txt

@@ -0,0 +1,13 @@
+1. 连接蓝牙过程中,重新打开蓝牙有重启现象
+
+2. ble连接超时,有蓝牙重启现象
+
+3. 自检程序
+
+4. 脚步同步
+
+5. 一小时调用陀螺仪零偏纠正算法。
+
+6. 内存优化
+
+7. 天线异常

BIN
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/Picture/Down.png


BIN
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/Picture/Hotkey.png


BIN
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/Picture/config.png


+ 26 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/README.md

@@ -0,0 +1,26 @@
+
+### 编译环境
+keil 5.3
+### 
+
+#### 准备
+1. 下载nordic SDK ,nRF5_SDK_17.0.0_9d13099 [链接](http://git.ouj.com/ouj/shoes/src/master/smart_shoes/nRF5_SDK_17.0.0_9d13099)   
+2. 下载并安装nrfjprom工具 [链接](https://www.nordicsemi.com/-/media/Software-and-other-downloads/Desktop-software/nRF-command-line-tools/sw/Versions-10-x-x/10-15-2/nRF-Command-Line-Tools-10.15.2-x86.exe)
+
+### 编译和烧录
+在keil 中打开工程,根据实际需要选择PCB板和鞋子的功能,打开Application目录下的usr_config.h
+#### 选择使用的板子
+     选择PCB板>>>> PCB_VERSION - PCB板选择  >>>> PCB2.1
+#### 烧录快捷键
+##### 1. 添加OTA down
+   Tools >>>> Customize Tools Menu  添加OTA down
+![image] (http://git.ouj.com/ouj/shoe_mcu/src/master/Picture/Down.png)
+
+##### 2. 设置快捷键
+   Edit >>> Configuration >>>>> Shortcut Keys
+![image] (http://git.ouj.com/ouj/shoe_mcu/src/master/Picture/Hotkey.png)
+#### 设置DFU功能
+   勾选 BleNameHoldOn_ENANBLE  
+   公共 >>> 系统设置  >>>> BleNameHoldOn_ENANBLE
+![image] (http://git.ouj.com/ouj/shoe_mcu/src/master/Picture/config.png)
+

+ 137 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_Calibration.c

@@ -0,0 +1,137 @@
+#include "app_Calibration.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_imu.h"
+#include "hal_flash.h"
+#include "hal_ble_client.h"
+#include "arm_math.h"
+#include "drv_calibration.h"
+#include "nrf_gpio.h"
+#include "app_charge.h"
+
+static int16_t Acc[3]={0};
+static int16_t Gry[3]={0};
+static int16_t FrontMag[3]={0};
+
+/***********************************
+ *未校准:灭灯
+ *校准中:指示灯常亮
+ *校准完成:指示灯慢闪,亮10ms,灭灯2S
+ *校准错误:指示灯快闪,亮10ms,灭灯100ms
+************************************/
+static void app_calibration_CalLed_Process(void){
+	
+		static uint32_t tim =0;
+	
+		if(tim == 0){
+			tim = TIME_GetTicks();
+		}else if(TIME_GetTicks()-tim >= 60000){								//亮1分钟
+			tim = 0;
+			Process_Stop(app_calibration_CalLed_Process);				//停止该任务	
+		}
+		
+		
+		
+		nrf_gpio_pin_write(PIN_LED_RUN,0); 
+		nrf_delay_ms(10);
+		nrf_gpio_pin_write(PIN_LED_RUN,1);
+	  
+	  char printdata[200]={0};
+	  sprintf(printdata,"caldata:%f,%f,%f,%f,%f,%f",mBackup.cal[0],mBackup.cal[1],mBackup.cal[2],mBackup.cal[3],mBackup.cal[4],mBackup.cal[5]);
+	  SEGGER_RTT_printf(0,"%s\n",printdata);
+		Mahony_PRINT("caldata:%f,%f,%f,%f,%f,%f",mBackup.cal[0],mBackup.cal[1],mBackup.cal[2],mBackup.cal[3],mBackup.cal[4],mBackup.cal[5]);
+		
+		
+
+}
+
+#define USED_MAG_CHECK_BAREBOARD_VALUE_START		0
+#define USED_MAG_CHECK_BAREBOARD_VALUE_END			300
+void app_calibration_is_BareBoard_Process(void)
+{
+	if(IMU_GetCurrentMode() == STATE_IDLE_MODE)
+	{
+		IMU_GetMagFront(FrontMag);
+		if(USED_MAG_CHECK_BAREBOARD_VALUE_START < FrontMag[0] &&  FrontMag[0] < USED_MAG_CHECK_BAREBOARD_VALUE_END){
+			IMU_SetBareBoardMode(1);		//进入板子模式
+		}else{
+			IMU_SetBareBoardMode(0);		//不进入板子模式
+		}
+	}
+}
+
+void app_calibration_is_Calibration_Process(void)
+{
+	if(IMU_GetCurrentMode() == STATE_BAREBOARD_MODE)
+	{
+		
+		if(IMU_GetBareBoardMode() == 1)IMU_SetBareBoardMode(0);		//进入板子模式后,将进入板子模式的标志位清零。
+		
+		IMU_GetAcc(Acc);
+		IMU_GetGry(Gry);
+		IMU_GetMagFront(FrontMag);
+		
+		ImuCalibration_pcs(Acc, Gry, FrontMag);
+		if(ImuCalibration_GetState() == ImuCal_GetData){
+				nrf_gpio_pin_write(PIN_LED_RUN,0);
+				IMU_SetCalibrationMode(1);														//进入校准模式
+		}else{
+			if(FrontMag[0] >= USED_MAG_CHECK_BAREBOARD_VALUE_END || USED_MAG_CHECK_BAREBOARD_VALUE_START >= FrontMag[0]){
+				IMU_SetLowPowerMode(1);																//进入低功耗模式。
+			}
+		}
+	}
+}
+
+void app_calibration_Calibration_in_Process(void)
+{
+	if(IMU_GetCurrentMode() == STATE_CALIBRATION_MODE)
+	{
+		
+		if(IMU_GetCalibrationMode() == 1)IMU_SetCalibrationMode(0);		//进入板子校准模式后,将进入板子校准模式的标志位清零。
+		
+		IMU_GetAcc(Acc);
+		IMU_GetGry(Gry);
+		IMU_GetMagFront(FrontMag);
+		
+		ImuCalibration_pcs(Acc, Gry, FrontMag);
+		if(ImuCalibration_GetState() == ImuCal_finish){
+			Flash_SaveBackup();
+			Mahony_PRINT("ImuCal_state ImuCal_finish");
+			Process_Start(2000,"app_calibration_CalLed_Process",app_calibration_CalLed_Process);
+			Process_UpdatePeroid(app_calibration_CalLed_Process,2000);
+			IMU_SetLowPowerMode(1);																																														//进入低功耗模式。
+		}else if(ImuCalibration_GetState() == ImuCal_error || ImuCalibration_GetState() == ImuCal_quiet){
+			Mahony_PRINT("ImuCal_state ImuCal_error");
+			if(app_charge_Getstate() == BLE_Client_T_CHARGE_INSERT ||	app_charge_Getstate() == BLE_Client_T_CHARGE_DONE){			//若是充电,重新校准
+				ImuCalibration_SetState(ImuCal_init);
+				IMU_SetBareBoardMode(1);																																												//进入板子模式
+			}else{
+				Process_Start(100,"app_calibration_CalLed_Process",app_calibration_CalLed_Process);
+				Process_UpdatePeroid(app_calibration_CalLed_Process,100);
+				IMU_SetLowPowerMode(1);																																													//进入低功耗模式。
+			}
+		}
+	}
+	
+}
+
+void app_calibration_Init(void)
+{
+	Process_Start(1000,"app_calibration_is_BareBoard_Process",app_calibration_is_BareBoard_Process);				//是否进入板子模式
+	Process_Start(200,"app_calibration_is_Calibration_Process",app_calibration_is_Calibration_Process);			//是否进入板子校准模式
+	Process_Start(10,"app_calibration_Calibration_in_Process",app_calibration_Calibration_in_Process);			//校准处理中
+}
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 19 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_Calibration.h

@@ -0,0 +1,19 @@
+#ifndef __APP_CALIBRATION_H__
+#define __APP_CALIBRATION_H__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+
+void app_calibration_Init(void);
+
+
+#endif
+
+
+
+
+

+ 488 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_ImuCalibration.c

@@ -0,0 +1,488 @@
+#include <math.h>
+#include "stdio.h"
+#include "ble_comm.h"
+#include "hal_flash.h"
+#include "hal_imu.h"
+#include "system.h"
+#include "bsp_time.h"
+#include "app_ImuCalibration.h"
+#include "app_charge.h"
+#include "hal_ble_client.h"
+
+
+#if CALIBRATION_ENANBLE
+
+enum{
+	ImuCal_init,
+	ImuCal_GetData,
+	ImuCal_Analyze,
+	ImuCal_finish,
+	ImuCal_error,
+  ImuCal_quiet,
+};
+
+char printfbuf[256];
+void send_ANO(unsigned char fun, unsigned char* p, int len);
+#define Mahony_PRINT(...) send_ANO(0,(unsigned char*)printfbuf,sprintf(printfbuf,__VA_ARGS__))
+#define ERROR_PIN_ON nrf_gpio_pin_write(PIN_LED_RUN,0);
+#define ERROR_PIN_OFF nrf_gpio_pin_write(PIN_LED_RUN,1);
+
+static float invSampleFreq = 0.010f;                                     //采样率(Hz)
+
+//匿名四轴上位机api
+void send_ANO(unsigned char fun, unsigned char* p, int len){
+    unsigned char buf[256];
+    int L = 0;
+    unsigned char ver = 0;
+    buf[L] = 0xAA;
+    ver += buf[L++];
+    buf[L] = 0x05;
+    ver += buf[L++];
+    buf[L] = 0xAF;
+    ver += buf[L++];
+    buf[L] = fun;
+    ver += buf[L++];
+    buf[L] = len;
+    ver += buf[L++];
+    for (int i = 0; i < len; i++)
+    {
+        buf[L] = p[i];
+        ver += buf[L++];
+    }
+    buf[L++] = ver;
+    //    extern void send_bytes_client(unsigned char* bytes, int len);
+    send_bytes_client(buf, L);
+//          SEGGER_RTT_Write(0,buf, L);
+    //  ESB_SendBuff(buf,L);
+}
+
+void send_ANO_Quaternion(float* Q){
+    unsigned char buf[256];
+    unsigned char L = 0;
+    int quat[4];
+    quat[0] = Q[0] * 10000;
+    quat[1] = Q[1] * 10000;
+    quat[2] = Q[2] * 10000;
+    quat[3] = Q[3] * 10000;
+    buf[L++] = (unsigned char)(quat[0] >> 24);
+    buf[L++] = (unsigned char)(quat[0] >> 16);
+    buf[L++] = (unsigned char)(quat[0] >> 8);
+    buf[L++] = (unsigned char)(quat[0] >> 0);
+    buf[L++] = (unsigned char)(quat[1] >> 24);
+    buf[L++] = (unsigned char)(quat[1] >> 16);
+    buf[L++] = (unsigned char)(quat[1] >> 8);
+    buf[L++] = (unsigned char)(quat[1] >> 0);
+    buf[L++] = (unsigned char)(quat[2] >> 24);
+    buf[L++] = (unsigned char)(quat[2] >> 16);
+    buf[L++] = (unsigned char)(quat[2] >> 8);
+    buf[L++] = (unsigned char)(quat[2] >> 0);
+    buf[L++] = (unsigned char)(quat[3] >> 24);
+    buf[L++] = (unsigned char)(quat[3] >> 16);
+    buf[L++] = (unsigned char)(quat[3] >> 8);
+    buf[L++] = (unsigned char)(quat[3] >> 0);
+    buf[L++] = 0;
+    send_ANO(0x03, buf, L);
+}
+
+void send_ANO_STATUS(float _roll, float _pitch, float _yaw, float _posx, float _posy, float _posz){
+    unsigned char buf[256];
+    unsigned char L = 0;
+    short roll = _roll * 100;
+    short pitch = _pitch * 100;
+    short yaw = _yaw * 100;
+    short posx = _posx * 100;
+    short posy = _posy * 100;
+    short posz = _posz * 100;
+    buf[L++] = (unsigned char)(roll >> 8);
+    buf[L++] = (unsigned char)(roll >> 0);
+    buf[L++] = (unsigned char)(pitch >> 8);
+    buf[L++] = (unsigned char)(pitch >> 0);
+    buf[L++] = (unsigned char)(yaw >> 8);
+    buf[L++] = (unsigned char)(yaw >> 0);
+    buf[L++] = (unsigned char)(posx >> 8);
+    buf[L++] = (unsigned char)(posx >> 0);
+    buf[L++] = (unsigned char)(posy >> 8);
+    buf[L++] = (unsigned char)(posy >> 0);
+    buf[L++] = (unsigned char)(posz >> 8);
+    buf[L++] = (unsigned char)(posz >> 0);
+    buf[L++] = 0;
+    send_ANO(0x01, buf, L);
+}
+
+void send_ANO_SENSER(short gx, short gy, short gz, short ax, short ay, short az, short mx, short my, short mz){
+    unsigned char buf[256];
+    unsigned char L = 0;
+    buf[L++] = (unsigned char)(ax >> 8);
+    buf[L++] = (unsigned char)(ax >> 0);
+    buf[L++] = (unsigned char)(ay >> 8);
+    buf[L++] = (unsigned char)(ay >> 0);
+    buf[L++] = (unsigned char)(az >> 8);
+    buf[L++] = (unsigned char)(az >> 0);
+    buf[L++] = (unsigned char)(gx >> 8);
+    buf[L++] = (unsigned char)(gx >> 0);
+    buf[L++] = (unsigned char)(gy >> 8);
+    buf[L++] = (unsigned char)(gy >> 0);
+    buf[L++] = (unsigned char)(gz >> 8);
+    buf[L++] = (unsigned char)(gz >> 0);
+    buf[L++] = (unsigned char)(mx >> 8);
+    buf[L++] = (unsigned char)(mx >> 0);
+    buf[L++] = (unsigned char)(my >> 8);
+    buf[L++] = (unsigned char)(my >> 0);
+    buf[L++] = (unsigned char)(mz >> 8);
+    buf[L++] = (unsigned char)(mz >> 0);
+    send_ANO(0x02, buf, L);
+}
+
+//LDLT分解法解线性方程组,和LDLTBKSB_6一起用
+char LDLTDCMP_6(int n, float (*a)[6]){
+    int k;
+    int m;
+    int i;
+    for (k = 0; k < n; k++){
+        for (m = 0; m < k; m++){
+            a[k][k] = a[k][k] - a[m][k] * a[k][m];
+        }
+        if (a[k][k] == 0){
+            return 1;//error
+        }
+        for(i = k + 1; i < n; i++){
+            for (m = 0; m < k; m++){
+                a[k][i] = a[k][i] - a[m][i] * a[k][m];
+            }
+            a[i][k] = a[k][i] / a[k][k];
+        }
+    }
+    return 0;
+}
+
+//LDLT分解法解线性方程组,和LDLTDCMP_6一起用
+void LDLTBKSB_6(int n, float (*a)[6], float* b)
+{
+    int k;
+    int i;
+    for (i = 0; i < n; i++){
+        for (k = 0; k < i; k++){
+            b[i] = b[i] - a[i][k] * b[k];
+        }
+    }
+    for (i = n - 1; i >= 0; i--){
+        b[i] = b[i] / a[i][i];
+        for (k = i + 1; k < n; k++){
+            b[i] = b[i] - a[k][i] * b[k];
+        }
+    }
+}
+
+float Acc_static_calibration_b[6] = {0.0f};
+float Acc_static_calibration_D[6][6] = {0.0f};
+float Acc_static_calibration_out[6] = {1.000718f, 1.001100f, 0.988632f, 0.012943f, 0.006423f, 0.0034f}; //V1.3板
+
+void Ellipsoidfit_six_pram_update(float X, float Y, float Z, float* b, float (*D)[6]){
+    float coft[6] = {0.0f};
+    int  r, j;
+    coft[0] = X * X;
+    coft[3] = 2.0f * X;
+    coft[1] = Y * Y;
+    coft[4] = 2.0f * Y;
+    coft[2] = Z * Z;
+    coft[5] = 2.0f * Z;
+    for (j = 0; j < 6; j++){
+        b[j] += coft[j];
+    }
+    for (r = 0; r < 6; r++){
+        for (j = 0; j <= r; j++){
+            D[r][j] += coft[r] * coft[j];
+        }
+    }
+    for (r = 0; r < 6; r++){
+        for (j = 5; j > r; j--){
+            D[r][j] = D[j][r];
+        }
+    }
+}
+
+void Ellipsoidfit_six_pram_Solution(float* b, float (*D)[6], float* out)
+{
+    float temp = 0;
+    //解线性方程组,求解超定方程最小二乘解
+    LDLTDCMP_6(6, D);
+    LDLTBKSB_6(6, D, b);
+    temp = b[1] * b[2] * b[3] * b[3] + b[0] * b[2] * b[4] * b[4] + b[0] * b[1] * b[5] * b[5];
+    temp = 1.0f - (temp / (temp + (b[0] * b[1] * b[2])));
+    out[0] = sqrtf(temp * b[0]);
+    out[1] = sqrtf(temp * b[1]);
+    out[2] = sqrtf(temp * b[2]);
+    out[3] = b[3] * temp / out[0];
+    out[4] = b[4] * temp / out[1];
+    out[5] = b[5] * temp / out[2];
+}
+
+
+	static float Acc_before[3];
+	static float accmod=0,accmodbef=0;
+	static char cun=0;
+static unsigned int  timer_cli=0;
+//需要200ms执行一次,开始信号检测,检测到返回1,否则返回0
+char begin_REC(float *acccli)
+{
+
+	float gyrmod = 0;
+	gyrmod = (acccli[0]*Acc_before[0]) + (acccli[1]*Acc_before[1]) + (acccli[2]*Acc_before[2]);
+	accmod = sqrtf(acccli[0] * acccli[0] + acccli[1] * acccli[1] + acccli[2] * acccli[2]);
+	gyrmod = gyrmod/(accmod * accmodbef);
+	gyrmod = acosf(gyrmod)*3.14f;
+	Acc_before[0]=acccli[0];Acc_before[1]=acccli[1];Acc_before[2]=acccli[2];
+	accmodbef=accmod;
+	Mahony_PRINT("gyrmod:%f,timer:%d cun:%d  %f\n",gyrmod,TIME_GetTicks()-timer_cli,cun,accmodbef);
+	timer_cli=TIME_GetTicks();
+
+	if((gyrmod > 0.25f)&&(gyrmod < 0.75f))
+	{
+		cun++;
+	}else 
+	{
+//		if(cun>=3)cun--;else 
+		cun=0;		
+	}
+	if(cun>=10){
+		cun=0;
+		return 1;
+	}
+	else return 0;
+}
+
+static uint8_t ImuCal_state = ImuCal_init;
+char Acc_static_calibration(float* Acc_in, float* Acc_out, const float* gyr)
+{
+    static int temp = 0;
+    static int overtime = 0;
+    static int caiyingcun = 0;
+    switch (ImuCal_state){
+        case ImuCal_init:{//未校准状态
+					if(begin_REC(Acc_in)){
+							ImuCal_state = ImuCal_GetData;
+							caiyingcun = 0;
+							overtime = 0;
+							for (int i = 0; i < 6; i++){
+									Acc_static_calibration_b[i] = 0.0f;
+									Acc_static_calibration_D[i][0] = 0.0f;
+									Acc_static_calibration_D[i][1] = 0.0f;
+									Acc_static_calibration_D[i][2] = 0.0f;
+									Acc_static_calibration_D[i][3] = 0.0f;
+									Acc_static_calibration_D[i][4] = 0.0f;
+									Acc_static_calibration_D[i][5] = 0.0f;
+							}
+							ERROR_PIN_ON
+							Mahony_PRINT("Acc_static_calibration -> start \r\n");
+							temp = 0;
+					}
+        }
+        break;
+        case ImuCal_GetData:{//采集校准数据状态
+        
+								float gyrmod = sqrtf(gyr[0] * gyr[0] + gyr[1] * gyr[1] + gyr[2] * gyr[2]);
+								if (gyrmod < 18.27f){ //静止检测
+										//采样数据
+										if(((Acc_in[0]<2.0f)||(Acc_in[0]>-2.0f))&&((Acc_in[1]<2.0f)||(Acc_in[1]>-2.0f))&&((Acc_in[2]<2.0f)||(Acc_in[2]>-2.0f))){
+											Ellipsoidfit_six_pram_update(Acc_in[0], Acc_in[1], Acc_in[2], Acc_static_calibration_b, Acc_static_calibration_D);
+											caiyingcun++;
+											send_ANO_SENSER(gyr[0] * 100, gyr[1] * 100, gyr[2] * 100, Acc_in[0] * 100, Acc_in[1] * 100, Acc_in[2] * 100, 0, 0, 0);	
+										}
+								}
+								
+								//检测结束条件
+								if ((gyrmod > 25.0f) && (gyrmod < 60.0f) && (caiyingcun > 20)){
+										temp = temp + 1;
+								}
+								else{
+									if(temp>50)temp--;else temp = 0;									
+								}								
+								
+								if (temp * invSampleFreq > 2.0f){
+										Ellipsoidfit_six_pram_Solution(Acc_static_calibration_b, Acc_static_calibration_D, Acc_static_calibration_out);
+										ImuCal_state = ImuCal_Analyze;
+									  Mahony_PRINT("ImuCal_GetData");
+								}
+								else
+								{
+//									Mahony_PRINT("ImuCal_GetData temp %d",temp);
+								}
+								overtime++;
+								
+								if (overtime * invSampleFreq > 300.0f){
+										ImuCal_state = ImuCal_error;
+									  Mahony_PRINT("ImuCal overtime ImuCal_error");
+								}
+						}
+        break;
+        case ImuCal_Analyze:{//校准数据处理状态
+								float gyrmod = sqrtf(gyr[0] * gyr[0] + gyr[1] * gyr[1] + gyr[2] * gyr[2]);
+								if (gyrmod < 18.27f){ //静止检测
+										if (((Acc_static_calibration_out[0] > 0.85f) && (Acc_static_calibration_out[0] < 1.15f)) &&
+												((Acc_static_calibration_out[1] > 0.85f) && (Acc_static_calibration_out[1] < 1.15f)) &&
+												((Acc_static_calibration_out[2] > 0.85f) && (Acc_static_calibration_out[2] < 1.15f))){
+//													Mahony_PRINT("out[%f,%f,%f,%f,%f,%f] \r\n", Acc_static_calibration_out[0], Acc_static_calibration_out[1], Acc_static_calibration_out[2], Acc_static_calibration_out[3], Acc_static_calibration_out[4], Acc_static_calibration_out[5]);
+													Mahony_PRINT("ImuCal_state ImuCal_finish");
+													temp = 0;
+													ImuCal_state = ImuCal_finish;
+													for(int a = 0; a < 6; a++){
+									            mBackup.cal[a] = Acc_static_calibration_out[a];
+								          } 
+										}
+										else{
+												ImuCal_state = ImuCal_quiet;
+										}
+										overtime = 0;
+								}
+             }
+        break;
+//        case ImuCal_finish:{//已经校准完状态
+//					    Mahony_PRINT("ImuCal_state ImuCal_init");
+//							ImuCal_state = 0;
+//            }
+//        break;
+//        case ImuCal_error:{//校准过程中断退出状态
+//					    Mahony_PRINT("ImuCal_state ImuCal_init");
+//							ImuCal_state = 0;
+//					    Mahony_PRINT("ImuCal_state ImuCal_init");
+//            }
+//        break;
+//        case ImuCal_quiet:{//校准过程中断退出状态
+//							ImuCal_state = 0;
+//					  }
+//        break;
+    }
+    return ImuCal_state;
+}
+
+void Mahony_imu_lbs(short* Acc_in, short* Gyr_in, short* Mag_in, float* Acc, float* Gyr, float* Mag)
+{
+    float ACC_LBS = 32768.0f / 16.0f;
+    float GYR_LBS = 32768.0f / 2000.0f;
+    Acc[0] = Acc_in[0] / ACC_LBS;
+    Acc[1] = Acc_in[1] / ACC_LBS;
+    Acc[2] = Acc_in[2] / ACC_LBS;
+    Gyr[0] = Gyr_in[0] / GYR_LBS;
+    Gyr[1] = Gyr_in[1] / GYR_LBS;
+    Gyr[2] = Gyr_in[2] / GYR_LBS;
+    Mag[0] = Mag_in[0] / 1.0f;
+    Mag[1] = Mag_in[1] / 1.0f;
+    Mag[2] = Mag_in[2] / 1.0f;
+}
+
+static float acc[3], gyr[3], mag[3];
+static void ImuCalibration_pcs(short* Acc, short* Gyr, short* Mag)
+{
+    Mahony_imu_lbs(Acc, Gyr, Mag, acc, gyr, mag); //转换IMU数据量程,加速度单位转换为G,陀螺仪单位转换为度每秒,磁力计不需要转换单位,后面会做归一化处理
+    Acc_static_calibration(acc, NULL, gyr);
+}
+
+/***********************************
+ *未校准:灭灯
+ *校准中:指示灯常亮
+ *校准完成:指示灯慢闪,亮10ms,灭灯2S
+ *校准错误:指示灯快闪,亮10ms,灭灯100ms
+************************************/
+static void app_ImuCalLed_process(void){
+		nrf_gpio_pin_write(PIN_LED_RUN,0); 
+		nrf_delay_ms(10);
+		nrf_gpio_pin_write(PIN_LED_RUN,1);
+	  
+	  char printdata[200]={0};
+	  sprintf(printdata,"caldata:%f,%f,%f,%f,%f,%f",mBackup.cal[0],mBackup.cal[1],mBackup.cal[2],mBackup.cal[3],mBackup.cal[4],mBackup.cal[5]);
+	  SEGGER_RTT_printf(0,"%s\n",printdata);
+		Mahony_PRINT("caldata:%f,%f,%f,%f,%f,%f",mBackup.cal[0],mBackup.cal[1],mBackup.cal[2],mBackup.cal[3],mBackup.cal[4],mBackup.cal[5]);
+
+}
+
+uint8_t app_imucal_getstate(void){
+	 if(ImuCal_GetData == ImuCal_state || ImuCal_Analyze == ImuCal_state)return 1;
+	 else return 0;
+}
+
+static void app_cal_process(void){
+	 static uint8_t state =0;
+   static uint8_t temp =0;
+	 int16_t Acc[3]={0};
+	 int16_t Gry[3]={0};
+	 int16_t Mag[3]={0};
+	 uint8_t isGameMode =0;
+	 switch(state){
+		 case 0: 
+			    IMU_GetFrontMagAndLowPowerAcc();
+			    IMU_GetAcc(Acc);
+          IMU_GetGry(Gry);
+		      
+					 ImuCalibration_pcs((short *)Acc,(short *)Gry,(short *)Mag);
+					 if(ImuCal_state == ImuCal_GetData){
+							Process_UpdatePeroid(app_cal_process,10);
+//							Process_SetHoldOn(app_cal_process,1);
+						  nrf_gpio_pin_write(PIN_LED_RUN,0);
+							state =1;
+						  isGameMode = 1;
+	            IMU_SetGameMode(isGameMode);
+						  temp=0;
+					 } 
+					 break;
+		 case 1:
+			     if(IMU_GetGameMode()){
+						  state =2;
+					 }else{
+						  temp++;
+						  if(temp >=20)state =0;
+					 }
+			     break;
+		 case 2:
+			    IMU_GetAcc(Acc);
+          IMU_GetGry(Gry);
+				  ImuCalibration_pcs((short *)Acc,(short *)Gry,(short *)Mag);
+//		      SEGGER_RTT_printf(0,">>>>>>>22222\n");
+				  if(ImuCal_state == ImuCal_finish){
+						Flash_SaveBackup();
+						Mahony_PRINT("ImuCal_state ImuCal_finish");
+						Process_Start(2000,"app_cal_process",app_ImuCalLed_process);
+						Process_UpdatePeroid(app_ImuCalLed_process,2000);
+						
+						Process_UpdatePeroid(app_cal_process,200);
+//						Process_SetHoldOn(app_cal_process,0);
+						state =3;
+				  }
+				  else if(ImuCal_state == ImuCal_error || ImuCal_state == ImuCal_quiet){
+						Mahony_PRINT("ImuCal_state ImuCal_error");
+						Process_Start(100,"app_cal_process",app_ImuCalLed_process);
+						Process_UpdatePeroid(app_ImuCalLed_process,100);
+						
+						Process_UpdatePeroid(app_cal_process,200);
+//						Process_SetHoldOn(app_cal_process,0);
+						isGameMode = 0;
+	          IMU_SetGameMode(isGameMode);
+						state =3;
+				  }
+					break;
+		 case 3:
+			    if(!IMU_GetGameMode()){
+					    state = 4;
+				  }
+				  else if(++temp>20){ temp = 0;
+					    state = 4;
+				  }
+			    break;
+		 case 4:
+			    if(app_charge_Getstate() == BLE_Client_T_CHARGE_INSERT ||	app_charge_Getstate() == BLE_Client_T_CHARGE_DONE){
+						  state =0;
+						  ImuCal_state = ImuCal_init;
+						  Process_Stop(app_ImuCalLed_process);
+					}
+
+			    break;
+	 }
+}
+
+void app_ImuCalibration_init(void){
+	 Process_Start(200,"app_cal_process",app_cal_process);
+	 Process_SetHoldOn(app_cal_process,1);
+}
+
+#endif
+
+

+ 13 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_ImuCalibration.h

@@ -0,0 +1,13 @@
+#ifndef __app_ImuCalibration_h__
+#define __app_ImuCalibration_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void app_ImuCalibration_init(void);
+uint8_t app_imucal_getstate(void);
+
+#endif

+ 171 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_baseinfo.c

@@ -0,0 +1,171 @@
+#include "usr.h"
+#include "app_baseinfo.h"
+#include "hal_ble_client.h"
+#include "hal_ble_host.h"
+#include "bsp_time.h"
+#include "hal_led.h"
+#include "ble_gap.h"
+#include "bsp_battery.h"
+#include "drv_ms5611.h"
+
+/*************************************************/
+#define SHOES_NAME "SMART SHOE"
+#define SHOES_NAME_LEN  64
+#define HARDWARE_VERSION	0x0100
+#define SOFTWARE_VERSION	0x0100
+#define BASEINFOBUFF_LEN  80
+static uint8_t baseinfoBuff[128];
+static uint8_t basedata[16];
+
+static uint8_t isGetClientInfo = 0;
+void Host_GetClientInfo(void)
+{
+	static uint8_t buf[16];
+	buf[0] = BLE_Host_T_UPDATE_BASEINFO;
+	BLE_Host_Tx_Send(BLE_Host_T_UPDATE,buf,9,1,0,0,0);
+}
+
+void BASEINFO_HostGetClientData(void)
+{
+	static uint32_t tim=0;
+	if(TIME_GetTicks()-tim>=10000){ tim = TIME_GetTicks();
+		if(isGetClientInfo==0) Host_GetClientInfo();
+	}
+}
+
+ //>> 0xA1: 查询
+void cb_BLE_Host_R_UPDATE(void* handle)
+{
+	BLE_Host_Rx_t *target = handle;
+	uint8_t _cmd = target->pDat[0];
+	switch(_cmd){
+		case BLE_Client_R_UPDATE_BASEINFO:{
+			//>> 0(设备基本信息): 开始时间ms(8)
+			//<< 0(子命令): 设备型号(64)+左鞋蓝牙地址(6)+硬件版本(2)+软件版本(2)+左鞋蓝牙地址(6)+硬件版本(6)+软件版本(2)
+			//>> AA 06 F9 A1 00 4A
+			//<< AA 55 AA A1 00 53 4D 41 52 54 20 53 48 4F 45 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C1 EB D0 E3 87 47 01 00 01 00 00 00 00 00 00 4F
+			BLE_Client_Tx_Send(BLE_Client_T_UPDATE,baseinfoBuff,BASEINFOBUFF_LEN,1,0,0,0);
+			break;}
+		case BLE_Client_R_UPDATE_DATA:{
+			//>> 1(设备数据)
+			//<< 1(子命令): 左鞋电量(1)+左鞋温度(1)+左鞋压力(4)+右鞋电量(1)+右鞋温度(1)+右鞋压力(4)
+			//>> AA 06 F9 A1 01 4B
+			//<< AA 12 ED A1 01 00 90 12 34 56 78 00 90 12 34 56 78 93
+
+			break;}
+		case BLE_Client_R_UPDATE_STEPNUM:{//>> 2: 查询步数 + 0 + byte[8]: 更新时间ms + byte[1]:距离上一个整点的分钟数 
+								//	<< 2 + 0: 开始 + byte[8]: 开始时间ms + byte[1]: 包的数量
+								//		<< 2 + byte[1]: 包序号 + byte[4]: 每小时步数(前面两个byte为步数,后面两个byte为距离) + byte[4]: 每小时步数(前面两个byte为步数,后面两个byte为距离) + byte[4]: 每小时步数(前面两个byte为步数,后面两个byte为距离) ..
+								//			>> 2 + byte[1]: 包序号(表示收到反馈)
+								//  	<< 2 + 2: byte[4]: 每小时步数 + byte[4]: 每小时步数 + byte[4]: 每小时步数 ..
+								//			>> 2 + byte[1]: 包序号(表示收到反馈).. 包的数量 == 序号 结束流程
+			
+			break;}
+		default:break;
+	}
+}
+
+void BASEINFO_SendUpdateData(void)
+{
+	//>> 1(设备数据)
+	//<< 1(子命令): 左鞋电量(1)+左鞋温度(1)+左鞋压力(4)+右鞋电量(1)+右鞋温度(1)+右鞋压力(4)
+	//>> AA 06 F9 A1 01 4B
+	//<< AA 12 ED A1 01 00 90 12 34 56 78 00 90 12 34 56 78 93
+	uint8_t L=0;
+	int32_t temperature;
+	uint32_t press;
+	sd_temp_get(&temperature);
+	temperature = temperature>>2; 
+	press = MS5611_ReadPressure();
+	SEGGER_RTT_printf(0,"temperature=%d\n",temperature);
+	SEGGER_RTT_printf(0,"press=%d\n",press);
+	temperature = 0x90;
+	press = 0x12345678;
+	
+	//子命令
+	basedata[L++] = BLE_Client_T_UPDATE_DATA;
+	//左鞋
+	basedata[L++] = ADC_GetBatteryPersent();
+	basedata[L++] = (uint8_t)temperature;
+	basedata[L++] = (uint8_t)(press>>24);
+	basedata[L++] = (uint8_t)(press>>16);
+	basedata[L++] = (uint8_t)(press>>8);
+	basedata[L++] = (uint8_t)(press>>0);
+	//右鞋
+	basedata[L++] = ADC_GetBatteryPersent();
+	basedata[L++] = (uint8_t)temperature;
+	basedata[L++] = (uint8_t)(press>>24);
+	basedata[L++] = (uint8_t)(press>>16);
+	basedata[L++] = (uint8_t)(press>>8);
+	basedata[L++] = (uint8_t)(press>>0);
+	BLE_Client_Tx_Send(BLE_Client_T_UPDATE,basedata,L,1,0,0,0);
+}
+
+ //>> 0xA1: 查询
+void cb_BLE_Client_R_UPDATE(void* handle)
+{
+	BLE_Client_Rx_t *target = handle;
+	uint8_t _cmd = target->pDat[0];
+	switch(_cmd){
+		case BLE_Client_R_UPDATE_BASEINFO:{
+			//>> 0(设备基本信息): 开始时间ms(8)
+			//<< 0(子命令): 设备型号(64)+左鞋蓝牙地址(6)+硬件版本(2)+软件版本(2)+左鞋蓝牙地址(6)+硬件版本(6)+软件版本(2)
+			//>> AA 06 F9 A1 00 4A
+			//<< AA 55 AA A1 00 53 4D 41 52 54 20 53 48 4F 45 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C1 EB D0 E3 87 47 01 00 01 00 00 00 00 00 00 4F
+			BLE_Client_Tx_Send(BLE_Client_T_UPDATE,baseinfoBuff,BASEINFOBUFF_LEN,1,0,0,0);
+			break;}
+		case BLE_Client_R_UPDATE_DATA:{
+			//>> 1(设备数据)
+			//<< 1(子命令): 左鞋电量(1)+左鞋温度(1)+左鞋压力(4)+右鞋电量(1)+右鞋温度(1)+右鞋压力(4)
+			//>> AA 06 F9 A1 01 4B
+			//<< AA 12 ED A1 01 00 90 12 34 56 78 00 90 12 34 56 78 93
+			BASEINFO_SendUpdateData();
+			break;}
+		case BLE_Client_R_UPDATE_STEPNUM:{//>> 2: 查询步数 + 0 + byte[8]: 更新时间ms + byte[1]:距离上一个整点的分钟数 
+								//	<< 2 + 0: 开始 + byte[8]: 开始时间ms + byte[1]: 包的数量
+								//		<< 2 + byte[1]: 包序号 + byte[4]: 每小时步数(前面两个byte为步数,后面两个byte为距离) + byte[4]: 每小时步数(前面两个byte为步数,后面两个byte为距离) + byte[4]: 每小时步数(前面两个byte为步数,后面两个byte为距离) ..
+								//			>> 2 + byte[1]: 包序号(表示收到反馈)
+								//  	<< 2 + 2: byte[4]: 每小时步数 + byte[4]: 每小时步数 + byte[4]: 每小时步数 ..
+								//			>> 2 + byte[1]: 包序号(表示收到反馈).. 包的数量 == 序号 结束流程
+			
+			break;}
+		default:break;
+	}
+}
+
+void BASEINFO_Set(void)
+{ //<< 0(设备基本信息): 设备型号(64)+左鞋蓝牙地址(6)+硬件版本(2)+软件版本(2)+左鞋蓝牙地址(6)+硬件版本(6)+软件版本(2)
+	ble_gap_addr_t mAddr;
+	uint32_t err_code;
+	uint8_t L = SHOES_NAME_LEN+1;
+	memset(baseinfoBuff,0,sizeof(baseinfoBuff));
+	//子命令
+	baseinfoBuff[0] = BLE_Client_T_UPDATE_BASEINFO;
+	//设备名称
+	for(int i=0;i<sizeof(SHOES_NAME);i++){
+		baseinfoBuff[i+1] = SHOES_NAME[i];
+	}
+	//MAC 地址
+	err_code = sd_ble_gap_addr_get(&mAddr); APP_ERROR_CHECK(err_code);
+	SEGGER_RTT_printf(0,"mac addr:");for(int i=0;i<6;i++){SEGGER_RTT_printf(0,"%02X ",mAddr.addr[i]);}SEGGER_RTT_printf(0,"\n");
+	for(int i=0;i<6;i++){
+		baseinfoBuff[L++] = mAddr.addr[5-i];
+	}
+	//硬件版本
+	baseinfoBuff[L++] = (uint8_t)((uint16_t)HARDWARE_VERSION>>8);
+	baseinfoBuff[L++] = (uint8_t)((uint16_t)HARDWARE_VERSION>>0);
+	//软件版本
+	baseinfoBuff[L++] = (uint8_t)((uint16_t)SOFTWARE_VERSION>>8);
+	baseinfoBuff[L++] = (uint8_t)((uint16_t)SOFTWARE_VERSION>>0);
+}
+
+void BASEINFO_Initialize(void)
+{
+	BASEINFO_Set();
+	BLE_Client_Rx_Regist(BLE_Client_R_UPDATE,cb_BLE_Client_R_UPDATE);
+	BLE_Host_Rx_Regist(BLE_Host_R_UPDATE,cb_BLE_Host_R_UPDATE);
+	Process_Regist(BASEINFO_HostGetClientData);
+	
+}
+
+

+ 15 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_baseinfo.h

@@ -0,0 +1,15 @@
+#ifndef __app_baseinfo_h__
+#define __app_baseinfo_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void BASEINFO_Initialize(void);
+
+#endif
+
+
+

+ 211 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_charge/app_charge.c

@@ -0,0 +1,211 @@
+#include "usr_config.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_led.h"
+#include "nrf_gpio.h"
+#include "hal_ble_client.h"
+#include "hal_ble_host.h"
+#include "app_charge.h"
+#include "app_flash.h"
+#include "hal_battery.h"
+#include "hal_ble_uart0.h"
+#include "ble_comm.h"
+
+/************************ 函数声明 ***********************************/
+void app_charge_Process(void);
+void cb_BLE_Client_T_CHARGE(void* handle);
+
+/************************ 变量 ***********************************/
+static uint8_t app_charge_state = BLE_CHARGE_PULLOUT;
+
+/********************************************************/
+uint8_t app_charge_Getstate(void)
+{
+	return app_charge_state;
+}
+
+void send_charge(void)
+{
+	static uint8_t sbuf[2];
+	uint8_t L = 0;
+	if(mFlash.isHost) sbuf[L++] = 0;
+	else sbuf[L++] = 1;
+	sbuf[L++] = app_charge_state;
+	BLE_Client_Tx_Send(0,BLE_CHARGE,sbuf,L);
+}
+
+void cb_BLE_Client_R_CHARGE(void* handle)
+{
+	BLE_Client_Rx_t* target = handle;
+	send_charge();
+	BLE_Host_Tx_Send(0,BLE_CHARGE,target->pDat,target->datLen);
+}
+
+void cb_BLE_Host_R_CHARGE(void* handle)
+{
+	BLE_Host_Rx_t* target = handle;
+	BLE_Client_Tx_Send(0,BLE_CHARGE,target->pDat,target->datLen);
+	
+//	SEGGER_RTT_printf(0,"cb_BLE_Host_R_CHARGE:%d,%d,%d\n",target->pDat[0],target->pDat[1],target->datLen);
+}
+
+void cb_BLE_Client_T_CHARGE(void* handle) 
+{
+	SEGGER_RTT_printf(0,"cb_BLE_Client_T_CHARGE\n");
+}
+
+void app_charge_Vol_Send(BLE_CMD_n cmd)
+{
+	uint8_t buf[32];
+	uint8_t L = 0;
+	
+	buf[L++] = GetBatteryPersent();
+	if(mFlash.isHost)BLE_Host_Tx_Send(0,cmd,buf,L);
+	else BLE_Client_Tx_Send(0,cmd,buf,L);
+}
+
+static uint8_t OtherShoesVol = 0;
+void cb_BLE_CLient_R_CHAR_VOL(void* handle)
+{	
+	UART0_Rx_t* target = handle;
+	OtherShoesVol = target->pDat[0];
+//	SEGGER_RTT_printf(0,"OtherShoesVol=%d\n",OtherShoesVol);
+}
+
+static void app_charge_Process(void)
+{
+	uint8_t client_connect =0;
+	uint8_t host_connect =0;
+	static uint8_t ResponseFlag =0;
+	
+	app_charge_Vol_Send(BLE_CHAR_VOL); //共享充电电量
+	
+	uint32_t ch = nrf_gpio_pin_read(PIN_CHARGING);
+	
+	//进入充电状态
+	client_connect = slave_isconnect();
+	if(mFlash.isHost){
+		 host_connect = host_isconnect();
+	}
+	else{
+		 host_connect = slave_isconnect();
+	}
+	
+//		SEGGER_RTT_printf(0,"charge state:%d\n",ch);
+	if(!ch){	//没充电
+		if(app_charge_state!=BLE_CHARGE_PULLOUT){ SEGGER_RTT_printf(0,"charge out...\n");
+			app_charge_state = BLE_CHARGE_PULLOUT;
+			Process_SetHoldOn(app_charge_Process,0);
+			LED_Stop(LED_CHARGE);
+			if(client_connect){
+				ResponseFlag = 0;
+				send_charge();
+			}
+			else ResponseFlag =1;
+		}
+		return;
+	}
+	
+	if(host_connect && GetBatteryPersent()>=100 && OtherShoesVol>=100){	//充满
+		if(app_charge_state!=BLE_CHARGE_DONE){ SEGGER_RTT_printf(0,"charge done:%d...\n",OtherShoesVol);
+			app_charge_state = BLE_CHARGE_DONE;
+			Process_SetHoldOn(app_charge_Process,1);
+			LED_Start(LED_CHARGE,COLOR_GREEN);
+			send_charge();
+		}
+	}else{	//正在充电
+		if(app_charge_state!=BLE_CHARGE_INSERT){ SEGGER_RTT_printf(0,"charge in...\n");
+			app_charge_state = BLE_CHARGE_INSERT;
+			Process_SetHoldOn(app_charge_Process,1);
+			LED_Start(LED_CHARGE,COLOR_ORANGE);
+			if(client_connect){
+				send_charge();
+				ResponseFlag = 0;
+			}
+			else ResponseFlag =1;
+		}
+	}
+	if(client_connect && ResponseFlag){
+		ResponseFlag =0;
+		send_charge();
+	}
+}
+
+static void app_charge_monitor_battery_charge_data_process(void)
+{
+	#define BATTERY_VOL_THRESHOLD_MIN											2500		//2.5V
+	#define BATTERY_VOL_THRESHOLD_MAX											4000		//4V
+	#define CHARGE_VOL_THRESHOLD													80			//充电前和充电期间的充电电压变化值,单位mv
+	
+	//监测电池和充电数据
+	int16_t						bat_vol;
+	int16_t						charge_vol;
+	int16_t						charge_threshold;
+	uint32_t 					ch = nrf_gpio_pin_read(PIN_CHARGING);
+	static uint32_t 	charge_cycle = 50;
+	static int16_t		before_charge_vol;		//充电前的电压值
+	static int16_t		charge_vol_max;				//充电期间最大的电压值
+	
+	if(!ch)//没充电
+	{		
+		charge_vol = ADC_RESULT_IN_MILLI_VOLTS(ADC_GetValue(PIN_ADC_CHARGMEASURE_CHANNEL));
+		before_charge_vol = before_charge_vol > charge_vol ? charge_vol : before_charge_vol;
+		charge_vol_max = 0;
+		charge_cycle = 50;
+	}else	//充电
+	{			
+		/* 过筛50轮 */
+		if(charge_cycle != 0){
+			charge_vol = ADC_RESULT_IN_MILLI_VOLTS(ADC_GetValue(PIN_ADC_CHARGMEASURE_CHANNEL));
+			charge_vol_max = charge_vol_max < charge_vol ? charge_vol : charge_vol_max;
+			charge_cycle--;
+			return;
+		}
+		charge_vol = ADC_RESULT_IN_MILLI_VOLTS(ADC_GetValue(PIN_ADC_CHARGMEASURE_CHANNEL));
+		charge_vol_max = charge_vol_max < charge_vol ? charge_vol : charge_vol_max;		
+		bat_vol    = ADC_RESULT_IN_MILLI_VOLTS(ADC_GetValue(PIN_ADC_BAT_CHANNEL))*5/3;
+		
+		//当电池电量没满,充电(经测试,电量没满的充电电压跟电池电压有关,最小充电电压100+mv)
+		charge_threshold = 	charge_vol_max - before_charge_vol;	//充电前和充电期间的充电电压变化值
+//		DEBUG_LOG("charge_threshold:%d,%d,%d,bat:%d\n",charge_threshold,ob_monitor.charge_vol_max,ob_monitor.before_charge_vol,bat_vol);
+		if(charge_threshold < CHARGE_VOL_THRESHOLD && bat_vol < BATTERY_VOL_THRESHOLD_MAX)
+		{		
+			Except_SetExceptype(EXCEPT_DATA_CHARGE);
+			Except_TxError(EXCEPT_DATA_CHARGE,"except_charging_chip");
+		}
+		else
+		{
+			Except_ClearExceptype(EXCEPT_DATA_CHARGE);
+		}
+		
+		//电池小于2.5V或充电电压变化小于阈值且电池电压大于4V
+		if(bat_vol <= BATTERY_VOL_THRESHOLD_MIN || (charge_threshold < CHARGE_VOL_THRESHOLD && bat_vol > BATTERY_VOL_THRESHOLD_MAX))
+		{
+			Except_SetExceptype(EXCEPT_DATA_BATTERY);
+			Except_TxError(EXCEPT_DATA_BATTERY,"except_battery");
+		}
+		else
+		{
+			Except_ClearExceptype(EXCEPT_DATA_BATTERY);
+		}
+	}
+}
+
+void app_charge_Init(void)
+{
+	nrf_gpio_cfg_input(PIN_CHARGING,NRF_GPIO_PIN_NOPULL); 
+
+	if(mFlash.isHost) 
+		BLE_Host_Rx_Regist(BLE_CHAR_VOL,cb_BLE_CLient_R_CHAR_VOL);
+	else 
+		BLE_Client_Rx_Regist(BLE_CHAR_VOL,cb_BLE_CLient_R_CHAR_VOL);
+	
+	BLE_Client_Rx_Regist(BLE_CHARGE,cb_BLE_Client_R_CHARGE);
+	BLE_Host_Rx_Regist(BLE_CHARGE,cb_BLE_Host_R_CHARGE);
+	Process_Start(1000,"app_charge",app_charge_Process);
+	app_charge_Process();
+	
+	Process_Start(10,"app_charge_monitor_battery_charge_data_process",app_charge_monitor_battery_charge_data_process);
+}
+
+

+ 15 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_charge/app_charge.h

@@ -0,0 +1,15 @@
+#ifndef __app_charge_h__
+#define __app_charge_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void app_charge_Init(void);
+uint8_t app_charge_Getstate(void);
+
+#endif
+
+

+ 195 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_client.c

@@ -0,0 +1,195 @@
+#include "system.h"
+#include "app_client.h"
+#include "hal_ble_client.h"
+#include "hal_ble_host.h"
+#include "bsp_time.h"
+#include "hal_led.h"
+#include "ble_gap.h"
+#include "app_host.h"
+#include "app_flash.h"
+#include "app_client_step.h"
+#include "hal_ser_imu_mode_manage.h"
+#include "hal_battery.h"
+#include "ble_comm.h"
+
+void app_client_DataUpdate_Send(void)
+{
+	//>> 1(设备数据)
+	//<< 1(子命令): 左鞋电量(1)+左鞋温度(1)+左鞋压力(4)+左鞋步数(4)+右鞋电量(1)+右鞋温度(1)+右鞋压力(4)+右鞋步数(4)
+	uint8_t buf[32];
+	uint8_t L=0;
+	int32_t temperature;
+ 
+	sd_temp_get(&temperature);
+	temperature = temperature>>2; 
+
+	//子命令
+	buf[L++] = BLE_UPDATE_DATA;
+	//左鞋
+	buf[L++] = GetBatteryPersent();
+	buf[L++] = (uint8_t)temperature;
+  //压力数据
+  buf[L++] = 0;
+	buf[L++] = 0;
+	buf[L++] = 0;
+	buf[L++] = 0;
+	
+	buf[L++] = (uint8_t)(mFlash.mStep.stepCur[0]>>24);
+	buf[L++] = (uint8_t)(mFlash.mStep.stepCur[0]>>16);
+	buf[L++] = (uint8_t)(mFlash.mStep.stepCur[0]>>8);
+	buf[L++] = (uint8_t)(mFlash.mStep.stepCur[0]>>0);
+	//右鞋
+	buf[L++] = app_host_GetVol_R();
+	buf[L++] = app_host_GetTemp_R();
+	buf[L++] = (uint8_t)(app_host_GetPress_R()>>24);
+	buf[L++] = (uint8_t)(app_host_GetPress_R()>>16);
+	buf[L++] = (uint8_t)(app_host_GetPress_R()>>8);
+	buf[L++] = (uint8_t)(app_host_GetPress_R()>>0);
+	buf[L++] = (uint8_t)(mFlash.mStep.stepCur[1]>>24);
+	buf[L++] = (uint8_t)(mFlash.mStep.stepCur[1]>>16);
+	buf[L++] = (uint8_t)(mFlash.mStep.stepCur[1]>>8);
+	buf[L++] = (uint8_t)(mFlash.mStep.stepCur[1]>>0);
+	
+	BLE_Client_Tx_Send(0,BLE_UPDATE,buf,L);
+}
+
+void app_client_infomation_Send_defineName(uint8_t name[],uint8_t lenth)
+{
+	//<< 0(设备基本信息): 设备型号(64)+左鞋蓝牙地址(6)+硬件版本(2)+软件版本(2)+左鞋蓝牙地址(6)+硬件版本(6)+软件版本(2)
+	ble_gap_addr_t mAddr;
+	uint32_t err_code;
+	uint8_t buf[128];
+	uint8_t L = SHOES_NAME_LEN+1;
+	
+	memset(buf,0,sizeof(buf));
+	//子命令
+	buf[0] = BLE_UPDATE_BASEINFO;
+	//设备名称
+	for(int i=0;i<lenth;i++){
+		buf[i+1] = name[i];
+	}
+	//MAC 地址
+	err_code = sd_ble_gap_addr_get(&mAddr); APP_ERROR_CHECK(err_code);
+	//SEGGER_RTT_printf(0,"mac addr:");for(int i=0;i<6;i++){SEGGER_RTT_printf(0,"%02X ",mAddr.addr[i]);}SEGGER_RTT_printf(0,"\n");
+	for(int i=0;i<6;i++){
+		buf[L++] = mAddr.addr[5-i];
+	} 
+	//硬件版本
+	buf[L++] = (uint8_t)((uint32_t)HARDWARE_VERSION>>24);
+	buf[L++] = (uint8_t)((uint32_t)HARDWARE_VERSION>>16);
+	buf[L++] = (uint8_t)((uint32_t)HARDWARE_VERSION>>8);
+	buf[L++] = (uint8_t)((uint32_t)HARDWARE_VERSION>>0);
+	//软件版本
+	buf[L++] = SOFTWARE_VERSION;
+	
+	//右鞋mac地址
+	for(int i=0;i<6;i++) buf[L++] = mFlash.mClient.macAddr[i];
+	
+	//右鞋硬件版本
+	buf[L++] = (uint8_t)((uint32_t)mFlash.mClient.hardVersion>>24);
+	buf[L++] = (uint8_t)((uint32_t)mFlash.mClient.hardVersion>>16);
+	buf[L++] = (uint8_t)((uint32_t)mFlash.mClient.hardVersion>>8);
+	buf[L++] = (uint8_t)((uint32_t)mFlash.mClient.hardVersion>>0);
+	//右鞋软件版本
+	buf[L++] =  mFlash.mClient.sotfVersion;
+	
+	BLE_Client_Tx_Send(0,BLE_UPDATE,buf,L);
+}
+
+void app_client_infomation_Send(void)
+{
+	//<< 0(设备基本信息): 设备型号(64)+左鞋蓝牙地址(6)+硬件版本(2)+软件版本(2)+左鞋蓝牙地址(6)+硬件版本(6)+软件版本(2)
+	ble_gap_addr_t mAddr;
+	uint32_t err_code;
+	uint8_t buf[128];
+	uint8_t L = SHOES_NAME_LEN+1;
+	
+	memset(buf,0,sizeof(buf));
+	//子命令
+	buf[0] = BLE_UPDATE_BASEINFO;
+	//设备名称
+	for(int i=0;i<sizeof(SHOES_NAME);i++){
+		buf[i+1] = SHOES_NAME[i];
+	}
+	//MAC 地址
+	err_code = sd_ble_gap_addr_get(&mAddr); APP_ERROR_CHECK(err_code);
+//	SEGGER_RTT_printf(0,"mac addr:");for(int i=0;i<6;i++){SEGGER_RTT_printf(0,"%02X ",mAddr.addr[i]);}SEGGER_RTT_printf(0,"\n");
+	for(int i=0;i<6;i++){
+		buf[L++] = mAddr.addr[5-i];
+	}
+	//硬件版本
+	buf[L++] = (uint8_t)((uint32_t)HARDWARE_VERSION>>24);
+	buf[L++] = (uint8_t)((uint32_t)HARDWARE_VERSION>>16);
+	buf[L++] = (uint8_t)((uint32_t)HARDWARE_VERSION>>8);
+	buf[L++] = (uint8_t)((uint32_t)HARDWARE_VERSION>>0);
+	//软件版本
+	buf[L++] = SOFTWARE_VERSION;
+	
+	//右鞋mac地址
+	for(int i=0;i<6;i++) buf[L++] = mFlash.mClient.macAddr[i];
+//	SEGGER_RTT_printf(0,"mac addr:");for(int i=0;i<6;i++){SEGGER_RTT_printf(0,"%02X ",mFlash.mClient.macAddr[i]);}SEGGER_RTT_printf(0,"\n");
+	//右鞋硬件版本
+	buf[L++] = (uint8_t)((uint32_t)mFlash.mClient.hardVersion>>24);
+	buf[L++] = (uint8_t)((uint32_t)mFlash.mClient.hardVersion>>16);
+	buf[L++] = (uint8_t)((uint32_t)mFlash.mClient.hardVersion>>8);
+	buf[L++] = (uint8_t)((uint32_t)mFlash.mClient.hardVersion>>0);
+	//右鞋软件版本
+	buf[L++] = mFlash.mClient.sotfVersion;
+	
+	BLE_Client_Tx_Send(0,BLE_UPDATE,buf,L);
+}
+
+//>> 0xA1: 查询
+void cb_BLE_Client_R_UPDATE(void* handle)
+{
+	BLE_Client_Rx_t *target = handle;
+	uint8_t _cmd = target->pDat[0];
+	switch(_cmd){
+		case BLE_UPDATE_BASEINFO:{
+			//>> 0(设备基本信息): 开始时间ms(8)
+			//<< 0(子命令): 设备型号(64)+左鞋蓝牙地址(6)+硬件版本(2)+软件版本(2)+右鞋蓝牙地址(6)+硬件版本(6)+软件版本(2)
+			//>> AA 06 F9 A1 00 4A
+			//<< AA 55 AA A1 00 53 4D 41 52 54 20 53 48 4F 45 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C1 EB D0 E3 87 47 01 00 01 00 00 00 00 00 00 4F
+			app_client_infomation_Send();
+			SEGGER_RTT_printf(0,"!!!!!!!!!!!!!!!=======>app_client_infomation_Send\n");
+			break;}
+		case BLE_UPDATE_DATA:{
+			//>> 1(设备数据)
+			//<< 1(子命令): 左鞋电量(1)+左鞋温度(1)+左鞋压力(4)+左鞋步数(4)+右鞋电量(1)+右鞋温度(1)+右鞋压力(4)+右鞋步数(4)
+				app_host_GetClientData(20);
+			break;}
+		case BLE_UPDATE_STEPNUM:{
+			//>> 2(查询步数): 包序号[0全部](2)
+			//<< 2(查询步数): +开始时间ms(8)+包的数量(2)+包序号(2)+每小时步数(4)+...
+			if(-1 == hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_REALSTEP))app_client_SendStep(target);
+			break;}
+		case BLE_UPDATE_STEPNUM_CLERA:{
+			//>> 3(删除步数): 开始时间ms(8)+距离上一个整点的分钟数(1)
+			//<< 3(删除步数): 开始时间ms(8)+距离上一个整点的分钟数(1)
+			BLE_Client_Tx_Send(0,BLE_UPDATE,target->pDat,target->datLen);
+			app_client_DeleteStep(target);
+			break;}
+		default:break;
+	}
+}
+
+static void app_client_Process(void)
+{
+	static uint8_t cnt =0;
+	if(slave_isconnect()){//右鞋连接上左鞋
+		if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_GAME) != -1){
+			 if(cnt++ >= 4){
+				  cnt =0;
+				  app_client_DataUpdate_Send();;
+			 }
+		}
+		else app_client_DataUpdate_Send();
+	}
+}
+
+void app_client_Initialize(void)
+{
+	BLE_Client_Rx_Regist(BLE_UPDATE,cb_BLE_Client_R_UPDATE);
+	app_client_step_Initialize();
+	if(0 == mFlash.isHost)Process_Start(2000,"app_client",app_client_Process);
+}

+ 17 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_client.h

@@ -0,0 +1,17 @@
+#ifndef __app_client_h__
+#define __app_client_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void app_client_Initialize(void);
+void app_client_DataUpdate_Send(void);
+void app_client_infomation_Send(void);
+
+#endif
+
+
+

+ 168 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_client_step.c

@@ -0,0 +1,168 @@
+#include "system.h"
+#include "app_client_step.h"
+#include "app_flash.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "app_host.h"
+#include "app_step.h"
+#include "ble_comm.h"
+#include "app_flash.h"
+
+
+/************************ 函数定义 ***************************/
+void cb_BLE_Client_T_UPDATE_STEPNUM(void* handle);
+
+/************************ 获取步数 ***************************/
+
+static uint8_t isScan = 0;
+
+uint8_t app_client_step_GetIsScan(void)
+{
+	return isScan;
+}
+
+void app_client_step_SetIsScan(void)
+{
+	isScan =1;
+}
+
+//一小时保存一次步数
+static void app_client_step_Process(void)
+{
+  static uint8_t state =0;
+	static uint32_t tim =0;
+	switch(state){
+		case 0:
+			    if(1 == isScan){
+						state =1;
+						tim = TIME_GetTicks();
+					}
+			    break;
+	  case 1:
+			    if(TIME_GetTicks() - tim >= 10000)state =2;
+				  else app_host_GetClientData(1);
+					break;
+		case 2:
+			    if(Flash_SaveInfomation() != ZONE_OP_SUCCESS)Except_TxError(EXCEPT_DATEStep,"save information fail");
+		      if(Flash_SaveStep() != ZONE_OP_SUCCESS)Except_TxError(EXCEPT_DATEStep,"save step fail");
+		      isScan = 0;
+		      state =0;
+//		      SEGGER_RTT_printf(0,"Flash_SaveInfomation:%d,mFlash.mStep.stepCur[1]:%d\r\n",TIME_GetTicks(),mFlash.mStep.stepCur[1]);
+			    break;
+		default:
+			    state =0;
+			    break;
+	}
+}
+
+
+
+/************************ 删除步数 ***************************/
+void app_client_DeleteStep(BLE_Client_Rx_t* target)
+{
+	for(uint8_t i=0;i<8;i++) mFlash.mStep.startTime[i] = target->pDat[i+1];
+	if(Flash_DeleteAllStep() != ZONE_OP_SUCCESS)Except_TxError(EXCEPT_DATEStep,"clear step fail");
+}
+
+/************************ 发送步数 ***************************/
+#define PACK_STEP_LEN 40		//发送 PACK_STEP_LEN*4 个字节
+
+static uint8_t isSendAll = 0;
+static uint16_t packDex = 0;
+static uint16_t packNum = 0;
+static uint16_t lastNum = 0;
+
+BLE_Client_Tx_t mSendStep = {
+	.n = 1,
+	.t = 1,
+	.cb = cb_BLE_Client_T_UPDATE_STEPNUM,
+};
+
+void app_client_SendStepAll(uint16_t n)
+{
+	static uint8_t buf[250];
+	uint8_t L=0;
+	
+	uint32_t addr = (Flash_GetStepZoneStartAddr()+PACK_STEP_LEN*4*(n-1));
+	buf[L++] = BLE_UPDATE_STEPNUM;
+	for(int i=0;i<8;i++){buf[L++] = mFlash.mStep.startTime[i];}
+	buf[L++] = (uint8_t)(packNum>>8);
+	buf[L++] = (uint8_t)(packNum>>0);
+	buf[L++] = (uint8_t)(n>>8);
+	buf[L++] = (uint8_t)(n>>0);
+	if(n==0){
+		uint32_t step = app_step_GetStep_L() + app_step_GetStep_R();
+		SEGGER_RTT_printf(0,"====>step=%d,app_step_GetStep_L()=%d,app_step_GetStep_R()=%d\n",step,app_step_GetStep_L(),app_step_GetStep_R());
+		buf[L++] = (uint8_t)(step>>24);
+		buf[L++] = (uint8_t)(step>>16);
+		buf[L++] = (uint8_t)(step>>8);
+		buf[L++] = (uint8_t)(step>>0);
+	}else if(n==packNum){
+		Zone_Read(addr,(uint32_t*)&buf[L],lastNum*4); L+=lastNum*4;
+	}else{
+		Zone_Read(addr,(uint32_t*)&buf[L],PACK_STEP_LEN*4); L+=PACK_STEP_LEN*4;
+	}
+	SEGGER_RTT_printf(0,"====>lastNum=%d,PACK_STEP_LEN=%d\n",lastNum,PACK_STEP_LEN);
+	SEGGER_RTT_printf(0,"app_client_SendStepAll:"); for(int i=0;i<L;i++){SEGGER_RTT_printf(0,"%02X ",buf[i]);} SEGGER_RTT_printf(0,"\r\n");
+	BLE_Client_Tx_Send(&mSendStep,BLE_UPDATE,buf,L);
+}
+
+void app_client_SendStepN(uint16_t n)
+{
+	uint8_t buf[250];
+	uint8_t L=0;
+	
+	uint32_t addr = (Flash_GetStepZoneStartAddr()+PACK_STEP_LEN*4*(n-1));
+	buf[L++] = BLE_UPDATE_STEPNUM;
+	for(int i=0;i<8;i++){buf[L++] = mFlash.mStep.startTime[i];}
+	
+	buf[L++] = (uint8_t)(packNum>>8);
+	buf[L++] = (uint8_t)(packNum>>0);
+	buf[L++] = (uint8_t)(n>>8);
+	buf[L++] = (uint8_t)(n>>0);
+	if(n==packNum){
+		Zone_Read(addr,(uint32_t*)&buf[L],lastNum*4); L+=lastNum*4;
+	}else{
+		Zone_Read(addr,(uint32_t*)&buf[L],PACK_STEP_LEN*4); L+=PACK_STEP_LEN*4;
+	}
+	SEGGER_RTT_printf(0,"app_client_SendStepN:"); for(int i=0;i<L;i++){SEGGER_RTT_printf(0,"%02X ",buf[i]);} SEGGER_RTT_printf(0,"\r\n");
+	BLE_Client_Tx_Send(0,BLE_UPDATE,buf,L);
+}
+
+void app_client_SendStep(BLE_Client_Rx_t* target)
+{
+	uint16_t n = ((uint16_t)target->pDat[1]<<8)|((uint16_t)target->pDat[2]<<0);
+	
+	if(mFlash.mStep.num>0){
+		packNum = ((mFlash.mStep.num-1)/PACK_STEP_LEN)+1;
+		lastNum = ((mFlash.mStep.num-1)%PACK_STEP_LEN)+1;
+	}else{
+		packNum = 0;
+		lastNum = 0;
+	}
+	
+//	SEGGER_RTT_printf(0,"====>mFlash.mStep.num=%d,packNum=%d,lastNum=%d\n",mFlash.mStep.num,packNum,lastNum);
+	
+	if(n==0){
+		isSendAll = 1;
+		packDex = 0;
+		app_client_SendStepAll(packDex);
+	}else{
+		app_client_SendStepN(n);
+	}
+}
+
+static void cb_BLE_Client_T_UPDATE_STEPNUM(void* handle)
+{
+	if(isSendAll==0) return;
+	if(packDex<packNum){
+		if(++packDex>=packNum) isSendAll = 0;
+		app_client_SendStepAll(packDex);
+	}
+}
+
+/************************ 初始化 ***************************/
+void app_client_step_Initialize(void)
+{
+	Process_Start(1000,"app_client_step",app_client_step_Process);
+}

+ 20 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_client_step.h

@@ -0,0 +1,20 @@
+#ifndef __app_client_step_h__
+#define __app_client_step_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+#include "hal_ble_client.h"
+
+void app_client_step_Initialize(void);
+void app_client_SendStep(BLE_Client_Rx_t* target);
+void app_client_DeleteStep(BLE_Client_Rx_t* target);
+uint8_t app_client_step_GetIsScan(void);
+void app_client_step_SetIsScan(void);
+
+#endif
+
+
+

+ 208 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_config.c

@@ -0,0 +1,208 @@
+#include "app_config.h"
+#include "nrf_gpio.h"
+#include "usr_config.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_mt.h"
+#include "hal_battery.h"
+#include "app_charge.h"
+#include "hal_ble_client.h"
+#include "hal_led.h"
+#include "hal_flash.h"
+#include "ble_gap.h"
+#include "hal_ble_uart0.h"
+#include "ble_comm.h"
+
+static ble_gap_addr_t mAddr;
+static uint8_t isConfig = 0;
+
+void UART0_Config_Send(uint8_t cmd)
+{
+	uint8_t buf[32];
+	uint8_t L = 0;
+	//MAC 地址
+	for(int i=0;i<6;i++){
+		buf[L++] = mAddr.addr[5-i];
+	}
+	//硬件版本
+	buf[L++] = (uint8_t)((uint16_t)HARDWARE_VERSION>>8);
+	buf[L++] = (uint8_t)((uint16_t)HARDWARE_VERSION>>0);
+	//软件版本
+	buf[L++] = (uint8_t)((uint16_t)SOFTWARE_VERSION>>8);
+	buf[L++] = (uint8_t)((uint16_t)SOFTWARE_VERSION>>0);
+	UART0_Tx_Send(0,cmd,buf,L);
+}
+
+void app_config_Process(void)
+{
+	static uint8_t flag = 0;
+	if(app_charge_Getstate()!=BLE_Client_T_CHARGE_PULLOUT){
+		if(flag != 1)
+		{
+//			UART0_Initialize();
+			flag = 1;
+		}
+		else if(isConfig<50){ isConfig++;
+			if(mFlash.isHost){ //充电模式下主机主机申请配对
+//				UART0_Config_Send(UART0_T_CONFIG_ASK);
+			}
+		}
+	}else{
+		if(flag != 2)
+		{
+//			UART0_unInit();
+			flag = 2;
+		}
+		else if(isConfig>0) isConfig = 0;
+	}
+}
+
+void app_config_LED(void)
+{
+	static uint8_t state = 0;
+	switch(state){
+		case 0:
+			Process_SetHoldOn(app_config_LED,1);
+			LED_SetColor(LED_CONFIG,COLOR_BLUE);
+			LED_Start(LED_CONFIG);
+			state = 1;
+			Process_UpdatePeroid(app_config_LED,2000);
+			break;
+		case 1:
+			Process_UpdatePeroid(app_config_LED,0);
+			LED_Stop(LED_CONFIG);
+			state = 0;
+			Process_SetHoldOn(app_config_LED,0);
+			Process_Stop(app_config_LED);
+			break;
+		default:state=0;Process_UpdatePeroid(app_config_LED,0);break;
+	}
+	
+}
+
+void cb_UART0_R_CONFIG_ASK(void* handle)
+{	//从机接收到配对申请
+	UART0_Rx_t* target = handle;
+	uint8_t mac[6];
+	char buf[16];
+	uint8_t ret = 0;
+	
+	if(app_charge_Getstate()==BLE_Client_T_CHARGE_PULLOUT) return; //非充电模式不匹配
+	if(mFlash.isHost) return; //主机自发自收
+	
+	for(int i=0;i<6;i++) mac[i] = target->pDat[i];
+	uint16_t hv = ((uint16_t)target->pDat[6]<<8)| ((uint16_t)target->pDat[7]<<0);
+	uint16_t sv = ((uint16_t)target->pDat[8]<<8)| ((uint16_t)target->pDat[9]<<0);
+
+	if(slave_isconnect()) slave_disconnect();
+	else advertising_stop();
+	
+	UART0_Config_Send(UART0_T_CONFIG_ACK);//应答主机申请
+	
+	mFlash.mClient.isConfig = 'C';
+	if(mBackup.isConfig != mFlash.mClient.isConfig)ret = 1;
+	for(int i=0;i<6;i++){
+		mFlash.mClient.macAddr[i] = mAddr.addr[5-i];	//从机自身mac地址
+		mFlash.macHost[i] = mac[i];						//主机发过来的mac地址
+		if(mBackup.macAddr_L[i]!=mFlash.macHost[i]) ret = 1;
+		if(mBackup.macAddr_R[i]!=mFlash.mClient.macAddr[i]) ret = 1;
+	}
+	mFlash.mClient.hardVersion = hv;
+	mFlash.mClient.sotfVersion = sv;
+	if(	mBackup.hardVersion != mFlash.mClient.hardVersion) ret = 1;
+	if( mBackup.sotfVersion != mFlash.mClient.sotfVersion) ret = 1;
+	SEGGER_RTT_printf(0,"mFlash.mClient.hardVersion:%X\n",mFlash.mClient.hardVersion);
+	SEGGER_RTT_printf(0,"mFlash.mClient.sotfVersion:%X\n",mFlash.mClient.sotfVersion);
+	SEGGER_RTT_printf(0,"mFlash.mClient.macAddr:%02X %02X %02X %02X %02X %02X\n",mFlash.mClient.macAddr[0],mFlash.mClient.macAddr[1],mFlash.mClient.macAddr[2],mFlash.mClient.macAddr[3],mFlash.mClient.macAddr[4],mFlash.mClient.macAddr[5]);
+	SEGGER_RTT_printf(0,"mFlash.macHost:%02X %02X %02X %02X %02X %02X\n",mFlash.macHost[0],mFlash.macHost[1],mFlash.macHost[2],mFlash.macHost[3],mFlash.macHost[4],mFlash.macHost[5]);
+	Process_Start(0,"config_LED",app_config_LED);
+	
+	memset(buf,0,16);
+	sprintf(buf,"%02X%02X%02X%02X%02X%02X",mFlash.macHost[0],mFlash.macHost[1],mFlash.macHost[2],mFlash.mClient.macAddr[3],mFlash.mClient.macAddr[4],mFlash.mClient.macAddr[5]);
+	SEGGER_RTT_printf(0,"advName(%d):%s\n",strlen(buf),buf);
+	slave_set_adv_name(buf,strlen(buf));
+	slave_adv_init();
+	if(ret >=1){
+		
+		for(int i=0;i<6;i++){
+				mBackup.macAddr_L[i] = mFlash.macHost[i];		     //主机地址
+				mBackup.macAddr_R[i] = mFlash.mClient.macAddr[i];//从机地址	
+		}
+		mBackup.hardVersion = mFlash.mClient.hardVersion;
+		mBackup.sotfVersion = mFlash.mClient.sotfVersion;
+		mBackup.isConfig = mFlash.mClient.isConfig;
+		//SEGGER_RTT_printf(0,"AAAAAbackup config:%d,hardVersion:%d,sotfVersion:%d\n",mBackup.isConfig,mBackup.hardVersion,mBackup.sotfVersion);
+		Flash_SaveInfomation();
+		Flash_SaveBackup();
+	}
+	
+	while(slave_isconnect());
+	advertising_start();
+//	nrf_gpio_cfg_output(PIN_LED_RUN); 	
+//	nrf_gpio_pin_write(PIN_LED_RUN,0);
+	
+}
+
+void cb_UART0_R_CONFIG_ACK(void* handle)
+{	//主机接收到配对应答
+	UART0_Rx_t* target = handle;
+	uint8_t mac[6];
+	char buf[16];
+	uint8_t ret = 0;
+	
+	if(app_charge_Getstate()==BLE_Client_T_CHARGE_PULLOUT) return; //非充电模式不匹配
+	if(!mFlash.isHost) return; //从机自发自收
+	
+	for(int i=0;i<6;i++) mac[i] = target->pDat[i];
+	uint16_t hv = ((uint16_t)target->pDat[6]<<8)| ((uint16_t)target->pDat[7]<<0);
+	uint16_t sv = ((uint16_t)target->pDat[8]<<8)| ((uint16_t)target->pDat[9]<<0);
+	
+	isConfig = 100;	//已配对,停止配对发送
+	
+	mFlash.mClient.isConfig = 'C';
+	if(mBackup.isConfig != mFlash.mClient.isConfig)ret = 1;
+	for(int i=0;i<6;i++){
+		mFlash.mClient.macAddr[i] = mac[i]; 	//收到的从机mac地址
+		mFlash.macHost[i] = mAddr.addr[5-i];	//主机本身mac地址
+		if(mBackup.macAddr_L[i]!=mFlash.macHost[i]) ret = 1;
+		if(mBackup.macAddr_R[i]!=mFlash.mClient.macAddr[i]) ret = 1;
+	}
+	mFlash.mClient.hardVersion = hv;
+	mFlash.mClient.sotfVersion = sv;
+	if(	mBackup.hardVersion != mFlash.mClient.hardVersion) ret = 1;
+	if( mBackup.sotfVersion != mFlash.mClient.sotfVersion) ret = 1;
+	SEGGER_RTT_printf(0,"mFlash.mClient.hardVersion:%X\n",mFlash.mClient.hardVersion);
+	SEGGER_RTT_printf(0,"mFlash.mClient.sotfVersion:%X\n",mFlash.mClient.sotfVersion);
+	SEGGER_RTT_printf(0,"mFlash.mClient.macAddr:%02X %02X %02X %02X %02X %02X\n",mFlash.mClient.macAddr[0],mFlash.mClient.macAddr[1],mFlash.mClient.macAddr[2],mFlash.mClient.macAddr[3],mFlash.mClient.macAddr[4],mFlash.mClient.macAddr[5]);
+	SEGGER_RTT_printf(0,"mFlash.macHost:%02X %02X %02X %02X %02X %02X\n",mFlash.macHost[0],mFlash.macHost[1],mFlash.macHost[2],mFlash.macHost[3],mFlash.macHost[4],mFlash.macHost[5]);
+	Process_Start(0,"config_LED",app_config_LED);
+	
+	memset(buf,0,16);
+	sprintf(buf,"%02X%02X%02X%02X%02X%02X",mFlash.macHost[0],mFlash.macHost[1],mFlash.macHost[2],mFlash.mClient.macAddr[3],mFlash.mClient.macAddr[4],mFlash.mClient.macAddr[5]);
+	SEGGER_RTT_printf(0,"scanName(%d):%s\n",strlen(buf),buf);
+	host_set_scan_name(buf,strlen(buf));
+	
+	if(ret >=1){
+		for(int i=0;i<6;i++){
+			mBackup.macAddr_L[i] = mFlash.macHost[i];		//主机地址
+			mBackup.macAddr_R[i] = mFlash.mClient.macAddr[i];//从机地址
+		}
+		mBackup.hardVersion = mFlash.mClient.hardVersion;
+		mBackup.sotfVersion = mFlash.mClient.sotfVersion;
+		mBackup.isConfig = mFlash.mClient.isConfig;
+		//SEGGER_RTT_printf(0,"AAAAAbackup config:%d,hardVersion:%d,sotfVersion:%d\n",mBackup.isConfig,mBackup.hardVersion,mBackup.sotfVersion);
+		Flash_SaveInfomation();
+		Flash_SaveBackup();
+	}
+	//nrf_gpio_cfg_output(PIN_LED_RUN); 	nrf_gpio_pin_write(PIN_LED_RUN,0);
+}
+
+void app_config_Init(void)
+{
+	uint32_t err_code = sd_ble_gap_addr_get(&mAddr); APP_ERROR_CHECK(err_code);
+	Process_Start(100,"app_config",app_config_Process);
+	UART0_Rx_Regist(UART0_R_CONFIG_ASK,cb_UART0_R_CONFIG_ASK);
+	UART0_Rx_Regist(UART0_R_CONFIG_ACK,cb_UART0_R_CONFIG_ACK);
+}
+
+

+ 12 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_config.h

@@ -0,0 +1,12 @@
+#ifndef __app_config_h__
+#define __app_config_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void app_config_Init(void);
+
+#endif

+ 215 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_connect_manage.c

@@ -0,0 +1,215 @@
+#include "app_connect_manage.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "ble_comm.h"
+#include "app_flash.h"
+#include "app_charge.h"
+#include "app_ota.h"
+#include "exception.h"
+#include "hal_ble_client.h"
+#include "hal_ble_host.h"
+#include "hal_led.h"
+#include "app_self_checking.h"
+#include "hal_ser_imu_mode_manage.h"
+#include "exception.h"
+#include "hal_mt.h"
+#include "hal_battery.h"
+
+/********************** 变量区 *************************/
+#define Ble_update_connted_Error 60//一次最多更新蓝牙连接间隔 次数
+
+enum{
+	shoes_
+};
+
+/********************** 函数声明区 *************************/
+extern uint8_t app_client_step_GetIsScan(void);
+
+BLE_Client_Tx_t mBLE_Client_T_CONNET_R = {
+	.n = 10,
+	.t = 500,
+	.cb = 0,
+};
+
+static uint16_t LedPlaytime =0;
+static uint32_t LedBlinktim =0;
+
+static void cb_BLE_BLINK_LED(void* handle)
+{	
+	BLE_Client_Rx_t* target = handle;
+	uint8_t buf[2]={0x0};
+
+	buf[0] = target->pDat[0];
+	buf[1] = target->pDat[1];
+	
+  LedPlaytime = ((target->pDat[0]<<8) + target->pDat[1]);
+	SEGGER_RTT_printf(0,"=======>cb_BLE_BLINK_LED,displaytime:%d\n",LedPlaytime);
+	BLE_Host_Tx_Send(0,BLE_BLINK_LED,buf,2); 
+	LedBlinktim = TIME_GetTicks();
+	if(GetBatteryPersent()>20){
+			LED_Start(LED_OVERTURN,COLOR_GREEN);
+	}else{
+			LED_Start(LED_OVERTURN,COLOR_ORANGE);
+	}
+}
+
+static uint8_t app_conneted_getRight(void){
+	uint8_t state =BLE_RIGHT_DISCONNTED;
+	if('C' != mFlash.mClient.isConfig)
+		 state =BLE_RIGHT_NOCONFIG;
+	else if(host_isconnect())
+		 state =BLE_RIGHT_CONNTED;
+	return state;
+}
+
+void app_connect_LED_Process(void)
+{
+	static uint8_t ResportCs_Flag = 0;
+	static uint8_t state =0;
+	static uint8_t host_state=0;
+	switch(state){
+		case 0:
+			    if(slave_isconnect()){
+						state =1;
+						ResportCs_Flag = 0;
+					}
+			    break;
+		case 1:
+			    if(host_isconnect()){ 
+							if(0 == ResportCs_Flag){			
+								ResportCs_Flag = 1;
+								host_state = app_conneted_getRight();
+								BLE_Client_Tx_Send(&mBLE_Client_T_CONNET_R,BLE_CONNET_R,&host_state,1);
+								SEGGER_RTT_printf(0,"====================>BLE_Host_T_CONNET_LED:%d\n",TIME_GetTicks());
+							}
+					}
+					else if(ResportCs_Flag > 0)	{
+						ResportCs_Flag = 0;
+						BLE_Client_Tx_Clear(&mBLE_Client_T_CONNET_R);
+					}
+					
+					if(LedPlaytime !=0){
+						 if(TIME_GetTicks() - LedBlinktim >=LedPlaytime){
+							 LedPlaytime =0;
+							 LED_Stop(LED_OVERTURN);
+						 }
+					}
+					if(!slave_isconnect()){
+						state =0;
+						BLE_Client_Tx_Clear(&mBLE_Client_T_CONNET_R);
+					}
+			    break;
+		default:
+			    break;
+	}
+}
+
+void cb_Slave_Connect(void)
+{
+	SEGGER_RTT_printf(0,"=======>cb_Slave_Connect\n");
+	if(mFlash.isHost) slave_update_conn_interval_request(30,30);
+}
+
+void cb_Host_Connect(void)
+{
+	SEGGER_RTT_printf(0,"=======>cb_Host_Connect\n");
+}
+
+void app_connect_Process(void)
+{
+	static uint8_t state = 0;
+	static uint32_t cnt = 0;
+	static uint16_t  update_temp = 0;
+	static uint8_t ble_con_int = 0;//左右鞋蓝牙之间的连接间隔
+	
+		switch(state){
+			case 0:{
+				if((app_client_step_GetIsScan()||slave_isconnect()||(app_charge_Getstate()!=BLE_CHARGE_PULLOUT)) && 0 == app_ota_host_state()){
+					SEGGER_RTT_printf(0,"=======>scan_start\n");
+					Process_SetHoldOn(app_connect_Process,1);
+					scan_start();
+					cnt = 0;
+					state = 1;
+				}
+				break;}
+			case 1:{
+				if(app_client_step_GetIsScan()==0&&slave_isconnect()==0&&(app_charge_Getstate()==BLE_CHARGE_PULLOUT)){
+					Except_TxError(EXCEPT_DFU,"adv disconnted over time");
+					SEGGER_RTT_printf(0,"=======>nrf_ble_scan_stop\n");
+					nrf_ble_scan_stop();
+					Process_SetHoldOn(app_connect_Process,0);
+					state = 0;
+				}else if(host_isconnect()){
+					SEGGER_RTT_printf(0,"=======>host_isconnect\n");
+					Process_SetHoldOn(app_connect_Process,0);
+					if(mFlash.isHost){
+						update_temp =0;
+						ble_con_int = 0;
+					}
+					state =2;
+				}
+				if(++cnt>=100){ if(0 == app_client_step_GetIsScan() && 'C' == mFlash.mClient.isConfig)Except_TxError(EXCEPT_CONNET,"scan right shoes over time");
+					SEGGER_RTT_printf(0,"=======>app_err_Set nrf_ble_scan_stop\n");
+					nrf_ble_scan_stop();
+					Process_SetHoldOn(app_connect_Process,0);
+					state = 0;
+				}
+				break;}
+			case 2:{
+				if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_GAME) != -1){//游戏模式下更新连接间隔
+						if(ble_con_int !=2 && update_temp <= Ble_update_connted_Error){
+							if(APP_SUCCESS ==  Ble_update_conn_interval(7.5,7.5)){
+								ble_con_int =2;
+								update_temp  =0;
+							}
+							else {
+							  if(Ble_update_connted_Error == update_temp)Except_TxError(EXCEPT_CONNET,"update Ble conn interval 7.5ms fail");
+								++update_temp;
+							}
+						}
+				}else{
+						if(ble_con_int !=1 && update_temp <= Ble_update_connted_Error){
+							if(APP_SUCCESS ==  Ble_update_conn_interval(100,100)){
+								ble_con_int =1;
+								update_temp =0;
+							}
+							else {
+							  if(Ble_update_connted_Error == update_temp)Except_TxError(EXCEPT_CONNET,"update Ble conn interval 100ms fail");
+								update_temp++;
+							}
+						}
+				}
+			
+				if(app_client_step_GetIsScan()==0&&slave_isconnect()==0&&(app_charge_Getstate()==BLE_CHARGE_PULLOUT)){
+					if(host_isconnect())host_disconnect();
+				}
+				if(!host_isconnect()){
+					SEGGER_RTT_printf(0,"=======>host_disconnect\n");
+					Process_SetHoldOn(app_connect_Process,0);
+					state = 0;
+				}
+				
+				break;}
+			default:state=0;break;
+		}
+}
+
+static void cb_BLE_BLE_CONNET_R(void* handle)
+{	
+	uint8_t host_state=BLE_RIGHT_DISCONNTED;
+	host_state =app_conneted_getRight();
+	SEGGER_RTT_printf(0,"!!!!app_conneted_getRight:%d\n",host_state);
+	BLE_Client_Tx_Send(0,BLE_CONNET_R,&host_state,1);
+}
+
+void app_connect_manage_Init(void)
+{
+	if(mFlash.isHost) Process_Start(100,"app_connect",app_connect_Process);
+	Ble_Slave_Connectd_Evt_Regist(cb_Slave_Connect);
+	Ble_Host_Connectd_Evt_Regist(cb_Host_Connect);
+	Process_Start(100,"app_connect_led",app_connect_LED_Process);
+	BLE_Client_Rx_Regist(BLE_CONNET_R,cb_BLE_BLE_CONNET_R);
+	BLE_Client_Rx_Regist(BLE_BLINK_LED,cb_BLE_BLINK_LED);
+}
+
+

+ 12 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_connect_manage.h

@@ -0,0 +1,12 @@
+#ifndef __app_connect_manage_h__
+#define __app_connect_manage_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void app_connect_manage_Init(void);
+
+#endif

+ 88 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_data_transfer.c

@@ -0,0 +1,88 @@
+/*Includes ----------------------------------------------*/
+#include "system.h"
+#include "ble_comm.h"
+#include "bsp_time.h"
+#include "hal_ble_host.h"
+#include "hal_ble_client.h"
+#include "hal_ble_common.h"
+#include "hal_ser_imu_mode_manage.h"
+#include "app_flash.h"
+#include "app_game.h"
+#include "app_data_transfer.h"
+	
+/*Local Functions ------------------------------------------------------------------------------------------------------------------------------------*/
+static void app_data_transfer_Process(void)
+{
+	static uint32_t tim 	= 0;
+	static uint32_t	tim2 	= 0;
+	static uint8_t	flag 	= 0;
+	
+	if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_GAME) != -1 || \
+		 hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_REALSTEP) != -1)
+	{
+		if(!flag){
+			Process_SetHoldOn(app_data_transfer_Process,1);
+			flag =1;
+		}
+		if(TIME_GetTicks()-tim>=500){tim = TIME_GetTicks();
+			if( 0 == slave_isconnect()){
+				SEGGER_RTT_printf(0,"app_data_transfer_Process advertising_start\r\n");
+				advertising_stop();
+				advertising_start();
+			}
+			if(mFlash.isHost && 0 == host_isconnect())scan_start();
+		}
+
+		if(TIME_GetTicks()-tim2>=3){tim2 = TIME_GetTicks();	
+			IMU_Dtalige();
+		}			
+	}
+	else{
+		if(flag){
+			Process_SetHoldOn(app_data_transfer_Process,0);
+			flag =0;
+		}
+	}
+
+}
+
+
+/*API -------------------------------------------------------*/
+/**
+	@brief 		将旧版本的IMU_SetSlaveData(uint8_t* pdat,uint8_t len)写在这里
+	@param 		pdat	略
+	@param 		len		略
+	@return 	无
+*/
+void app_data_transfer_set_SlaveData(uint8_t* pdat,uint8_t len)
+{
+	if(pdat[3]==BLE_TRACK){
+		IMU_Rec_data(pdat,len);
+		
+	}
+	app_game_SetClientGameMode();
+}
+/**
+	@brief 		初始化数据传输应用
+	@param 		无
+	@return 	错误代码					- [out]	-1失败,0成功
+*/
+int	app_data_transfer_Init(void)
+{
+	//设置数据传输线程
+	Process_Start(0,"app_data_transfer_Process",app_data_transfer_Process);
+	
+	BLE_Host_Rx_Regist_Game(app_data_transfer_set_SlaveData);
+	
+	return 0;
+}
+
+void send_protocol(uint8_t index,uint8_t cmd,uint8_t* p,uint8_t datLen)
+{
+	BLE_Client_Tx_Send(0,(BLE_CMD_n)cmd,p,datLen);
+}	
+
+
+
+
+

+ 55 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_data_transfer.h

@@ -0,0 +1,55 @@
+#ifndef __APP_DATA_TRANSFER_H__
+#define __APP_DATA_TRANSFER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*Includes ------------------------------------------------------*/
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+/*STRUCTION ----------------------------------------------------*/	
+	
+	
+	
+/*API -------------------------------------------------------*/
+/**
+	@brief 		初始化数据传输应用
+	@param 		无
+	@return 	错误代码					- [out]	-1失败,0成功
+*/
+int		app_data_transfer_Init(void);
+/**
+	@brief 		将旧版本的IMU_SetSlaveData(uint8_t* pdat,uint8_t len)写在这里
+	@param 		pdat	略
+	@param 		len		略
+	@return 	无
+*/
+void	app_data_transfer_set_SlaveData(uint8_t* pdat,uint8_t len);
+	
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 709 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_flash.c

@@ -0,0 +1,709 @@
+#include "app_flash.h"
+#include "bsp_wdt.h"
+#include "exception.h"
+
+/*************************************
+ *DEFINITION
+ */
+
+#define FLASH_HEAD									0xAA5555AA
+
+#define FLASH_TAIL_H								0xA5						//高位字节不能为0,因为结构体强制4字节对齐缘故,会导致解析错误。
+#define FLASH_TAIL_L								0x55						//低字节随意,最好是0101组合
+
+#define FLASH_ADDR_INFO_PAGENUM			1
+#define FLASH_ADDR_STEP_PAGENUM 		2
+#define FLASH_ADDR_BACKUP_PAGENUM 	1
+
+#define MaxLength(a,b) 							a>b?a:b
+
+/*********************************************************************
+ * LOCAL VARIABLES
+ */
+ 
+static uint32_t info_zone;
+static uint32_t step_zone;
+static uint32_t backup_zone;
+ 
+Flash_t 				mFlash;
+FlashBackup_t 	mBackup;
+
+/*********************************************************************
+ * LOCAL FUCTIONS
+ */
+
+/**
+ @brief crc16校验码
+ @param crc - [in]		默认0
+ @param buf - [in]		指向需要校验的数据
+ @param len - [in]		校验数据的长度
+ @return 返回crc16校验码
+*/
+static int CalCrc(int crc, const char *buf, int len)
+{
+    unsigned int byte;
+    unsigned char k;
+    unsigned short ACC,TOPBIT;
+
+    unsigned short remainder = crc;
+    TOPBIT = 0x8000;
+    for (byte = 0; byte < len; ++byte)
+    {
+        ACC = buf[byte];
+        remainder ^= (ACC <<8);
+        for (k = 8; k > 0; --k)
+        {
+            if (remainder & TOPBIT)
+            {
+                remainder = (remainder << 1) ^0x8005;
+            }
+            else
+            {
+                remainder = (remainder << 1);
+            }
+        }
+    }
+    remainder=remainder^0x0000;
+    return remainder;
+}
+
+/****************************************************接口****************************************************/
+void Flash_Initialize(void)
+{
+	uint8_t 	ret = 0;
+	uint32_t* addr_R;
+	uint32_t* BackupHead;
+	
+	Fstorage_FlashInit();
+	
+	SEGGER_RTT_printf(0,"Zone_Alloca(FLASH_ADDR_INFO_PAGENUM, &info_zone):%d\n",Zone_Alloca(FLASH_ADDR_INFO_PAGENUM, &info_zone));
+	SEGGER_RTT_printf(0,"Zone_Alloca(FLASH_ADDR_STEP_PAGENUM, &step_zone):%d\n",Zone_Alloca(FLASH_ADDR_STEP_PAGENUM, &step_zone));
+	SEGGER_RTT_printf(0,"Zone_Alloca(FLASH_ADDR_BACKUP_PAGENUM, &backup_zone):%d\n",Zone_Alloca(FLASH_ADDR_BACKUP_PAGENUM, &backup_zone));
+	
+	uint32_t sucess = Flash_GetBackup(&mBackup);
+	SEGGER_RTT_printf(0,"Flash_GetBackup (&mBackup):%d\n",sucess);
+		
+	if(mBackup.ErrorStartFlag >= 5){//连续五次重启的情况下,清空所有的flash数据
+		Flash_DeleteAllInformation();
+		Flash_DeleteAllStep();
+		mBackup.ErrorStartFlag =0;
+		Flash_SaveBackup();
+		SEGGER_RTT_printf(0,"mBackup.ErrorStartFlag >= 5!!!!!!!!!!!\n");
+		NVIC_SystemReset();
+	}
+	else{
+		mBackup.ErrorStartFlag++;
+		Flash_SaveBackup();
+	}
+	
+	addr_R = (uint32_t*)info_zone;
+	SEGGER_RTT_printf(0,"Flash head read(%04X).\n",*addr_R);
+	if((*addr_R)!=FLASH_HEAD){  SEGGER_RTT_printf(0,"Flash first init(%04X),write infomation to flash.\n",*addr_R);
+		memset((uint8_t*)(&mFlash),0,sizeof(Flash_t));
+		mFlash.head = FLASH_HEAD;
+		mFlash.m_struct_size = sizeof(mFlash);
+		
+		BackupHead = (uint32_t*)backup_zone;//备份区域有数据的话,拷贝备份区域的数据到information
+		if((*BackupHead) == FLASH_HEAD){
+			 uint8_t i=0;
+			 for(int i=0;i<6;i++){
+				 mFlash.macHost[i] =	mBackup.macAddr_L[i];	     //主机地址
+				 mFlash.mClient.macAddr[i] = mBackup.macAddr_R[i];//从机地址
+			 }
+			 
+			 SEGGER_RTT_printf(0,"Back macAddr_L:");for(i=0;i<6;i++){SEGGER_RTT_printf(0,"%02X:",mBackup.macAddr_L[i]);}SEGGER_RTT_printf(0,"\r\n");
+			 SEGGER_RTT_printf(0,"Back macAddr_R:");for(i=0;i<6;i++){SEGGER_RTT_printf(0,"%02X:",mBackup.macAddr_R[i]);}SEGGER_RTT_printf(0,"\r\n");
+			 
+			 mFlash.mClient.hardVersion = mBackup.hardVersion;
+			 mFlash.mClient.sotfVersion = mBackup.sotfVersion;
+			 mFlash.mClient.isConfig = mBackup.isConfig;
+			 SEGGER_RTT_printf(0,"Back Data:ifconfig:%d,hardVer:%d,backup.softversion:%d\n",mBackup.isConfig,mBackup.hardVersion,mBackup.sotfVersion);
+		}else{
+			 memset((uint8_t*)(&mBackup),0,sizeof(FlashBackup_t));
+		   Flash_SaveBackup();
+		}
+		
+		Flash_SaveInfomation();
+		SEGGER_RTT_printf(0,"Flash head second read(%04X).\n",*addr_R);
+		if((*addr_R)!=FLASH_HEAD){ 
+			SEGGER_RTT_printf(0,"Flash write head fail.\n");
+			Except_TxError(EXCEPT_FLASH,"Flash write head fail");
+			ret = 1;
+			return;
+		}
+		SEGGER_RTT_printf(0,"System reset...\n",*addr_R);
+		for(uint8_t i =0;i<6;i++){
+			nrf_delay_ms(500);
+			feed_watchdog();
+		}
+		NVIC_SystemReset();
+	}
+	if(ret==0){
+		sucess = Flash_GetInfomation(&mFlash);
+		SEGGER_RTT_printf(0,"Flash_GetInfomation(&mFlash):%d \n",sucess);
+	}
+	if(mFlash.mStep.stepCur[0]<mFlash.mStep.step[0])
+		mFlash.mStep.step[0] = mFlash.mStep.stepCur[0];
+	SEGGER_RTT_printf(0,"mFlash.mStep.num=%d\n",mFlash.mStep.num);
+	SEGGER_RTT_printf(0,"mFlash.mStep.stepCur[0]=%d,mFlash.mStep.stepCur[1]=%d\n",mFlash.mStep.stepCur[0],mFlash.mStep.stepCur[1]);
+	SEGGER_RTT_printf(0,"err code :%s\n",mFlash.mFlashLog.logData);
+	
+	SEGGER_RTT_printf(0,"Flash init ok.\n");
+	
+	mFlash.isHost = _IS_HOST;
+	
+	#ifdef PIN_SEL
+	nrf_gpio_cfg_input(PIN_SEL,NRF_GPIO_PIN_PULLUP);
+	nrf_delay_ms(100);
+	mFlash.isHost = (uint8_t)nrf_gpio_pin_read(PIN_SEL);
+	if(1 == mFlash.isHost)nrf_gpio_cfg_input(PIN_SEL,NRF_GPIO_PIN_PULLDOWN);
+	else nrf_gpio_cfg_input(PIN_SEL,NRF_GPIO_PIN_NOPULL);
+	#endif
+	if(mFlash.isHost){
+		SEGGER_RTT_printf(0,"======= Left  shooe ======= \n");
+	}else{
+		SEGGER_RTT_printf(0,"======= Right shooe ======= \n");
+	}
+	
+	
+	//TestHalFlashInterface();
+}
+ 
+/**
+ @brief 存储步数
+ @param 无
+ @return 错误代码
+*/
+uint32_t Flash_SaveStep(void)
+{
+	uint32_t 				err_code;
+	uint32_t 				flash_data;
+	static uint32_t Max_Hour = PAGE_INT_SIZE * FLASH_ADDR_STEP_PAGENUM;
+	
+	if(mFlash.mStep.num < Max_Hour)
+	{
+		uint32_t step = app_step_GetStep_L() + app_step_GetStep_R(); //获取左右鞋步数
+		flash_data =  ((step<<24 & 0xff000000) | (step<<8 & 0x00ff0000) | (step>>8 & 0x0000ff00) | (step>>24 & 0x000000ff));
+		
+		err_code = Zone_Write(step_zone + (mFlash.mStep.num * 4), &flash_data, 4);
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+		
+		mFlash.mStep.num++;
+		mFlash.mStep.step[0] = mFlash.mStep.stepCur[0];
+		mFlash.mStep.step[1] = mFlash.mStep.stepCur[1];		
+	}
+	else return ZONE_ERROR_WRITE_FAIL;
+	return ZONE_OP_SUCCESS;
+}
+
+/**
+ @brief 获取步数区域首地址
+ @param 无
+ @return 错误代码
+*/
+uint32_t Flash_GetStepZoneStartAddr(void)
+{
+	return step_zone;
+}
+
+/**
+ @brief 获取步数区域数据
+ @param 无
+ @return 错误代码
+*/
+uint32_t Flash_GetStep(uint32_t destination_addr, uint32_t *pData, uint32_t dataLen)
+{
+	return Zone_Read(destination_addr,pData,dataLen);
+}
+
+/**
+ @brief 删除所有步数
+ @param 无
+ @return 错误代码
+*/
+uint32_t Flash_DeleteAllStep(void)
+{
+	mFlash.mStep.num = 0;
+	return Zone_Erase(step_zone);
+}
+
+/**
+ @brief 删除所有的信息区域
+ @param 无
+ @return 错误代码
+*/
+uint32_t Flash_DeleteAllInformation(void)
+{
+	return Zone_Erase(info_zone);
+}
+
+/**
+ @brief 存储基本信息
+ @param 无
+ @return 错误代码
+*/
+uint32_t Flash_SaveInfomation(void)
+{
+	uint32_t 	err_code;
+	uint32_t 	zone_bytes;
+	Flash_t	 	temp_flash;
+	int32_t  	offset;
+	uint16_t 	crc;
+	uint8_t		tail_h;
+	
+	memset(&temp_flash,0,sizeof(temp_flash));
+	
+	err_code = Zone_GetByteSize(info_zone, &zone_bytes);
+	if(err_code != ZONE_OP_SUCCESS)return err_code;
+	
+	//从区域尾开始找起,找到最新的帧尾
+	for(offset = zone_bytes - 1; offset >= 0; offset--)
+	{
+		err_code = Zone_Read(info_zone + offset, (uint32_t*)&tail_h, 1);
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+		
+		if(tail_h == FLASH_TAIL_H)break;
+	}
+	//重新获取crc16校验码
+	mFlash.tail_crc16 = 0;
+	mFlash.m_struct_size = sizeof(mFlash);
+	mFlash.head = FLASH_HEAD;
+	crc = CalCrc(0, (char*)&mFlash, sizeof(mFlash));//计算得到的16位CRC校验码
+	mFlash.tail_crc16 = (uint32_t)((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc;
+	//写入
+	if(offset < 0){	//意味着整个区域是干净的,直接写开头。
+		err_code = Zone_Write(info_zone, (uint32_t*)&mFlash, sizeof(mFlash));
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+		SEGGER_RTT_printf(0,"write zone all clear,mFlash.tail_crc16:0x%x\r\n",mFlash.tail_crc16);
+	}else{
+		//这里要偏移才能对齐成员
+		offset++;		
+		//获取最新的帧尾
+		err_code = Zone_Read(info_zone + offset - sizeof(temp_flash.tail_crc16), (uint32_t*)&temp_flash.tail_crc16, sizeof(temp_flash.tail_crc16));
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+		//获取最新的帧长度
+		err_code = Zone_Read(info_zone + offset - sizeof(temp_flash.tail_crc16) - sizeof(temp_flash.m_struct_size) , (uint32_t*)&temp_flash.m_struct_size, sizeof(temp_flash.m_struct_size));
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+		//因为结构体强制4字节对齐缘故,所以tail_crc16未必是真实存储的帧尾,后面可能带一些数据为0的填充字节。所以要做校准。
+//		uint32_t pad_len = temp_flash.m_struct_size - ((uint32_t)&temp_flash.tail_crc16 + sizeof(temp_flash.tail_crc16) - (uint32_t)&temp_flash.head);
+		
+		uint32_t pad_len = 0;
+//		SEGGER_RTT_printf(0,"save info_zone:0x%x offset:%d pad_len:%d temp_flash.m_struct_size:%d\n",info_zone,offset,pad_len,temp_flash.m_struct_size);
+		if(offset + pad_len < temp_flash.m_struct_size)pad_len = temp_flash.m_struct_size - offset;
+		err_code = Zone_Read(info_zone + offset + pad_len - temp_flash.m_struct_size, (uint32_t*)&temp_flash.head, sizeof(temp_flash.head));
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+//		SEGGER_RTT_printf(0,"save >>>>>>p_head:0x%x,addr:0x%x\n",temp_flash.head,info_zone + offset + pad_len - temp_flash.m_struct_size);
+		while(temp_flash.head != FLASH_HEAD){
+			pad_len++;
+			err_code = Zone_Read(info_zone + offset + pad_len - temp_flash.m_struct_size, (uint32_t*)&temp_flash.head, sizeof(temp_flash.head));
+			if(err_code != ZONE_OP_SUCCESS)return err_code;
+//			SEGGER_RTT_printf(0,"save >>>>>>p_head:0x%x,addr:0x%x\n",temp_flash.head,info_zone + offset + pad_len - temp_flash.m_struct_size);
+//			nrf_delay_ms(5);
+		}
+
+		err_code = Zone_Write(info_zone + offset + pad_len, (uint32_t*)&mFlash, sizeof(mFlash));
+//		if(err_code == ZONE_OP_SUCCESS)SEGGER_RTT_printf(0,"write zone forward ,mFlash.tail_crc16:0x%x\r\n",mFlash.tail_crc16);
+		if(err_code != ZONE_OP_SUCCESS){	//如果写失败了
+			//擦除该区域
+			err_code = Zone_Erase(info_zone);
+			if(err_code != ZONE_OP_SUCCESS)return err_code;
+			//写在开头
+			err_code = Zone_Write(info_zone, (uint32_t*)&mFlash, sizeof(mFlash));
+			if(err_code != ZONE_OP_SUCCESS)return err_code;
+//			SEGGER_RTT_printf(0,"write zone all erase ,mFlash.tail_crc16:0x%x\r\n",mFlash.tail_crc16);
+		}
+	}
+	
+	return ZONE_OP_SUCCESS;
+}
+
+
+
+/**
+ @brief 获取基本信息
+ @param 无
+ @return 错误代码
+*/
+uint32_t Flash_GetInfomation(Flash_t *pflash)
+{
+	uint32_t 	err_code;
+	uint32_t 	zone_bytes;
+	Flash_t	 	temp_flash;
+	int32_t  	offset;
+	uint16_t 	crc;
+	uint8_t		tail_h;
+	
+	memset(&temp_flash,0,sizeof(temp_flash));
+	
+	SEGGER_RTT_printf(0,"Zone_GetByteSize(info_zone, &zone_bytes):%d\n",zone_bytes);
+	
+	err_code = Zone_GetByteSize(info_zone, &zone_bytes);
+	if(err_code != ZONE_OP_SUCCESS)return err_code;
+	
+	SEGGER_RTT_printf(0,"Zone_GetByteSize(info_zone, &zone_bytes):%d\n",zone_bytes);
+	
+	//从区域尾开始找起,找到最新的帧尾
+	for(offset = zone_bytes - 1; offset >= 0; offset--)
+	{
+		err_code = Zone_Read(info_zone + offset, (uint32_t*)&tail_h, 1);
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+		
+		if(tail_h == FLASH_TAIL_H)break;
+	}
+	
+	//意味着整个区域是干净的
+	if(offset < 0){
+		memset(pflash,0,sizeof(Flash_t));
+		pflash->head = FLASH_HEAD;
+		pflash->m_struct_size = sizeof(Flash_t);				//这里是包括填充字节的
+		crc = CalCrc(0, (char*)pflash, sizeof(Flash_t));//计算得到的16位CRC校验码,这里注意,有可能会将填充的字节也拿来做运算
+		pflash->tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc;		//这里最后才加,是因为不知道填充字节的个数
+		SEGGER_RTT_printf(0,"read zone all clear,pflash->tail_crc16:0x%x\r\n",pflash->tail_crc16);
+		return ZONE_OP_SUCCESS;
+	}
+	//这里要偏移才能对齐成员
+	offset++;		
+	//获取最新的帧尾
+	err_code = Zone_Read(info_zone + offset - sizeof(temp_flash.tail_crc16), (uint32_t*)&temp_flash.tail_crc16, sizeof(temp_flash.tail_crc16));
+	if(err_code != ZONE_OP_SUCCESS)return err_code;
+	//获取最新的帧长度
+	err_code = Zone_Read(info_zone + offset - sizeof(temp_flash.tail_crc16) - sizeof(temp_flash.m_struct_size) , (uint32_t*)&temp_flash.m_struct_size, sizeof(temp_flash.m_struct_size));
+	if(err_code != ZONE_OP_SUCCESS)return err_code;
+	//因为结构体强制4字节对齐缘故,所以tail_crc16未必是真实存储的帧尾,后面可能带一些数据为0的填充字节。所以要做校准。
+
+	
+//  uint32_t pad_len = temp_flash.m_struct_size - ((uint32_t)&temp_flash.tail_crc16 + sizeof(temp_flash.tail_crc16) - (uint32_t)&temp_flash.head);
+	uint32_t pad_len = 0;
+//	SEGGER_RTT_printf(0,"get info_zone:0x%x offset:%d pad_len:%d temp_flash.m_struct_size:%d\n",info_zone,offset,pad_len,temp_flash.m_struct_size);
+	if(offset + pad_len < temp_flash.m_struct_size)pad_len = temp_flash.m_struct_size - offset;
+	err_code = Zone_Read(info_zone + offset + pad_len - temp_flash.m_struct_size, (uint32_t*)&temp_flash.head, sizeof(temp_flash.head));
+	if(err_code != ZONE_OP_SUCCESS)return err_code;
+//	SEGGER_RTT_printf(0,">>>>>>p_head:0x%x,addr:0x%x\n",temp_flash.head,info_zone + offset + pad_len - temp_flash.m_struct_size);
+	while(temp_flash.head != FLASH_HEAD){
+		pad_len++;
+		err_code = Zone_Read(info_zone + offset + pad_len - temp_flash.m_struct_size, (uint32_t*)&temp_flash.head, sizeof(temp_flash.head));
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+//		SEGGER_RTT_printf(0,">>>>>>p_head:0x%x,addr:0x%x\n",temp_flash.head,info_zone + offset + pad_len - temp_flash.m_struct_size);
+//		nrf_delay_ms(5);
+	}
+
+		
+//	SEGGER_RTT_printf(0,"read pad_len 0x%x info_zone + offset + pad_len - temp_flash.m_struct_size:0x%x\r\n",pad_len,info_zone + offset + pad_len - temp_flash.m_struct_size);
+	//获取最新的帧
+	if(temp_flash.m_struct_size <= (sizeof(temp_flash.tail_crc16)+sizeof(temp_flash.m_struct_size)+pad_len))return ZONE_ERROR_READ_FAIL;
+	err_code = Zone_Read(info_zone + offset + pad_len - temp_flash.m_struct_size , (uint32_t*)&temp_flash, temp_flash.m_struct_size - sizeof(temp_flash.tail_crc16)-sizeof(temp_flash.m_struct_size)-pad_len);
+	if(err_code != ZONE_OP_SUCCESS)return err_code;
+	//判断一下是否正确读取到最新的帧
+	if(temp_flash.m_struct_size <= (sizeof(temp_flash.tail_crc16)+sizeof(temp_flash.m_struct_size)+pad_len))//证明结构体被修改了
+	{
+		//校验没通过
+		SEGGER_RTT_printf(0,"struct change,read crc fail :0x%x 0x%x \r\n",crc,temp_flash.tail_crc16 & 0xFFFF);
+		memset(pflash,0,sizeof(Flash_t));
+		pflash->head = FLASH_HEAD;
+		pflash->m_struct_size = sizeof(Flash_t);
+		//将备份区域的数据拷贝
+		FlashBackup_t	 	temp_backup;
+		Flash_GetBackup(&temp_backup);
+		for(int i=0;i<6;i++){
+			pflash->mClient.macAddr[i] = temp_backup.macAddr_R[i];
+			pflash->macHost[i] = temp_backup.macAddr_L[i];
+	  }
+		pflash->mClient.isConfig = temp_backup.isConfig;
+		pflash->mClient.hardVersion = temp_backup.hardVersion;
+		pflash->mClient.sotfVersion = temp_backup.sotfVersion;
+		crc = CalCrc(0, (char*)pflash, sizeof(Flash_t));//计算得到的16位CRC校验码
+		pflash->tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc;
+		err_code = Zone_Erase(info_zone);
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+		err_code = Flash_SaveInfomation();
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+		return ZONE_OP_SUCCESS;
+	}
+	
+	
+	//校验数据
+	Flash_t	crc_buf;//单纯做一个缓冲区
+	memset(&crc_buf,0,sizeof(crc_buf));
+	char *buf = (char*)&crc_buf;
+	//获取成员head ~ m_struct_size
+//	SEGGER_RTT_printf(0,"crc_buf:%d temp_flash.m_struct_size:%d,temp_flash.tail_crc16:%d\n",sizeof(crc_buf),temp_flash.m_struct_size,sizeof(temp_flash.tail_crc16));
+//	SEGGER_RTT_printf(0,"sizeof(temp_flash.m_struct_size):%d,pad_len:%d\n",sizeof(temp_flash.m_struct_size),pad_len);
+	memcpy(buf,&temp_flash,temp_flash.m_struct_size - sizeof(temp_flash.tail_crc16)-sizeof(temp_flash.m_struct_size)-pad_len);
+//	SEGGER_RTT_printf(0,"read pad_len:%d,info_zone:0x%x,offset:%d,pad_len:%d,temp_flash.m_struct_size:%d\r\n",pad_len,info_zone,offset,pad_len,temp_flash.m_struct_size);
+//	SEGGER_RTT_printf(0,"2:buf:0x%x sizeof(temp_flash.m_struct_size):%d\n",buf + temp_flash.m_struct_size - sizeof(temp_flash.tail_crc16)-sizeof(temp_flash.m_struct_size)-pad_len,sizeof(temp_flash.m_struct_size));
+	memcpy(buf + temp_flash.m_struct_size - sizeof(temp_flash.tail_crc16)-sizeof(temp_flash.m_struct_size)-pad_len,(uint32_t*)&temp_flash.m_struct_size,sizeof(temp_flash.m_struct_size));
+	//计算得到的16位CRC校验码
+	crc = CalCrc(0, buf, temp_flash.m_struct_size);
+	
+	
+	if(crc == (temp_flash.tail_crc16 & 0xFFFF)){
+//		SEGGER_RTT_printf(0,"read crc success :0x%x 0x%x \r\n",crc,temp_flash.tail_crc16 & 0xFFFF);
+		temp_flash.head = FLASH_HEAD;
+		temp_flash.m_struct_size = sizeof(temp_flash);
+		temp_flash.tail_crc16 = 0;
+		crc = CalCrc(0, (char*)&temp_flash, sizeof(temp_flash));//计算得到的16位CRC校验码
+		temp_flash.tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc;
+		*pflash = temp_flash;//校验通过
+	}
+	else{
+		//校验没通过
+//		SEGGER_RTT_printf(0,"read crc fail :0x%x 0x%x \r\n",crc,temp_flash.tail_crc16 & 0xFFFF);
+		memset(pflash,0,sizeof(Flash_t));
+		pflash->head = FLASH_HEAD;
+		pflash->m_struct_size = sizeof(Flash_t);
+		//将备份区域的数据拷贝
+		FlashBackup_t	 	temp_backup;
+		Flash_GetBackup(&temp_backup);
+		for(int i=0;i<6;i++){
+			pflash->mClient.macAddr[i] = temp_backup.macAddr_R[i];
+			pflash->macHost[i] = temp_backup.macAddr_L[i];
+	  }
+		pflash->mClient.isConfig = temp_backup.isConfig;
+		pflash->mClient.hardVersion = temp_backup.hardVersion;
+		pflash->mClient.sotfVersion = temp_backup.sotfVersion;
+		crc = CalCrc(0, (char*)pflash, sizeof(Flash_t));//计算得到的16位CRC校验码
+		pflash->tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc;
+		err_code = Zone_Erase(info_zone);
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+		err_code = Flash_SaveInfomation();
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+	}
+	
+	
+	return ZONE_OP_SUCCESS;
+}
+
+/**
+ @brief 存储备份信息
+ @param 无
+ @return 错误代码
+*/
+uint32_t Flash_SaveBackup(void)
+{
+	uint32_t 				err_code;
+	mBackup.head = FLASH_HEAD;
+	err_code =  Zone_Erase(backup_zone);
+	if(err_code != ZONE_OP_SUCCESS)return err_code;
+	err_code = Zone_Write(backup_zone, (uint32_t*)&mBackup, sizeof(mBackup));
+	return err_code;
+}
+
+/**
+ @brief 获取备份信息
+ @param 无
+ @return 错误代码
+*/
+uint32_t Flash_GetBackup(FlashBackup_t *pbackup)
+{
+	uint32_t 				err_code;
+	err_code = Zone_Read(backup_zone, (uint32_t*)pbackup, sizeof(FlashBackup_t));
+	return err_code;
+}
+
+/**
+ @brief 保存日志信息
+ @param[in] id    Fault identifier. See @ref NRF_FAULT_IDS.
+ @param[in] pc    The program counter of the instruction that triggered the fault, or 0 if
+                  unavailable.
+ @param[in] info  Optional additional information regarding the fault. The value of the @p id
+                  parameter dictates how to interpret this parameter. Refer to the documentation
+                  for each fault identifier (@ref NRF_FAULT_IDS and @ref APP_ERROR_FAULT_IDS) for
+                  details about interpreting @p info.
+ @return 错误代码
+*/
+uint32_t Flash_SaveLog(uint32_t id, uint32_t pc, uint32_t info)
+{
+	memset((uint8_t*)(&mFlash.mFlashLog),0,sizeof(FlashLog));
+	mFlash.mFlashLog.Errorflag =1;
+	switch (id)
+ {
+	#if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT
+					case NRF_FAULT_ID_SD_ASSERT:
+							memcpy(mFlash.mFlashLog.logData,"SD: ASSERTION FAILED\r\n",MaxLength(sizeof("SD: ASSERTION FAILED\r\n"),sizeof(mFlash.mFlashLog.logData)));
+							break;
+					case NRF_FAULT_ID_APP_MEMACC:
+							memcpy(mFlash.mFlashLog.logData,"SD: INVALID MEMORY ACCESS\r\n",MaxLength(sizeof("SD: INVALID MEMORY ACCESS\r\n"),sizeof(mFlash.mFlashLog.logData)));
+							break;
+	#endif
+					case NRF_FAULT_ID_SDK_ASSERT:
+					{
+							assert_info_t * p_info = (assert_info_t *)info;
+							sprintf((char *)mFlash.mFlashLog.logData,"ASSERTION FAILED %s:%u\r\n",
+														p_info->p_file_name,
+														p_info->line_num);
+							break;
+					}
+					case NRF_FAULT_ID_SDK_ERROR:
+					{
+							error_info_t * p_info = (error_info_t *)info;
+						  
+						  sprintf((char *)mFlash.mFlashLog.logData,"error:%u,%s:%u\r\n",
+														p_info->err_code,
+														p_info->p_file_name,
+														p_info->line_num);
+							SEGGER_RTT_printf(0,">>>>>err code :%d,%s",p_info->err_code,mFlash.mFlashLog.logData);
+
+							break;
+					}
+					default:
+							sprintf((char *)mFlash.mFlashLog.logData,"UNKNOWN FAULT 0x%08X\n", pc);
+							break;
+	}
+ 
+	return Flash_SaveInfomation();
+}
+
+/**
+ @brief 返回主机标志位
+ @param 无
+ @return 主机标志位
+*/
+uint8_t Get_isHost(void)
+{
+	return mFlash.isHost;
+}
+
+
+
+
+/**
+ @brief 测试halflash接口
+ @param 无
+ @return 无
+*/
+void TestHalFlashInterface(void)
+{
+	
+	Fstorage_FlashInit();
+	
+	SEGGER_RTT_printf(0,"Zone_Alloca(FLASH_ADDR_INFO_PAGENUM, &info_zone):%d\n",Zone_Alloca(FLASH_ADDR_INFO_PAGENUM, &info_zone));
+	SEGGER_RTT_printf(0,"Zone_Alloca(FLASH_ADDR_STEP_PAGENUM, &step_zone):%d\n",Zone_Alloca(FLASH_ADDR_STEP_PAGENUM, &step_zone));
+	SEGGER_RTT_printf(0,"Zone_Alloca(FLASH_ADDR_BACKUP_PAGENUM, &backup_zone):%d\n",Zone_Alloca(FLASH_ADDR_BACKUP_PAGENUM, &backup_zone));
+
+	SEGGER_RTT_printf(0,"Flash_GetInfomation(&mFlash):%d \n",Flash_GetInfomation(&mFlash));
+	SEGGER_RTT_printf(0,"Flash_GetInfomation(&mBackup):%d \n",Flash_GetBackup(&mBackup));
+	
+	
+	uint32_t i; 
+//	Flash_t m_testflash;
+//	FlashBackup_t m_testbackup;
+	
+//	//测试基本信息和备份信息的写入和读取
+//	for(i=0;i<10000;i++)
+//	{
+//		mFlash.mStep.num = i;
+//		SEGGER_RTT_printf(0,"Flash_SaveInfomation[%d]:%d \n",i,Flash_SaveInfomation());
+//		
+//		mBackup.hardVersion = i;
+//		SEGGER_RTT_printf(0,"Flash_SaveBackup[%d]:%d \n",i,Flash_SaveBackup());
+//	}
+//	
+//	SEGGER_RTT_printf(0,"Flash_GetInfomation[%d]:%d \n",i,Flash_GetInfomation(&m_testflash));
+//	SEGGER_RTT_printf(0,"m_testflash:%d \n",m_testflash.mStep.num);
+//	
+//	SEGGER_RTT_printf(0,"Flash_GetBackup[%d]:%d \n",i,Flash_GetBackup(&m_testbackup));
+//	SEGGER_RTT_printf(0,"m_testbackup:%d \n",m_testbackup.hardVersion);
+	
+	//测试步数信息的写入和读取
+	for(i=0;i<(PAGE_INT_SIZE * FLASH_ADDR_STEP_PAGENUM+100);i++)
+	{
+		mFlash.mStep.stepCur[0] = 0;
+		mFlash.mStep.stepCur[1] = i;
+		SEGGER_RTT_printf(0,"Flash_SaveStep[%d]:%d \n\n",i,Flash_SaveStep());
+	}
+	
+	uint8_t checkflash[4] = {0};
+	for(i=0;i<(PAGE_INT_SIZE * FLASH_ADDR_STEP_PAGENUM);i+=4)
+	{
+//		Zone_Read(step_zone + i, (uint32_t*)&step, 4);
+//		SEGGER_RTT_printf(0,"step[%d]:0x%x ",i,step);
+		Zone_Read(step_zone + i,(uint32_t*)&checkflash[0], 4);
+		SEGGER_RTT_printf(0,"checkflash[%d]:%02x,%02x,%02x,%02x ",i,checkflash[0],checkflash[1],checkflash[2],checkflash[3]);
+		if(i%5 == 0)SEGGER_RTT_printf(0,"\n");
+		nrf_delay_ms(5);
+	}
+
+	
+	
+	
+	
+	
+	
+	
+
+////uint32_t Flash_SaveStep(void);
+//////存储基本信息
+////uint32_t Flash_SaveInfomation(void);
+//////存储备份信息
+////uint32_t Flash_SaveBackup(void);
+//////获取基本信息
+////uint32_t Flash_GetInfomation(Flash_t *pflash);
+//////获取备份信息
+////uint32_t Flash_GetBackup(FlashBackup_t *pbackup);
+//	
+//	uint32_t i;
+//	Flash_t m_testflash;
+//	FlashBackup_t m_testbackup;
+
+//	Fstorage_FlashInit();
+//	
+//	#define INFO_PAGE_SIZE			1
+//	#define BACKUP_PAGE_SIZE		1
+//	#define STEP_PAGE_SIZE			2
+//	
+//	static uint32_t info_index;
+//	static uint32_t backup_index;
+//	static uint32_t step_index;
+//	
+//	Zone_Init(INFO_PAGE_SIZE, &info_index);
+//	Zone_Init(BACKUP_PAGE_SIZE, &backup_index);
+//	Zone_Init(STEP_PAGE_SIZE, &step_index);
+//	
+//	SEGGER_RTT_printf(0,"info_index=%d backup_index=%d step_index=%d\n",info_index,backup_index,step_index);
+//	
+//	
+//	
+//	while(1);
+//	
+//	//测试基本信息和备份信息的写入和读取
+//	for(i=0;i<10000;i++)
+//	{
+//		mFlash.mStep.num = i;
+//		SEGGER_RTT_printf(0,"Flash_SaveInfomation[%d]:%d \n",i,Flash_SaveInfomation());
+//		
+//		mBackup.hardVersion = i;
+//		SEGGER_RTT_printf(0,"Flash_SaveBackup[%d]:%d \n",i,Flash_SaveBackup());
+//	}
+//	
+//	SEGGER_RTT_printf(0,"Flash_GetInfomation[%d]:%d \n",i,Flash_GetInfomation(&m_testflash));
+//	SEGGER_RTT_printf(0,"m_testflash:%d \n",m_testflash.mStep.num);
+//	
+//	SEGGER_RTT_printf(0,"Flash_GetInfomation[%d]:%d \n",i,Flash_GetBackup(&m_testbackup));
+//	SEGGER_RTT_printf(0,"m_testbackup:%d \n",m_testbackup.hardVersion);
+
+
+//	//测试步数信息的写入和读取
+//	for(i=0;i<1500;i++)
+//	{
+//		mFlash.mStep.num = i;
+//		mFlash.mStep.stepCur[0] = i;
+//		mFlash.mStep.stepCur[1] = i+i;
+//		
+//		SEGGER_RTT_printf(0,"Flash_SaveStep[%d]:%d \n\n",i,Flash_SaveStep());
+//	}
+//	uint32_t checkflash[750];
+//	Read_N_Byte_flash(FLASH_ADDR_STEP , (uint32_t*)checkflash, sizeof(checkflash));
+//	
+//	for(i=0;i<750;i++)
+//	{
+//		SEGGER_RTT_printf(0,"checkflash[%d]:0x%x ",i,checkflash[i]);
+//		if(i%5 == 0)SEGGER_RTT_printf(0,"\n");
+//		nrf_delay_ms(5);
+//	}
+
+	
+	
+	SEGGER_RTT_printf(0,"TestHalFlashInterface done !!!!!!!\n");
+}
+
+

+ 130 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_flash.h

@@ -0,0 +1,130 @@
+#ifndef __APP_FLASH_H__
+#define __APP_FLASH_H__
+/*************************************
+ *INCLUDES
+ */
+#include "hal_flash.h"
+#include "app_step.h"
+#include "exception.h"
+#include "app_power.h"
+#include "nrf_gpio.h"
+#include "nrf_delay.h"
+#include "nrf_sdm.h"
+
+/*************************************
+ *STRUCTIONS
+ */
+//__attribute__((packed,aligned(4))) : 先按实际字节占位算,最后才4字节对齐。
+//size:20
+typedef struct __attribute__((packed,aligned(4))) _FlashBackup{
+	uint32_t 	head;	
+	uint8_t 	macAddr_L[6];
+	uint8_t 	macAddr_R[6];
+	uint32_t 	hardVersion;
+	uint8_t 	sotfVersion;
+	uint8_t 	isConfig;
+	uint8_t   ErrorStartFlag;
+}FlashBackup_t;
+//size:36
+typedef struct __attribute__((packed,aligned(4))) _FlashStep{
+	uint8_t 	startTime[8];				//记录时间
+	uint8_t 	newStartTime[8];		//当前时间
+	uint32_t 	stepCur[2];					//当前永久步数
+	uint32_t 	step[2];						//每小时记录的左右鞋永久步数0左1右
+	uint32_t 	num;								//已经记录的每小时步数数量
+}FlashStep_t;
+//size:12
+typedef struct __attribute__((packed,aligned(4))) _FlashClient{
+	uint8_t 	isConfig;
+	uint32_t 	hardVersion;
+	uint8_t 	sotfVersion;
+	uint8_t	 	macAddr[6];
+}FlashClient_t;
+//size:
+typedef struct __attribute__((packed,aligned(4))) _FlashLog{
+	uint8_t Errorflag;
+	uint8_t logData[50];
+}FlashLog;
+//size:64
+typedef struct __attribute__((packed,aligned(4))) _Flash_Param{					//后期版本修改结构体,不能删除或修改现有成员,只能追加新的成员。																	
+	uint32_t 			head;
+	uint8_t  			isHost;
+	uint8_t 			macHost[6];
+	FlashStep_t 	mStep;
+	FlashClient_t mClient;
+	FlashLog 			mFlashLog;
+	uint8_t       Safe_cnt;
+	
+	uint32_t			m_struct_size;			//结构体自身大小	
+	uint32_t			tail_crc16;					//crc16校准只能做成员 head ~ m_struct_size,因为未知的填充字节原因,tail_crc16和未知填充字节(默认为0)都为0好计算。
+}Flash_t;
+
+
+extern Flash_t mFlash;
+extern FlashBackup_t mBackup;
+
+/*1.当新API读到旧的数据的时候,新API多的参数用默认值填充,写回的时候按照新API的格式写回。(向后兼容)
+  2.当旧API读到新数据,自己不认识的那段buff,要保存起来,写回的时候,将这段buff原样memcpy。(向前兼容,没实现)
+*/
+ 
+/********************************************
+ *API FUCTIONS
+ */
+void Flash_Initialize(void);
+//存储步数
+uint32_t Flash_SaveStep(void);
+//获取步数区域首地址
+uint32_t Flash_GetStepZoneStartAddr(void);
+//获取步数区域数据
+uint32_t Flash_GetStep(uint32_t destination_addr, uint32_t *pData, uint32_t dataLen);
+//删除所有步数
+uint32_t Flash_DeleteAllStep(void);
+//删除所有的基本信息
+uint32_t Flash_DeleteAllInformation(void);
+//存储基本信息
+uint32_t Flash_SaveInfomation(void);
+//获取基本信息
+uint32_t Flash_GetInfomation(Flash_t *pflash);
+//存储备份信息
+uint32_t Flash_SaveBackup(void);
+//获取备份信息
+uint32_t Flash_GetBackup(FlashBackup_t *pbackup);
+//保存日志信息
+uint32_t Flash_SaveLog(uint32_t id, uint32_t pc, uint32_t info);
+//返回主机标志位
+uint8_t Get_isHost(void);
+//测试接口
+void TestHalFlashInterface(void);
+
+
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 149 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_game.c

@@ -0,0 +1,149 @@
+#include "app_game.h"
+#include "nrf_gpio.h"
+#include "usr_config.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_mt.h"
+#include "hal_battery.h"
+#include "app_charge.h"
+#include "hal_ble_client.h"
+#include "hal_ble_host.h"
+#include "nrf_delay.h"
+#include "app_flash.h"
+#include "ble_comm.h"
+#include "exception.h"
+#include "hal_ser_imu_mode_manage.h"
+#include "ble_comm.h"
+
+/********************** 函数声明区 *************************/
+
+typedef struct game_manager{
+ uint8_t clientCnt;       //右鞋游戏模式的标志位
+ uint8_t right_discnt;    //右鞋断开连接计数器
+ uint8_t client_discnt;   //主机连接断开计数器
+ uint8_t isGameMode;      //游戏模式标志位
+ uint8_t GameModeHeartCnt;//游戏模式心跳维护,左鞋
+}game_manager_t;
+
+static game_manager_t game_manager ={0};
+
+void app_game_SetClientGameMode(void)
+{
+	if(game_manager.clientCnt != 3) game_manager.clientCnt = 3;
+}
+
+void cb_BLE_Client_R_GAMEMODE(void* handle)
+{
+	BLE_Client_Rx_t* target = handle;
+	game_manager.isGameMode = target->pDat[0];
+	if(game_manager.isGameMode){
+		hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_GAME, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_ON);
+		game_manager.GameModeHeartCnt =0;
+	}else{
+		hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_GAME, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+	}
+	
+	switch(game_manager.isGameMode)
+	{
+		case 1:
+			IMU_Dtalige_Rowdata_OFF();
+			break;
+		case 2:
+			IMU_Dtalige_Rowdata_ON();
+			break;
+	}
+	
+	BLE_Host_Tx_Send(0,BLE_GAMEMODE,&game_manager.isGameMode,1);
+	SEGGER_RTT_printf(0,">>>>>>>>>>cb_BLE_Client_R_GAMEMODE:%d\r\n",game_manager.isGameMode);
+}
+
+static void app_AutoOutgame_Process(void){
+	if(mFlash.isHost && (hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_GAME) != -1)){
+		SEGGER_RTT_printf(0,"game_manager.GameModeHeartCnt:%d\r\n",game_manager.GameModeHeartCnt);
+		if(game_manager.GameModeHeartCnt++ >= 5){
+			 game_manager.isGameMode = 0;
+			 hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_GAME, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+			 BLE_Host_Tx_Send(0,BLE_GAMEMODE,&game_manager.isGameMode,1); 
+		}
+	}
+}
+
+static void app_game_notify_host(uint8_t mode){
+	uint8_t clientMode = mode;
+	BLE_Host_Tx_Send(0,BLE_GAMEMODE,&clientMode,1);
+}
+
+static void app_game_Process(void)
+{
+	static uint8_t errCnt = 0;
+  static uint8_t state_imu_gamemode = 0;
+	
+	if(game_manager.clientCnt>0) game_manager.clientCnt--;
+	switch(state_imu_gamemode){
+		case 0:
+			    if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_GAME) == -1){
+						 if(1 == game_manager.isGameMode){
+								hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_GAME, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_ON);
+								if(++errCnt >= 20){
+									errCnt =0;
+									Except_TxError(EXCEPT_GAME,"shoes into game mode fail");
+								}
+						 }
+						 if(game_manager.clientCnt >0 && mFlash.isHost) app_game_notify_host(0);
+					}
+					else state_imu_gamemode =1;
+			    break;
+		case 1:
+			   if(mFlash.isHost){//管理右鞋状态
+						 if(host_isconnect()){
+							 if(0 == game_manager.clientCnt){
+									app_game_notify_host(1);
+									if(++errCnt >= 10){
+										errCnt =0;
+										SEGGER_RTT_printf(0,"ERR_NUM_GAME app_game_Process\r\n");
+										Except_TxError(EXCEPT_GAME,"no get right shoes data");
+									}
+							 }
+							 else if(errCnt>0) errCnt = 0;
+							 game_manager.right_discnt =0;
+						 }
+						 else{
+							 if(game_manager.right_discnt++ >10){//与右鞋断开10秒后,退出游戏模式
+									game_manager.isGameMode = 0;
+									errCnt =0;
+								  state_imu_gamemode =0;
+									hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_GAME, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+								  
+									Except_TxError(EXCEPT_GAME,"In game mode,right shoes disconnted long time");
+							 }
+						 }
+			    }
+			
+					if(0 == game_manager.isGameMode){
+							errCnt =0;
+							state_imu_gamemode =0;
+							hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_GAME, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);//收到退出游戏指令,退出游戏模式
+							if(mFlash.isHost)app_game_notify_host(0);
+					}
+					
+					 //与主机断开5秒后,退出游戏模式
+					 if(!slave_isconnect()){
+							if(game_manager.client_discnt++ >5){
+								game_manager.isGameMode = 0;
+								errCnt =0;
+								state_imu_gamemode =0;
+								hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_GAME, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+								Except_TxError(EXCEPT_GAME,"In game mode,client disconnted long time");
+							}
+					 }
+					 else game_manager.client_discnt =0;
+			     break;
+	  }
+}
+
+void app_game_Init(void)
+{
+	Process_Start(1000,"app_game",app_game_Process);
+	BLE_Client_Rx_Regist(BLE_GAMEMODE,cb_BLE_Client_R_GAMEMODE);
+	Process_Start(60000,"app_AutoOutgame",app_AutoOutgame_Process);
+}

+ 13 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_game.h

@@ -0,0 +1,13 @@
+#ifndef __app_game_h__
+#define __app_game_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void app_game_Init(void);
+void app_game_SetClientGameMode(void);
+
+#endif

+ 90 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_host.c

@@ -0,0 +1,90 @@
+#include "system.h"
+#include "app_host.h"
+#include "hal_ble_client.h"
+#include "hal_ble_host.h"
+#include "bsp_time.h"
+#include "hal_led.h"
+#include "ble_gap.h"
+#include "hal_battery.h"
+#include "app_flash.h"
+#include "ble_comm.h"
+#include "app_client.h"
+#include "hal_ser_imu_mode_manage.h"
+
+/************************ 定义 ***************************/
+static uint8_t vol_R = 0;		//右鞋电量
+static uint8_t temp_R = 0;		//右鞋温度
+static uint32_t press_R = 0;	//右鞋压力
+
+uint8_t app_host_GetVol_R(void){ return vol_R; }
+uint8_t app_host_GetTemp_R(void){ return temp_R; }
+uint32_t app_host_GetPress_R(void){ return press_R; }
+
+/***************************** 主动获取从机信息 ******************************/
+static BLE_Host_Tx_t mBLE_Host_T_UPDATE_INFO_R = {
+	.n = 10,
+	.t = 1000,
+	.cb = 0,
+};
+
+void app_host_GetClientInfo(void)
+{//AA 06 F9 A1 00 4A
+	static uint8_t buf=BLE_UPDATE_BASEINFO;
+	BLE_Host_Tx_Send(&mBLE_Host_T_UPDATE_INFO_R,BLE_UPDATE,&buf,1);
+}
+
+static BLE_Host_Tx_t mBLE_Host_T_UPDATE_DATA_R = {
+	.n = 0,
+	.t = 500,
+	.cb = 0,
+};
+
+void app_host_GetClientData(uint8_t temp)
+{//AA 06 F9 A1 01 4B
+	static uint8_t buf=BLE_UPDATE_DATA;
+	BLE_Host_Tx_Send(0,BLE_UPDATE,&buf,1);
+	if(0 == mBLE_Host_T_UPDATE_DATA_R.n && temp >=2){
+		mBLE_Host_T_UPDATE_DATA_R.n = temp;
+		BLE_Host_Tx_Send(&mBLE_Host_T_UPDATE_DATA_R,BLE_UPDATE,&buf,1);
+	}
+}
+
+ //>> 0xA1: 查询
+void cb_BLE_Host_R_UPDATE(void* handle)
+{
+	BLE_Host_Rx_t *target = handle;
+	uint8_t _cmd = target->pDat[0];
+	switch(_cmd){
+		case BLE_UPDATE_BASEINFO:{
+			//<< 0(子命令): 设备型号(64)+左鞋蓝牙地址(6)+硬件版本(2)+软件版本(2)+右鞋蓝牙地址(6)+硬件版本(6)+软件版本(2)
+			for(int i=0;i<6;i++) mFlash.mClient.macAddr[i] = target->pDat[i+1+SHOES_NAME_LEN];
+			SEGGER_RTT_printf(0,"mFlash.mClient.macAddr:%02X %02X %02X %02X %02X %02X\n",mFlash.mClient.macAddr[0],mFlash.mClient.macAddr[1],mFlash.mClient.macAddr[2],mFlash.mClient.macAddr[3],mFlash.mClient.macAddr[4],mFlash.mClient.macAddr[5]);
+			uint8_t L = SHOES_NAME_LEN+7;
+			mFlash.mClient.hardVersion = ((uint32_t)target->pDat[L]<<24)  |((uint32_t)target->pDat[L+1]<<16) |((uint32_t)target->pDat[L+2]<<8) |((uint32_t)target->pDat[L+3]);
+			mFlash.mClient.sotfVersion =  target->pDat[L+4];
+//			SEGGER_RTT_printf(0,"BLE_Host_R_UPDATE_BASEINFO:"); for(int i=64;i<(28+64);i++){SEGGER_RTT_printf(0,"%02X ",target->pDat[i]);} SEGGER_RTT_printf(0,"\r\n");
+//			SEGGER_RTT_printf(0,"sotfVersion,hardVersion:%x,%x\n",mFlash.mClient.sotfVersion,mFlash.mClient.hardVersion);
+			app_client_infomation_Send();
+			break;}
+		case BLE_UPDATE_DATA:{
+			//<< 1(子命令): 左鞋电量(1)+左鞋温度(1)+左鞋压力(4)+左鞋步数(4)+右鞋电量(1)+右鞋温度(1)+右鞋压力(4)+右鞋步数(4)
+			vol_R = target->pDat[1];
+			temp_R = target->pDat[2];
+			press_R = ((uint32_t)target->pDat[3]<<24)|((uint32_t)target->pDat[4]<<16)|((uint32_t)target->pDat[5]<<8)|((uint32_t)target->pDat[6]<<0);
+			mFlash.mStep.stepCur[1]  = ((uint32_t)target->pDat[7]<<24)|((uint32_t)target->pDat[8]<<16)|((uint32_t)target->pDat[9]<<8)|((uint32_t)target->pDat[10]<<0);
+			mBLE_Host_T_UPDATE_DATA_R.n = 0;
+			app_client_DataUpdate_Send();
+//			SEGGER_RTT_printf(0,"right step:%d\n",mFlash.mStep.stepCur[1]);
+			break;}
+	default:break;
+	}
+}
+
+
+void app_host_Initialize(void)
+{
+	if(mFlash.isHost==1){
+		BLE_Host_Rx_Regist(BLE_UPDATE,cb_BLE_Host_R_UPDATE);
+	}
+}
+

+ 26 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_host.h

@@ -0,0 +1,26 @@
+#ifndef __app_host_h__
+#define __app_host_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void app_host_Initialize(void);
+
+//void app_host_GetMac_R(uint8_t* p);
+//uint16_t app_host_HardVer_R(void);
+//uint16_t app_host_SoftVer_R(void);
+
+uint8_t app_host_GetVol_R(void);
+uint8_t app_host_GetTemp_R(void);
+uint32_t app_host_GetPress_R(void);
+void app_host_GetClientInfo(void);
+void app_host_GetClientData(uint8_t temp);
+
+
+#endif
+
+
+

+ 39 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_losspack.c

@@ -0,0 +1,39 @@
+#include "app_losspack.h"
+#include "bsp_time.h"
+#include "app_flash.h"
+#include "system.h"
+#include "hal_ble_client.h"
+#include "ble_comm.h"
+
+#if LOSSPACK_ENANBLE 
+uint16_t lose_pack_all =0;
+
+void LossPack_process(void){
+	
+	uint16_t pack_l =0;
+	
+	uint8_t rssi = 0-host_get_rssi();
+	
+	pack_l = lose_pack_all;
+	uint8_t buf[8];
+	uint8_t L = 0;
+	buf[L++] = (uint8_t)(pack_l>>8);
+	buf[L++] = (uint8_t)(pack_l);
+	buf[L++] = (uint8_t)(rssi);
+	BLE_Client_Tx_Send(0,(BLE_CMD_n)0x03,buf,L);
+//	SEGGER_RTT_printf(0,"lose_pack_all:%d, h_rssi=%d\r\n",lose_pack_all,rssi);
+	
+	lose_pack_all = 0;
+}
+
+
+void app_losspack_Init(void)
+{
+	if(mFlash.isHost)Process_Start(1000,"LossPack_process",LossPack_process);
+}
+#endif
+
+
+
+
+

+ 17 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_losspack.h

@@ -0,0 +1,17 @@
+#ifndef __APP_LOSSPACK_H__
+#define __APP_LOSSPACK_H__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+
+
+void app_losspack_Init(void);
+
+#endif
+
+
+

+ 257 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_math.c

@@ -0,0 +1,257 @@
+#include "app_math.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_ser_imu_mode_manage.h"
+#include "math.h"
+#include "ble_comm.h"
+#include "app_flash.h"
+#include "detect_zero_vel.h"
+#include "tool.h"
+#include "app_switchimu.h"
+#include "detect_step_by_mag.h"
+#include "pdrStatus.h"
+#include "detect_step_by_mag.h"
+#include "app_client_step.h"
+
+#define IMU_MAX_GROUP_NUM 20
+
+static int16_t 	acc_front[IMU_MAX_GROUP_NUM][3];
+static int16_t  gry_front[IMU_MAX_GROUP_NUM][3];
+static int16_t	mag6310_front[IMU_MAX_GROUP_NUM][3];
+
+static int16_t	mag6310_back[3];
+static int32_t	timestamp_front[IMU_MAX_GROUP_NUM];
+static uint8_t  rssi;
+
+static int16_t  IMU_STATUS; //记录状态用来重新记录时间戳
+
+static int32_t  timestamp;
+
+static int32_t  last_timestamp;
+
+void process_imu_data_front(int front_index)
+{
+	if(IMU_STATUS != 1)
+	{
+		IMU_STATUS = 1;
+		
+		last_timestamp = timestamp_front[0];
+		
+		timestamp = 0;
+	}
+	
+	if(front_index >IMU_MAX_GROUP_NUM)return;
+	for(int i = 0; i < front_index; i++)
+	{
+		int32_t dt = timestamp_front[i] - last_timestamp;
+		
+		if(dt > 20000 || dt < 0)
+		{
+			dt = 10000;
+		}
+		
+		timestamp += dt;
+		
+		SEGGER_RTT_printf(0,"timestamp_front[i] - last_timestamp : %d;  i = %d NRF_RTC0->COUNTER:%d\r\n", timestamp_front[i] - last_timestamp, i,NRF_RTC0->COUNTER);
+		
+		last_timestamp = timestamp_front[i];
+		
+//		SEGGER_RTT_printf(0,"timestamp_front[i] : %d;  i = %d\r\n", timestamp_front[i], i);
+		
+		IMU_Process_motion_queue(mFlash.isHost, timestamp, acc_front[i],
+		gry_front[i],mag6310_front[i], mag6310_back, rssi);
+	}
+}
+
+void app_math_TimerCounter(int front_num, int back_num)
+{
+	ser_imu_data_t		data;
+	int16_t 				group_num = 0;
+	
+	//游戏模式
+	if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_GAME) != -1){
+
+		
+		rssi = 0-host_get_rssi();
+		group_num = hal_ser_imu_mode_manage_get_data_num(SER_IMU_DIR_FRONT);
+		if(group_num >IMU_MAX_GROUP_NUM || front_num == 0)return;
+		for(int i=0;i<group_num;i++){
+			hal_ser_imu_mode_manage_get_data(SER_IMU_DIR_FRONT, i, &data);
+			gry_front[i][0] = data.gry[0];gry_front[i][1] = data.gry[1];gry_front[i][2] = data.gry[2];
+			acc_front[i][0] = data.acc[0];acc_front[i][1] = data.acc[1];acc_front[i][2] = data.acc[2];
+			mag6310_front[i][0] = data.mag[0];mag6310_front[i][1] = data.mag[1];mag6310_front[i][2] = data.mag[2];
+			timestamp_front[i] = data.fifo_timestamp;
+//			JS_RTT_Print_06(acc_front[i][0],acc_front[i][1],acc_front[i][2],gry_front[i][0],gry_front[i][1],gry_front[i][2]);
+//			JS_RTT_Print_06(mag6310_front[i][0],mag6310_front[i][1],mag6310_front[i][2],timestamp_front[i],0,0);
+		}
+		
+		if(hal_ser_imu_mode_manage_get_data_num(SER_IMU_DIR_BACK) >= 1){
+			hal_ser_imu_mode_manage_get_data(SER_IMU_DIR_BACK, 0, &data);
+			mag6310_back[0] = data.mag[0];mag6310_back[1] = data.mag[1];mag6310_back[2] = data.mag[2];
+		}
+		
+		if(mFlash.isHost){
+				process_imu_data_front(group_num);
+			}else if(Slave_Get7_5ms_interval()){
+				process_imu_data_front(group_num);
+			}
+			
+	}else{
+	 //将状态重设为0
+	 IMU_STATUS = 0;
+	 set_pdr_status();
+	}
+			 
+	
+	//实时计步模式
+	if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_REALSTEP) != -1){
+		rssi = 0-host_get_rssi();
+		group_num = hal_ser_imu_mode_manage_get_data_num(SER_IMU_DIR_FRONT);
+		if(group_num >IMU_MAX_GROUP_NUM || front_num == 0)return;
+		for(int i=0;i<group_num;i++){
+			hal_ser_imu_mode_manage_get_data(SER_IMU_DIR_FRONT, i, &data);
+			gry_front[i][0] = data.gry[0];gry_front[i][1] = data.gry[1];gry_front[i][2] = data.gry[2];
+			acc_front[i][0] = data.acc[0];acc_front[i][1] = data.acc[1];acc_front[i][2] = data.acc[2];
+			mag6310_front[i][0] = data.mag[0];mag6310_front[i][1] = data.mag[1];mag6310_front[i][2] = data.mag[2];
+			timestamp_front[i] = data.fifo_timestamp;
+		}
+		if(hal_ser_imu_mode_manage_get_data_num(SER_IMU_DIR_BACK) >= 1){
+			hal_ser_imu_mode_manage_get_data(SER_IMU_DIR_BACK, 0, &data);
+			mag6310_back[0] = data.mag[0];mag6310_back[1] = data.mag[1];mag6310_back[2] = data.mag[2];
+		}
+		
+//		SEGGER_RTT_printf(0,"======RealTimeStep=====%d\r\n",TIME_GetTicks());
+		if(RealTimeStep((int16_t*)mag6310_front, (int16_t*)mag6310_back, (int16_t*)acc_front)){
+			 mFlash.mStep.stepCur[0]++;
+			 SEGGER_RTT_printf(0,"======RealTimeStep=====step %d\r\n",mFlash.mStep.stepCur[0]);
+		}		 
+	}
+}
+
+static void app_math_DailyStep_Process(void)
+{
+	int16_t 	acc[3];
+	int16_t		mag6310[3];
+	int16_t 					group_num = 0;
+	ser_imu_data_t		data;
+	
+	if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_NORMAL) != -1 && hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_REALSTEP) == -1){
+
+		group_num = hal_ser_imu_mode_manage_get_data_num(SER_IMU_DIR_FRONT);
+		for(int i=0; i < group_num; i++){
+			hal_ser_imu_mode_manage_get_data(SER_IMU_DIR_FRONT, i, &data);
+			mag6310[0] = data.mag[0];mag6310[1] = data.mag[1];mag6310[2] = data.mag[2];
+			acc[0] = data.acc[0];acc[1] = data.acc[1];acc[2] = data.acc[2];
+			
+//			SEGGER_RTT_printf(0,"f_mx=%d\r,f_my=%d\r,f_mz=%d\r\n",mag6310[0],mag6310[1],mag6310[2]);
+			if(1 == detect_step_by_mag(mag6310,acc[2])){
+					mFlash.mStep.stepCur[0]++;
+				  SEGGER_RTT_printf(0,"DailyStep current step:%d\r\n",mFlash.mStep.stepCur[0]);
+				  break;
+			}
+		}
+	}
+}
+
+
+static uint32_t timeCNT = 0;
+static uint8_t FlagFix_process = 0;
+//一小时计时
+static void app_math_Hour_process(void){
+	uint32_t sec = 0;
+	static uint32_t cnt_b=0;
+	uint32_t cnt = NRF_RTC0->COUNTER;
+	if(cnt<cnt_b) cnt += 16777216;
+	timeCNT += cnt - cnt_b;
+	sec = timeCNT/32768;
+	if(sec >= 130000 )SEGGER_RTT_printf(0,"!!!!!!!!!!!!!!! sec over,%d,%d,%d\n",cnt,cnt_b,sec);
+	if(cnt >16777216)cnt_b = cnt - 16777216;
+	else cnt_b = cnt;
+	
+	if(sec>=60*60){
+		app_client_step_SetIsScan();
+		FlagFix_process =1;
+		timeCNT =0;
+		SEGGER_RTT_printf(0,"timeCNT(%d)(%d)\n",timeCNT,sec);
+		
+	}
+}
+
+static void app_gyro_Fix_process(void){//陀螺仪零偏矫正
+	static uint8_t state =0;
+	static int16_t sample_count =0;
+	static uint32_t tim =0;
+	int16_t f_gry[3];
+	ser_imu_data_t data;
+	
+	switch(state){
+		case 0:
+			    if(-1 == hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_GAME) && 1 == FlagFix_process){
+							Process_SetHoldOn(app_gyro_Fix_process,1);
+							hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_CALIBRATION, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_ON);
+							state =1;
+						  FlagFix_process =0;
+						  tim = TIME_GetTicks();
+//							SEGGER_RTT_printf(0,"====>>>>HAL_SER_IMU_MODE_MANAGE_CALIBRATION\r\n");
+					}
+			    break;
+		case 1:
+			    if(0 == hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_CALIBRATION)){
+						 state =2;
+						 Process_UpdatePeroid(app_gyro_Fix_process,10);
+						 sample_count =0;
+						 tim = TIME_GetTicks();
+//						 SEGGER_RTT_printf(0,"====INTO HAL_SER_IMU_MODE_MANAGE_CALIBRATION\r\n");
+					}else{
+						 if(TIME_GetTicks()-tim>=30000){tim = TIME_GetTicks();//进入游戏模式30秒失败
+//							 SEGGER_RTT_printf(0,"====cnt >= 3000\r\n");
+						   state =3;
+						 }
+					}
+					if(0 == hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_GAME))state =3;//游戏模式下退出
+			    break;
+		case 2:
+					//读取ACC值
+					if(hal_ser_imu_mode_manage_get_data_num(SER_IMU_DIR_FRONT) >= 1){
+						hal_ser_imu_mode_manage_get_data(SER_IMU_DIR_FRONT, 0, &data);
+						f_gry[0] = data.gry[0];f_gry[1] = data.gry[1];f_gry[2] = data.gry[2];
+						estimate_gyr_bias_interface(f_gry,sample_count);
+//						SEGGER_RTT_printf(0,"====>>>>gry:%d,%d,%d,tim:%d\r\n",f_gry[0],f_gry[1],f_gry[2],sample_count);
+						sample_count++;
+					}
+					if(TIME_GetTicks()-tim>=10000){ //跑完10秒退出
+						 state =3;
+//						 SEGGER_RTT_printf(0,"====>>>>HAL_SER_IMU_MODE_MANAGE_CALIBRATION\r\n");
+					}
+					if(0 == hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_GAME))state =3;//游戏模式下退出
+			    break;
+		case 3:
+			    Process_UpdatePeroid(app_gyro_Fix_process,1000);
+		      hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_CALIBRATION, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+		      Process_SetHoldOn(app_gyro_Fix_process,0);
+				  state =0;
+//		      SEGGER_RTT_printf(0,"====OUT app_gyro_Fix_process\r\n");
+			    break;
+	}
+	
+}
+
+void app_math_Init(void)
+{
+	Process_Start(100,"app_math_DailyStep_Process",app_math_DailyStep_Process);
+//	Process_Start(10,"app_math_TimerCounter",app_math_TimerCounter);
+	
+	hal_ser_imu_data_update_notify(app_math_TimerCounter);
+	
+	Process_Start(500,"app_gyro_Fix_process",app_gyro_Fix_process);
+	Process_Start(1000,"app_math_Hour",app_math_Hour_process);
+}
+
+
+
+
+
+
+
+
+

+ 15 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_math.h

@@ -0,0 +1,15 @@
+#ifndef __APP_MATH_H__
+#define __APP_MATH_H__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void app_math_Init(void);
+
+#endif
+
+
+

+ 55 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_organ.c

@@ -0,0 +1,55 @@
+
+#include "app_organ.h"
+#include "nrf_gpio.h"
+#include "usr_config.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_mt.h"
+#include "app_host.h"
+#include "app_charge.h"
+#include "hal_ble_client.h"
+#include "hal_ble_host.h"
+#include "nrf_delay.h"
+#include "hal_flash.h"
+#include "ble_comm.h"
+#include "hal_imu.h"
+
+#if LASER_ENABLE
+static uint8_t OrganIs_open = 0;
+
+void cb_BLE_CLient_R_SET_ORGAN(void* handle)
+{
+	BLE_Client_Rx_t* target = handle;
+	OrganIs_open = target->pDat[0];
+	SEGGER_RTT_printf(0,"cb_BLE_CLient_R_SET_ORGAN...%d\n",OrganIs_open);
+	IMU_SwitchOrgan(OrganIs_open);
+	BLE_Host_Tx_Send(0,BLE_Host_T_SET_ORGAN,&OrganIs_open,1);
+}
+
+//void app_oragan_Process(void)
+//{
+//	static uint32_t tim=0;
+//	if(TIME_GetTicks()-tim>=1000){ tim = TIME_GetTicks();
+//	  
+// }   
+//}
+
+/*********************** ½ÓÊÕ´Ó»úÃüÁî ************************/
+void cb_Host_R_SET_ORGAN(void* handle)
+{
+	uint8_t data =0;
+	BLE_Host_Rx_t* target = handle;
+	data = (*target->pDat+IMU_GetOrgan());
+	SEGGER_RTT_printf(0,"Host_R_SET_ORGA...%d\n",data);
+	BLE_Client_Tx_Send(0,BLE_CLient_T_SET_ORGAN,&data,1);	//´Ó»úÓ¦´ð
+}
+
+void app_organ_Init(void)
+{
+//AA 06 F9 A9 01 53
+		BLE_Client_Rx_Regist(BLE_CLient_R_SET_ORGAN,cb_BLE_CLient_R_SET_ORGAN);
+//	  Process_Start(" ",app_oragan_Process);
+	  BLE_Host_Rx_Regist(BLE_Host_R_SET_ORGAN,cb_Host_R_SET_ORGAN);
+}
+#endif
+

+ 12 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_organ.h

@@ -0,0 +1,12 @@
+#ifndef __app_organ_h__
+#define __app_organ_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void app_organ_Init(void);
+
+#endif

+ 197 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_ota.c

@@ -0,0 +1,197 @@
+#include "app_ota.h"
+#include "nrf_gpio.h"
+#include "usr_config.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_mt.h"
+#include "app_host.h"
+#include "app_charge.h"
+#include "hal_ble_client.h"
+#include "hal_ble_host.h"
+#include "nrf_delay.h"
+#include "app_flash.h"
+#include "ble_comm.h"
+#include "exception.h"
+
+static ble_gap_addr_t mAddr;
+static uint32_t isOTA=0;
+static uint8_t isHostOTA=0;
+
+static bool app_shutdown_handler(nrf_pwr_mgmt_evt_t event)
+{
+    switch (event){
+        case NRF_PWR_MGMT_EVT_PREPARE_DFU:
+            break;
+        default:
+            return true;
+    }
+    SEGGER_RTT_printf(0,"Into bootloader\n");
+    return true;
+}
+
+
+NRF_PWR_MGMT_HANDLER_REGISTER(app_shutdown_handler, 0);
+
+static void app_ota_Process(void)
+{
+	static uint8_t state = 0;
+	char buf[16];
+
+	uint8_t responhost =0;
+	switch(state){
+		case 0:{
+			if(mFlash.isHost > 0){//左鞋
+				 if(1 == isHostOTA){
+					 SEGGER_RTT_printf(0,"------>isHostOTA\n");
+					 state = 1;
+					 host_disconnect();
+					 nrf_ble_scan_stop();
+					 Process_UpdatePeroid(app_ota_Process,60000);
+					 BLE_Client_Tx_Send(0,BLE_DFU,&responhost,1);
+				 }
+			}
+			else{
+					if(isOTA==1){ isOTA = 0;
+						if(slave_isconnect()) slave_disconnect();
+						else advertising_stop();
+						memset(buf,0,16);
+						sprintf(buf,"SH_%02X%02X%02X%02X%02X%02X",mAddr.addr[5],mAddr.addr[4],mAddr.addr[3],mAddr.addr[2],mAddr.addr[1],mAddr.addr[0]);
+						SEGGER_RTT_printf(0,"OTA name(%d):%s\n",strlen(buf),buf);
+						slave_set_adv_name(buf,strlen(buf));
+						slave_adv_init();
+						state = 1;
+						Process_UpdatePeroid(app_ota_Process,2000);
+					}
+			}
+			break;}
+		case 1:{
+			if(mFlash.isHost > 0){//左鞋
+				isHostOTA =0;
+				state =0;
+				SEGGER_RTT_printf(0,"------>left out to dfu\n");
+			}
+			else{
+				if(slave_isconnect()==0){
+					SEGGER_RTT_printf(0,"app_ota_Process advertising_start\r\n");
+					advertising_start();
+					Process_UpdatePeroid(app_ota_Process,60000);
+					state = 2;
+				}
+				else slave_disconnect();
+			}
+			break;}
+		case 2:{
+			if(slave_isconnect()) state = 0;
+			Process_UpdatePeroid(app_ota_Process,0);
+			advertising_stop();
+			memset(buf,0,16);
+			
+			#if BleNameHoldOn_ENANBLE 
+			slave_set_adv_name((char *)RIGHT_NAME,sizeof(RIGHT_NAME));
+			SEGGER_RTT_printf(0,"AdvName(%d):%s\n",sizeof(RIGHT_NAME),RIGHT_NAME);
+		  #else
+			sprintf(buf,"%02X%02X%02X%02X%02X%02X",mFlash.macHost[0],mFlash.macHost[1],mFlash.macHost[2],mFlash.mClient.macAddr[3],mFlash.mClient.macAddr[4],mFlash.mClient.macAddr[5]);
+			SEGGER_RTT_printf(0,"ADV name(%d):%s\n",strlen(buf),buf);
+			slave_set_adv_name(buf,strlen(buf));
+			#endif
+			
+			Except_TxError(EXCEPT_DFU,"adv disconnted over time");
+			slave_adv_init();
+			advertising_start();
+			state = 0;
+			break;}
+		  default:state = 0;Process_UpdatePeroid(app_ota_Process,0);break;
+	}
+	
+	
+}
+
+static uint8_t number =0;
+static uint8_t left_dfu_state =0;
+static void app_ota_sendleftstate(void)
+{
+	 if(number>0){
+		  BLE_Client_Tx_Send(0,BLE_DFU,&left_dfu_state,1);
+		  number--;
+	 }
+	 else Process_Stop(app_ota_sendleftstate);
+}
+
+/*********************** 接收从机命令 ************************/
+void cb_BLE_Host_R_DFU(void* handle)
+{
+	BLE_Host_Rx_t* target = handle;
+	Process_Start(500,"app_ota_sendleftstate",app_ota_sendleftstate);
+	number =10;
+	left_dfu_state = target->pDat[0];
+}
+
+/*********************** 接收手机命令 ************************/
+void cb_BLE_Client_R_DFU(void* handle)
+{
+	  SEGGER_RTT_printf(0,">>>>>>>>>>BLE_Client_R_DFU\n");
+		BLE_Client_Rx_t* target = handle;
+		if(mFlash.isHost>0){
+			 if(*target->pDat == 0){isHostOTA = 1;
+				  return; //左鞋不需要理会
+			 }
+			 else if(*target->pDat == 1){
+				  BLE_Host_Tx_Send(0,BLE_DFU,target->pDat,1);	//发给从机
+			 }
+		}
+		else {
+			uint8_t responhost =1;
+			BLE_Client_Tx_Send(0,BLE_DFU,&responhost,1);
+			isOTA = 1;
+		  SEGGER_RTT_printf(0,">>>>>>>>>>DFU start....\n");
+		}
+}
+
+uint8_t app_ota_host_state(void)
+{
+	  return isHostOTA;
+}
+
+#if BleNameHoldOn_ENANBLE
+extern uint8_t SaveFlashFlag_holdOn;
+static void app_ota_SaveFlash(void){
+	if(1 ==SaveFlashFlag_holdOn ){
+		 SaveFlashFlag_holdOn =0;
+		 if(Flash_SaveInfomation() != ZONE_OP_SUCCESS)Except_TxError(EXCEPT_DFU,"save information fail");
+		 if(Flash_SaveBackup() != ZONE_OP_SUCCESS)Except_TxError(EXCEPT_DFU,"save backup fail");
+		 uint8_t i =0;
+		 SEGGER_RTT_printf(0,"mac host addr:");for(i=0;i<6;i++){SEGGER_RTT_printf(0,"%02X ",mFlash.macHost[i]);}SEGGER_RTT_printf(0,"\n");
+		 SEGGER_RTT_printf(0,"mClient addr:");for(i=0;i<6;i++){SEGGER_RTT_printf(0,"%02X ",mFlash.mClient.macAddr[i]);}SEGGER_RTT_printf(0,"\n");
+		 SEGGER_RTT_printf(0,"macAddr_L:");for(i=0;i<6;i++){SEGGER_RTT_printf(0,"%02X ",mBackup.macAddr_L[i]);}SEGGER_RTT_printf(0,"\n");
+		 SEGGER_RTT_printf(0,"mBackup.macAddr_R:");for(i=0;i<6;i++){SEGGER_RTT_printf(0,"%02X ",mBackup.macAddr_R[i]);}SEGGER_RTT_printf(0,"\n");
+	}
+}
+#endif
+
+
+void app_ota_Init(void)
+{
+	uint32_t err_code = sd_ble_gap_addr_get(&mAddr); APP_ERROR_CHECK(err_code); 
+	Process_Start(0,"app_ota_Process",app_ota_Process);
+	BLE_Client_Rx_Regist(BLE_DFU,cb_BLE_Client_R_DFU);
+  BLE_Host_Rx_Regist(BLE_DFU,cb_BLE_Host_R_DFU);
+	
+	#if BleNameHoldOn_ENANBLE
+	SEGGER_RTT_printf(0,"mac addr:");for(int i=0;i<6;i++){SEGGER_RTT_printf(0,"%02X ",mAddr.addr[i]);}SEGGER_RTT_printf(0,"\n");
+	uint8_t i=0;
+	for(i=0;i<6;i++)if(mFlash.macHost[i] !=0xff)break;
+	if(6 ==i){
+		 for(uint8_t a=0;a<6;a++){
+			   mFlash.macHost[a] = mAddr.addr[5-a];
+			   mBackup.macAddr_L[a] = mAddr.addr[5-a];
+		 }
+		 SaveFlashFlag_holdOn =1;
+	}
+	
+	Process_Start(1000,"app_ota_SaveFlash",app_ota_SaveFlash);
+	#endif
+	
+	
+}
+
+

+ 13 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_ota.h

@@ -0,0 +1,13 @@
+#ifndef __app_ota_h__
+#define __app_ota_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void app_ota_Init(void);
+uint8_t app_ota_host_state(void);
+
+#endif

+ 140 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_overturn.c

@@ -0,0 +1,140 @@
+#include "usr_config.h"
+#include "hal_battery.h"
+#include "nrf_drv_saadc.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_led.h"
+#include "hal_ser_imu_mode_manage.h"
+#include "app_overturn.h"
+#include "hal_wearshoes.h"
+
+#define acc1iValue_noshoes 1200
+
+#define acc0Value  -1400
+
+#define acc1iValue -1400
+#define acc1aValue 1800
+#define acc2iValue -1500
+#define acc2aValue 400				
+				
+/************************ 踮脚显示电量 ***********************************/
+static uint8_t flag_move =0;
+
+void app_BatDispaly_Process_N(void)        
+{
+		int16_t acc[3] = {0,0,0};
+	  ser_imu_data_t data;
+		static uint32_t cnt = 0;
+					
+		if(-1 == hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_STANDBY)) return;//停止状态
+					
+		//获取最新一组前脚加速度
+		if(hal_ser_imu_mode_manage_get_data_num(SER_IMU_DIR_FRONT) >= 1){
+			hal_ser_imu_mode_manage_get_data(SER_IMU_DIR_FRONT, 0, &data);
+			acc[0] = data.acc[0];acc[1] = data.acc[1];acc[2] = data.acc[2];
+		}
+	  
+//		SEGGER_RTT_printf(0,"0:acc[0]=%d,acc[1]=%d,acc[2]=%d\n",acc[0],acc[1],acc[2]);
+		if(acc[2] > acc1iValue_noshoes){
+				cnt++;
+				if(cnt ==(1500/StandByPower_Interval) ){ 
+//					  SEGGER_RTT_printf(0,">>>>>>>0:acc[0]=%d,acc[1]=%d,acc[2]=%d\n",acc[0],acc[1],acc[2]);
+						if(GetBatteryPersent()>20){
+								LED_Start(LED_OVERTURN,COLOR_GREEN);
+						}else{
+								LED_Start(LED_OVERTURN,COLOR_ORANGE);
+						}
+						Process_SetHoldOn(app_BatDispaly_Process_N,1);
+				}
+				if(cnt >= (10000/StandByPower_Interval)){
+						LED_Stop(LED_OVERTURN);
+						Process_SetHoldOn(app_BatDispaly_Process_N,0);
+				}
+		}else{
+				if(cnt>0){ cnt = 0;
+						LED_Stop(LED_OVERTURN);
+						Process_SetHoldOn(app_BatDispaly_Process_N,0);
+				}
+				if(1== flag_move){
+					 flag_move =0;
+					 LED_Stop(LED_OVERTURN);
+					 Process_SetHoldOn(app_BatDispaly_Process_N,0);
+				}
+		}
+}
+
+void app_BatDispaly_Process(void)
+{
+		int16_t acc[3] = {0,0,0};
+	  ser_imu_data_t data;
+		static uint32_t cnt = 0;
+		static int16_t         acc0 = acc0Value;
+		static int16_t         acc1i = acc1iValue;
+		static int16_t         acc1a = acc1aValue;
+		static int16_t         acc2i = acc2iValue;
+		static int16_t         acc2a = acc2aValue;
+
+		if(-1 == hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_NORMAL)) return;//走路状态
+	
+		//获取最新一组前脚加速度
+	  if(hal_ser_imu_mode_manage_get_data_num(SER_IMU_DIR_FRONT) >= 1){
+			hal_ser_imu_mode_manage_get_data(SER_IMU_DIR_FRONT, 0, &data);
+			acc[0] = data.acc[0];acc[1] = data.acc[1];acc[2] = data.acc[2];
+		}
+		
+//     SEGGER_RTT_printf(0,"1:acc[0]=%d,acc[1]=%d,acc[2]=%d\n",acc[0],acc[1],acc[2]);
+		if(acc[0] < acc0 &&  
+			(acc[1] > acc1i && acc[1] < acc1a) &&  
+			(acc[2] < acc2a && acc[2] > acc2i)){
+				cnt++;
+				if(cnt==(1500/StandByPower_Interval)){ 
+						if(GetBatteryPersent()>20){
+							LED_Start(LED_OVERTURN,COLOR_GREEN);
+						}else{
+							LED_Start(LED_OVERTURN,COLOR_ORANGE);
+						}
+						Process_SetHoldOn(app_BatDispaly_Process,1);
+						acc0 = acc0Value;
+						acc1i = acc1iValue;
+						acc1a = acc1aValue;
+						acc2i = acc2iValue;
+						acc2a = acc2aValue;
+				}
+				if(cnt == (10000/StandByPower_Interval)){
+						LED_Stop(LED_OVERTURN);
+						Process_SetHoldOn(app_BatDispaly_Process,0);
+						acc0 = acc0Value-200;
+						acc1i = acc1iValue;
+						acc1a = acc1aValue;
+						acc2i = acc2iValue;
+						acc2a = acc2aValue;
+				}
+		}else{
+				if(cnt>0){ cnt = 0;
+						LED_Stop(LED_OVERTURN);
+						Process_SetHoldOn(app_BatDispaly_Process,0);
+						acc0 = acc0Value;
+						acc1i = acc1iValue;
+						acc1a = acc1aValue;
+						acc2i = acc2iValue;
+						acc2a = acc2aValue;
+				}
+				if(flag_move == 0){
+					 flag_move =1;
+					 LED_Stop(LED_OVERTURN);
+					 Process_SetHoldOn(app_BatDispaly_Process,0);
+					 acc0 = acc0Value;
+					 acc1i = acc1iValue;
+					 acc1a = acc1aValue;
+					 acc2i = acc2iValue;
+					 acc2a = acc2aValue;
+				}
+		}
+}
+
+
+void app_overturn_Init(void)
+{
+	Process_Start(StandByPower_Interval,"BatDispaly",app_BatDispaly_Process);
+	Process_Start(StandByPower_Interval,"BatDispaly_N",app_BatDispaly_Process_N);
+}

+ 14 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_overturn.h

@@ -0,0 +1,14 @@
+#ifndef __app_overturn_h__
+#define __app_overturn_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void app_overturn_Init(void);
+
+#endif
+
+

+ 315 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_pair.c

@@ -0,0 +1,315 @@
+/*********************************************************************
+ * INCLUDES
+ */
+#include "ble_comm.h"
+#include "ble_gap.h"
+#include "nrf_gpio.h"
+#include "bsp_time.h"
+#include "app_flash.h"
+#include "hal_ble_uart0.h"
+#include "hal_ble_client.h"
+#include "hal_ble_host.h"
+#include "hal_led.h"
+#include "app_charge.h"
+#include "app_pair.h"
+#include "hal_mt.h"
+
+/*********************************************************************
+* LOCAL DEFINETION
+*/
+
+/*********************************************************************
+* LOCAL VARIABLES
+*/
+static ble_gap_addr_t mAddr;
+static uint16_t isConfigcnt = 0;
+static uint8_t PairFlagHost =0;
+static uint8_t GetUartData =0;
+
+/*********************************************************************
+* LOCAL FUNCTIONS
+*/
+
+static pair_reslt_t  Pair_result_t_head ={
+	.next =NULL,
+};
+
+void app_UartPair_Regist(pair_reslt_t *cb){
+	pair_reslt_t *target = &Pair_result_t_head;
+	while(NULL != target->next){
+		if(target->next == cb)return;//检查是否已经存在
+		target = target->next;
+	}
+	cb->next = NULL;
+	target->next = cb; 
+}
+
+void app_UartPair_Clear(pair_reslt_t *cb){
+	pair_reslt_t *target = &Pair_result_t_head;
+	while(NULL != target->next){
+		if(cb == target->next){
+			target->next = cb->next;
+			return;
+		}
+		target = target->next;
+	}
+}
+
+static void app_UartPair_Result_Add(void){
+	 pair_reslt_t *target = &Pair_result_t_head;
+	 while(NULL != target->next){
+			target->next->flag =1;
+			target = target->next;
+	 }
+}
+
+
+void UART0_Config_Send(uint8_t cmd)
+{
+	uint8_t buf[32];
+	uint8_t L = 0;
+	//MAC 地址
+	for(int i=0;i<6;i++){
+		buf[L++] = mAddr.addr[5-i];
+	}
+	//硬件版本
+	buf[L++] = (uint8_t)((uint32_t)HARDWARE_VERSION>>24);
+	buf[L++] = (uint8_t)((uint16_t)HARDWARE_VERSION>>16);
+	buf[L++] = (uint8_t)((uint32_t)HARDWARE_VERSION>>8);
+	buf[L++] = (uint8_t)((uint16_t)HARDWARE_VERSION>>0);
+	//软件版本
+	buf[L++] = (uint8_t)((uint32_t)HARDWARE_VERSION>>24);
+	buf[L++] = (uint8_t)((uint16_t)HARDWARE_VERSION>>16);
+	buf[L++] = (uint8_t)((uint32_t)HARDWARE_VERSION>>8);
+	buf[L++] = SOFTWARE_VERSION;
+	UART0_Tx_Send(0,cmd,buf,L);
+}
+
+#define PAIR_TIMES								50					//配对次数
+static void app_pair_Process(void)
+{
+	static uint8_t flag = 0;
+	if(app_charge_Getstate()!=BLE_CHARGE_PULLOUT){
+		if(flag != 1)
+		{
+			if(mFlash.isHost)UART0_Initialize(PIN_TXD_BLE,PIN_RXD_BLE,UART_HZ);
+			else UART0_Initialize(UART0_INVALID_PIN,PIN_RXD_BLE,UART_HZ);
+			flag = 1;
+		}
+		else if(isConfigcnt<PAIR_TIMES){ isConfigcnt++;
+			if(mFlash.isHost){ //充电模式下主机主机申请配对
+				UART0_Initialize(PIN_TXD_BLE,PIN_RXD_BLE,UART_HZ);
+				UART0_Config_Send(UART0_T_CONFIG_ASK);
+				UART0_Initialize(UART0_INVALID_PIN,PIN_RXD_BLE,UART_HZ);
+			}
+		}
+	}else{
+		if(flag != 2)
+		{
+			UART0_unInit(PIN_TXD_BLE,PIN_RXD_BLE);
+			flag = 2;
+//			nrf_gpio_cfg_output(PIN_LED_RUN); 	nrf_gpio_pin_write(PIN_LED_RUN,LED_SMALL_DISABLE);
+		}
+		else if(isConfigcnt>0) isConfigcnt = 0;
+	}
+	
+	static uint8_t Pair_state =0;
+	static uint32_t tim =0;
+	char buf[16];
+	uint8_t i =0;
+	switch(Pair_state){
+				case 0:
+					    if(PairFlagHost){
+								 mFlash.mClient.isConfig = 'C';
+								 memset(&mFlash.mStep,0,sizeof(FlashStep_t));//配对时候清空步数
+								 MT_Run(500);
+								 PairFlagHost =0;
+								 Pair_state =1;
+								 for(i=0;i<6;i++){
+									 mBackup.macAddr_L[i] = mFlash.macHost[i];		//主机地址
+									 mBackup.macAddr_R[i] = mFlash.mClient.macAddr[i];//从机地址
+								 }
+								 mBackup.hardVersion = mFlash.mClient.hardVersion;
+								 mBackup.sotfVersion = mFlash.mClient.sotfVersion;
+								 mBackup.isConfig    = mFlash.mClient.isConfig;
+								 if(Flash_SaveInfomation() != ZONE_OP_SUCCESS)Except_TxError(EXCEPT_Pair,"save information fail");
+								 if(Flash_SaveBackup() != ZONE_OP_SUCCESS)Except_TxError(EXCEPT_Pair,"save backup fail");
+								 if(Flash_SaveStep() != ZONE_OP_SUCCESS)Except_TxError(EXCEPT_DATEStep,"save step fail");
+								 
+								 SEGGER_RTT_printf(0,"mFlash.mClient.macAddr:%02X %02X %02X %02X %02X %02X\n",mFlash.mClient.macAddr[0],mFlash.mClient.macAddr[1],mFlash.mClient.macAddr[2],mFlash.mClient.macAddr[3],mFlash.mClient.macAddr[4],mFlash.mClient.macAddr[5]);
+								 SEGGER_RTT_printf(0,">>>>>>>>Pair_state =1 \r\n");
+								 tim = TIME_GetTicks();
+							}
+							break;
+				case 1:
+					    if(TIME_GetTicks()-tim>=10000){tim = TIME_GetTicks();//10秒超时退出
+								 Pair_state =0;
+								 SEGGER_RTT_printf(0,"Pair_state =0 \r\n");
+							}
+							if(mFlash.isHost){//主机处理
+									if(host_isconnect()){
+										 host_disconnect();
+									}else{
+										 SEGGER_RTT_printf(0,">>>>>ST_scan_start =0 \r\n");
+										 memset(buf,0,sizeof(buf));
+										 sprintf(buf,"%02X%02X%02X%02X%02X%02X",mFlash.macHost[0],mFlash.macHost[1],mFlash.macHost[2],mFlash.mClient.macAddr[3],mFlash.mClient.macAddr[4],mFlash.mClient.macAddr[5]);
+										 SEGGER_RTT_printf(0,"scanName(%d):%s\n",strlen(buf),buf);
+										 host_set_scan_name(buf,strlen(buf));
+										 ST_scan_stop();
+										 ST_scan_start();
+										 Pair_state = 0;
+									}
+							}else{//从机处理
+								 if(slave_isconnect()) slave_disconnect();
+								 else {
+										 memset(buf,0,sizeof(buf));
+										 sprintf(buf,"%02X%02X%02X%02X%02X%02X",mFlash.macHost[0],mFlash.macHost[1],mFlash.macHost[2],mFlash.mClient.macAddr[3],mFlash.mClient.macAddr[4],mFlash.mClient.macAddr[5]);
+										 SEGGER_RTT_printf(0,"advName(%d):%s\n",strlen(buf),buf);
+										 slave_set_adv_name(buf,strlen(buf));
+										 advertising_stop();
+										 slave_adv_init();
+										 SEGGER_RTT_printf(0,">>>>>>>>advertising_start =0 \r\n");
+										 advertising_start();
+										 Pair_state = 0;
+								 }
+							}
+							break;
+			default:
+				      Pair_state = 0;
+				      break;
+								
+	}
+}
+
+#if BLUE_LED_TEST_ENANBLE
+void app_config_LED(void)
+{
+	static uint8_t state = 0;
+	switch(state){
+		case 0:
+			Process_SetHoldOn(app_config_LED,1);
+			LED_Start(LED_CONFIG,COLOR_BLUE);
+			state = 1;
+			Process_UpdatePeroid(app_config_LED,2000);
+			break;
+		case 1:
+			Process_UpdatePeroid(app_config_LED,0);
+			LED_Stop(LED_CONFIG);
+			state = 0;
+			Process_SetHoldOn(app_config_LED,0);
+			Process_Stop(app_config_LED);
+			break;
+		default:state=0;Process_UpdatePeroid(app_config_LED,0);break;
+	}
+}
+#endif
+
+void cb_UART0_R_CONFIG_ASK(void* handle)
+{	//从机接收到配对申请
+	UART0_Rx_t* target = handle;
+	uint8_t mac[6];
+	uint8_t ret = 0;
+  uint8_t i =0;
+	if(app_charge_Getstate()==BLE_CHARGE_PULLOUT) return; //非充电模式不匹配
+	if(mFlash.isHost)return; //防止主机自发自收
+	
+	for(i=0;i<6;i++) mac[i] = target->pDat[i];
+	
+  uint32_t hv = ((uint32_t)target->pDat[6]<<24)| ((uint32_t)target->pDat[7]<<16) | ((uint32_t)target->pDat[8]<<8) | ((uint32_t)target->pDat[9]<<0);
+	uint8_t  sv = target->pDat[10];
+	
+	UART0_Initialize(PIN_TXD_BLE,UART0_INVALID_PIN,UART_HZ);
+	for(i=0; i < 10; i++){
+	  UART0_Config_Send(UART0_T_CONFIG_ACK);//应答主机申请
+	}
+	UART0_Initialize(UART0_INVALID_PIN,PIN_RXD_BLE,UART_HZ);
+	
+	for(i=0;i<6;i++){
+		if(mFlash.macHost[i] != mac[i]){						        //检验主机发过来的mac地址是否上次的一样
+			 ret =1;
+			 break;
+		}
+	}
+
+	if(mFlash.mClient.hardVersion != hv || mFlash.mClient.sotfVersion != sv \
+		 || mBackup.isConfig != mFlash.mClient.isConfig
+	   || ret !=0
+	){
+		  mFlash.mClient.hardVersion = hv;
+	    mFlash.mClient.sotfVersion = sv;
+		  mBackup.hardVersion = mFlash.mClient.hardVersion;
+		  mBackup.hardVersion = mFlash.mClient.hardVersion;
+		
+		  for(i=0;i<6;i++){
+				 mFlash.mClient.macAddr[i] = mAddr.addr[5-i];	//从机自身mac地址
+				 mFlash.macHost[i] = mac[i];						      //主机发过来的mac地址
+	    }
+		  PairFlagHost =1;
+		  SEGGER_RTT_printf(0,"backup config:%d,hardVersion:%d,sotfVersion:%d\n",mBackup.isConfig,mBackup.hardVersion,mBackup.sotfVersion);
+	}
+	
+	app_UartPair_Result_Add();
+	#if BLUE_LED_TEST_ENANBLE
+	Process_Start(0,"config_LED",app_config_LED);
+	#endif
+}
+
+void cb_UART0_R_CONFIG_ACK(void* handle)
+{	//主机接收到配对应答
+	UART0_Rx_t* target = handle;
+	uint8_t mac[6];
+	uint8_t ret = 0;
+	uint8_t i=0;
+	if(app_charge_Getstate()==BLE_CHARGE_PULLOUT) return; //非充电模式不匹配
+	if(!mFlash.isHost) return; //从机自发自收
+	
+	for(i=0;i<6;i++) mac[i] = target->pDat[i];
+	uint32_t hv = ((uint32_t)target->pDat[6]<<24)| ((uint32_t)target->pDat[7]<<16) | ((uint32_t)target->pDat[8]<<8) | ((uint32_t)target->pDat[9]<<0);
+	uint8_t  sv = target->pDat[10];
+	
+	isConfigcnt = PAIR_TIMES+1;			//已配对,停止配对发送
+	
+	for(i=0;i<6;i++){
+		if(mFlash.mClient.macAddr[i] != mac[i]){						        //检验主机发过来的mac地址是否上次的一样
+			 ret =1;
+			 break;
+		}
+	}
+	
+	if(mFlash.mClient.hardVersion != hv || mFlash.mClient.sotfVersion != sv \
+		 || mBackup.isConfig != mFlash.mClient.isConfig
+	   || ret !=0
+	){
+		  mFlash.mClient.hardVersion = hv;
+	    mFlash.mClient.sotfVersion = sv;
+		  mBackup.hardVersion = hv;
+		  mBackup.hardVersion = sv;
+		
+		  for(i=0;i<6;i++){
+				 mFlash.mClient.macAddr[i] = mac[i]; 	//收到的从机mac地址
+		     mFlash.macHost[i] = mAddr.addr[5-i];	//主机本身mac地址
+	    }
+		  PairFlagHost =1;
+		  SEGGER_RTT_printf(0,"backup config:%d,hardVersion:%d,sotfVersion:%d\n",mBackup.isConfig,mBackup.hardVersion,mBackup.sotfVersion);
+	}
+	
+	app_UartPair_Result_Add();
+	#if BLUE_LED_TEST_ENANBLE
+	Process_Start(0,"config_LED",app_config_LED);
+	#endif
+}
+
+void app_pair_Init(void)
+{
+	uint32_t err_code = sd_ble_gap_addr_get(&mAddr); APP_ERROR_CHECK(err_code);
+	Process_Start(100,"app_pair_Process",app_pair_Process);
+	UART0_Rx_Regist(UART0_R_CONFIG_ASK,cb_UART0_R_CONFIG_ASK);
+	UART0_Rx_Regist(UART0_R_CONFIG_ACK,cb_UART0_R_CONFIG_ACK);
+}
+
+ 
+
+
+
+
+

+ 23 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_pair.h

@@ -0,0 +1,23 @@
+#ifndef __APP_PAIR_H__
+#define __APP_PAIR_H__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "system.h"
+#include "usr_config.h"
+
+typedef struct _pair_reslt_t{
+	 uint8_t flag;
+	 struct _pair_reslt_t *next;
+}pair_reslt_t;
+
+void app_pair_Init(void);
+void UART0_Config_Send(uint8_t cmd);
+void app_UartPair_Clear(pair_reslt_t *cb);
+void app_UartPair_Regist(pair_reslt_t *cb);
+
+#endif
+
+

+ 70 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_power/app_power.c

@@ -0,0 +1,70 @@
+#include "app_power.h"
+#include "nrf_gpio.h"
+#include "usr_config.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_mt.h"
+#include "hal_battery.h"
+#include "app_charge.h"
+#include "hal_ble_client.h"
+#include "nrf_delay.h"
+#include "app_flash.h"
+#include "bsp_wdt.h"
+#include "app_timer.h"
+#include "system.h"
+#include "bsp_pwm.h"
+#include "app_client.h"
+#include "hal_ble_uart0.h"
+#include "hal_led.h"
+#include "lsm6ds3tr_c.h"
+#include "hal_ser_imu_mode_manage.h"
+#include "app_math.h"
+
+/********************** 变量区 *************************/
+
+/********************** 函数声明区 *************************/
+void PWR_Off(void)
+{
+		UART0_unInit(PIN_TXD_BLE,PIN_RXD_BLE);
+	  LED_Close_Enforce();
+		hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_STANDBY, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+		hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_NORMAL, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+		hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+		hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_GAME, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+		hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_REALSTEP, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+		drv_lsm_power_off();
+		drv_qmc6310_power_off();
+	  
+		nrf_gpio_pin_write(PIN_MT_EN,0);
+		nrf_delay_ms(200);
+		nrf_gpio_cfg_sense_input(PIN_CHARGING, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH);//IO 
+		uint32_t err_code = sd_power_system_off();
+	  SEGGER_RTT_printf(0,"power off...BAT:%d,ERR:%d\n",GetBatteryPersent(),err_code);
+    //APP_ERROR_CHECK(err_code);
+}
+
+static void PWR_Process(void)
+{
+	if((0 == GetBatteryPersent() && app_charge_Getstate()==BLE_CHARGE_PULLOUT)){
+		SEGGER_RTT_printf(0,"BatteryPersent:%d\n",GetBatteryPersent());
+		SEGGER_RTT_printf(0,"power off...\n");
+		//保存数据到flash
+		if(Flash_SaveStep() != ZONE_OP_SUCCESS)Except_TxError(EXCEPT_Power,"save step fail");
+		if(Flash_SaveInfomation() != ZONE_OP_SUCCESS)Except_TxError(EXCEPT_Power,"save information fail");
+		MT_Run(1000);
+		feed_watchdog();
+		for(uint8_t temp = 0;temp < 10; temp++){
+				app_client_DataUpdate_Send();
+				nrf_delay_ms(100);
+		}
+		PWR_Off();
+	}
+}
+
+
+void PWR_Init(void)
+{
+	Process_Start(10000,"PWR_Process",PWR_Process);
+}
+
+

+ 13 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_power/app_power.h

@@ -0,0 +1,13 @@
+#ifndef __app_power_h__
+#define __app_power_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void PWR_Init(void);
+void PWR_Off(void);
+
+#endif

+ 33 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_safe.c

@@ -0,0 +1,33 @@
+/*********************************************************************
+ * INCLUDES
+ */
+#include "ble_comm.h"
+#include "app_flash.h"
+#include "hal_ble_client.h"
+#include "app_safe.h"
+#include "app_flash.h"
+
+static void app_safe_Process(void)
+{
+  static uint8_t cnt =0;
+	if(mBackup.ErrorStartFlag >0){
+		cnt++;
+		if(cnt >=6){//一分钟后清空标志位
+			mBackup.ErrorStartFlag =0;
+		  Flash_SaveBackup();
+			SEGGER_RTT_printf(0,"clear mBackup.ErrorStartFlag\n");
+		}
+	}
+}
+
+void app_safe_Init(void)
+{
+	Process_Start(10000,"app_safe_Process",app_safe_Process);
+}
+
+ 
+
+
+
+
+

+ 15 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_safe.h

@@ -0,0 +1,15 @@
+#ifndef __APP_SAFE_H__
+#define __APP_SAFE_H__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "system.h"
+#include "usr_config.h"
+
+void app_safe_Init(void);
+
+#endif
+
+

+ 398 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_self_checking - 副本.c

@@ -0,0 +1,398 @@
+/*Includes ----------------------------------------------*/
+#include "system.h"
+#include "exception.h"
+#include "app_charge.h"
+#include "app_flash.h"
+#include "app_self_checking.h"
+#include "hal_led.h"
+#include "hal_mt.h"
+#include "hal_ble_uart0.h"
+#include "hal_ble_client.h"
+#include "hal_ser_imu_mode_manage.h"
+#include "app_flash.h"
+#include "app_pair.h"
+#include "bsp_time.h"
+#include "hal_scan_manage.h"
+#include "ble_comm.h"
+
+/*Private macro ------------------------------------------------*/
+#define	SELF_CHECK_WHEEL_EMPTY_TIMES_MAX		MONITOR_SUSPEND_MODE_OVERFLOW_ERR_SUM_MAX			//允许最大轮空次数
+#define SELF_CHECK_ITEMS										6																							//自检项数
+#define SELF_CHECK_ITEM_SUCCESS							0																							//自检项目成功
+#define SELF_CHECK_ITEM_FAIL								1																							//自检项目失败
+
+#define SELF_CHECK_ITEM_FRONT_SENSOR_INDEX	0																							//自检项目 - 前脚传感器
+#define SELF_CHECK_ITEM_BACK_SENSOR_INDEX		1																							//自检项目 - 后脚传感器
+#define SELF_CHECK_ITEM_BATTERY_INDEX				2																							//自检项目 - 电量
+#define	SELF_CHECK_ITEM_CHARGE_INDEX				3																							//自检项目 - 充电电压
+#define SELF_CHECK_ITEM_ANT_INDEX						4																							//自检项目 - 天线
+#define SELF_CHECK_ITEM_SUSPEND_MODE_INDEX	5																							//自检项目 - 异常挂起			
+
+#define SELF_CHECK_PROCESS_CYCLE						10																						//自检线程周期 - ms为单位
+
+#define SELF_CHECK_LED_DISPLAY_TIME					3000					  //自检灯显示时长 - ms为单位
+
+#define SELF_CHECK_LED_TOGGLE_TIME					200						  //自检灯翻转时长 - ms为单位
+
+#define SELF_CHECK_SCAN_TRIGGER_TIMEOUT			10000						//扫描触发自检超时时间 - ms为单位
+
+#define SELF_CHECK_SET_IMU_TIMEOUT			    20000						//等待IMU初始化成功的时间
+
+#define SELF_CHECK_SCAN_TARGET_ADV_NAME			"SH_SELF_CHECK"																//扫描触发的目标广播名字
+
+/*STRUCTION --------------------------------------------------
+--*/
+typedef enum {
+	SELF_CHECK_STAGE_READY,																																	//准备阶段
+	SELF_CHECK_STAGE_CHECK,																																	//自检阶段
+	
+} SELF_CHECK_STAGE_e;
+typedef enum{
+	SELF_CHECK_LED_ON,																																			//自检灯 - 开
+	SELF_CHECK_LED_OFF,																																			//自检灯 - 关
+	
+} SELF_CHECK_LED_SWITCH_e;
+typedef struct self_check
+{
+	/*private member*/
+	SELF_CHECK_STAGE_e				stage;																												//阶段字段
+	
+	uint32_t								  ImuSetTime_times;																						  //轮空次数
+	
+	uint8_t										result[SELF_CHECK_ITEMS];																			//自检结果
+	
+	uint8_t										item_fail_num;																								//自检项目失败数量
+	
+	SELF_CHECK_LED_SWITCH_e		led_switch;																										//自检灯开关
+
+	uint32_t									led_display_time;																							//自检灯显示时长
+	
+	uint32_t									led_toggle_time;																							//自检灯翻转时长
+	
+	uint32_t									scan_trigger_timeout;																					//扫描触发自检超时时间
+	
+	bool											is_scan_success;																							//是否找到广播名字
+
+} Self_Check_t;
+
+/*Local Variable -----------------------------------------------*/
+static Self_Check_t ob_self_check;
+
+/*Local Functions ----------------------------------------------*/
+static void clear_all_except(void)
+{
+	Except_ClearExceptype(EXCEPT_DATA_BACK_MAG);
+	Except_ClearExceptype(EXCEPT_DATA_FRONT_ACC);
+	Except_ClearExceptype(EXCEPT_DATA_FRONT_GRY);
+	Except_ClearExceptype(EXCEPT_DATA_FRONT_MAG);
+	Except_ClearExceptype(EXCEPT_DATA_CHARGE);
+	Except_ClearExceptype(EXCEPT_DATA_BATTERY);
+	Except_ClearExceptype(EXCEPT_IMU_SUSPEND_OVERFLOW);
+	Except_ClearExceptype(EXCEPT_ANT_DAMAGE);
+}
+
+static void selft_scan_cb(void)
+{
+	ob_self_check.is_scan_success = true;
+}
+
+static scan_reslt_t scan_reslt_handle ={
+	.handle = selft_scan_cb,
+	.scanname =SELF_CHECK_SCAN_TARGET_ADV_NAME,
+};
+
+static uint8_t self_uart_check_flag =0;
+static void cb_UART0_R_LINE_CHECK_ACK(void* handle)
+{	
+	//主机接收到配对应答
+	if(!mFlash.isHost) return; //从机自发自收
+	self_uart_check_flag = 1;
+}
+
+static void cb_UART0_R_LINE_CHECK_ASK(void* handle)
+{	//从机接收到配对申请
+  uint32_t 		txd,rxd;
+	if(mFlash.isHost){
+		return; //防止主机自发自收
+	}
+	self_uart_check_flag =1;
+	
+	UART0_GetPinConfig(&txd, &rxd);
+	UART0_Initialize(PIN_TXD_BLE,UART0_INVALID_PIN,UART_HZ);
+	UART0_Config_Send(UART0_T_LINE_CHECK_ACK);//应答主机申请
+	if(rxd == 0 && txd == 0){txd = UART0_INVALID_PIN;rxd = PIN_RXD_BLE;}
+	UART0_Initialize(txd,rxd,UART_HZ);
+}
+
+
+static void app_UartLine_Pair_Process(){
+	  static uint8_t state =0;
+	  uint32_t 		txd,rxd;
+	  switch(state){
+			case 0:
+				    if(true == ob_self_check.is_scan_success){
+							 state =1;
+							 self_uart_check_flag =0;
+						}
+				    break;
+			case 1:
+				    if(mFlash.isHost){
+							UART0_GetPinConfig(&txd, &rxd);
+							UART0_Initialize(PIN_TXD_BLE,UART0_INVALID_PIN,UART_HZ);
+							UART0_Config_Send(UART0_T_LINE_CHECK_ASK);
+							if(rxd == 0 && txd == 0){txd = UART0_INVALID_PIN;rxd = PIN_RXD_BLE;}
+							UART0_Initialize(txd,rxd,UART_HZ);
+					  } 
+			      if(false == ob_self_check.is_scan_success){
+							  state = 0;						
+						}
+				    break;
+			default:
+				    break;
+		}
+}
+
+
+static void app_self_check_getreslut(){
+		/*获取自检结果前---------------------------------------------------------------------*/
+		ob_self_check.result[SELF_CHECK_ITEM_FRONT_SENSOR_INDEX] = SELF_CHECK_ITEM_SUCCESS;
+		ob_self_check.result[SELF_CHECK_ITEM_BACK_SENSOR_INDEX] = SELF_CHECK_ITEM_SUCCESS;
+		ob_self_check.result[SELF_CHECK_ITEM_BATTERY_INDEX] = SELF_CHECK_ITEM_SUCCESS;
+		ob_self_check.result[SELF_CHECK_ITEM_CHARGE_INDEX] = SELF_CHECK_ITEM_SUCCESS;
+		ob_self_check.result[SELF_CHECK_ITEM_ANT_INDEX] = SELF_CHECK_ITEM_SUCCESS;
+		ob_self_check.result[SELF_CHECK_ITEM_SUSPEND_MODE_INDEX] = SELF_CHECK_ITEM_SUCCESS;						
+		ob_self_check.item_fail_num = 0;
+
+		/*获取自检结果中---------------------------------------------------------------------*/
+		
+		//自检结果 - 异常挂起
+		if(Except_IsError(EXCEPT_IMU_SUSPEND_OVERFLOW)){ob_self_check.result[SELF_CHECK_ITEM_SUSPEND_MODE_INDEX] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_SUSPEND_MODE_INDEX + 1;}	
+		//自检结果 - 前脚传感器
+		if(Except_IsError(EXCEPT_DATA_FRONT_ACC)){ob_self_check.result[SELF_CHECK_ITEM_FRONT_SENSOR_INDEX] = SELF_CHECK_ITEM_FAIL;}
+		if(Except_IsError(EXCEPT_DATA_FRONT_GRY)){ob_self_check.result[SELF_CHECK_ITEM_FRONT_SENSOR_INDEX] = SELF_CHECK_ITEM_FAIL;}
+		if(Except_IsError(EXCEPT_DATA_FRONT_MAG)){ob_self_check.result[SELF_CHECK_ITEM_FRONT_SENSOR_INDEX] = SELF_CHECK_ITEM_FAIL;}
+		if(Except_IsError(EXCEPT_DATA_FRONT_ACC) || Except_IsError(EXCEPT_DATA_FRONT_GRY) || Except_IsError(EXCEPT_DATA_FRONT_MAG)){ob_self_check.item_fail_num = SELF_CHECK_ITEM_FRONT_SENSOR_INDEX + 1;}
+		//自检结果 - 后脚传感器
+		if(Except_IsError(EXCEPT_DATA_BACK_MAG)){ob_self_check.result[SELF_CHECK_ITEM_BACK_SENSOR_INDEX] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_BACK_SENSOR_INDEX + 1;}
+		//自检结果 - 电量
+		if(Except_IsError(EXCEPT_DATA_BATTERY)){ob_self_check.result[SELF_CHECK_ITEM_BATTERY_INDEX] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_BATTERY_INDEX + 1;}
+		//自检结果 - 充电电压
+		if(Except_IsError(EXCEPT_DATA_CHARGE)){ob_self_check.result[SELF_CHECK_ITEM_CHARGE_INDEX] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_CHARGE_INDEX + 1;}
+		//自检结果 - 天线
+		if(Except_IsError(EXCEPT_ANT_DAMAGE)){ob_self_check.result[SELF_CHECK_ITEM_ANT_INDEX] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_ANT_INDEX + 1;}					
+		
+		//设置自检灯显示时长和翻转时长
+		if(ob_self_check.item_fail_num != 0){
+			ob_self_check.led_switch = SELF_CHECK_LED_ON;
+			ob_self_check.led_display_time = TIME_GetTicks();
+			ob_self_check.led_toggle_time = TIME_GetTicks();
+		}else{
+			ob_self_check.led_switch = SELF_CHECK_LED_ON;
+			if(self_uart_check_flag){
+				LED_Start(LED_SELF_CHECK,COLOR_BLUE);
+			}
+			else{
+				LED_Start(LED_SELF_CHECK,COLOR_CYAN);
+			}
+		}
+}
+
+static void ReadyIntoSelfMode(void){
+		//设置为自检模式,且跳转到下一个流程
+		hal_ble_scan_result_Regist(&scan_reslt_handle);
+		ob_self_check.is_scan_success 			= false;
+		ob_self_check.scan_trigger_timeout 	= TIME_GetTicks();
+	  ob_self_check.stage = SELF_CHECK_STAGE_READY;
+		clear_all_except();	//清除所有异常
+		LED_Start(LED_SELF_CHECK,COLOR_BLACK); 
+		LED_Stop(LED_SELF_CHECK);
+		hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_ON);
+		
+		memset(ob_self_check.result, SELF_CHECK_ITEM_SUCCESS, SELF_CHECK_ITEMS);	
+		SEGGER_RTT_printf(0,"app_self_checking_Process clear_all_except\r\n");
+}
+
+
+static void app_self_checking_Process(void)
+{
+	static uint8_t state =0;
+	static uint8_t state_selft =0;
+	static uint8_t displaycnt =0;
+
+	switch(state){
+		case 0:
+			    if(BLE_Client_T_CHARGE_DONE == app_charge_Getstate() || \
+						 BLE_Client_T_CHARGE_INSERT == app_charge_Getstate()
+						){
+							if(Except_IsErrorExist())																																														//如果存在错误
+							{
+								if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK) != -1)																		//如果当前是自检配置
+								{
+									hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);	//关掉自检配置
+								}
+								else{																																																							//如果当前不是自检配置{
+									ST_scan_start();
+									ReadyIntoSelfMode();
+									state =1;
+									state_selft =0;
+								}
+							}
+							else{
+								//设置为自检模式,且跳转到下一个流程
+								ST_scan_start();
+								ReadyIntoSelfMode();
+								state =1;
+								state_selft =0;
+							}
+					}
+			    break;
+    case 1:
+					if(ob_self_check.is_scan_success == true)
+					{
+						ob_self_check.stage = SELF_CHECK_STAGE_CHECK;																				//进入自检阶段
+						state =2;
+						Process_SetHoldOn(app_self_checking_Process,1);
+						SEGGER_RTT_printf(0,"ob_self_check.is_scan_success\r\n");
+					}else{
+             if((TIME_GetTicks() - ob_self_check.scan_trigger_timeout) > SELF_CHECK_SCAN_TRIGGER_TIMEOUT)		//超时且没扫描到广播名
+						 {
+							  state = 2;
+							  state_selft =3;
+							  SEGGER_RTT_printf(0,"ob_self_check.scan_trigger_timeout\r\n");
+						 }
+					}
+			    break;
+		case 2:
+			    if(BLE_Client_T_CHARGE_PULLOUT == app_charge_Getstate()){
+						 ob_self_check.is_scan_success 			= false;																					//重置扫描成功标志位	
+			       hal_ble_scan_result_Clear(&scan_reslt_handle);																				//禁止扫描触发
+						 ST_scan_stop();
+						 state = 0;
+					}
+			    break;
+		default:
+			    break;
+	}
+	
+	switch(state_selft)
+	{
+		case 0:																															   
+			  if(SELF_CHECK_STAGE_CHECK == ob_self_check.stage){//扫描成功
+					  MT_Run(500);
+						if(-1 == hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK)){
+					       hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_ON);
+						}
+				    state_selft = 1;
+					  ob_self_check.ImuSetTime_times = TIME_GetTicks();
+				}
+				break;
+		case 1:
+			  if(BLE_Client_T_CHARGE_PULLOUT == app_charge_Getstate()){
+					 state_selft = 3;
+				}
+			  else {
+						if(0 == hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK)){
+							state_selft = 2;
+							displaycnt =0;
+							app_self_check_getreslut();
+						}
+						else if(TIME_GetTicks() - ob_self_check.ImuSetTime_times >= SELF_CHECK_SET_IMU_TIMEOUT){
+							Except_SetExceptype(EXCEPT_DATA_FRONT_ACC);
+							Except_SetExceptype(EXCEPT_DATA_FRONT_GRY);
+							Except_SetExceptype(EXCEPT_DATA_FRONT_MAG);
+							Except_SetExceptype(EXCEPT_IMU_SUSPEND_OVERFLOW); 
+							state_selft = 2;
+							displaycnt =0;
+						}
+			  }
+			  break;
+	  case 2:
+			   if(displaycnt < ob_self_check.item_fail_num){
+						if(TIME_GetTicks() - ob_self_check.led_toggle_time >= SELF_CHECK_LED_TOGGLE_TIME){ob_self_check.led_toggle_time = TIME_GetTicks();
+							if(ob_self_check.led_switch == SELF_CHECK_LED_ON){
+								LED_Start(LED_SELF_CHECK,COLOR_LIGHRED);
+								ob_self_check.led_switch = SELF_CHECK_LED_OFF;
+							}
+							else{
+								LED_Start(LED_SELF_CHECK,COLOR_BLACK);
+								ob_self_check.led_switch = SELF_CHECK_LED_ON;
+								displaycnt++;
+							}
+						}
+					}
+				  else if(TIME_GetTicks() - ob_self_check.led_display_time >= SELF_CHECK_LED_DISPLAY_TIME){//显示时间到了,重现读取自检结果,并显示
+						ob_self_check.led_display_time = TIME_GetTicks();
+						displaycnt =0;
+						app_self_check_getreslut();
+					}
+			    break;
+		 case 3:
+				 state_selft = 0;
+		     ob_self_check.stage = SELF_CHECK_STAGE_READY;
+         LED_Start(LED_SELF_CHECK,COLOR_BLACK); 
+				 LED_Stop(LED_SELF_CHECK);
+				 ob_self_check.led_switch = SELF_CHECK_LED_OFF;																					//设置自检灯为关
+				 if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK) != -1)        //当前是自检模式,退出。
+				 {
+						hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+				 }								
+				 break;
+		 default:
+			   break;
+	}	
+}
+static void app_self_checking_printf_process(void)
+{
+	SEGGER_RTT_printf(0,"self_check: FRONT_SENSOR:%d BACK_SENSOR:%d BATTERY:%d CHARGE:%d ANT:%d suspend_mode:%d scan_trigger_timeout:%d\n", \
+	Except_IsError(EXCEPT_DATA_FRONT_ACC) || Except_IsError(EXCEPT_DATA_FRONT_GRY) || Except_IsError(EXCEPT_DATA_FRONT_MAG), \
+	Except_IsError(EXCEPT_DATA_BACK_MAG), \
+	Except_IsError(EXCEPT_DATA_BATTERY), \
+	Except_IsError(EXCEPT_DATA_CHARGE), \
+	Except_IsError(EXCEPT_ANT_DAMAGE), \
+	Except_IsError(EXCEPT_IMU_SUSPEND_OVERFLOW),ob_self_check.scan_trigger_timeout);
+}
+
+/*API ----------------------------------------------------------*/
+void app_self_checking_Init(void)
+{
+	ob_self_check.stage = SELF_CHECK_STAGE_READY;
+	ob_self_check.ImuSetTime_times = 0;
+	ob_self_check.item_fail_num = 0;
+	ob_self_check.led_switch = SELF_CHECK_LED_OFF;
+	ob_self_check.led_display_time = 0;
+	ob_self_check.led_toggle_time = 0;
+	ob_self_check.is_scan_success = false;																		
+	ob_self_check.scan_trigger_timeout = SELF_CHECK_SCAN_TRIGGER_TIMEOUT;								
+
+	
+	Process_Start(SELF_CHECK_PROCESS_CYCLE,"app_self_checking_Process",app_self_checking_Process);
+	Process_Start(300,"app_UartLine_Pair_Process",app_UartLine_Pair_Process);
+	UART0_Rx_Regist(UART0_R_LINE_CHECK_ASK,cb_UART0_R_LINE_CHECK_ASK);
+	UART0_Rx_Regist(UART0_R_LINE_CHECK_ACK,cb_UART0_R_LINE_CHECK_ACK);
+//	Process_Start(1000,"app_self_checking_printf_process",app_self_checking_printf_process);
+}
+
+uint32_t app_self_checking_get_scan_trigger_timeout(void)
+{
+	return ob_self_check.scan_trigger_timeout;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 347 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_self_checking.c

@@ -0,0 +1,347 @@
+/*Includes ----------------------------------------------*/
+#include "system.h"
+#include "exception.h"
+#include "app_charge.h"
+#include "app_flash.h"
+#include "app_self_checking.h"
+#include "hal_led.h"
+#include "hal_mt.h"
+#include "hal_ble_uart0.h"
+#include "hal_ble_client.h"
+#include "hal_ser_imu_mode_manage.h"
+#include "app_flash.h"
+#include "app_pair.h"
+#include "bsp_time.h"
+#include "hal_scan_manage.h"
+#include "ble_comm.h"
+
+/*Private macro ------------------------------------------------*/
+#define	SELF_CHECK_WHEEL_EMPTY_TIMES_MAX		MONITOR_SUSPEND_MODE_OVERFLOW_ERR_SUM_MAX			//允许最大轮空次数
+
+#define SELF_CHECK_ITEM_SUCCESS							0																							//自检项目成功
+#define SELF_CHECK_ITEM_FAIL								1	
+
+//自检项目失败
+enum{
+	SELF_CHECK_ITEM_FRONT_SENSOR=0,																	//自检项目 - 前脚传感器
+	SELF_CHECK_ITEM_BACK_SENSOR,																		//自检项目 - 后脚传感器
+	SELF_CHECK_ITEM_BATTERY,																				//自检项目 - 电量
+	SELF_CHECK_ITEM_CHARGE,																					//自检项目 - 充电电压
+	SELF_CHECK_ITEM_ANT,																						//自检项目 - 天线
+	SELF_CHECK_ITEM_SUSPEND_MODE,																		//自检项目 - 异常挂起		
+	SELF_CHECK_ITEMS																					      //自检项数	
+};
+
+#define SELF_CHECK_LED_DISPLAY_TIME					3000					  //自检灯显示时长 - ms为单位
+
+#define SELF_CHECK_LED_TOGGLE_TIME					200						  //自检灯翻转时长 - ms为单位
+
+#define SELF_CHECK_SCAN_TRIGGER_TIMEOUT			10000						//扫描触发自检超时时间 - ms为单位
+
+#define SELF_CHECK_SET_IMU_TIMEOUT			    20000						//等待IMU初始化成功的时间
+
+#define SELF_CHECK_SCAN_TARGET_ADV_NAME			"SH_SELF_CHECK"																//扫描触发的目标广播名字
+
+/*STRUCTION --------------------------------------------------
+--*/
+typedef enum {
+	SELF_CHECK_STAGE_READY,																																	//准备阶段
+	SELF_CHECK_STAGE_CHECK,																																	//自检阶段
+	
+} SELF_CHECK_STAGE_e;
+typedef enum{
+	SELF_CHECK_LED_ON,																																			//自检灯 - 开
+	SELF_CHECK_LED_OFF,																																			//自检灯 - 关
+} SELF_CHECK_LED_SWITCH_e;
+typedef struct self_check
+{
+	/*private member*/
+	SELF_CHECK_STAGE_e				stage;																												//阶段字段
+	
+	uint32_t								  ImuSetTime_times;																						  //轮空次数
+	
+	uint8_t										result[SELF_CHECK_ITEMS];																			//自检结果
+	
+	uint8_t										item_fail_num;																								//自检项目失败数量
+	
+	SELF_CHECK_LED_SWITCH_e		led_switch;																										//自检灯开关
+
+	uint32_t									led_display_time;																							//自检灯显示时长
+	
+	uint32_t									led_toggle_time;																							//自检灯翻转时长
+	
+	uint32_t									scan_trigger_timeout;																					//扫描触发自检超时时间
+	
+	bool											is_scan_success;																							//是否找到广播名字
+
+} Self_Check_t;
+
+/*Local Variable -----------------------------------------------*/
+static Self_Check_t ob_self_check;
+
+/*Local Functions ----------------------------------------------*/
+static void clear_all_except(void)
+{
+	Except_ClearExceptype(EXCEPT_DATA_BACK_MAG);
+	Except_ClearExceptype(EXCEPT_DATA_FRONT_ACC);
+	Except_ClearExceptype(EXCEPT_DATA_FRONT_GRY);
+	Except_ClearExceptype(EXCEPT_DATA_FRONT_MAG);
+	Except_ClearExceptype(EXCEPT_DATA_CHARGE);
+	Except_ClearExceptype(EXCEPT_DATA_BATTERY);
+	Except_ClearExceptype(EXCEPT_IMU_SUSPEND_OVERFLOW);
+	Except_ClearExceptype(EXCEPT_ANT_DAMAGE);
+}
+
+static void selft_scan_cb(void)
+{
+	ob_self_check.is_scan_success = true;
+}
+
+static scan_reslt_t scan_reslt_handle ={
+	.handle = selft_scan_cb,
+	.scanname =SELF_CHECK_SCAN_TARGET_ADV_NAME,
+};
+
+static pair_reslt_t UartPair_result ={
+	.flag = 0,
+};
+
+static void app_self_check_getreslut(){
+	  uint8_t i=0;
+		/*获取自检结果前---------------------------------------------------------------------*/
+	  for(i=0;i<SELF_CHECK_ITEMS;i++)ob_self_check.result[i] = SELF_CHECK_ITEM_SUCCESS;
+		ob_self_check.item_fail_num = 0;
+
+		/*获取自检结果中---------------------------------------------------------------------*/
+		
+		//自检结果 - 异常挂起
+		if(Except_IsError(EXCEPT_IMU_SUSPEND_OVERFLOW)){ob_self_check.result[SELF_CHECK_ITEM_SUSPEND_MODE] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_SUSPEND_MODE + 1;}	
+		//自检结果 - 前脚传感器
+		if(Except_IsError(EXCEPT_DATA_FRONT_ACC)){ob_self_check.result[SELF_CHECK_ITEM_FRONT_SENSOR] = SELF_CHECK_ITEM_FAIL;}
+		if(Except_IsError(EXCEPT_DATA_FRONT_GRY)){ob_self_check.result[SELF_CHECK_ITEM_FRONT_SENSOR] = SELF_CHECK_ITEM_FAIL;}
+		if(Except_IsError(EXCEPT_DATA_FRONT_MAG)){ob_self_check.result[SELF_CHECK_ITEM_FRONT_SENSOR] = SELF_CHECK_ITEM_FAIL;}
+		if(Except_IsError(EXCEPT_DATA_FRONT_ACC) || Except_IsError(EXCEPT_DATA_FRONT_GRY) || Except_IsError(EXCEPT_DATA_FRONT_MAG)){ob_self_check.item_fail_num = SELF_CHECK_ITEM_FRONT_SENSOR + 1;}
+		//自检结果 - 后脚传感器
+		if(Except_IsError(EXCEPT_DATA_BACK_MAG)){ob_self_check.result[SELF_CHECK_ITEM_BACK_SENSOR] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_BACK_SENSOR + 1;}
+		//自检结果 - 电量
+		if(Except_IsError(EXCEPT_DATA_BATTERY)){ob_self_check.result[SELF_CHECK_ITEM_BATTERY] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_BATTERY + 1;}
+		//自检结果 - 充电电压
+		if(Except_IsError(EXCEPT_DATA_CHARGE)){ob_self_check.result[SELF_CHECK_ITEM_CHARGE] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_CHARGE+ 1;}
+		//自检结果 - 天线
+		if(Except_IsError(EXCEPT_ANT_DAMAGE)){ob_self_check.result[SELF_CHECK_ITEM_ANT] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_ANT + 1;}					
+		
+		//设置自检灯显示时长和翻转时长
+		if(ob_self_check.item_fail_num != 0){
+			ob_self_check.led_switch = SELF_CHECK_LED_ON;
+			ob_self_check.led_display_time = TIME_GetTicks();
+			ob_self_check.led_toggle_time = TIME_GetTicks();
+		}else{
+			ob_self_check.led_switch = SELF_CHECK_LED_ON;
+			if(UartPair_result.flag){
+				LED_Start(LED_SELF_CHECK,COLOR_BLUE);
+			}
+			else{
+				LED_Start(LED_SELF_CHECK,COLOR_CYAN);
+			}
+		}
+}
+
+static void ReadyIntoSelfMode(void){
+		//设置为自检模式,且跳转到下一个流程
+		hal_ble_scan_result_Regist(&scan_reslt_handle);
+		ob_self_check.is_scan_success 			= false;
+		ob_self_check.scan_trigger_timeout 	= TIME_GetTicks();
+	  ob_self_check.stage = SELF_CHECK_STAGE_READY;
+		clear_all_except();	//清除所有异常
+		LED_Start(LED_SELF_CHECK,COLOR_BLACK); 
+		LED_Stop(LED_SELF_CHECK);
+		hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_ON);
+		
+		memset(ob_self_check.result, SELF_CHECK_ITEM_SUCCESS, SELF_CHECK_ITEMS);	
+	  UartPair_result.flag =0;
+	  app_UartPair_Regist(&UartPair_result);
+		SEGGER_RTT_printf(0,"app_self_checking_Process clear_all_except\r\n");
+}
+
+
+static void app_self_checking_Process(void)
+{
+	static uint8_t state =0;
+	static uint8_t state_selft =0;
+	static uint8_t displaycnt =0;
+
+	switch(state){
+		case 0:
+			    if(BLE_CHARGE_DONE == app_charge_Getstate() || \
+						 BLE_CHARGE_INSERT == app_charge_Getstate()
+						){
+							if(Except_IsErrorExist())																																														//如果存在错误
+							{
+								if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK) != -1)																		//如果当前是自检配置
+								{
+									hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);	//关掉自检配置
+								}
+								else{																																																							//如果当前不是自检配置{
+									ST_scan_start();
+									ReadyIntoSelfMode();
+									state =1;
+									state_selft =0;
+								}
+							}
+							else{
+								ST_scan_start();//设置为自检模式,且跳转到下一个流程
+								ReadyIntoSelfMode();
+								state =1;
+								state_selft =0;
+							}
+					}
+			    break;
+    case 1:
+					if(ob_self_check.is_scan_success == true)
+					{
+						ob_self_check.stage = SELF_CHECK_STAGE_CHECK;																				//进入自检阶段
+						state =2;
+						Process_SetHoldOn(app_self_checking_Process,1);
+						SEGGER_RTT_printf(0,"ob_self_check.is_scan_success\r\n");
+					}else{
+             if((TIME_GetTicks() - ob_self_check.scan_trigger_timeout) > SELF_CHECK_SCAN_TRIGGER_TIMEOUT)		//超时且没扫描到广播名
+						 {
+							  state = 2;
+							  ob_self_check.is_scan_success 			= false;																					//重置扫描成功标志位
+							  state_selft =3;
+							  hal_ble_scan_result_Clear(&scan_reslt_handle);																				//禁止扫描触发
+						    ST_scan_stop();
+							  SEGGER_RTT_printf(0,"ob_self_check.scan_trigger_timeout\r\n");
+						 }
+					}
+			    break;
+		case 2:
+			    if(BLE_CHARGE_PULLOUT == app_charge_Getstate()){
+						 state = 0;
+						 app_UartPair_Clear(&UartPair_result);
+						 SEGGER_RTT_printf(0,"ob_self_check.scan BLE_Client_T_CHARGE_PULLOUT\r\n");
+					}
+			    break;
+		default:
+			    break;
+	}
+	
+	switch(state_selft)
+	{
+		case 0:																															   
+			  if(SELF_CHECK_STAGE_CHECK == ob_self_check.stage){//扫描成功
+					  MT_Run(500);
+						if(-1 == hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK)){
+					       hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_ON);
+						}
+				    state_selft = 1;
+					  ob_self_check.ImuSetTime_times = TIME_GetTicks();
+				}
+				break;
+		case 1:
+			  if(BLE_CHARGE_PULLOUT == app_charge_Getstate()){
+					 state_selft = 3;
+				}
+			  else {
+						if(0 == hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK)){
+							state_selft = 2;
+							displaycnt =0;
+							app_self_check_getreslut();
+						}
+						else if(TIME_GetTicks() - ob_self_check.ImuSetTime_times >= SELF_CHECK_SET_IMU_TIMEOUT){
+							Except_SetExceptype(EXCEPT_DATA_FRONT_ACC);
+							Except_SetExceptype(EXCEPT_DATA_FRONT_GRY);
+							Except_SetExceptype(EXCEPT_DATA_FRONT_MAG);
+							Except_SetExceptype(EXCEPT_IMU_SUSPEND_OVERFLOW); 
+							state_selft = 2;
+							displaycnt =0;
+						}
+			  }
+			  break;
+	  case 2:
+			   if(displaycnt < ob_self_check.item_fail_num){
+						if(TIME_GetTicks() - ob_self_check.led_toggle_time >= SELF_CHECK_LED_TOGGLE_TIME){ob_self_check.led_toggle_time = TIME_GetTicks();
+							if(ob_self_check.led_switch == SELF_CHECK_LED_ON){
+								LED_Start(LED_SELF_CHECK,COLOR_LIGHRED);
+								ob_self_check.led_switch = SELF_CHECK_LED_OFF;
+							}
+							else{
+								LED_Start(LED_SELF_CHECK,COLOR_BLACK);
+								ob_self_check.led_switch = SELF_CHECK_LED_ON;
+								displaycnt++;
+							}
+						}
+					}
+				  else if(TIME_GetTicks() - ob_self_check.led_display_time >= SELF_CHECK_LED_DISPLAY_TIME){//显示时间到了,重现读取自检结果,并显示
+						ob_self_check.led_display_time = TIME_GetTicks();
+						displaycnt =0;
+						app_self_check_getreslut();
+					}
+			    break;
+		 case 3:
+				 state_selft = 0;
+		     ob_self_check.stage = SELF_CHECK_STAGE_READY;
+         LED_Start(LED_SELF_CHECK,COLOR_BLACK); 
+				 LED_Stop(LED_SELF_CHECK);
+				 ob_self_check.led_switch = SELF_CHECK_LED_OFF;																					//设置自检灯为关
+				 if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK) != -1)        //当前是自检模式,退出。
+				 {
+						hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+				 }								
+				 break;
+		 default:
+			   break;
+	}	
+}
+//static void app_self_checking_printf_process(void)
+//{
+//	SEGGER_RTT_printf(0,"self_check: FRONT_SENSOR:%d BACK_SENSOR:%d BATTERY:%d CHARGE:%d ANT:%d suspend_mode:%d scan_trigger_timeout:%d\n", \
+//	Except_IsError(EXCEPT_DATA_FRONT_ACC) || Except_IsError(EXCEPT_DATA_FRONT_GRY) || Except_IsError(EXCEPT_DATA_FRONT_MAG), \
+//	Except_IsError(EXCEPT_DATA_BACK_MAG), \
+//	Except_IsError(EXCEPT_DATA_BATTERY), \
+//	Except_IsError(EXCEPT_DATA_CHARGE), \
+//	Except_IsError(EXCEPT_ANT_DAMAGE), \
+//	Except_IsError(EXCEPT_IMU_SUSPEND_OVERFLOW),ob_self_check.scan_trigger_timeout);
+//}
+
+/*API ----------------------------------------------------------*/
+void app_self_checking_Init(void)
+{
+	ob_self_check.stage = SELF_CHECK_STAGE_READY;
+	ob_self_check.ImuSetTime_times = 0;
+	ob_self_check.item_fail_num = 0;
+	ob_self_check.led_switch = SELF_CHECK_LED_OFF;
+	ob_self_check.led_display_time = 0;
+	ob_self_check.led_toggle_time = 0;
+	ob_self_check.is_scan_success = false;																		
+	ob_self_check.scan_trigger_timeout = SELF_CHECK_SCAN_TRIGGER_TIMEOUT;								
+
+	Process_Start(10,"app_self_checking_Process",app_self_checking_Process);
+  
+//	Process_Start(1000,"app_self_checking_printf_process",app_self_checking_printf_process);
+}
+
+uint32_t app_self_checking_get_scan_trigger_timeout(void)
+{
+	return ob_self_check.scan_trigger_timeout;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 39 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_self_checking.h

@@ -0,0 +1,39 @@
+#ifndef __APP_SELF_CHECKING_H__
+#define __APP_SELF_CHECKING_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*Includes ------------------------------------------------------*/
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+/*API -------------------------------------------------------*/
+void app_self_checking_Init(void);
+
+uint32_t app_self_checking_get_scan_trigger_timeout(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 131 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_step.c

@@ -0,0 +1,131 @@
+#include "app_step.h"
+#include "nrf_gpio.h"
+#include "usr_config.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_mt.h"
+#include "app_host.h"
+#include "app_charge.h"
+#include "hal_ble_client.h"
+#include "hal_ble_host.h"
+#include "nrf_delay.h"
+#include "app_flash.h"
+#include "hal_ser_imu_mode_manage.h"
+#include "ble_comm.h"
+#include "exception.h"
+
+static uint8_t realStepMode = 0;        //是否为实时计步模式
+static uint32_t realStepCur_L = 0;      //左鞋步数记录点
+static uint32_t realStepAdd_R = 0;      //右鞋步数
+static uint8_t realStepTimCnt = 0;      //连接右鞋计时
+static uint8_t  realStepHeartCnt = 0;   //游戏模式心跳计时
+
+/********************** 函数声明区 *************************/
+uint32_t app_step_GetStep_L(void)
+{
+	return mFlash.mStep.stepCur[0];
+}
+
+uint32_t app_step_GetStep_R(void)
+{ 
+	return mFlash.mStep.stepCur[1];
+}
+
+//右鞋实时计步发送
+static void app_step_RealSendProcess(void)
+{
+	if(-1 != hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_REALSTEP)){
+		uint8_t buf[8];
+		uint8_t L = 0;
+		buf[L++] = BLE_REALTIMESTEP_ENTER;
+		buf[L++] = (uint8_t)((mFlash.mStep.stepCur[0]-realStepCur_L)>>24);
+		buf[L++] = (uint8_t)((mFlash.mStep.stepCur[0]-realStepCur_L)>>16);
+		buf[L++] = (uint8_t)((mFlash.mStep.stepCur[0]-realStepCur_L)>>8);
+		buf[L++] = (uint8_t)((mFlash.mStep.stepCur[0]-realStepCur_L)>>0);
+		buf[L++] = (uint8_t)(realStepAdd_R>>24);
+		buf[L++] = (uint8_t)(realStepAdd_R>>16);
+		buf[L++] = (uint8_t)(realStepAdd_R>>8);
+		buf[L++] = (uint8_t)(realStepAdd_R>>0);
+//		SEGGER_RTT_printf(0,"mFlash.mStep.stepCur[0]-realStepCur_L:%d,realStepAdd_R:%d\n",(mFlash.mStep.stepCur[0]-realStepCur_L),realStepAdd_R);
+		BLE_Client_Tx_Send(0,BLE_REALTIMESTEP,buf,L);
+	}
+}
+
+//右鞋实时计步连接管理
+void app_step_RealConnectProcess(void)
+{
+	 if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_REALSTEP) != -1){
+		  if(realStepHeartCnt < 255)realStepHeartCnt++;
+			if(realStepHeartCnt >= 60){//与手机断开连接
+				hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_REALSTEP, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+				if(realStepTimCnt > 0){ realStepTimCnt = 0; //从机在发步数
+					uint8_t mod = BLE_REALTIMESTEP_HANDUP;
+					BLE_Host_Tx_Send(0,BLE_REALTIMESTEP,&mod,1); //挂起从机实时步数
+				}
+			}else{
+				if(realStepTimCnt>0) realStepTimCnt--;
+				if(realStepTimCnt==0) BLE_Host_Tx_Send(0,BLE_REALTIMESTEP,&realStepMode,1);
+			}
+		}else{
+				if(realStepTimCnt>0){ realStepTimCnt = 0;
+						BLE_Host_Tx_Send(0,BLE_REALTIMESTEP,&realStepMode,1);
+				}
+     }
+}
+
+//接收右鞋实时步数并发送到手机
+void cb_BLE_Host_R_REALTIMESTEP(void* handle)
+{
+	BLE_Client_Rx_t* target = handle;
+	#if DEBUG_STEP
+	extern step_count_t mIstep_count_t_right;
+	
+	mIstep_count_t_right.F_val_now = ((uint32_t)target->pDat[1]<<8)|((uint32_t)target->pDat[2]<<0);
+	mIstep_count_t_right.F_val_now_B = ((uint32_t)target->pDat[3]<<8)|((uint32_t)target->pDat[4]<<0);
+	mIstep_count_t_right.F_filter_val = ((uint32_t)target->pDat[5]<<8)|((uint32_t)target->pDat[6]<<0);
+	mIstep_count_t_right.F_flag_step = ((uint32_t)target->pDat[7]<<8)|((uint32_t)target->pDat[8]<<0);
+	hal_step_matlib_Test(0x01);
+	if(mIstep_count_t_right.F_flag_step > 0)mIstep_count_t_right.F_flag_step =0;
+	#else
+	if(target->pDat[0]==BLE_REALTIMESTEP_ENTER){
+		  realStepAdd_R = ((uint32_t)target->pDat[1]<<24) | (uint32_t)(target->pDat[2]<<16) | (uint32_t)(target->pDat[3]<<8) | ((uint32_t)target->pDat[4]<<0);
+		  app_step_RealSendProcess();
+//		  SEGGER_RTT_printf(0,">>>>>>realStepAdd_R:%ld\n",realStepAdd_R);
+			realStepTimCnt = 3;
+	}
+	#endif
+}
+
+//接收手机命令
+void cb_BLE_Client_R_REALTIMESTEP(void* handle)
+{
+	BLE_Client_Rx_t* target = handle;
+	uint8_t cmd = target->pDat[0];
+
+	if(cmd==BLE_REALTIMESTEP_ENTER){
+		realStepHeartCnt = 0;
+		hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_REALSTEP, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_ON);
+	}
+	else if(cmd==BLE_REALTIMESTEP_EXIT){
+		hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_REALSTEP, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
+	}
+	
+	BLE_Host_Tx_Send(0,BLE_REALTIMESTEP,&cmd,1);
+	
+	if(cmd==BLE_REALTIMESTEP_ENTER && realStepMode==BLE_REALTIMESTEP_EXIT){
+			realStepCur_L = mFlash.mStep.stepCur[0]; //重新计数
+		  realStepAdd_R = 0;
+	}
+	realStepMode = cmd;
+}
+
+void app_step_Init(void)
+{
+	if(0 == mFlash.isHost)Process_Start(100,"step_RealSend",app_step_RealSendProcess);
+	Process_Start(1000,"step_RealConnect",app_step_RealConnectProcess);
+	
+	BLE_Client_Rx_Regist(BLE_REALTIMESTEP,cb_BLE_Client_R_REALTIMESTEP);
+  BLE_Host_Rx_Regist(BLE_REALTIMESTEP,cb_BLE_Host_R_REALTIMESTEP);
+}
+
+

+ 14 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_step.h

@@ -0,0 +1,14 @@
+#ifndef __app_step_h__
+#define __app_step_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void app_step_Init(void);
+uint32_t app_step_GetStep_L(void);
+uint32_t app_step_GetStep_R(void);
+
+#endif

+ 47 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_switchimu.c

@@ -0,0 +1,47 @@
+#include "app_switchimu.h"
+#include "usr_config.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_ble_client.h"
+#include "hal_ble_host.h"
+#include "hal_mt.h"
+#include "nrf_delay.h"
+
+static uint8_t switch_front_or_center_lsm = USED_FRONT_LSM;
+
+uint8_t app_switchimu_GetGameModeLsm(void)
+{
+	return switch_front_or_center_lsm;
+}
+
+//½ÓÊÕÊÖ»úÃüÁî
+void cb_BLE_Client_R_SWITCH_IMU(void* handle)
+{
+	BLE_Client_Rx_t* target = handle;
+	uint8_t cmd = target->pDat[0];
+	
+	switch(cmd)
+	{
+		case 0:
+			switch_front_or_center_lsm = USED_FRONT_LSM;
+			MT_Run(1000);
+		  break;
+		
+		case 1:
+			switch_front_or_center_lsm = USED_CENTER_LSM;
+			MT_Run(1000);
+		  break;
+	}
+	
+	BLE_Host_Tx_Send(0,BLE_SWITCH_IMU,&cmd,1);
+}
+
+void app_switchimu_Init(void)
+{
+	BLE_Client_Rx_Regist(BLE_SWITCH_IMU,cb_BLE_Client_R_SWITCH_IMU);
+}
+
+
+
+
+

+ 19 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/app/app_switchimu.h

@@ -0,0 +1,19 @@
+#ifndef __app_switchimu_h__
+#define __app_switchimu_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+#define USED_FRONT_LSM					0
+#define USED_CENTER_LSM					1
+
+void app_switchimu_Init(void);
+uint8_t app_switchimu_GetGameModeLsm(void);
+
+#endif
+
+
+

+ 457 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/ble_comm.h

@@ -0,0 +1,457 @@
+/** @file
+ *
+ * @API 文档
+ *
+ */
+
+#ifndef __BLE_COMM__
+#define __BLE_COMM__
+
+#include "sdk_common.h"
+#include "ble_db_discovery.h"
+#include "sdk_errors.h"
+#include "app_error.h"
+#include "app_util.h"
+#include "bsp_btn_ble.h"
+#include "ble.h"
+#include "ble_gap.h"
+#include "ble_hci.h"
+#include "nrf_sdh.h"
+#include "nrf_sdh_ble.h"
+#include "nrf_sdh_soc.h"
+#include "ble_nus_c.h"
+#include "nrf_ble_gatt.h"
+#include "nrf_pwr_mgmt.h"
+#include "nrf_ble_scan.h"
+#include "app_timer.h"
+#include "ble_conn_state.h"
+
+#include "SEGGER_RTT.h"
+#include "nrf_delay.h"
+#include "main.h"
+#include "queue.h"
+#include "ringframe.h"
+#include "ble_advdata.h"
+
+// <<< Use Configuration Wizard in Context Menu >>>\r\n
+#define APP_BLE_CONN_CFG_TAG 1
+
+// <q> USE_LADDR  - 广播名称是否添加地址后缀
+#ifndef USE_LADDR
+#define USE_LADDR 1
+#endif
+// <q> USENAMEFR  - 扫描是否采用名字匹配
+#ifndef USENAMEFR
+#define USENAMEFR 1
+#endif
+// <q> USEMACNAME  - 采用mac地址作为蓝牙名称
+#ifndef USEMACNAME
+#define USEMACNAME 0
+#endif
+
+// <q> USEFIFO  - 采用FIFO方式发送
+#ifndef USEFIFO
+#define USEFIFO 1
+#endif
+
+#define TARFET_LEN_MAX NRF_BLE_SCAN_NAME_MAX_LEN
+
+// <q> BLE_PRINTF  - 调试信息
+#ifndef BLE_PRINTF
+#define BLE_PRINTF 0
+#endif
+#if BLE_PRINTF
+#define BLE_PRINT(...) SEGGER_RTT_printf(0, __VA_ARGS__)
+#else
+#define BLE_PRINT(...) ;
+#endif
+#define APP_ERR_BASE 0
+
+/**@brief 各种错误数据类型. */
+enum
+{
+	APP_SUCCESS = APP_ERR_BASE,
+	APP_ERR_DISCONN,
+	APP_ERR_CONNECTED,
+	APP_ERR_PARAMERR,
+	APP_ERR_OVERLENGTH,
+	APP_ERR_BUSY,
+	APP_ERROR_RESOURCES,
+};
+
+/**@brief 报错函数.
+ *
+ * @param[in]      err_num       	 错误代码
+ *
+ * @warning 
+ */
+void err(int err_num);
+
+/**@brief 扫描到的广播数据包回调事件类型
+ *
+ * @param[in]      unsigned short   广播数据包的长度
+ * @param[out]     unsigned char *  接收到的完整广播数据包的指针
+ * @param[in]      signed char      RSSI
+ *
+ * @warning 
+ */
+typedef void (*advdata_rep_handler_t)(unsigned char *, unsigned short ,signed char);
+
+/**@brief 数据接收类型
+ *
+ * @warning 
+ */
+typedef void (*Ble_receive_handler_t)(unsigned char *, int);
+
+/**@brief 蓝牙时间回调类型
+ *
+ * @warning 
+ */
+typedef void (*Ble_evt_cb)(void);
+
+/**@brief 发送数据到从机
+ *
+ * @param[in]      bytes       要发送的数据的指针.
+ * @param[in]      len  			 要发送的数据的长度
+ *
+ * @retval 0  			操作成功
+ * @retval 1 				发送失败
+ *
+ * @warning 
+ */
+unsigned int send_bytes_server(uint8_t *bytes, uint16_t len);
+
+/**@brief 发送数据到主机
+ *
+ * @param[in]      bytes       要发送的数据的指针.
+ * @param[in]      len  			 要发送的数据的长度
+ *
+ * @retval 0  			操作成功
+ * @retval 1 				发送失败
+ *
+ * @warning 
+ */
+unsigned int send_bytes_client(unsigned char *bytes, uint16_t len);
+
+/**@brief 主机初始化
+ *
+ * @warning 
+ */
+void host_init(Ble_receive_handler_t receive_handler);
+
+/**@brief 从机初始化
+ *
+ * @warning 
+ */
+void slave_init(Ble_receive_handler_t receive_handler);
+
+/**@brief 从机角色获取链接是否建立
+ *
+ * @retval 1   链接已经建立
+ * @retval 0   链接未建立
+ *
+ * @warning 
+ */
+unsigned char slave_isconnect(void);
+
+/**@brief 主机角色获取链接是否建立
+ *
+ * @retval 1   链接已经建立
+ * @retval 0   链接未建立
+ *
+ * @warning 
+ */
+unsigned char host_isconnect(void);
+
+/**@brief 设置扫描名称
+ *
+ * @param[in]      name      要设置的名称
+ * @param[in]      len       要设置的名称的长度
+ *
+ * @retval APP_SUCCESS            操作成功
+ * @retval APP_ERR_CONNECTED      链接已经建立
+ * @retval APP_ERR_OVERLENGTH     长度太长
+ *
+ * @warning 
+ */
+unsigned int host_set_scan_name(char *name, int len);
+
+/**@brief 设置广播名称
+ *
+ * @param[in]      name      要设置的广播名称
+ * @param[in]      len       要设置的广播名称的长度
+ *
+ * @retval APP_SUCCESS            操作成功 
+ *
+ * @warning 
+ */
+unsigned int slave_set_adv_name(char *name, int len);
+
+/**@brief 获取当前正在广播的名称长度
+ *
+ * @param[out]     len  					 广播的名称长度
+ *
+ * @warning 
+ */
+void slave_get_advname_len(int *len);
+
+/**@brief 获取当前正在广播的名称,要和void slave_get_advname_len(int *len);合用
+ *
+ * @param[in]      len    广播名称的长度
+ * @param[out]     name   广播名称
+ *
+ * @warning 
+ */
+void slave_get_advname(char *name, int len);
+
+/**@brief 注册一个在连接建立的时候的通知
+ *
+ * @param[in]      cb       要注册的回调函数指针
+ *
+ * @retval -1     要注册的回调已经存在
+ * @retval 0 			注册成功
+ * @retval -2     注册的队列已经满了
+ *
+ * @warning 
+ */
+int Ble_Host_Connectd_Evt_Regist(Ble_evt_cb cb);
+
+/**@brief 注册一个在连接断开的时候的通知
+ *
+ * @param[in]      cb       要注册的回调函数指针
+ *
+ * @retval -1     要注册的回调已经存在
+ * @retval 0 			注册成功
+ * @retval -2     注册的队列已经满了
+ *
+ * @warning 
+ */
+int Ble_Host_Disconn_Evt_Regist(Ble_evt_cb cb);
+
+/**@brief 注册一个在连接建立的时候的通知
+ *
+ * @param[in]      cb       要注册的回调函数指针
+ *
+ * @retval -1     要注册的回调已经存在
+ * @retval 0 			注册成功
+ * @retval -2     注册的队列已经满了
+ *
+ * @warning 
+ */
+int Ble_Slave_Connectd_Evt_Regist(Ble_evt_cb cb);
+
+/**@brief 注册一个在连接断开的时候的通知
+ *
+ * @param[in]      cb       要注册的回调函数指针
+ *
+ * @retval -1     要注册的回调已经存在
+ * @retval 0 			注册成功
+ * @retval -2     注册的队列已经满了
+ *
+ * @warning 
+ */
+int Ble_Slave_Disconn_Evt_Regist(Ble_evt_cb cb);
+
+/**@brief 作为主机时申请更新链接间隔
+ *
+ * @param[in]      min_conn_interval   最小链接间隔
+ * @param[in]      max_conn_interval   最大链接间隔
+ *  
+ * @retval APP_ERR_PARAMERR   输如的参数错误
+ * @retval APP_ERR_DISCONN    链接已经断开
+ *
+ * @warning 
+ */
+unsigned int Ble_update_conn_interval(float min_conn_interval, float max_conn_interval);
+
+/**@brief 作为从机时申请更新链接间隔
+ *
+ * @param[in]      min_conn_interval   最小链接间隔
+ * @param[in]      max_conn_interval   最大链接间隔
+ *
+ * @retval APP_ERR_BUSY       正处在一个申请流程中,此时不接受新的申请     
+ * @retval APP_ERR_PARAMERR   输如的参数错误
+ * @retval APP_ERR_DISCONN    链接已经断开
+ *
+ * @warning 
+ */
+unsigned int slave_update_conn_interval_request(float min_conn_interval, float max_conn_interval);
+
+/**@brief 关闭广播
+ *
+ * @warning 
+ */
+void advertising_stop(void);
+
+/**@brief 开启广播
+ *
+ * @warning 
+ */
+void advertising_start(void);
+
+/**@brief 开启扫描
+ *
+ * @warning 
+ */
+void scan_start(void);
+
+//关掉扫描直接调用  void nrf_ble_scan_stop(void);
+
+/**@brief 略
+ *
+ * @warning 
+ */
+uint8_t Slave_Get7_5ms_interval(void);
+
+/**@brief 作为从机角色的时候主动断开蓝牙链接
+ *
+ * @warning 
+ */
+void slave_disconnect(void);
+
+/**@brief 作为主机角色的时候主动断开蓝牙链接
+ *
+ * @warning 
+ */
+void host_disconnect(void);
+
+/**@brief 作为从机角色的时候获取连接参数
+ *
+ * @param[out]     p  获取到的链接参数的存放指针
+ *
+ * @warning 
+ */
+void slave_get_conn_params(ble_gap_conn_params_t *p);
+
+/**@brief 作为主机角色的时候获取连接参数
+ *
+ * @param[out]     p  获取到的链接参数的存放指针
+ *
+ * @warning 
+ */
+void host_get_conn_params(ble_gap_conn_params_t *p);
+
+/**@brief 从机广播初始化
+ * @warning 
+ */
+void slave_adv_init(void);
+
+/**@brief 作为从机角色的时候获取RSSI
+ *
+ * @retval 获取到的RSSI  
+ *
+ * @warning 
+ */
+signed char slave_get_rssi(void);
+
+/**@brief 作为主机角色的时候获取RSSI
+ *
+ * @retval 获取到的RSSI  
+ *
+ * @warning 
+ */
+signed char host_get_rssi(void);
+
+/**@brief 运动算法处理
+ *
+ * @param[in]      IS_HOST     是否是左鞋.
+ * @param[in]      time_stamp  时间戳.
+ * @param[in]      _acc        加速度.
+ * @param[in]      _gry        陀螺仪.
+ * @param[in]      front_mag   前磁力计.
+ * @param[in]      back_mag    后磁力计.
+ * @param[in]      _rssi       信号强度.
+ *
+ * @warning 
+ */
+void IMU_Process_motion_queue(uint8_t IS_HOST, int32_t time_stamp, int16_t* _acc,int16_t* _gry, int16_t* front_mag, int16_t* back_mag, uint8_t _rssi);
+
+/**@brief 对齐功能驱动
+ *
+ * @details 
+ * @warning 
+ */
+void IMU_Rec_data(uint8_t* pdat,uint8_t len);
+
+/**@brief IMU_Dtalige 对齐函数
+ * @warning 
+ */
+void IMU_Dtalige(void);
+
+/**@brief 打开原始数据上传模式
+ * @warning 
+ */
+void IMU_Dtalige_Rowdata_ON(void);
+
+/**@brief 关闭原始数据上传模式
+ * @warning 
+ */
+void IMU_Dtalige_Rowdata_OFF(void);
+
+/**@brief 这个函数是在系统大循环中调的
+ *
+ * @warning 
+ */
+void send_bytes_client_pcs(void);
+
+/**@brief Function for searching through encoded Advertising data for a complete local name.
+ *
+ * @param[in]    p_encoded_data Data buffer containing the encoded Advertising data.
+ * @param[in]    data_len       Length of the data buffer \p p_encoded_data.
+ * @param[in]    p_target_name  Name to search for.
+ *
+ * @retval true   If \p p_target_name was found among \p p_encoded_data, as a complete local name.
+ * @retval false  If \p p_target_name was not found among \p p_encoded_data, or if \p p_encoded_data
+ *                or \p p_target_name was NULL.
+ */
+bool advdata_name_find(uint8_t const * p_encoded_data,
+                           uint16_t        data_len,
+                           char    const * p_target_name);
+
+/**@brief Function for searching through encoded Advertising data for a device shortened name.
+ *
+ * @param[in]    p_encoded_data     Data buffer containing the encoded Advertising data.
+ * @param[in]    data_len           Length of the data buffer \p p_encoded_data.
+ * @param[in]    p_target_name      Name to search for.
+ * @param[in]    short_name_min_len Minimum length of the shortened name.
+ *               For example, if the advertising data has a shortened name 'No' and this parameter is
+ *               set to 4 with a target_name set to Nordic_XXX it will return false, but if
+ *               the shortened name in the advertising data is 'Nord', it will return true.
+ * @note: If the shortened name in the Advertising data has the same length as the target name,
+ *        this function will return false, since this means that the complete name is actually
+ *        longer, thus different than the target name.
+ *
+ * @retval true   If \p p_target_name was found among \p p_encoded_data, as short local name.
+ * @retval false  If \p p_target_name was not found among \p p_encoded_data, or if \p p_encoded_data
+ *                or \p p_target_name was NULL.
+ */
+bool advdata_short_name_find(uint8_t const * p_encoded_data,
+                                 uint16_t        data_len,
+                                 char    const * p_target_name,
+                                 uint8_t const   short_name_min_len);
+																 
+/**@brief 这个函数用来注册收到广播数据包时候的事件.
+ *
+ * @param[in]   handler     需要注册的回调函数的函数指针
+ *
+ * @note: 			此函数每次调用都会覆盖上一次的注册的handler,建议只调用一次,注册成功后会在每次收到广播数据包以后产生事件回调。
+ *
+ */
+void advdata_report_Evt_Regist(advdata_rep_handler_t handler);
+																 
+/**@brief 关闭扫描
+ * @warning 
+ */																 
+void ST_scan_stop(void);
+
+/**@brief 无条件打开扫描
+ * @warning 
+ *
+ * @retval APP_ERROR_RESOURCES   radio占用过多,先关闭一个或多个链路后再打开就好了   
+ * @retval APP_SUCCESS           操作成功
+ *  			
+ * @note:
+ */
+unsigned int ST_scan_start(void);																 
+																 														 
+#endif

+ 699 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/cli.c

@@ -0,0 +1,699 @@
+#include "cli.h"
+
+extern void *cli_cmd$$Base;
+extern void *cli_cmd$$Limit;
+
+void cli_write(cli_t *p_cli)
+{
+	for (int i = 0; i < p_cli->chartemplen; i++)
+		p_cli->char_put(p_cli->tempbuf[i]);
+}
+
+int ringbufcmp(unsigned char *ringbuf, unsigned char ringbufis, const char *cr, int len)
+{
+	unsigned char i = ringbufis;
+	for (int j = 0; j < len; j++)
+	{
+		if (ringbuf[i] != cr[j])
+			return 1;
+		i++;
+	}
+	return 0;
+}
+
+/**
+ * @brief CLI colors for @ref nrf_cli_fprintf function.
+ */
+#define NRF_CLI_DEFAULT NRF_CLI_VT100_COLOR_DEFAULT /**< Turn off character attributes. */
+#define NRF_CLI_NORMAL NRF_CLI_VT100_COLOR_WHITE	/**< Normal color printf.           */
+#define NRF_CLI_INFO NRF_CLI_VT100_COLOR_GREEN		/**< Info color printf.             */
+#define NRF_CLI_OPTION NRF_CLI_VT100_COLOR_CYAN		/**< Option color printf.           */
+#define NRF_CLI_WARNING NRF_CLI_VT100_COLOR_YELLOW	/**< Warning color printf.          */
+#define NRF_CLI_ERROR NRF_CLI_VT100_COLOR_RED		/**< Error color printf.            */
+static void vt100_color_set(cli_t *p_cli, nrf_cli_vt100_color_t color)
+{
+	if (p_cli->col.col == color)
+	{
+		return;
+	}
+	p_cli->col.col = color;
+	cli_printf(p_cli, "\033[3%dm", color); //设置颜色
+}
+
+static void vt100_bgcolor_set(cli_t *p_cli, nrf_cli_vt100_color_t bgcolor)
+{
+	if (p_cli->col.bgcol == bgcolor)
+	{
+		return;
+	}
+	p_cli->col.bgcol = bgcolor;
+	cli_printf(p_cli, "\033[4%dm", bgcolor); //设置颜色
+}
+
+static inline void vt100_colors_store(cli_t *p_cli,
+									  nrf_cli_vt100_colors_t *p_color)
+{
+	memcpy(p_color, &p_cli->col, sizeof(nrf_cli_vt100_colors_t));
+}
+
+static void vt100_colors_restore(cli_t *p_cli,
+								 nrf_cli_vt100_colors_t const *p_color)
+{
+	vt100_color_set(p_cli, p_color->col);
+	vt100_bgcolor_set(p_cli, p_color->bgcol);
+}
+
+#define print_name cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_GREEN, "\033[1m \r%s", p_cli->p_name)
+
+void Tab_pcs(cli_t *p_cli)
+{
+	int temp = 0;
+	cli_section_cmd_t *stmy;
+	if (p_cli->cmdwp == p_cli->cmdrp)
+	{
+		cli_printf(p_cli, "\n\r\t");
+		for (int p = (unsigned int)&cli_cmd$$Base; p < (unsigned int)&cli_cmd$$Limit; p += sizeof(cli_section_cmd_t))
+		{
+			stmy = ((cli_section_cmd_t *)p);
+			cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "%s\t", stmy->_p_cmd_str);
+			temp++;
+			if (temp % 5 == 0)
+				cli_printf(p_cli, "\n\r\t");
+		}
+		cli_printf(p_cli, "\n");
+		print_name;
+	}
+	else
+	{
+		for (int p = (unsigned int)&cli_cmd$$Base; p < (unsigned int)&cli_cmd$$Limit; p += sizeof(cli_section_cmd_t))
+		{
+			stmy = ((cli_section_cmd_t *)p);
+			if (ringbufcmp(p_cli->cmdbuf, p_cli->cmdrp, stmy->_p_cmd_str, p_cli->cmdwp - p_cli->cmdrp) == 0)
+			{
+				for (int i = p_cli->cmdwp - p_cli->cmdrp; i < strlen(stmy->_p_cmd_str); i++)
+					p_cli->cmdbuf[p_cli->cmdwp++] = stmy->_p_cmd_str[i];
+				cli_printf(p_cli, "\n\r");
+				print_name;
+				cli_printf(p_cli, "%s", stmy->_p_cmd_str);
+				break;
+			}
+		}
+	}
+}
+void Backspace_pcs(cli_t *p_cli)
+{
+	if (p_cli->cmdwp != p_cli->cmdrp)
+	{
+		NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEAREOL); //清除光标后面的内容
+		p_cli->cmdwp--;
+	}
+	else
+	{
+		cli_printf(p_cli, "\033[1C"); //光标右移动
+	}
+}
+void Delete_pcs(cli_t *p_cli)
+{
+	
+}
+
+#define Historyshowlen 50
+void Up_pcs(cli_t *p_cli)
+{
+	unsigned char showH_p = 0;
+	unsigned char fir = 1;
+	nrf_cli_vt100_colors_t col;
+	if (p_cli->cmdbuf[(unsigned char)(p_cli->historyrp - 1)] != '*')
+		return;
+	if (p_cli->historyrp != p_cli->cmdwp)
+	{
+		p_cli->cmdwp = p_cli->cmdrp;
+		cli_printf(p_cli, "\r");
+		print_name;
+		cli_printf(p_cli, "\033[K");
+	}
+	for (unsigned char i = (unsigned char)p_cli->historyrp - 2; i != (unsigned char)(p_cli->historyrp - Historyshowlen); i--)
+	{
+		if (p_cli->cmdbuf[i] == '*')
+		{
+			if (fir)
+			{
+				for (int j = 0; j < showH_p; j++)
+				{
+					p_cli->char_put(p_cli->cmdbuf[(unsigned char)(i + j + 1)]);
+					p_cli->cmdbuf[p_cli->cmdwp++] = p_cli->cmdbuf[(unsigned char)(i + j + 1)];
+				}
+				cli_printf(p_cli, "\033[s");
+				p_cli->char_put(' ');
+				p_cli->historyrp = i + 1;
+				fir = 0;
+				vt100_colors_store(p_cli, &col);
+				vt100_color_set(p_cli, NRF_CLI_VT100_COLOR_CYAN);
+				p_cli->char_put('[');
+			}
+			else
+			{
+				for (int j = 0; j < showH_p; j++)
+					p_cli->char_put(p_cli->cmdbuf[(unsigned char)(i + j + 1)]);
+				p_cli->char_put(' ');
+			}
+
+			showH_p = 0;
+		}
+		else
+			showH_p++;
+		if ((p_cli->cmdbuf[i] == 0) || (i == p_cli->cmdwp))
+			break;
+	}
+	if (fir == 0)
+	{
+		p_cli->char_put(']');
+		vt100_colors_restore(p_cli, &col);
+		cli_printf(p_cli, "\033[u");
+	}
+}
+
+void Down_pcs(cli_t *p_cli)
+{
+	for (unsigned char j = 0; j < p_cli->cmdwp; j++)
+		p_cli->char_put(p_cli->cmdbuf[j]);
+}
+
+void Left_pcs(cli_t *p_cli)
+{
+	cli_printf(p_cli, "\033[1D"); 
+}
+
+void Right_pcs(cli_t *p_cli)
+{
+	cli_printf(p_cli, "\033[1C");
+}
+#define ARGVCUNMAX 25
+char *cmd_argv[ARGVCUNMAX]; //最多存放25个参数的指针
+
+void cmd_pcs(cli_t *p_cli)
+{
+	cli_section_cmd_t *stmy;
+	int stmy_len = 0;
+	char sgv_tag = 0;
+	unsigned short agvc = 0;
+	char argvtrg = 0;
+	for (int p = (unsigned int)&cli_cmd$$Base; p < (unsigned int)&cli_cmd$$Limit; p += sizeof(cli_section_cmd_t))
+	{
+		stmy = ((cli_section_cmd_t *)p);
+		stmy_len = strlen(stmy->_p_cmd_str);
+		if (
+				((unsigned char)stmy_len == (unsigned char)(p_cli->cmdwp - p_cli->cmdrp))||
+				(((unsigned char)stmy_len < (unsigned char)(p_cli->cmdwp - p_cli->cmdrp))&&(p_cli->cmdbuf[(unsigned char)(p_cli->cmdrp + stmy_len)] == ' '))
+			 )
+		{
+			if (ringbufcmp(p_cli->cmdbuf, p_cli->cmdrp, stmy->_p_cmd_str, stmy_len) == 0)
+			{
+				cli_printf(p_cli, "\r\n");
+				if ((unsigned char)stmy_len == (unsigned char)(p_cli->cmdwp - p_cli->cmdrp))
+				{
+					(*(cli_cmd_t *)(&(stmy->_p_cmd_hander)))(p_cli, 0, NULL); //调用没参数的命令
+				}
+				else 
+				{
+					agvc = 0;
+					p_cli->cmdbuf[p_cli->cmdwp++] = ' ';
+					//找出所有参数的指针
+					for (unsigned char i = (unsigned char)(p_cli->cmdrp + stmy_len); (unsigned char)i != p_cli->cmdwp; i++)
+					{
+						switch (sgv_tag)
+						{
+						case 0:
+							if (p_cli->cmdbuf[i] != ' ')
+							{
+								cmd_argv[agvc++] = (char *)(&(p_cli->cmdbuf[i]));
+								sgv_tag++;
+							}
+							break;
+						default:
+							if (p_cli->cmdbuf[i] == ' ')
+							{
+								p_cli->cmdbuf[i] = 0;
+								sgv_tag = 0;
+							}
+							else if ((i == 255) && (p_cli->cmdbuf[0] != ' ')) //参数不连续
+							{
+								argvtrg = 1;
+							}
+							break;
+						}
+					}
+
+					if (argvtrg == 0) //没有出现参数不连续的情况
+					{
+						//调用命令,带参数					
+						(*(cli_cmd_t *)(&(stmy->_p_cmd_hander)))(p_cli, agvc, cmd_argv);
+					}
+					else
+					{
+						cli_fprintf(p_cli, NRF_CLI_ERROR, "\tPlase try once again! ");
+					}
+					if(agvc>0)p_cli->cmdwp = (unsigned char)((unsigned int)(&cmd_argv[agvc - 1][strlen(cmd_argv[agvc - 1])]) - (unsigned int)&p_cli->cmdbuf[0]);
+					for (int i = 0; i < agvc; i++)
+					{
+						cmd_argv[i][strlen(cmd_argv[i])] = ' ';
+					}
+				}
+				cli_printf(p_cli, "\n");
+				print_name;		
+				p_cli->cmdbuf[p_cli->cmdwp++] = '*';	
+				for(unsigned char i=p_cli->cmdwp-1;i>p_cli->cmdrp-1;i--)
+				{
+					if(p_cli->cmdbuf[i]!= p_cli->cmdbuf[(unsigned char)(i-(p_cli->cmdwp-p_cli->cmdrp))])
+					{	
+						//添加到运行历史
+						p_cli->cmdrp = p_cli->cmdwp;						
+						return ;
+					}
+				}
+				p_cli->cmdwp = p_cli->cmdrp;
+				return;
+			}
+		}
+	}
+	p_cli->cmdbuf[p_cli->cmdwp] = 0;
+	cli_fprintf(p_cli, NRF_CLI_ERROR, "\tCan not find cmd [");
+	for (unsigned char i = p_cli->cmdrp; i != p_cli->cmdwp; i++)
+		p_cli->char_put(p_cli->cmdbuf[i]);
+	cli_fprintf(p_cli, NRF_CLI_ERROR, "]\n");
+	print_name;
+	p_cli->cmdwp = p_cli->cmdrp;
+}
+
+void Enter_pcs(cli_t *p_cli)
+{
+	if (p_cli->cmdwp == p_cli->cmdrp)
+	{
+		print_name;
+	}
+	else
+	{
+		cmd_pcs(p_cli);
+	}
+	p_cli->historyrp = p_cli->cmdwp;
+}
+
+void F4_pcs(cli_t *p_cli)
+{
+	NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CURSORHOME);
+	NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEARSCREEN);
+	print_name;
+}
+void F5_pcs(cli_t *p_cli)
+{
+	Up_pcs(p_cli);
+	cli_printf(p_cli, "\r\n");
+	Enter_pcs(p_cli);
+}
+
+void cli_process(cli_t *p_cli)
+{
+	static unsigned char FN = 0;
+	unsigned char key = 0;
+	if (p_cli->char_ok())
+	{
+		key = p_cli->char_get();
+		switch (key)
+		{
+#if 1
+		case 0x08: //Backspace
+			Backspace_pcs(p_cli);
+			break;
+		case 0x09: //Tab
+			Tab_pcs(p_cli);
+			break;
+
+		case 0x0d:
+			FN = 20;
+			break;
+		case 0x0a: //Enter
+			if (FN == 20)
+			{
+				Enter_pcs(p_cli);
+				FN = 0;
+			}
+
+			break;
+
+		case 0x1B: //Esc
+			FN = 1;
+			break;
+
+		case 'A':
+			if (FN == 1)
+			{
+				Up_pcs(p_cli);
+				FN = 0;
+			}
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+		case 'B':
+			if (FN == 1)
+			{
+				Down_pcs(p_cli);
+				FN = 0;
+			}
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+		case 'C':
+			if (FN == 1)
+			{
+				Right_pcs(p_cli);
+				FN = 0;
+			}
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+		case 'D':
+			if (FN == 1)
+			{
+				Left_pcs(p_cli);
+				FN = 0;
+			}
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+		case 'O': //
+			if (FN == 1)
+				FN = 2;
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+
+		case 'P':
+			if (FN == 2)
+			{
+				FN = 0;
+				p_cli->char_put('F');
+				p_cli->char_put('1');
+			}
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+
+		case 'Q':
+			if (FN == 2)
+			{
+				FN = 0;
+				p_cli->char_put('F');
+				p_cli->char_put('2');
+			}
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+
+		case 'R':
+			if (FN == 2)
+			{
+				FN = 0;
+				p_cli->char_put('F');
+				p_cli->char_put('3');
+			}
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+
+		case 'S':
+			if (FN == 2)
+			{
+				FN = 0;
+				F4_pcs(p_cli); //F4按钮
+			}
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+
+		case '[':
+			FN = 1;
+			break;
+		case '0':
+			if (FN == 2)
+				FN = 9;
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+		case '1':
+			if (FN == 2)
+				FN = 10;
+			else if (FN == 1)
+				FN = 2;
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+		case '2':
+			if (FN == 1)
+				FN = 2;
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+		case '3':
+			if (FN == 2)
+				FN = 11;
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+		case '4':
+			if (FN == 2)
+				FN = 12;
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+		case '5':
+			if (FN == 2)
+			{
+				FN = 5;
+			}
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+
+		case '7':
+			if (FN == 2)
+			{
+				FN = 6;
+			}
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+
+		case '8':
+			if (FN == 2)
+			{
+				FN = 7;
+			}
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+
+		case '9':
+			if (FN == 2)
+			{
+				FN = 8;
+			}
+			else
+				p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+
+		case '~':
+			switch (FN)
+			{
+			case 5:
+				F5_pcs(p_cli);
+				break;
+			case 6:
+				p_cli->char_put('F');
+				p_cli->char_put('6');
+				FN = 0;
+				break;
+			case 7:
+				p_cli->char_put('F');
+				p_cli->char_put('7');
+				FN = 0;
+				break;
+			case 8:
+				p_cli->char_put('F');
+				p_cli->char_put('8');
+				FN = 0;
+				break;
+			case 9:
+				p_cli->char_put('F');
+				p_cli->char_put('9');
+				FN = 0;
+				break;
+			case 10:
+				p_cli->char_put('F');
+				p_cli->char_put('1');
+				p_cli->char_put('0');
+				FN = 0;
+				break;
+			case 11:
+				p_cli->char_put('F');
+				p_cli->char_put('1');
+				p_cli->char_put('1');
+				FN = 0;
+				break;
+			case 12:
+				p_cli->char_put('F');
+				p_cli->char_put('1');
+				p_cli->char_put('2');
+				FN = 0;
+				break;
+			default:
+				SEGGER_RTT_Write(0, &key, 1);
+				break;
+			}
+			break;
+
+		case 0x7f: //Delete
+			Delete_pcs(p_cli);
+			break;
+#endif
+		default:
+			p_cli->cmdbuf[p_cli->cmdwp++] = key;
+			break;
+		}
+	}
+extern 	void recall_cmd_pcs(cli_t *p_cli);
+	recall_cmd_pcs(p_cli);
+}
+
+void cli_exe_cmd(cli_t *p_cli,char *cmd)
+{
+	int len =strlen(cmd);
+	if(len>128)return;
+	for(unsigned char i= 0;i<len;i++)
+	{
+		p_cli->cmdbuf[p_cli->cmdwp++]=cmd[i];
+	}
+	Enter_pcs(p_cli);
+}
+
+void clc_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+	NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CURSORHOME);
+	NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEARSCREEN);
+}
+
+CLI_CMD_REGISTER(clc, "clear sereen", clc_pcs);
+CLI_CMD_REGISTER(clear, "clear sereen", clc_pcs);
+
+void History_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+	cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "[1]History");
+}
+CLI_CMD_REGISTER(history, "Cli cmd history", History_pcs);
+void print_param_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+	for (int i = 0; i < argc; i++)
+	{
+		cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "%s\r\n", argv[i]);
+	}
+}
+CLI_CMD_REGISTER(print_param, "Cli cmd history", print_param_pcs);
+
+#define RECALL_CMD_LEN_MAX 30
+unsigned char recall_cmd_buff[RECALL_CMD_LEN_MAX];
+static int recall_cmd_buff_len=0;
+static unsigned int recall_cmd_pcs_interval = 0;
+static int recall_cmd_times = 0;
+static char allcall=0;
+void recall_cmd_pcs(cli_t *p_cli)
+{
+	static unsigned int cun = 0;
+	if ((recall_cmd_times > 0)||(allcall))
+	{
+		if (cun >= recall_cmd_pcs_interval)
+		{
+			cun = 0;			
+			for(int i=0;i<recall_cmd_buff_len;i++)
+			{
+				p_cli->cmdbuf[p_cli->cmdwp++]=recall_cmd_buff[i];
+			}
+			cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "recall times %d ...\r\n",recall_cmd_times);
+			Enter_pcs(p_cli);
+			if(!allcall)recall_cmd_times--;
+		}
+		cun++;
+	}
+}
+void recall_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+	if (argc == 0)
+	{
+		recall_cmd_times = 0;
+		allcall=0;
+		cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "help: recall interval times cmd ...");
+	}
+	else if (argc >= 3)
+	{
+		recall_cmd_pcs_interval = atoi(argv[0]);
+		recall_cmd_times = atoi(argv[1]);
+		if((recall_cmd_times==0)||(recall_cmd_pcs_interval==0))
+		{
+			if((recall_cmd_times==0)&&(recall_cmd_pcs_interval!=0)&&(argv[1][0]=='*'))
+			{
+				allcall=1;				
+			}
+			else
+			{
+				cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "help: recall interval times cmd ...\r\n");
+				cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "interval and times is a number\r\n");
+				return ;
+			}
+		}
+		recall_cmd_buff_len=0;
+		for (int i = 2; i < argc; i++)
+		{
+			memcpy(&recall_cmd_buff[recall_cmd_buff_len],argv[i],strlen(argv[i]));
+			recall_cmd_buff_len+=strlen(argv[i]);
+			recall_cmd_buff[recall_cmd_buff_len++]=' ';
+		}
+		cli_printf(p_cli, "recall [ ");			
+		for(int i=0;i<recall_cmd_buff_len;i++)
+		{
+			p_cli->char_put(recall_cmd_buff[i]);
+		}
+		if(allcall){cli_printf(p_cli, " ] interval =%d times= **** success\r\n",recall_cmd_pcs_interval);	
+		}else {cli_printf(p_cli, " ] interval =%d times= %d success\r\n",recall_cmd_pcs_interval,recall_cmd_times);	
+		}SEGGER_RTT_Write(0,recall_cmd_buff,recall_cmd_buff_len);
+	}
+	else
+	{
+		cli_printf(p_cli, "recall_pcs -> param err");
+	}
+}
+CLI_CMD_REGISTER(recall, "Cli cmd history", recall_pcs);
+
+char rttok(void)
+{
+	if (SEGGER_RTT_HasKey())
+		return 1;
+	return 0;
+}
+unsigned char rttget(void)
+{
+	unsigned char buf[60];
+	SEGGER_RTT_Read(0, buf, 60);
+	return buf[0];
+}
+void rttput(unsigned char p)
+{
+	unsigned char buf[60];
+	buf[0] = p;
+	SEGGER_RTT_Write(0, buf, 1);
+}
+
+CLI_DEFINE(clirtt, "CLI^$:", rttok, rttget, rttput);
+
+int mai5n(void)
+{
+	while (1)
+		cli_process(&clirtt);
+}

+ 100 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/cli.h

@@ -0,0 +1,100 @@
+#ifndef _CLI_H__
+#define _CLI_H__
+#include "SEGGER_RTT.h"
+#include "string.h"
+#include "stdlib.h"
+#include "cli_vt100.h" //¿ÉÖ±½Ó¸´ÖÆÎļþ
+
+typedef enum
+{
+	NRF_CLI_VT100_COLOR_BLACK = 0,
+	NRF_CLI_VT100_COLOR_RED,
+	NRF_CLI_VT100_COLOR_GREEN,
+	NRF_CLI_VT100_COLOR_YELLOW,
+	NRF_CLI_VT100_COLOR_BLUE,
+	NRF_CLI_VT100_COLOR_MAGENTA,
+	NRF_CLI_VT100_COLOR_CYAN,
+	NRF_CLI_VT100_COLOR_WHITE,
+} nrf_cli_vt100_color_t;
+
+typedef struct
+{
+	nrf_cli_vt100_color_t col;	 // text color
+	nrf_cli_vt100_color_t bgcol; // background color
+} nrf_cli_vt100_colors_t;
+
+typedef void (*cli_char_put_t)(unsigned char);
+typedef unsigned char (*cli_char_get_t)(void);
+typedef char (*cli_char_ok_t)(void);
+
+typedef struct
+{
+	const char *_p_cmd_str;
+	const char *_p_cmd_help_str;
+	const void *_p_cmd_hander;
+} cli_section_cmd_t;
+
+typedef struct
+{
+	char const *const p_name;
+	cli_char_put_t char_put;
+	cli_char_get_t char_get;
+	cli_char_ok_t char_ok;
+	unsigned char cmdbuf[256];
+	unsigned char cmdwp;
+	unsigned char cmdrp;
+	unsigned char historyrp;
+	char tempbuf[256];
+	unsigned chartemplen;
+	unsigned char tab_sta;
+	nrf_cli_vt100_colors_t col;
+} cli_t;
+
+/**
+ * @brief CLI command handler prototype.
+ */
+typedef void (*cli_cmd_t)(cli_t const *p_cli, unsigned short argc, char **argv);
+
+#define CLI_CMD_REGISTER(_p_cmd, _p_help, _p_handler)                                    \
+	__attribute__((section("cli_cmd"))) cli_section_cmd_t const cli_cmd_##_p_cmd##_row = \
+		{                                                                                \
+			._p_cmd_str = (const char *)STRINGIFY(_p_cmd),                               \
+			._p_cmd_help_str = (const char *)_p_help,                                    \
+			._p_cmd_hander = (const void *)_p_handler}
+
+#define cli_fprintf(p_cli, color, ...)     \
+	{                                      \
+		nrf_cli_vt100_colors_t col;        \
+		vt100_colors_store(p_cli, &col);   \
+		vt100_color_set(p_cli, color);     \
+		cli_printf(p_cli, __VA_ARGS__);    \
+		vt100_colors_restore(p_cli, &col); \
+	}
+
+#define cli_printf(p_cli, ...)                                     \
+	{                                                              \
+		p_cli->chartemplen = sprintf(p_cli->tempbuf, __VA_ARGS__); \
+		for (int i = 0; i < p_cli->chartemplen; i++)               \
+			p_cli->char_put(p_cli->tempbuf[i]);                    \
+	}
+
+#define NRF_CLI_VT100_CMD(_p_cli_, _cmd_) \
+	{                                     \
+		static char const cmd[] = _cmd_;  \
+		cli_printf(_p_cli_, "%s", cmd);   \
+	}
+
+#define CLI_DEFINE(name, cli_prefix, p_char_ok, p_char_get, p_char_put) \
+	cli_t name = {                                                      \
+		.p_name = cli_prefix,                                           \
+		.char_ok = p_char_ok,                                           \
+		.char_get = p_char_get,                                         \
+		.char_put = p_char_put,                                         \
+		.cmdbuf[255] = '*',                                             \
+		.col.col = NRF_CLI_VT100_COLOR_WHITE}
+
+void cli_process(cli_t *p_cli);
+void cli_exe_cmd(cli_t *p_cli,char *cmd);
+		
+extern cli_t clirtt;
+#endif

+ 593 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/cli_vt100.h

@@ -0,0 +1,593 @@
+#ifndef NRF_CLI_VT100_H__
+#define NRF_CLI_VT100_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NRF_CLI_VT100_ASCII_ESC     (0x1b)
+#define NRF_CLI_VT100_ASCII_DEL     (0x7F)
+#define NRF_CLI_VT100_ASCII_BSPACE  (0x08)
+#define NRF_CLI_VT100_ASCII_CTRL_A  (0x1)
+#define NRF_CLI_VT100_ASCII_CTRL_C  (0x03)
+#define NRF_CLI_VT100_ASCII_CTRL_E  (0x5)
+#define NRF_CLI_VT100_ASCII_CTRL_L  (0x0C)
+#define NRF_CLI_VT100_ASCII_CTRL_U  (0x15)
+#define NRF_CLI_VT100_ASCII_CTRL_W  (0x17)
+
+
+#define NRF_CLI_VT100_SETNL                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '2', '0', 'h', '\0'               \
+    } /* Set new line mode */
+#define NRF_CLI_VT100_SETAPPL                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '1', 'h', '\0'               \
+    } /* Set cursor key to application */
+#define NRF_CLI_VT100_SETCOL_132                                        \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '3', 'h', '\0'               \
+    } /* Set number of columns to 132 */
+#define NRF_CLI_VT100_SETSMOOTH                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '4', 'h', '\0'               \
+    } /* Set smooth scrolling */
+#define NRF_CLI_VT100_SETREVSCRN                                        \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '5', 'h', '\0'               \
+    } /* Set reverse video on screen */
+#define NRF_CLI_VT100_SETORGREL                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '6', 'h', '\0'               \
+    } /* Set origin to relative */
+#define NRF_CLI_VT100_SETWRAP_ON                                        \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '7', 'h', '\0'               \
+    } /* Set auto-wrap mode */
+#define NRF_CLI_VT100_SETWRAP_OFF                                       \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '7', 'l', '\0'               \
+    } /* Set auto-wrap mode */
+
+#define NRF_CLI_VT100_SETREP                                            \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '8', 'h', '\0'               \
+    } /* Set auto-repeat mode */
+#define NRF_CLI_VT100_SETINTER                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '9', 'h', '\0'               \
+    } /* Set interlacing mode */
+
+#define NRF_CLI_VT100_SETLF                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '2', '0', 'l', '\0'               \
+    } /* Set line feed mode */
+#define NRF_CLI_VT100_SETCURSOR                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '1', 'l', '\0'               \
+    } /* Set cursor key to cursor */
+#define NRF_CLI_VT100_SETVT52                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '2', 'l', '\0'               \
+    } /* Set VT52 (versus ANSI) */
+#define NRF_CLI_VT100_SETCOL_80                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '3', 'l', '\0'               \
+    } /* Set number of columns to 80 */
+#define NRF_CLI_VT100_SETJUMP                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '4', 'l', '\0'               \
+    } /* Set jump scrolling */
+#define NRF_CLI_VT100_SETNORMSCRN                                       \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '5', 'l', '\0'               \
+    } /* Set normal video on screen */
+#define NRF_CLI_VT100_SETORGABS                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '6', 'l', '\0'               \
+    } /* Set origin to absolute */
+#define NRF_CLI_VT100_RESETWRAP                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '7', 'l', '\0'               \
+    } /* Reset auto-wrap mode */
+#define NRF_CLI_VT100_RESETREP                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '8', 'l', '\0'               \
+    } /* Reset auto-repeat mode */
+#define NRF_CLI_VT100_RESETINTER                                        \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '9', 'l', '\0'               \
+    } /* Reset interlacing mode */
+
+#define NRF_CLI_VT100_ALTKEYPAD                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '=', '\0'                              \
+    } /* Set alternate keypad mode */
+#define NRF_CLI_VT100_NUMKEYPAD                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '>', '\0'                              \
+    } /* Set numeric keypad mode */
+
+#define NRF_CLI_VT100_SETUKG0                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '(', 'A', '\0'                         \
+    } /* Set United Kingdom G0 character set */
+#define NRF_CLI_VT100_SETUKG1                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, ')', 'A', '\0'                         \
+    } /* Set United Kingdom G1 character set */
+#define NRF_CLI_VT100_SETUSG0                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '(', 'B', '\0'                         \
+    } /* Set United States G0 character set */
+#define NRF_CLI_VT100_SETUSG1                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, ')', 'B', '\0'                         \
+    } /* Set United States G1 character set */
+#define NRF_CLI_VT100_SETSPECG0                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '(', '0', '\0'                         \
+    } /* Set G0 special chars. & line set */
+#define NRF_CLI_VT100_SETSPECG1                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, ')', '0', '\0'                         \
+    } /* Set G1 special chars. & line set */
+#define NRF_CLI_VT100_SETALTG0                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '(', '1', '\0'                         \
+    } /* Set G0 alternate character ROM */
+#define NRF_CLI_VT100_SETALTG1                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, ')', '1', '\0'                         \
+    } /* Set G1 alternate character ROM */
+#define NRF_CLI_VT100_SETALTSPECG0                                      \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '(', '2', '\0'                         \
+    } /* Set G0 alt char ROM and spec. graphics */
+#define NRF_CLI_VT100_SETALTSPECG1                                      \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, ')', '2', '\0'                         \
+    } /* Set G1 alt char ROM and spec. graphics */
+
+#define NRF_CLI_VT100_SETSS2                                            \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'N', '\0'                              \
+    } /* Set single shift 2 */
+#define NRF_CLI_VT100_SETSS3                                            \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', '\0'                              \
+    } /* Set single shift 3 */
+
+#define NRF_CLI_VT100_MODESOFF                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', 'm', '\0'                         \
+    } /* Turn off character attributes */
+#define NRF_CLI_VT100_MODESOFF_                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '0', 'm', '\0'                    \
+    } /* Turn off character attributes */
+#define NRF_CLI_VT100_BOLD                                              \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '1', 'm', '\0'                    \
+    } /* Turn bold mode on */
+#define NRF_CLI_VT100_LOWINT                                            \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '2', 'm', '\0'                    \
+    } /* Turn low intensity mode on */
+#define NRF_CLI_VT100_UNDERLINE                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '4', 'm', '\0'                    \
+    } /* Turn underline mode on */
+#define NRF_CLI_VT100_BLINK                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '5', 'm', '\0'                    \
+    } /* Turn blinking mode on */
+#define NRF_CLI_VT100_REVERSE                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '7', 'm', '\0'                    \
+    } /* Turn reverse video on */
+#define NRF_CLI_VT100_INVISIBLE                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '8', 'm', '\0'                    \
+    } /* Turn invisible text mode on */
+
+#define NRF_CLI_VT100_SETWIN(t, b)                                      \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', (t), ';', (b), 'r', '\0'          \
+    } /* Set top and bottom line#s of a window */
+
+#define NRF_CLI_VT100_CURSORUP(n)                                       \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', (n), 'A', '\0'                    \
+    } /* Move cursor up n lines */
+#define NRF_CLI_VT100_CURSORDN(n)                                       \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', (n), 'B', '\0'                    \
+    } /* Move cursor down n lines */
+#define NRF_CLI_VT100_CURSORRT(n)                                       \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', (n), 'C', '\0'                    \
+    } /* Move cursor right n lines */
+#define NRF_CLI_VT100_CURSORLF(n)                                       \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', (n), 'D', '\0'                    \
+    } /* Move cursor left n lines */
+#define NRF_CLI_VT100_CURSORHOME                                        \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', 'H', '\0'                         \
+    } /* Move cursor to upper left corner */
+#define NRF_CLI_VT100_CURSORHOME_                                       \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', ';', 'H', '\0'                    \
+    } /* Move cursor to upper left corner */
+#define NRF_CLI_VT100_CURSORPOS(v, h)                                   \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', (v), ';', (h), 'H', '\0'          \
+    } /* Move cursor to screen location v,h */
+
+#define NRF_CLI_VT100_HVHOME                                            \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', 'f', '\0'                         \
+    } /* Move cursor to upper left corner */
+#define NRF_CLI_VT100_HVHOME_                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', ';', 'f', '\0'                    \
+    } /* Move cursor to upper left corner */
+#define NRF_CLI_VT100_HVPOS(v, h)                                       \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', (v), ';', (h), 'f', '\0'          \
+    } /* Move cursor to screen location v,h */
+#define NRF_CLI_VT100_INDEX                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'D', '\0'                              \
+    } /* Move/scroll window up one line */
+#define NRF_CLI_VT100_REVINDEX                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'M', '\0'                              \
+    } /* Move/scroll window down one line */
+#define NRF_CLI_VT100_NEXTLINE                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'E', '\0'                              \
+    } /* Move to next line */
+#define NRF_CLI_VT100_SAVECURSOR                                        \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '7', '\0'                              \
+    } /* Save cursor position and attributes */
+#define NRF_CLI_VT100_RESTORECURSOR                                     \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '8', '\0'                              \
+    } /* Restore cursor position and attribute */
+
+#define NRF_CLI_VT100_TABSET                                            \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'H', '\0'                              \
+    } /* Set a tab at the current column */
+#define NRF_CLI_VT100_TABCLR                                            \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', 'g', '\0'                         \
+    } /* Clear a tab at the current column */
+#define NRF_CLI_VT100_TABCLR_                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '0', 'g', '\0'                    \
+    } /* Clear a tab at the current column */
+#define NRF_CLI_VT100_TABCLRALL                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '3', 'g', '\0'                    \
+    } /* Clear all tabs */
+
+#define NRF_CLI_VT100_DHTOP                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '#', '3', '\0'                         \
+    } /* Double-height letters, top half */
+#define NRF_CLI_VT100_DHBOT                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '#', '4', '\0'                         \
+    } /* Double-height letters, bottom hal */
+#define NRF_CLI_VT100_SWSH                                              \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '#', '5', '\0'                         \
+    } /* Single width, single height letters */
+#define NRF_CLI_VT100_DWSH                                              \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '#', '6', '\0'                         \
+    } /* Double width, single height letters */
+
+#define NRF_CLI_VT100_CLEAREOL                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', 'K', '\0'                         \
+    } /* Clear line from cursor right */
+#define NRF_CLI_VT100_CLEAREOL_                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '0', 'K', '\0'                    \
+    } /* Clear line from cursor right */
+#define NRF_CLI_VT100_CLEARBOL                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '1', 'K', '\0'                    \
+    } /* Clear line from cursor left */
+#define NRF_CLI_VT100_CLEARLINE                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '2', 'K', '\0'                    \
+    } /* Clear entire line */
+
+#define NRF_CLI_VT100_CLEAREOS                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', 'J', '\0'                         \
+    } /* Clear screen from cursor down */
+#define NRF_CLI_VT100_CLEAREOS_                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '0', 'J', '\0'                    \
+    } /* Clear screen from cursor down */
+#define NRF_CLI_VT100_CLEARBOS                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '1', 'J', '\0'                    \
+    } /* Clear screen from cursor up */
+#define NRF_CLI_VT100_CLEARSCREEN                                       \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '2', 'J', '\0'                    \
+    } /* Clear entire screen */
+
+#define NRF_CLI_VT100_DEVSTAT                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '5', 'n', '\0'                         \
+    } /* Device status report */
+#define NRF_CLI_VT100_TERMOK                                            \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '0', 'n', '\0'                         \
+    } /* Response: terminal is OK */
+#define NRF_CLI_VT100_TERMNOK                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '3', 'n', '\0'                         \
+    } /* Response: terminal is not OK */
+
+#define NRF_CLI_VT100_GETCURSOR                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '6', 'n', '\0'                    \
+    } /* Get cursor position */
+#define NRF_CLI_VT100_CURSORPOSAT                                       \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, (v), ';', (h), 'R', '\0'               \
+    } /* Response: cursor is at v,h */
+
+#define NRF_CLI_VT100_IDENT                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', 'c', '\0'                         \
+    } /* Identify what terminal type */
+#define NRF_CLI_VT100_IDENT_                                            \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '0', 'c', '\0'                    \
+    } /* Identify what terminal type */
+#define NRF_CLI_VT100_GETTYPE                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '?', '1', ';', (n), '0', 'c', '\0'\
+    } /* Response: terminal type code n */
+
+#define NRF_CLI_VT100_RESET                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'c', '\0'                              \
+    } /*  Reset terminal to initial state */
+
+#define NRF_CLI_VT100_ALIGN                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '#', '8', '\0'                         \
+    } /* Screen alignment display */
+#define NRF_CLI_VT100_TESTPU                                            \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '2', ';', '1', 'y', '\0'          \
+    } /* Confidence power up test */
+#define NRF_CLI_VT100_TESTLB                                            \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '2', ';', '2', 'y', '\0'          \
+    } /* Confidence loopback test */
+#define NRF_CLI_VT100_TESTPUREP                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '2', ';', '9', 'y', '\0'          \
+    } /* Repeat power up test */
+#define NRF_CLI_VT100_TESTLBREP                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '2', ';', '1', '0', 'y', '\0'     \
+    } /* Repeat loopback test */
+
+#define NRF_CLI_VT100_LEDSOFF                                           \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '0', 'q', '\0'                    \
+    } /* Turn off all four leds */
+#define NRF_CLI_VT100_LED1                                              \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '1', 'q', '\0'                    \
+    } /* Turn on LED #1 */
+#define NRF_CLI_VT100_LED2                                              \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '2', 'q', '\0'                    \
+    } /* Turn on LED #2 */
+#define NRF_CLI_VT100_LED3                                              \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '3', 'q', '\0'                    \
+    } /* Turn on LED #3 */
+#define NRF_CLI_VT100_LED4                                              \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, '[', '4', 'q', '\0'                    \
+    } /* Turn on LED #4 */
+
+/* Function Keys */
+
+#define NRF_CLI_VT100_PF1                                               \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'P', '\0'                         \
+    }
+#define NRF_CLI_VT100_PF2                                               \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'Q', '\0'                         \
+    }
+#define NRF_CLI_VT100_PF3                                               \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'R', '\0'                         \
+    }
+#define NRF_CLI_VT100_PF4                                               \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'S', '\0'                         \
+    }
+
+/* Arrow keys */
+
+#define NRF_CLI_VT100_UP_RESET                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'A', '\0'                              \
+    }
+#define NRF_CLI_VT100_UP_SET                                            \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'A', '\0'                         \
+    }
+#define NRF_CLI_VT100_DOWN_RESET                                        \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'B', '\0'                              \
+    }
+#define NRF_CLI_VT100_DOWN_SET                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'B', '\0'                         \
+    }
+#define NRF_CLI_VT100_RIGHT_RESET                                       \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'C', '\0'                              \
+    }
+#define NRF_CLI_VT100_RIGHT_SET                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'C', '\0'                         \
+    }
+#define NRF_CLI_VT100_LEFT_RESET                                        \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'D', '\0'                              \
+    }
+#define NRF_CLI_VT100_LEFT_SET                                          \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'D', '\0'                         \
+    }
+
+/* Numeric Keypad Keys */
+
+#define NRF_CLI_VT100_NUMERIC_0                                         \
+    {                                                                   \
+        '0', '\0'                                                       \
+    }
+#define NRF_CLI_VT100_ALT_0                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'p', '\0'                         \
+    }
+#define NRF_CLI_VT100_NUMERIC_1                                         \
+    {                                                                   \
+        '1', '\0'                                                       \
+    }
+#define NRF_CLI_VT100_ALT_1                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'q', '\0'                         \
+    }
+#define NRF_CLI_VT100_NUMERIC_2                                         \
+    {                                                                   \
+        '2', '\0'                                                       \
+    }
+#define NRF_CLI_VT100_ALT_2                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'r', '\0'                         \
+    }
+#define NRF_CLI_VT100_NUMERIC_3                                         \
+    {                                                                   \
+        '3', '\0'                                                       \
+    }
+#define NRF_CLI_VT100_ALT_3                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 's', '\0'                         \
+    }
+#define NRF_CLI_VT100_NUMERIC_4                                         \
+    {                                                                   \
+        '4', '\0'                                                       \
+    }
+#define NRF_CLI_VT100_ALT_4                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 't', '\0'                         \
+    }
+#define NRF_CLI_VT100_NUMERIC_5                                         \
+    {                                                                   \
+        '5', '\0'                                                       \
+    }
+#define NRF_CLI_VT100_ALT_5                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'u', '\0'                         \
+    }
+#define NRF_CLI_VT100_NUMERIC_6                                         \
+    {                                                                   \
+        '6', '\0'                                                       \
+    }
+#define NRF_CLI_VT100_ALT_6                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'v', '\0'                         \
+    }
+#define NRF_CLI_VT100_NUMERIC_7                                         \
+    {                                                                   \
+        '7', '\0'                                                       \
+    }
+#define NRF_CLI_VT100_ALT_7                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'w', '\0'                         \
+    }
+#define NRF_CLI_VT100_NUMERIC_8                                         \
+    {                                                                   \
+        '8', '\0'                                                       \
+    }
+#define NRF_CLI_VT100_ALT_8                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'x', '\0'                         \
+    }
+#define NRF_CLI_VT100_NUMERIC_9                                         \
+    {                                                                   \
+        '9', '\0'
+#define NRF_CLI_VT100_ALT_9                                             \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'y'                               \
+    }
+#define NRF_CLI_VT100_NUMERIC_MINUS                                     \
+    {                                                                   \
+        '-', '\0'                                                       \
+    }
+#define NRF_CLI_VT100_ALT_MINUS                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'm', '\0'                         \
+    }
+#define NRF_CLI_VT100_NUMERIC_COMMA                                     \
+    {                                                                   \
+        ',', '\0'                                                       \
+    }
+#define NRF_CLI_VT100_ALT_COMMA                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'l', '\0'                         \
+    }
+#define NRF_CLI_VT100_NUMERIC_PERIOD                                    \
+    {                                                                   \
+        '.', '\0'                                                       \
+    }
+#define NRF_CLI_VT100_ALT_PERIOD                                        \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'n', '\0'                         \
+    }
+#define NRF_CLI_VT100_NUMERIC_ENTER                                     \
+    {                                                                   \
+        ASCII_CR                                                        \
+    }
+#define NRF_CLI_VT100_ALT_ENTER                                         \
+    {                                                                   \
+        NRF_CLI_VT100_ASCII_ESC, 'O', 'M', '\0'                         \
+    }
+
+#define NRF_CLI_VT100_COLOR(__col)                                            \
+    {                                                                         \
+        NRF_CLI_VT100_ASCII_ESC, '[', '1', ';', '3', '0' + (__col), 'm', '\0' \
+    }
+#define NRF_CLI_VT100_BGCOLOR(__col)                                          \
+    {                                                                         \
+        NRF_CLI_VT100_ASCII_ESC, '[', '4', '0' + (__col), 'm', '\0'           \
+    }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NRF_CLI_VT100_H__ */
+

+ 289 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/dtalige.c

@@ -0,0 +1,289 @@
+#include "ble_comm.h"
+#include "vl53l1.h"
+#include "tool.h"
+
+
+#define GAMEUSEDTALIGE 1
+
+static unsigned char USEdtalige = 1;
+
+void IMU_Dtalige_Rowdata_ON(void)
+{
+	USEdtalige = 0;
+}
+
+void IMU_Dtalige_Rowdata_OFF(void)
+{
+	USEdtalige = 1;
+}
+
+//.....................重写运动库接口.............................
+unsigned char left_right_buff[60];
+unsigned char left_right_data_len;
+
+static void d_integrate_left_right(uint8_t* left_buff, uint8_t left_len, uint8_t* right_buff, uint8_t right_len)
+{
+	unsigned char L=0;
+	for(int i=0;i<left_len;i++)
+	{
+		left_right_buff[L++]=left_buff[i];
+	}
+	for(int i=0;i<right_len;i++)
+	{
+		left_right_buff[L++]=right_buff[i];
+	}
+	left_right_data_len=L;
+}
+
+static void d_get_game_package(uint8_t* buff_address, uint8_t * buff_len)
+{
+	for(int i=0;i<left_right_data_len;i++)
+	{
+		buff_address[i]=left_right_buff[i];
+	}
+	*buff_len=left_right_data_len;
+}
+
+unsigned char mofoot_buff[30];
+unsigned char mofoot_data_len;
+
+static void d_process_motion(int32_t time_stamp, int16_t _acc[3], int16_t _gry[3],  int16_t front_mag[3], int16_t back_mag[3], uint8_t _rssi)
+{
+	int L=0;
+	
+	mofoot_buff[L++]=_acc[0]>>8;
+	mofoot_buff[L++]=_acc[0];
+	mofoot_buff[L++]=_acc[1]>>8;
+	mofoot_buff[L++]=_acc[1];
+	mofoot_buff[L++]=_acc[2]>>8;
+	mofoot_buff[L++]=_acc[2];
+	
+	mofoot_buff[L++]=_gry[0]>>8;
+	mofoot_buff[L++]=_gry[0];
+	mofoot_buff[L++]=_gry[1]>>8;
+	mofoot_buff[L++]=_gry[1];
+	mofoot_buff[L++]=_gry[2]>>8;
+	mofoot_buff[L++]=_gry[2];
+	
+	mofoot_buff[L++]=front_mag[0]>>8;
+	mofoot_buff[L++]=front_mag[0];
+	mofoot_buff[L++]=front_mag[1]>>8;
+	mofoot_buff[L++]=front_mag[1];
+	mofoot_buff[L++]=front_mag[2]>>8;
+	mofoot_buff[L++]=front_mag[2];
+	
+	mofoot_buff[L++]=back_mag[0]>>8;
+	mofoot_buff[L++]=back_mag[0];
+	mofoot_buff[L++]=back_mag[1]>>8;
+	mofoot_buff[L++]=back_mag[1];
+	mofoot_buff[L++]=back_mag[2]>>8;
+	mofoot_buff[L++]=back_mag[2];
+	
+//	mofoot_buff[L++]=_rssi;
+//	
+//	mofoot_buff[L++]=time_stamp>>24;
+//	mofoot_buff[L++]=time_stamp>>16;
+//	mofoot_buff[L++]=time_stamp>>8;
+//	mofoot_buff[L++]=time_stamp;
+	
+	mofoot_data_len=L;
+}
+
+static void d_get_foot_data(uint8_t *buf, uint8_t *buff_len)
+{
+	for(int i=0;i<mofoot_data_len;i++)
+	{
+		buf[i]=mofoot_buff[i];
+	}
+	*buff_len=mofoot_data_len;
+}
+//.....................重写运动库接口.............................end
+
+typedef struct {
+	unsigned char imubuff[72];
+	unsigned char imubuff_len;
+	uint16_t        ts;
+}IMU_Hal_t;
+
+typedef struct {
+        IMU_Hal_t         h;
+        IMU_Hal_t         s;
+}IMU_Hal_RL_t;
+
+typedef void (*process_motion_t)(uint8_t* left_buff,uint8_t left_len, uint8_t* right_buff, uint8_t right_len);
+
+extern void get_game_package(uint8_t* buff_address, uint8_t * buff_len);
+extern void integrate_left_right(uint8_t* left_buff,uint8_t left_len, uint8_t* right_buff, uint8_t right_len);
+extern void get_foot_data(uint8_t *buf, uint8_t *buff_len);
+
+IMU_Hal_t rev_s={.ts=0};
+IMU_Hal_t rev={.ts=0};
+IMU_Hal_t rev_io;
+IMU_Hal_RL_t temp_IMU_DAT;
+QUEUE_DEF(IMU_Hal_t, IMU_DAT_H_queue, size_4, QUEUE_MODE_OVERFLOW);
+QUEUE_DEF(IMU_Hal_t, IMU_DAT_S_queue, size_4, QUEUE_MODE_OVERFLOW);
+
+extern uint16_t lose_pack_all;
+void IMU_dtalige(IMU_Hal_RL_t *outp, queue_t *ph, queue_t *ps, process_motion_t process_p)
+{
+    static char sta = 0;
+    static unsigned short R_timestamp_re = 0;
+    switch (sta)
+    {
+    case 0:
+        if (ps->element_count > 0)
+        {
+            BLE_PRINT( "IMU_dtalige init.\r\n");
+            sta = 1;
+            queue_reset(ps);
+            queue_reset(ph);
+        }
+        break;
+    case 1:  
+				while (ps->element_count > ph->element_count)
+				{
+						queue_out(ps, &outp->s);
+						R_timestamp_re = outp->s.ts;
+				}
+				if (ps->element_count > 0)
+				{
+						queue_out(ps, &outp->s);
+						R_timestamp_re++;
+						if (R_timestamp_re != outp->s.ts)
+						{
+								do
+								{
+										BLE_PRINT( "lose packet %d\r\n", R_timestamp_re);
+										#if LOSSPACK_ENANBLE
+									
+										extern uint16_t lose_pack_all;
+										lose_pack_all++;
+										#endif
+									
+										R_timestamp_re++;
+										queue_out(ph, &outp->h);
+										if (R_timestamp_re == outp->h.ts)
+										{
+												queue_out(ph, &outp->h);
+												process_p(outp->h.imubuff, outp->h.imubuff_len, outp->s.imubuff, outp->s.imubuff_len);
+												get_game_package(rev_io.imubuff, &rev_io.imubuff_len); 
+											
+												rev_io.ts++;
+												rev_io.imubuff[rev_io.imubuff_len + 1] = rev_io.ts;
+												rev_io.imubuff[rev_io.imubuff_len] = rev_io.ts >> 8;
+												if(rev_io.ts%2==0)
+												send_protocol(0, 4, rev_io.imubuff, rev_io.imubuff_len);
+												break;
+										}
+										if (ph->element_count <= 0)
+										{
+												sta = 0;
+												break;
+										}
+								} while (1);
+						}
+						else
+						{
+								queue_out(ph, &outp->h);
+							
+								process_p(outp->h.imubuff, outp->h.imubuff_len, outp->s.imubuff, outp->s.imubuff_len);
+								get_game_package(rev_io.imubuff, &rev_io.imubuff_len);
+							
+								rev_io.ts++;
+								rev_io.imubuff[rev_io.imubuff_len + 1] = rev_io.ts;
+								rev_io.imubuff[rev_io.imubuff_len] = rev_io.ts >> 8;
+								if(rev_io.ts%2==0)
+								send_protocol(0, 4, rev_io.imubuff, rev_io.imubuff_len);
+						}
+				}       
+        break;
+    }
+//		SEGGER_RTT_printf(0, "%d,%d\r\n",ph->element_count,ps->element_count);
+}
+
+void IMU_Dtalige(void)
+{
+	if( USEdtalige )
+	{
+		#if GAMEUSEDTALIGE
+		IMU_dtalige(&temp_IMU_DAT, &IMU_DAT_H_queue, &IMU_DAT_S_queue, integrate_left_right);
+		#endif
+	}
+}
+
+void IMU_Rec_data(uint8_t* pdat,uint8_t len)
+{
+	if(pdat[3]==4)
+	{		
+		memcpy(rev_s.imubuff,&pdat[4],pdat[1]);
+		rev_s.imubuff_len=pdat[1]-7;
+		rev_s.ts=((uint16_t)pdat[pdat[1]-3]<<8) |((uint16_t)pdat[pdat[1]-2]<<0);
+		if( USEdtalige )
+		{
+			#if GAMEUSEDTALIGE
+			queue_in(&IMU_DAT_S_queue,&rev_s);	
+			#endif
+		}
+	}
+}
+
+void IMU_Process_motion_queue(uint8_t IS_HOST, int32_t time_stamp, int16_t* _acc,int16_t* _gry, int16_t* front_mag, int16_t* back_mag, uint8_t _rssi)
+{
+	if( USEdtalige )
+	{		
+		process_motion(time_stamp, _acc, _gry, front_mag, back_mag, _rssi);
+
+		get_foot_data(rev.imubuff,&rev.imubuff_len);
+	}
+	else
+	{
+		d_process_motion(time_stamp, _acc, _gry, front_mag, back_mag, _rssi);
+
+		d_get_foot_data(rev.imubuff,&rev.imubuff_len);
+	}
+	rev.ts++;		
+		
+	if(IS_HOST)
+	{
+		if( USEdtalige )
+		{
+			#if GAMEUSEDTALIGE
+			queue_in(&IMU_DAT_H_queue,&rev);
+			#else
+			integrate_left_right(rev.imubuff, rev.imubuff_len, rev_s.imubuff, rev_s.imubuff_len);
+			get_game_package(rev_io.imubuff, &rev_io.imubuff_len);
+			rev_io.ts++;
+			rev_io.imubuff[rev_io.imubuff_len + 1] = rev_io.ts;
+			rev_io.imubuff[rev_io.imubuff_len] = rev_io.ts >> 8;
+			if(rev_io.ts%2==0)
+			send_protocol(0, 4, rev_io.imubuff, rev_io.imubuff_len);
+			#endif
+		}
+		else
+		{
+			d_integrate_left_right(rev.imubuff, rev.imubuff_len, rev_s.imubuff, rev_s.imubuff_len);
+			d_get_game_package(rev_io.imubuff, &rev_io.imubuff_len);
+			rev_io.ts++;
+			rev_io.imubuff[rev_io.imubuff_len + 1] = rev_io.ts;
+			rev_io.imubuff[rev_io.imubuff_len] = rev_io.ts >> 8;
+			if(rev_io.ts%2==0)
+			send_protocol(0, 4, rev_io.imubuff, rev_io.imubuff_len);
+		}
+	}
+	else
+	{
+		rev.imubuff[rev.imubuff_len+1]=rev.ts;
+		rev.imubuff[rev.imubuff_len]=rev.ts>>8;
+		send_protocol(0,4,rev.imubuff,rev.imubuff_len+2);
+	}
+}
+
+
+
+
+
+
+
+
+
+

+ 678 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/host.c

@@ -0,0 +1,678 @@
+#include "ble_comm.h"
+#include "app_flash.h"
+
+#if USENAMEFR
+char Target_scan[TARFET_LEN_MAX] = "SH_E9F4";
+#else
+char Target_scan[TARFET_LEN_MAX] = {0x01, 0xf9, 0x84, 0x6a, 0x83, 0xeb};
+#endif
+
+static Ble_receive_handler_t Rec_h = NULL;
+
+#define APP_BLE_CONN_CFG_TAG 1                           /**< Tag that refers to the BLE stack configuration set with @ref sd_ble_cfg_set. The default tag is @ref BLE_CONN_CFG_TAG_DEFAULT. */
+#define APP_BLE_OBSERVER_PRIO 3                          /**< BLE observer priority of the application. There is no need to modify this value. */
+#define UART_TX_BUF_SIZE 1024                            /**< UART TX buffer size. */
+#define UART_RX_BUF_SIZE 1024                            /**< UART RX buffer size. */
+#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */
+#define ECHOBACK_BLE_UART_DATA 1                         /**< Echo the UART data that is received over the Nordic UART Service (NUS) back to the sender. */
+BLE_NUS_C_DEF(m_ble_nus_c);                              /**< BLE Nordic UART Service (NUS) client instance. */
+NRF_BLE_GATT_DEF(m_gatt);                                /**< GATT module instance. */
+BLE_DB_DISCOVERY_DEF(m_db_disc);                         /**< Database discovery module instance. */
+NRF_BLE_SCAN_DEF(m_scan);                                /**< Scanning Module instance. */
+NRF_BLE_GQ_DEF(m_ble_gatt_queue,                         /**< BLE GATT Queue instance. */
+               NRF_SDH_BLE_CENTRAL_LINK_COUNT,
+               NRF_BLE_GQ_QUEUE_SIZE);
+static uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH; /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
+unsigned char connect_to_server = 0;
+ble_gap_conn_params_t host_conn_params = {0};
+static void db_disc_handler(ble_db_discovery_evt_t *p_evt)
+{
+    ble_nus_c_on_db_disc_evt(&m_ble_nus_c, p_evt);
+}
+void timer_init(void)
+{
+    ret_code_t err_code = app_timer_init();
+    APP_ERROR_CHECK(err_code);
+}
+static void db_discovery_init(void)
+{
+    ble_db_discovery_init_t db_init;
+
+    memset(&db_init, 0, sizeof(ble_db_discovery_init_t));
+
+    db_init.evt_handler = db_disc_handler;
+    db_init.p_gatt_queue = &m_ble_gatt_queue;
+
+    ret_code_t err_code = ble_db_discovery_init(&db_init);
+    APP_ERROR_CHECK(err_code);
+}
+void power_management_init(void)
+{
+    ret_code_t err_code;
+    err_code = nrf_pwr_mgmt_init();
+    APP_ERROR_CHECK(err_code);
+}
+static void gatt_evt_handler(nrf_ble_gatt_t *p_gatt, nrf_ble_gatt_evt_t const *p_evt)
+{
+    if (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)
+    {
+        BLE_PRINT("GATT MTU exchange completed.\r\r\n");
+
+        m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
+        BLE_PRINT("Ble NUS max data length set to 0x%X(%d)\r\r\n", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
+    }
+}
+void gatt_init(void)
+{
+    ret_code_t err_code;
+
+    err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
+    APP_ERROR_CHECK(err_code);
+
+    err_code = nrf_ble_gatt_att_mtu_central_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
+    APP_ERROR_CHECK(err_code);
+	
+	  err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
+    APP_ERROR_CHECK(err_code);
+}
+void scan_start(void)
+{
+    ret_code_t ret;
+
+	if(connect_to_server)return;
+    ret = nrf_ble_scan_start(&m_scan);
+    APP_ERROR_CHECK(ret);
+	BLE_PRINT("scan_start -> scan_name  <%s> \r\n", Target_scan);
+}
+
+
+void ST_scan_stop(void)
+{
+  nrf_ble_scan_stop();
+	BLE_PRINT("ST_scan_stop \r\n");
+}
+
+unsigned int ST_scan_start(void)
+{
+  ret_code_t ret;
+  ret = nrf_ble_scan_start(&m_scan);
+  APP_ERROR_CHECK(ret);
+	BLE_PRINT("ST_scan_start -> scan_name  <%s> \r\n", Target_scan);
+	if(ret != APP_SUCCESS)
+	{
+		return APP_ERROR_RESOURCES;
+	}
+	return APP_SUCCESS;
+}
+
+
+static void ble_nus_c_evt_handler(ble_nus_c_t *p_ble_nus_c, ble_nus_c_evt_t const *p_ble_nus_evt)
+{
+    ret_code_t err_code;
+
+    switch (p_ble_nus_evt->evt_type)
+    {
+    case BLE_NUS_C_EVT_DISCOVERY_COMPLETE:
+        BLE_PRINT("Discovery complete.\r\n");
+        err_code = ble_nus_c_handles_assign(p_ble_nus_c, p_ble_nus_evt->conn_handle, &p_ble_nus_evt->handles);
+        APP_ERROR_CHECK(err_code);
+
+        err_code = ble_nus_c_tx_notif_enable(p_ble_nus_c);
+        APP_ERROR_CHECK(err_code);
+        BLE_PRINT("Connected to device with Nordic UART Service.\r\n");
+        break;
+
+    case BLE_NUS_C_EVT_NUS_TX_EVT: //作为主机接收从机的数据
+        Rec_h(p_ble_nus_evt->p_data, p_ble_nus_evt->data_len);
+        break;
+
+    case BLE_NUS_C_EVT_DISCONNECTED:
+        BLE_PRINT("Disconnected.\r\n");
+#if		DEBUGBLE
+        scan_start();
+#endif
+        break;
+    }
+}
+static void nus_error_handler(uint32_t nrf_error)
+{
+    if (nrf_error == NRF_ERROR_RESOURCES)
+        return;
+		if (nrf_error == NRF_ERROR_INVALID_STATE)
+        return;
+    APP_ERROR_HANDLER(nrf_error);
+}
+static void nus_c_init(void)
+{
+    ret_code_t err_code;
+    ble_nus_c_init_t init;
+
+    init.evt_handler = ble_nus_c_evt_handler;
+    init.error_handler = nus_error_handler;
+    init.p_gatt_queue = &m_ble_gatt_queue;
+
+    err_code = ble_nus_c_init(&m_ble_nus_c, &init);
+    APP_ERROR_CHECK(err_code);
+}
+
+#define host_connected_evt_num_max 3
+static uint8_t host_connected_evt_num = 0;
+static Ble_evt_cb ble_host_connected_evt_cb[host_connected_evt_num_max] = {0};
+int Ble_Host_Connectd_Evt_Regist(Ble_evt_cb cb)
+{
+    for (int i = 0; i < host_connected_evt_num_max; i++)
+    {
+        if (ble_host_connected_evt_cb[i] == cb)
+            return -1;
+        if (ble_host_connected_evt_cb[i] == 0)
+        {
+            host_connected_evt_num++;
+            ble_host_connected_evt_cb[i] = cb; //回调函数
+            return 0;
+        }
+    }
+    SEGGER_RTT_printf(0, "ble_evt_Regist -> too many!\n");
+    return -2;
+}
+
+void ble_host_connected_evt_pcs(void)
+{
+    for (int i = 0; i < host_connected_evt_num; i++)
+    { //SEGGER_RTT_printf(0,"time_cb[%d]=%d\n",i,time_cb[i]);
+        if (ble_host_connected_evt_cb[i])
+        {
+            ble_host_connected_evt_cb[i](); //回调函数
+        }
+    }
+}
+
+#define host_disconn_evt_num_max 16
+static uint8_t host_disconn_evt_num = 0;
+static Ble_evt_cb ble_Host_disconn_evt_cb[host_disconn_evt_num_max] = {0};
+int Ble_Host_Disconn_Evt_Regist(Ble_evt_cb cb)
+{
+    for (int i = 0; i < host_disconn_evt_num_max; i++)
+    {
+        if (ble_Host_disconn_evt_cb[i] == cb)
+            return -1;
+        if (ble_Host_disconn_evt_cb[i] == 0)
+        {
+            host_disconn_evt_num++;
+            ble_Host_disconn_evt_cb[i] = cb; //回调函数
+            return 0;
+        }
+    }
+    SEGGER_RTT_printf(0, "Ble_Slave_Disconn_Evt_Regist -> too many!\r\n");
+    return -2;
+}
+
+void ble_host_dicconn_evt_pcs(void)
+{
+    for (int i = 0; i < host_disconn_evt_num; i++)
+    { //SEGGER_RTT_printf(0,"time_cb[%d]=%d\n",i,time_cb[i]);
+        if (ble_Host_disconn_evt_cb[i])
+        {
+            ble_Host_disconn_evt_cb[i](); //回调函数
+        }
+    }
+}
+
+bool advdata_name_find(uint8_t const * p_encoded_data,
+                           uint16_t        data_len,
+                           char    const * p_target_name)
+{
+	return ble_advdata_name_find(p_encoded_data,data_len,p_target_name);
+}
+
+bool advdata_short_name_find(uint8_t const * p_encoded_data,
+                                 uint16_t        data_len,
+                                 char    const * p_target_name,
+                                 uint8_t const   short_name_min_len)
+{
+	return ble_advdata_short_name_find(p_encoded_data,data_len,p_target_name,short_name_min_len);
+}
+
+#if BleNameHoldOn_ENANBLE
+uint8_t SaveFlashFlag_holdOn =0;
+#endif
+
+advdata_rep_handler_t _advdata_rep_callback = NULL;
+void advdata_report_Evt_Regist(advdata_rep_handler_t handler)
+{
+	if(handler==NULL)
+	{
+		BLE_PRINT("advdata_report_Evt_Regist ERROR\r\n"); 
+	}
+	else
+	{
+		BLE_PRINT("advdata_report_Evt_Regist SUCCESS\r\n"); 
+		_advdata_rep_callback=handler;
+	}
+}
+
+static void on_ble_central_evt(ble_evt_t const *p_ble_evt, void *p_context) //作为主设备时的处理
+{
+    ret_code_t err_code;
+    ble_gap_evt_t const *p_gap_evt = &p_ble_evt->evt.gap_evt;
+
+    switch (p_ble_evt->header.evt_id)
+    {
+    case BLE_GAP_EVT_CONNECTED:
+        err_code = ble_nus_c_handles_assign(&m_ble_nus_c, p_ble_evt->evt.gap_evt.conn_handle, NULL);
+        APP_ERROR_CHECK(err_code);
+
+        BLE_PRINT("start discovery services\r\n"); //添加开始发现服务提示
+        connect_to_server = 1;
+        // start discovery of services. The NUS Client waits for a discovery result
+        err_code = ble_db_discovery_start(&m_db_disc, p_ble_evt->evt.gap_evt.conn_handle);
+        APP_ERROR_CHECK(err_code);
+        ble_host_connected_evt_pcs();
+		
+        #if BleNameHoldOn_ENANBLE
+		    if(mFlash.isHost >0){
+						uint8_t i =0;
+						for(i=0;i<6;i++){
+							 if(mFlash.mClient.macAddr[i] != 0xff)break;
+						}
+						if(6 == i){
+							for(i=0;i<6;i++){
+									mFlash.mClient.macAddr[i] = p_ble_evt->evt.gap_evt.params.connected.peer_addr.addr[5-i];
+									mBackup.macAddr_R[i] = p_ble_evt->evt.gap_evt.params.connected.peer_addr.addr[5-i];
+							}
+							SaveFlashFlag_holdOn = 1;
+						}
+				}
+		    #endif
+				
+        sd_ble_gap_rssi_start(m_ble_nus_c.conn_handle, BLE_GAP_RSSI_THRESHOLD_INVALID, 0);
+        break;
+
+    case BLE_GAP_EVT_DISCONNECTED:
+        connect_to_server = 0;
+        BLE_PRINT("Disconnected. conn_handle: 0x%x, reason: 0x%x",
+                  p_gap_evt->conn_handle,
+                  p_gap_evt->params.disconnected.reason);
+        BLE_PRINT("Disconnected to Server.\r\n");
+        ble_host_dicconn_evt_pcs();
+
+        sd_ble_gap_rssi_stop(m_ble_nus_c.conn_handle);
+        break;
+
+    case BLE_GAP_EVT_TIMEOUT:
+        if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
+        {
+            BLE_PRINT("Connection Request timed out.\r\n");
+        }
+        break;
+
+    case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
+        // Pairing not supported.
+        err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
+        APP_ERROR_CHECK(err_code);
+        BLE_PRINT("on_ble_central_evt -> BLE_GAP_EVT_SEC_PARAMS_REQUEST\r\n");
+        break;
+
+    case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
+    {
+        BLE_PRINT("Connection 0x%x PHY update request.", p_ble_evt->evt.gap_evt.conn_handle);
+        ble_gap_phys_t const phys =
+            {
+                .rx_phys = BLE_GAP_PHY_AUTO,
+                .tx_phys = BLE_GAP_PHY_AUTO,
+            };
+        err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
+        APP_ERROR_CHECK(err_code);
+    }
+    break;
+
+    case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
+        // Accepting parameters requested by peer.
+        err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
+                                                &p_gap_evt->params.conn_param_update_request.conn_params); //主机接受从机连接参数更新连接参数
+        APP_ERROR_CHECK(err_code);
+        BLE_PRINT("on_ble_central_evt -> BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST\r\n");
+        break;
+
+    case BLE_GAP_EVT_CONN_PARAM_UPDATE:
+			
+        BLE_PRINT("on_ble_central_evt -> BLE_GAP_EVT_CONN_PARAM_UPDATE\r\n");
+        memcpy(&host_conn_params, &p_gap_evt->params.conn_param_update_request.conn_params, sizeof(ble_gap_conn_params_t));
+        BLE_PRINT("min_conn_interval : %d * 1.25 ms\r\n", p_gap_evt->params.conn_param_update_request.conn_params.min_conn_interval);
+        BLE_PRINT("max_conn_interval : %d * 1.25 ms\r\n", p_gap_evt->params.conn_param_update_request.conn_params.max_conn_interval);
+        BLE_PRINT("slave_latency     : %d\r\n", p_gap_evt->params.conn_param_update_request.conn_params.slave_latency);
+        BLE_PRINT("conn_sup_timeout  : %d * 10   ms\r\n", p_gap_evt->params.conn_param_update_request.conn_params.conn_sup_timeout);
+        break;
+
+    case BLE_GATTC_EVT_TIMEOUT:
+        // Disconnect on GATT Client timeout event.
+        BLE_PRINT("GATT Client Timeout.\r\n");
+        err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
+                                         BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
+        APP_ERROR_CHECK(err_code);
+        break;
+
+    case BLE_GATTS_EVT_TIMEOUT:
+        // Disconnect on GATT Server timeout event.
+        BLE_PRINT("GATT Server Timeout.\r\n");
+        err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
+                                         BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
+        APP_ERROR_CHECK(err_code);
+        break;
+		
+		case BLE_GAP_EVT_ADV_REPORT:
+				{					
+					if(p_gap_evt->params.adv_report.type.scan_response == 0)
+					{
+						if(_advdata_rep_callback != NULL)
+						{
+							_advdata_rep_callback(p_gap_evt->params.adv_report.data.p_data , p_gap_evt->params.adv_report.data.len ,p_gap_evt->params.adv_report.rssi);
+						}
+//						unsigned short parsed_name_len;
+//						uint16_t offset = 0;
+//						parsed_name_len = ble_advdata_search(p_gap_evt->params.adv_report.data.p_data,p_gap_evt->params.adv_report.data.len,&offset,BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME);
+//						if(parsed_name_len>0)
+//						{
+//							printf( " RSSI:%d \tNAME :",p_gap_evt->params.adv_report.rssi);
+//							for(int k=0;k<parsed_name_len;k++)
+//							{
+//								printf( "%c" ,p_gap_evt->params.adv_report.data.p_data[k+offset] );
+//							}
+//							printf( "\r\n");
+//						}		
+							
+					}
+				}
+			break;
+
+    default:
+        break;
+    }
+}
+extern bool ble_evt_is_advertising_timeout(ble_evt_t const *p_ble_evt);
+extern void on_ble_peripheral_evt(ble_evt_t const *p_ble_evt); //作为从设备的处理
+static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context)
+{
+    uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
+    uint16_t role = ble_conn_state_role(conn_handle);
+
+    // Based on the role this device plays in the connection, dispatch to the right handler.不同角色下所做的处理
+    if (role == BLE_GAP_ROLE_PERIPH || ble_evt_is_advertising_timeout(p_ble_evt))
+    {
+        //			  ble_nus_on_ble_evt(p_ble_evt, &m_nus);
+        on_ble_peripheral_evt(p_ble_evt);
+    }
+    else if ((role == BLE_GAP_ROLE_CENTRAL) || (p_ble_evt->header.evt_id == BLE_GAP_EVT_ADV_REPORT))
+    {
+        //        ble_nus_c_on_ble_evt(p_ble_evt, &m_ble_nus_c);
+        on_ble_central_evt(p_ble_evt, NULL);
+    }
+    else
+    {
+        BLE_PRINT("ble_evt_handler -> other\r\n");
+    }
+}
+void ble_stack_init(void)
+{
+    ret_code_t err_code;
+
+    err_code = nrf_sdh_enable_request();
+    APP_ERROR_CHECK(err_code);
+
+    // Configure the BLE stack using the default settings.
+    // Fetch the start address of the application RAM.
+    uint32_t ram_start = 0;
+    err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
+    APP_ERROR_CHECK(err_code);
+
+    // Enable BLE stack.
+    err_code = nrf_sdh_ble_enable(&ram_start);
+    APP_ERROR_CHECK(err_code);
+
+    // Register a handler for BLE events.
+    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
+}
+#define PRINT_MAC 0
+/**@brief Function for handling Scanning Module events.
+ */
+static void scan_evt_handler(scan_evt_t const *p_scan_evt)
+{
+    ret_code_t err_code;
+
+    switch (p_scan_evt->scan_evt_id)
+    {
+    case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
+    {
+        err_code = p_scan_evt->params.connecting_err.err_code;
+//        APP_ERROR_CHECK(err_code);
+        BLE_PRINT("scan_evt_handler -> NRF_BLE_SCAN_EVT_CONNECTING_ERROR \r\n");
+    }
+    break;
+
+    case NRF_BLE_SCAN_EVT_CONNECTED:
+    {
+        BLE_PRINT("scan_evt_handler -> NRF_BLE_SCAN_EVT_CONNECTED\r\n");
+#if PRINT_MAC
+        ble_gap_evt_connected_t const *p_connected =
+            p_scan_evt->params.connected.p_connected;
+        // Scan is automatically stopped by the connection.
+        BLE_PRINT("Connecting to Host %02x%02x %02x%02x %02x%02x\r\r\n",
+                  p_connected->peer_addr.addr[0],
+                  p_connected->peer_addr.addr[1],
+                  p_connected->peer_addr.addr[2],
+                  p_connected->peer_addr.addr[3],
+                  p_connected->peer_addr.addr[4],
+                  p_connected->peer_addr.addr[5]);
+#endif
+    }
+    break;
+
+    case NRF_BLE_SCAN_EVT_SCAN_TIMEOUT:
+    {
+        BLE_PRINT("scan_evt_handler -> NRF_BLE_SCAN_EVT_SCAN_TIMEOUT -> Scan timed out.\r\n");
+        scan_start();
+    }
+    break;
+
+    case NRF_BLE_SCAN_EVT_FILTER_MATCH:
+    {
+        BLE_PRINT("scan_evt_handler -> NRF_BLE_SCAN_EVT_FILTER_MATCH\r\n");
+    }
+    break;
+
+    case NRF_BLE_SCAN_EVT_WHITELIST_REQUEST:
+    {
+        BLE_PRINT("scan_evt_handler -> NRF_BLE_SCAN_EVT_WHITELIST_REQUEST\r\n");
+    }
+    break;
+
+    case NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT:
+    {
+        BLE_PRINT("scan_evt_handler -> NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT\r\n");
+    }
+    break;
+
+    case NRF_BLE_SCAN_EVT_NOT_FOUND:
+    {
+        //						 BLE_PRINT("scan_evt_handler -> NRF_BLE_SCAN_EVT_NOT_FOUND");
+    }
+    break;
+
+    default:
+        BLE_PRINT("scan_evt_handler -> default:%d \r\n", p_scan_evt->scan_evt_id);
+        break;
+    }
+}
+
+unsigned int send_bytes_server(uint8_t *bytes, uint16_t len)
+{
+    if (connect_to_server == 0)
+    {
+        BLE_PRINT("send_bytes_server -> APP_ERR_DISCONN\r\n");
+        return APP_ERR_DISCONN;
+    }
+    if (len > m_ble_nus_max_data_len)
+    {
+        BLE_PRINT("send_bytes_server -> fail ->overlength\r\n");
+        return APP_ERR_OVERLENGTH;
+    }
+    if (NRF_SUCCESS != ble_nus_c_string_send(&m_ble_nus_c, bytes, len))
+    {
+        BLE_PRINT("send_bytes_server -> fail\r\n");
+    }
+    return APP_SUCCESS;
+}
+
+static void scan_init(void)
+{
+    ret_code_t err_code;
+    nrf_ble_scan_init_t init_scan;
+
+    memset(&init_scan, 0, sizeof(init_scan));
+
+    init_scan.connect_if_match = true;
+    init_scan.conn_cfg_tag = APP_BLE_CONN_CFG_TAG;
+
+    err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
+    APP_ERROR_CHECK(err_code);
+
+#if USENAMEFR
+    err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_NAME_FILTER, &Target_scan);
+    APP_ERROR_CHECK(err_code);
+
+    err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_NAME_FILTER, false);
+    APP_ERROR_CHECK(err_code);
+    BLE_PRINT("scan_init -> scan_name  <%s> \r\n", Target_scan);
+#else
+    err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_ADDR_FILTER, &Target_scan);
+    APP_ERROR_CHECK(err_code);
+
+    err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_ADDR_FILTER, false);
+    APP_ERROR_CHECK(err_code);
+
+    BLE_PRINT("scan_start -> scan_MAC [ %02X %02X %02X %02X %02X %02X ]\r\n", Target_scan[0], Target_scan[1], Target_scan[2], Target_scan[3], Target_scan[4], Target_scan[5]);
+
+#endif
+}
+
+unsigned char host_isconnect(void)
+{
+    return connect_to_server;
+}
+char ble_stack_init_sta = 1;
+char host_init_sta = 0;
+void host_init(Ble_receive_handler_t receive_handler)
+{
+    if (receive_handler == NULL)
+    {
+        BLE_PRINT("host_init -> param err \r\n");
+        return;
+    }
+    Rec_h = receive_handler;
+    if (ble_stack_init_sta)
+    {
+        timer_init();            //
+        power_management_init(); //
+        ble_stack_init();        //
+        gatt_init();             //
+        ble_stack_init_sta = 0;
+    }
+
+    db_discovery_init();
+    nus_c_init();
+
+    scan_init();
+		host_init_sta=1;
+}
+
+void err(int err_num)
+{
+    BLE_PRINT("APP ERROR -> %d \r\n", err_num);
+}
+
+unsigned int host_set_scan_name(char *name, int len)
+{
+	unsigned int err_code;
+    if (len > TARFET_LEN_MAX)
+        return APP_ERR_OVERLENGTH;
+		if(connect_to_server)
+				return APP_ERR_CONNECTED;
+		memset(Target_scan, 0, TARFET_LEN_MAX);
+		if(host_init_sta)
+		{
+			memcpy(Target_scan, name, len);
+					err_code =nrf_ble_scan_all_filter_remove(&m_scan);
+					APP_ERROR_CHECK(err_code);
+			#if USENAMEFR
+					err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_NAME_FILTER, &Target_scan);
+					APP_ERROR_CHECK(err_code);
+
+					err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_NAME_FILTER, false);
+					APP_ERROR_CHECK(err_code);
+					BLE_PRINT("host_set_scan_name -> scan_name  <%s> \r\n", Target_scan);
+			#else
+					err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_ADDR_FILTER, &Target_scan);
+					APP_ERROR_CHECK(err_code);
+
+					err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_ADDR_FILTER, false);
+					APP_ERROR_CHECK(err_code);
+
+					BLE_PRINT("host_set_scan_name -> scan_MAC [ %02X %02X %02X %02X %02X %02X ]\r\n", Target_scan[0], Target_scan[1], Target_scan[2], Target_scan[3], Target_scan[4], Target_scan[5]);
+
+			#endif
+		}
+		else
+		{
+			memcpy(Target_scan, name, len);
+		}
+    return APP_SUCCESS;
+}
+
+unsigned int Ble_update_conn_interval(float min_conn_interval, float max_conn_interval)
+{
+    ret_code_t err_code;
+    ble_gap_conn_params_t bgcp;
+    //主机接受从机连接参数更新连接参数
+	
+    if (connect_to_server)
+    {	
+				if ((max_conn_interval > 1.25 * 1599) || (max_conn_interval < min_conn_interval))
+						return APP_ERR_PARAMERR;
+				if (min_conn_interval < 7.5f)
+						return APP_ERR_PARAMERR;
+				bgcp.max_conn_interval = MSEC_TO_UNITS(max_conn_interval, UNIT_1_25_MS);
+				bgcp.min_conn_interval = MSEC_TO_UNITS(min_conn_interval, UNIT_1_25_MS);
+				bgcp.conn_sup_timeout = MSEC_TO_UNITS(4000, UNIT_10_MS);
+				bgcp.slave_latency = 0;
+				
+        err_code = sd_ble_gap_conn_param_update(m_ble_nus_c.conn_handle, &bgcp);
+				if(err_code != NRF_ERROR_INVALID_STATE && err_code != NRF_ERROR_BUSY && err_code != NRF_SUCCESS){
+					APP_ERROR_CHECK(err_code);
+				}
+        return err_code;
+    }
+    else
+    {
+        return APP_ERR_DISCONN;
+    }
+}
+
+void host_disconnect(void)
+{
+    if (connect_to_server)
+        sd_ble_gap_disconnect(m_ble_nus_c.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
+}
+void host_get_conn_params(ble_gap_conn_params_t *p)
+{
+    memcpy(p, &host_conn_params, sizeof(ble_gap_conn_params_t));
+}
+static signed char rssi = 0;
+signed char host_get_rssi(void)
+{
+    unsigned char channel;
+    if (connect_to_server == 0)
+        return 1;
+    sd_ble_gap_rssi_get(m_ble_nus_c.conn_handle, &rssi, &channel);
+    ///BLE_PRINT("rssi= %d  channel=%d\r\n", rssi, channel);
+    return rssi;
+}
+

+ 46 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/queue.c

@@ -0,0 +1,46 @@
+#include "queue.h"
+
+
+unsigned short queue_in(queue_t * p_queue, void const * p_element)
+{
+	unsigned char * p = (unsigned char*)p_queue->p_buffer + ((p_queue->front & (p_queue->size-1))*(p_queue->element_size));
+	if(p_queue->element_count>=p_queue->size)return 0;
+	for(int i=0;i<p_queue->element_size;i++)
+	{
+		p[i]=((unsigned char*)(void*)p_element)[i];
+	}
+	p_queue->front++;
+	p_queue->element_count++;
+	return 1;
+}
+
+unsigned short queue_out(queue_t * p_queue, void * p_element)
+{
+	unsigned char * p = (unsigned char*)p_queue->p_buffer + ((p_queue->back & (p_queue->size-1))*(p_queue->element_size));
+	if(p_queue->element_count<1)return 0;
+	for(int i=0;i<p_queue->element_size;i++)
+	{
+		((unsigned char*)(void*)p_element)[i]=p[i];
+	}
+	p_queue->back++;
+	p_queue->element_count--;
+	return 1;
+}
+
+unsigned short queue_peek(queue_t * p_queue, void * p_element)
+{
+	unsigned char * p = (unsigned char*)p_queue->p_buffer + ((p_queue->back & (p_queue->size-1))*(p_queue->element_size));
+	if(p_queue->element_count<1)return 0;
+	for(int i=0;i<p_queue->element_size;i++)
+	{
+		((unsigned char*)(void*)p_element)[i]=p[i];
+	}
+	return 1;
+}
+
+void queue_reset(queue_t * p_queue)
+{
+	p_queue->back=0;
+	p_queue->front=0;              
+	p_queue->element_count=0;																		
+}

+ 76 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/queue.h

@@ -0,0 +1,76 @@
+#ifndef __QUEUE_H
+#define __QUEUE_H
+
+/**@brief   队列模式类型
+ * @details 
+ *          Also, it keeps the information about which memory is allocated for the buffer
+ *          and its size. This structure must be initialized by app_fifo_init() before use.
+ */
+typedef enum
+{
+    QUEUE_MODE_OVERFLOW,        //!< If the queue is full, new element will overwrite the oldest.
+    QUEUE_MODE_NO_OVERFLOW,     //!< If the queue is full, new element will not be accepted.
+} queue_mode_t;
+/**@brief   A FIFO instance structure.
+ * @details Keeps track of which bytes to read and write next.
+ *          Also, it keeps the information about which memory is allocated for the buffer
+ *          and its size. This structure must be initialized by app_fifo_init() before use.
+ */
+typedef enum
+{
+	size_4 		  = 0x0004U,
+	size_8 		  = 0x0008U,
+	size_16 		= 0x0010U,								 	                            
+	size_32 		= 0x0020U,
+	size_64 		= 0x0040U,
+	size_128 		= 0x0080U,
+  size_256 		= 0x0100U,         
+	size_512 		= 0x0200U,
+	size_1024 	= 0x0400U,
+	size_2048 	= 0x0800U,
+	size_4096 	= 0x1000U,
+	size_8192 	= 0x2000U,
+	size_16384	= 0x4000U,
+	size_32768	= 0x8000U,
+} queue_size_t;
+
+typedef struct
+{
+  volatile unsigned short front;          //!< Queue front index.
+  volatile unsigned short back;           //!< Queue back index.
+	void           		* p_buffer;          //!< Pointer to the memory that is used as storage.
+	queue_size_t  		size;              //!< Size of the queue.
+	unsigned short    element_count;
+	unsigned short  	element_size;      //!< Size of one element.
+	queue_mode_t      mode;
+} queue_t;
+
+/******************************API 接口*************************************/
+#define QUEUE_DEF(element_type, _name, _size, _mode)        \
+				element_type   _name##_queue_buffer[(_size)];      	\
+				queue_t _name=                             					\
+								{                             							\
+									.front 					= 0,              				\
+									.back 					= 0,                    	\
+									.p_buffer 			= _name##_queue_buffer,   \
+									.size  					= (_size),          			\
+									.element_count	= 0,											\
+									.element_size   = sizeof(element_type),   \
+									.mode           = _mode,       						\
+								}    
+
+//元素进队列
+unsigned short queue_in(queue_t * p_queue, void const * p_element);
+//元素出队列
+unsigned short queue_out(queue_t * p_queue, void * p_element);
+//查看队列中最后一个元素,队列中元素并没有减少
+unsigned short queue_peek(queue_t * p_queue, void * p_element);
+//清空队列
+void queue_reset(queue_t * p_queue);	
+//获取队列中元素个数
+unsigned short queue_element_count(queue_t * p_queue);	
+//查看队列中指定数组下标的元素的从最早进入队列的元素下标index==0开始算								
+unsigned short queue_read(queue_t * p_queue, void * p_element ,int index);		
+//扔掉掉列最后一个元素								
+unsigned short queue_throw_element(queue_t * p_queue);
+#endif 

+ 82 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/ringframe.c

@@ -0,0 +1,82 @@
+#include "ringframe.h"
+
+unsigned short ringframe_in(ringframe_t * p_ringframe, void * p_data,unsigned char data_size)
+{
+		unsigned char * p;
+		if(p_ringframe->freespace < ( data_size + 1 ))return 1;
+		p = (unsigned char*)p_ringframe->p_buffer + p_ringframe->front ;        
+		* p=data_size;
+		p_ringframe->front++;
+		p_ringframe->front &= p_ringframe->size-1;
+		for(int i=0;i<data_size;i++)
+		{
+						p = (unsigned char*)p_ringframe->p_buffer + p_ringframe->front ;
+						* p=((unsigned char*)p_data)[i];
+						p_ringframe->front++;
+						p_ringframe->front &= p_ringframe->size-1;
+		}
+		p_ringframe->freespace -= (data_size+1);
+		p_ringframe->element_count++;
+		return 0;
+}
+
+unsigned short ringframe_out(ringframe_t * p_ringframe, void * p_data,unsigned char * data_size)
+{
+	unsigned char * p;
+	if(p_ringframe->element_count < 1)return 1;
+	p = (unsigned char*)p_ringframe->p_buffer + p_ringframe->back ;	
+	* data_size = * p;
+	p_ringframe->back++;
+	p_ringframe->back &= p_ringframe->size-1;
+	for(int i=0;i < *data_size;i++)
+	{
+		p = (unsigned char*)p_ringframe->p_buffer + p_ringframe->back ;
+		((unsigned char*)p_data)[i]= * p;
+		p_ringframe->back++;
+		p_ringframe->back &= p_ringframe->size-1;
+	}
+	p_ringframe->freespace += (* data_size+1);
+	p_ringframe->element_count--;
+	return 0;
+}
+
+unsigned short ringframe_peek(ringframe_t * p_ringframe, void * p_data,unsigned char * data_size)
+{
+	unsigned char * p;
+	unsigned short temp = p_ringframe->back;
+	if(p_ringframe->element_count < 1)return 1;
+	p = (unsigned char*)p_ringframe->p_buffer + temp ;	
+	* data_size = * p;
+	temp++;
+	temp &= p_ringframe->size-1;
+	for(int i=0;i < *data_size;i++)
+	{
+		p = (unsigned char*)p_ringframe->p_buffer + temp ;
+		((unsigned char*)p_data)[i]= * p;
+		temp++;
+		temp &= p_ringframe->size-1;
+	}
+	return 0;
+}
+
+unsigned short ringframe_throw(ringframe_t * p_ringframe)
+{
+	unsigned char * p;
+	if(p_ringframe->element_count < 1)return 1;
+	p = (unsigned char*)p_ringframe->p_buffer + p_ringframe->back ;	
+	p_ringframe->back = p_ringframe->back + * p + 1;
+	p_ringframe->back &= p_ringframe->size-1;
+	p_ringframe->freespace += (* p +1);
+	p_ringframe->element_count--;
+	return 0;
+}
+
+void ringframe_reset(ringframe_t * p_ringframe)
+{
+	p_ringframe->back=0;
+	p_ringframe->front=0;              
+	p_ringframe->element_count=0;	
+	p_ringframe->freespace =	p_ringframe->size -1;
+}
+
+

+ 62 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/ringframe.h

@@ -0,0 +1,62 @@
+#ifndef __RINGFRAME_H
+#define __RINGFRAME_H
+
+/**@brief   A FIFO instance structure.
+ * @details Keeps track of which bytes to read and write next.
+ *          Also, it keeps the information about which memory is allocated for the buffer
+ *          and its size. This structure must be initialized by app_fifo_init() before use.
+ */
+typedef enum
+{
+	ringframe_size_4 		  = 0x0004U,
+	ringframe_size_8 		  = 0x0008U,
+	ringframe_size_16 		= 0x0010U,								 	                            
+	ringframe_size_32 		= 0x0020U,
+	ringframe_size_64 		= 0x0040U,
+	ringframe_size_128 		= 0x0080U,
+  ringframe_size_256 		= 0x0100U,         
+	ringframe_size_512 		= 0x0200U,
+	ringframe_size_1024 	= 0x0400U,
+	ringframe_size_2048 	= 0x0800U,
+	ringframe_size_4096 	= 0x1000U,
+	ringframe_size_8192 	= 0x2000U,
+	ringframe_size_16384	= 0x4000U,
+	ringframe_size_32768	= 0x8000U,
+}ringframe_size_t;
+
+typedef struct
+{
+  volatile unsigned short front;          //!< ringframe front index.
+  volatile unsigned short back;           //!< ringframe back index.
+	void           		* p_buffer;          //!< Pointer to the memory that is used as storage.
+	ringframe_size_t  size;									//单位为字节
+	unsigned short    element_count;
+	unsigned short 		freespace;
+} ringframe_t;
+
+/******************************API 接口*************************************/
+#define RINGFRAME_DEF( _name, _size)        								  \
+				unsigned char   _name##_ringframe_buffer[(_size)];    \
+				ringframe_t _name=                             			  \
+								{                             							  \
+									.front 					= 0,              				  \
+									.back 					= 0,                    	  \
+									.p_buffer 			= _name##_ringframe_buffer, \
+									.size  					= (_size),          			  \
+									.element_count	= 0,											  \
+									.freespace      = (_size)-1,       				  \
+								}    
+
+//返回0表示操作成功,否则失败
+unsigned short ringframe_in(ringframe_t * p_ringframe, void * p_data,unsigned char data_size);
+//返回0表示操作成功,否则失败								
+unsigned short ringframe_out(ringframe_t * p_ringframe, void * p_data,unsigned char * data_size);
+								
+void ringframe_reset(ringframe_t * p_ringframe);
+//返回0表示操作成功,否则失败																	
+unsigned short ringframe_peek(ringframe_t * p_ringframe, void * p_data,unsigned char * data_size);
+//返回0表示操作成功,否则失败									
+unsigned short ringframe_throw(ringframe_t * p_ringframe);
+								
+								
+#endif 

+ 1614 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/slave.c

@@ -0,0 +1,1614 @@
+#include "ble_comm.h"
+
+#include "ble_advertising.h"
+#include "ble_conn_params.h"
+#include "nrf_ble_qwr.h"
+
+#include "nrf_fstorage.h"
+#include "nrf_soc.h"
+#include "ble_nus.h"
+
+#include "bsp_time.h"
+#include "system.h"
+
+// <<< Use Configuration Wizard in Context Menu >>>\r\n
+
+#define APP_ADV_INTERVAL 320                                 /**< The advertising interval (in units of 0.625 ms). This value corresponds to 187.5 ms. */
+#define APP_ADV_DURATION 18000                               /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
+#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(1000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
+#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000)  /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
+#define MAX_CONN_PARAMS_UPDATE_COUNT 1
+static char DEVICE_NAME[TARFET_LEN_MAX] = "SH";
+#if USE_LADDR == 1
+char BleReallyName[TARFET_LEN_MAX] = {0};
+#endif
+#define MIN_CONN_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS)         /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
+#define MAX_CONN_INTERVAL MSEC_TO_UNITS(1.25 * 1599, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
+#define SLAVE_LATENCY 0                                            /**< Slave latency. */
+#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)
+#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN
+static ble_uuid_t m_adv_uuids[] =
+    {
+        {BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}};
+static unsigned char connect_to_client = 0;
+static Ble_receive_handler_t Rec_h = NULL;
+BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT);
+BLE_ADVERTISING_DEF(m_advertising);
+NRF_BLE_QWRS_DEF(m_qwr, NRF_SDH_BLE_TOTAL_LINK_COUNT);
+uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID;
+
+ble_gap_conn_params_t slave_conn_params = {0};
+
+static void nrf_qwr_error_handler(uint32_t nrf_error) //?óáDD′′í?ó2ù×÷
+{
+    APP_ERROR_HANDLER(nrf_error);
+}
+//′ó BLE ?óêüêy?Y
+static void nus_data_handler(ble_nus_evt_t *p_evt)
+{
+    if (p_evt->type == BLE_NUS_EVT_RX_DATA)
+    {
+        Rec_h((unsigned char *)(p_evt->params.rx_data.p_data), p_evt->params.rx_data.length);
+    }
+}
+static void services_init(void) //·t??3?ê??ˉ
+{
+    uint32_t err_code;
+    ble_nus_init_t nus_init;
+    nrf_ble_qwr_init_t qwr_init = {0};
+
+    // Initialize Queued Write Module.
+    qwr_init.error_handler = nrf_qwr_error_handler;
+
+    for (uint32_t i = 0; i < NRF_SDH_BLE_TOTAL_LINK_COUNT; i++)
+    {
+        err_code = nrf_ble_qwr_init(&m_qwr[i], &qwr_init);
+        APP_ERROR_CHECK(err_code);
+    }
+
+    // Initialize NUS.
+    memset(&nus_init, 0, sizeof(nus_init));
+
+    nus_init.data_handler = nus_data_handler;
+
+    err_code = ble_nus_init(&m_nus, &nus_init);
+    APP_ERROR_CHECK(err_code);
+}
+static void on_adv_evt(ble_adv_evt_t ble_adv_evt) //1?2¥ê??t
+{
+    switch (ble_adv_evt)
+    {
+    case BLE_ADV_EVT_FAST:
+    {
+        BLE_PRINT("Fast advertising.\r\n");
+    }
+    break;
+
+    case BLE_ADV_EVT_IDLE:
+    {
+        BLE_PRINT("on_adv_evt->BLE_ADV_EVT_IDLE\r\n");
+        ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); //?aê?1?2¥
+        APP_ERROR_CHECK(err_code);
+    }
+    break;
+
+    default:
+        // No implementation needed.
+        break;
+    }
+}
+static void advertising_init(void)
+{
+    uint32_t err_code;
+    ble_advertising_init_t init;
+    int8_t txpower = 4;
+
+    memset(&init, 0, sizeof(init));
+
+    init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
+    init.advdata.include_appearance = false;
+    init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
+    init.advdata.p_tx_power_level = &txpower;
+
+    init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
+    init.srdata.uuids_complete.p_uuids = m_adv_uuids;
+
+    init.config.ble_adv_fast_enabled = true;
+    init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
+    init.config.ble_adv_fast_timeout = APP_ADV_DURATION;
+    init.evt_handler = on_adv_evt;
+
+    err_code = ble_advertising_init(&m_advertising, &init);
+    APP_ERROR_CHECK(err_code);
+
+    ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
+}
+static void conn_params_error_handler(uint32_t nrf_error)
+{
+    APP_ERROR_HANDLER(nrf_error);
+}
+static void conn_params_init(void)
+{
+    ret_code_t err_code;
+    ble_conn_params_init_t cp_init;
+
+    memset(&cp_init, 0, sizeof(cp_init));
+
+    cp_init.p_conn_params = NULL;
+    cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
+    cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY;
+    cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT;
+    cp_init.start_on_notify_cccd_handle = BLE_CONN_HANDLE_INVALID; // Start upon connection.
+    cp_init.disconnect_on_fail = true;
+    cp_init.evt_handler = NULL; // Ignore events.
+    cp_init.error_handler = conn_params_error_handler;
+
+    err_code = ble_conn_params_init(&cp_init);
+    APP_ERROR_CHECK(err_code);
+}
+void advertising_start(void)
+{
+    ret_code_t err_code;
+    err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); //同时开始广播
+    APP_ERROR_CHECK(err_code);
+}
+void advertising_stop(void)
+{
+    ret_code_t err_code;
+    err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle); //停止广播
+    APP_ERROR_CHECK(err_code);
+}
+bool ble_evt_is_advertising_timeout(ble_evt_t const *p_ble_evt)
+{
+    return (p_ble_evt->header.evt_id == BLE_GAP_EVT_ADV_SET_TERMINATED);
+}
+static void multi_qwr_conn_handle_assign(uint16_t conn_handle)
+{
+    for (uint32_t i = 0; i < NRF_SDH_BLE_TOTAL_LINK_COUNT; i++)
+    {
+        if (m_qwr[i].conn_handle == BLE_CONN_HANDLE_INVALID)
+        {
+            ret_code_t err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr[i], conn_handle);
+            APP_ERROR_CHECK(err_code);
+            break;
+        }
+    }
+}
+
+#define slave_connected_evt_num_max 16
+static uint8_t slave_connected_evt_num = 0;
+static Ble_evt_cb ble_Slave_evt_cb[slave_connected_evt_num_max] = {0};
+int Ble_Slave_Connectd_Evt_Regist(Ble_evt_cb cb)
+{
+    for (int i = 0; i < slave_connected_evt_num_max; i++)
+    {
+        if (ble_Slave_evt_cb[i] == cb)
+            return -1;
+        if (ble_Slave_evt_cb[i] == 0)
+        {
+            slave_connected_evt_num++;
+            ble_Slave_evt_cb[i] = cb; //??μ÷oˉêy
+            return 0;
+        }
+    }
+    SEGGER_RTT_printf(0, "ble_evt_Regist -> too many!\n");
+    return -2;
+}
+
+void ble_slave_connected_evt_pcs(void)
+{
+    for (int i = 0; i < slave_connected_evt_num; i++)
+    { //SEGGER_RTT_printf(0,"time_cb[%d]=%d\n",i,time_cb[i]);
+        if (ble_Slave_evt_cb[i])
+        {
+            ble_Slave_evt_cb[i](); //??μ÷oˉêy
+        }
+    }
+}
+
+#define slave_disconn_evt_num_max 16
+static uint8_t slave_disconn_evt_num = 0;
+static Ble_evt_cb ble_Slave_disconn_evt_cb[slave_disconn_evt_num_max] = {0};
+int Ble_Slave_Disconn_Evt_Regist(Ble_evt_cb cb)
+{
+    for (int i = 0; i < slave_disconn_evt_num_max; i++)
+    {
+        if (ble_Slave_disconn_evt_cb[i] == cb)
+            return -1;
+        if (ble_Slave_disconn_evt_cb[i] == 0)
+        {
+            slave_disconn_evt_num++;
+            ble_Slave_disconn_evt_cb[i] = cb; //??μ÷oˉêy
+            return 0;
+        }
+    }
+    SEGGER_RTT_printf(0, "Ble_Slave_Disconn_Evt_Regist -> too many!\r\n");
+    return -2;
+}
+
+void ble_slave_dicconn_evt_pcs(void)
+{
+    for (int i = 0; i < slave_disconn_evt_num; i++)
+    { //SEGGER_RTT_printf(0,"time_cb[%d]=%d\n",i,time_cb[i]);
+        if (ble_Slave_disconn_evt_cb[i])
+        {
+            ble_Slave_disconn_evt_cb[i](); //??μ÷oˉêy
+        }
+    }
+}
+unsigned char slave_update_conn_interval_request_sta = 0;
+static ble_gap_phys_t const phys =
+{
+		.rx_phys = BLE_GAP_PHY_1MBPS,
+		.tx_phys = BLE_GAP_PHY_1MBPS,
+};
+
+static uint8_t _7_5ms_intervalFlag =0;
+uint8_t Slave_Get7_5ms_interval(void){
+	return _7_5ms_intervalFlag;
+}
+
+void on_ble_peripheral_evt(ble_evt_t const *p_ble_evt) //×÷?a′óéè±?μ?′|àí
+{
+    ret_code_t err_code;
+    ble_gap_evt_t const *p_gap_evt = &p_ble_evt->evt.gap_evt;
+    
+    switch (p_ble_evt->header.evt_id)
+    {
+    case BLE_GAP_EVT_CONNECTED:{
+        BLE_PRINT("on_ble_peripheral_evt -> BLE_GAP_EVT_CONNECTED\r\n");
+        m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
+        multi_qwr_conn_handle_assign(p_ble_evt->evt.gap_evt.conn_handle); //QWR句柄分配
+        connect_to_client = 1;
+        ble_slave_connected_evt_pcs();
+#if 1		
+				BLE_PRINT("PHY update request.");
+				err_code = sd_ble_gap_phy_update(p_gap_evt->conn_handle, &phys);
+				APP_ERROR_CHECK(err_code);
+#endif
+		   
+        BLE_PRINT("Connection 0x%x Received ble gap evt data length update request.", p_ble_evt->evt.gap_evt.conn_handle);
+        ble_gap_data_length_params_t dlp =
+				{
+						.max_rx_time_us= BLE_GAP_DATA_LENGTH_AUTO,
+						.max_tx_time_us= BLE_GAP_DATA_LENGTH_AUTO,
+						.max_rx_octets = BLE_GAP_DATA_LENGTH_AUTO,
+						.max_tx_octets = BLE_GAP_DATA_LENGTH_AUTO,
+				};
+        err_code = sd_ble_gap_data_length_update(p_ble_evt->evt.gap_evt.conn_handle, &dlp, NULL);
+        APP_ERROR_CHECK(err_code);
+				
+				
+        sd_ble_gap_rssi_start(m_conn_handle, BLE_GAP_RSSI_THRESHOLD_INVALID, 0);
+			  }
+        break;
+    case BLE_GAP_EVT_DISCONNECTED:
+        connect_to_client = 0;
+        ble_slave_dicconn_evt_pcs();
+
+        sd_ble_gap_rssi_stop(m_conn_handle);
+		    _7_5ms_intervalFlag =0;
+		    BLE_PRINT("on_ble_peripheral_evt -> BLE_GAP_EVT_DISCONNECTED,reason:%d\r\n",p_gap_evt->params.disconnected.reason);
+        break;
+
+    case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
+    {
+        BLE_PRINT("on_ble_peripheral_evt -> BLE_GAP_EVT_PHY_UPDATE_REQUEST\r\n");
+        err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
+        APP_ERROR_CHECK(err_code);
+    }
+    break;
+
+    case BLE_GATTC_EVT_TIMEOUT:
+        // Disconnect on GATT Client timeout event.
+        BLE_PRINT("on_ble_peripheral_evt -> BLE_GATTC_EVT_TIMEOUT\r\n");
+        err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
+                                         BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
+        APP_ERROR_CHECK(err_code);
+        break;
+
+    case BLE_GATTS_EVT_TIMEOUT:
+        // Disconnect on GATT Server timeout event.
+        BLE_PRINT("on_ble_peripheral_evt -> BLE_GATTS_EVT_TIMEOUT\r\n");
+        err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
+                                         BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
+        APP_ERROR_CHECK(err_code);
+        break;
+
+    case BLE_GAP_EVT_CONN_PARAM_UPDATE:
+		{
+        BLE_PRINT("on_ble_peripheral_evt -> BLE_GAP_EVT_CONN_PARAM_UPDATE\r\n");
+        slave_update_conn_interval_request_sta = 0;
+        memcpy(&slave_conn_params, &p_gap_evt->params.conn_param_update_request.conn_params, sizeof(ble_gap_conn_params_t));
+        BLE_PRINT("min_conn_interval : %d * 1.25 ms\r\n", p_gap_evt->params.conn_param_update_request.conn_params.min_conn_interval);
+        BLE_PRINT("max_conn_interval : %d * 1.25 ms\r\n", p_gap_evt->params.conn_param_update_request.conn_params.max_conn_interval);
+        BLE_PRINT("slave_latency     : %d\r\n", p_gap_evt->params.conn_param_update_request.conn_params.slave_latency);
+        BLE_PRINT("conn_sup_timeout  : %d * 10   ms\r\n", p_gap_evt->params.conn_param_update_request.conn_params.conn_sup_timeout);
+			  
+			  if(6 == p_gap_evt->params.conn_param_update_request.conn_params.min_conn_interval && 6 == p_gap_evt->params.conn_param_update_request.conn_params.max_conn_interval)
+						    _7_5ms_intervalFlag =1;
+					else 	_7_5ms_intervalFlag =0;
+        }BLE_PRINT("_7_5ms_intervalFlag  : %d\r\n", _7_5ms_intervalFlag);
+		break;
+				
+	case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
+        {
+					BLE_PRINT("on_ble_peripheral_evt -> BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST\r\n");
+					ble_gap_conn_params_t params;
+					params = p_gap_evt->params.conn_param_update_request.conn_params;
+					err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle, &params);
+					BLE_PRINT("=====>BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST error:%d\r\n",err_code);
+					APP_ERROR_CHECK(err_code);
+
+					
+					memcpy(&slave_conn_params, &p_gap_evt->params.conn_param_update_request.conn_params, sizeof(ble_gap_conn_params_t));
+					BLE_PRINT("min_conn_interval : %d * 1.25 ms\r\n", p_gap_evt->params.conn_param_update_request.conn_params.min_conn_interval);
+					BLE_PRINT("max_conn_interval : %d * 1.25 ms\r\n", p_gap_evt->params.conn_param_update_request.conn_params.max_conn_interval);
+					BLE_PRINT("slave_latency     : %d\r\n", p_gap_evt->params.conn_param_update_request.conn_params.slave_latency);
+					BLE_PRINT("conn_sup_timeout  : %d * 10   ms\r\n", p_gap_evt->params.conn_param_update_request.conn_params.conn_sup_timeout);
+          
+        } break;
+
+    case BLE_GAP_EVT_RSSI_CHANGED:
+        BLE_PRINT("on_ble_peripheral_evt -> BLE_GAP_EVT_RSSI_CHANGED\r\n");
+        break;
+				
+    case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
+    {
+				BLE_PRINT("on_ble_peripheral_evt -> BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST\r\n");
+        ble_gap_data_length_params_t const dlp =
+				{
+						.max_rx_octets = BLE_GAP_DATA_LENGTH_AUTO,
+						.max_tx_octets = BLE_GAP_DATA_LENGTH_AUTO,
+				};
+        err_code = sd_ble_gap_data_length_update(p_ble_evt->evt.gap_evt.conn_handle, &dlp, NULL);
+        APP_ERROR_CHECK(err_code);
+    }
+    break;
+
+    case BLE_GAP_EVT_DATA_LENGTH_UPDATE:
+    {
+			  BLE_PRINT("on_ble_peripheral_evt -> BLE_GAP_EVT_DATA_LENGTH_UPDATE\r\n");
+        BLE_PRINT("max_rx_octets   : %d \r\n", p_gap_evt->params.data_length_update.effective_params.max_rx_octets);
+        BLE_PRINT("max_rx_time_us  : %d \r\n", p_gap_evt->params.data_length_update.effective_params.max_rx_time_us);
+        BLE_PRINT("max_tx_octets   : %d \r\n", p_gap_evt->params.data_length_update.effective_params.max_tx_octets);
+        BLE_PRINT("max_tx_time_us  : %d \r\n", p_gap_evt->params.data_length_update.effective_params.max_tx_time_us);
+    }
+    break;		
+		
+    case BLE_GAP_EVT_ADV_SET_TERMINATED:
+        BLE_PRINT("on_ble_peripheral_evt -> BLE_GAP_EVT_ADV_SET_TERMINATED\r\n");
+        break;
+    case BLE_GATTS_EVT_HVN_TX_COMPLETE:
+        //        BLE_PRINT("on_ble_peripheral_evt -> BLE_GATTS_EVT_HVN_TX_COMPLETE\r\n");
+        break;
+    case BLE_GATTS_EVT_WRITE: //D′è?2ù×÷ò??-íê3é
+                              //        BLE_PRINT("on_ble_peripheral_evt -> BLE_GATTS_EVT_WRITE\r\n");
+        break;
+		
+    case BLE_GATTC_EVT_EXCHANGE_MTU_RSP:				
+//				err_code = sd_ble_gattc_exchange_mtu_request(p_ble_evt->evt.gattc_evt.conn_handle,247);		
+//				APP_ERROR_CHECK(err_code);		
+        BLE_PRINT("on_ble_peripheral_evt -> BLE_GATTC_EVT_EXCHANGE_MTU_RSP  -> server_rx_mtu = %d\r\n",p_ble_evt->evt.gattc_evt.params.exchange_mtu_rsp.server_rx_mtu);
+        break;
+		case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST://?÷?ú?ò′ó?úéê??mtuê±μ?ê??t
+	  {
+	    sd_ble_gatts_exchange_mtu_reply(m_conn_handle, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
+	    BLE_PRINT("on_ble_peripheral_evt -> BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST -> client_rx_mtu=%d\r\n",p_ble_evt->evt.gatts_evt.params.exchange_mtu_request.client_rx_mtu);
+	  }break;
+		
+    default:
+        BLE_PRINT("on_ble_peripheral_evt -> default : 0x%2x\r\n", p_ble_evt->header.evt_id);
+        // No implementation needed.
+        break;
+    }
+}
+#if USE_LADDR == 1
+ble_gap_addr_t m_my_addr;
+char set_adv_name = 0;
+#endif
+static void gap_params_init(void) //GAP3?ê??ˉ
+{
+    uint32_t err_code;
+    ble_gap_conn_params_t gap_conn_params;
+    ble_gap_conn_sec_mode_t sec_mode;
+
+    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
+#if USE_LADDR == 1
+    err_code = sd_ble_gap_addr_get(&m_my_addr);
+    APP_ERROR_CHECK(err_code);
+    if (set_adv_name == 0)
+    {
+        BLE_PRINT("MAC [ %02X %02X %02X %02X %02X %02X ]\r\n", m_my_addr.addr[0], m_my_addr.addr[1], m_my_addr.addr[2], m_my_addr.addr[3], m_my_addr.addr[4], m_my_addr.addr[5]);
+
+        sprintf(BleReallyName, "%s_%02X%02X", DEVICE_NAME, m_my_addr.addr[4], m_my_addr.addr[5]);
+                err_code = sd_ble_gap_device_name_set(&sec_mode,
+                                          (const uint8_t *)BleReallyName,
+                                          strlen(DEVICE_NAME) + 5);         
+		}
+		else
+		{
+						err_code = sd_ble_gap_device_name_set(&sec_mode,
+																			(const uint8_t *)BleReallyName,
+																			strlen(BleReallyName));
+		}
+		BLE_PRINT(">>>>>>>name:%d,%s",set_adv_name,BleReallyName);	
+#else
+
+    err_code = sd_ble_gap_device_name_set(&sec_mode,
+                                          (const uint8_t *)DEVICE_NAME,
+                                          strlen(DEVICE_NAME));
+#endif
+    APP_ERROR_CHECK(err_code);
+
+    memset(&gap_conn_params, 0, sizeof(gap_conn_params));
+
+    gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
+    gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
+    gap_conn_params.slave_latency = SLAVE_LATENCY;
+    gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT;
+
+    err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
+    APP_ERROR_CHECK(err_code);
+    //		err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN,m_conn_handle,0);
+    //		APP_ERROR_CHECK(err_code);
+}
+
+#if USEFIFO 
+RINGFRAME_DEF(sbc,ringframe_size_1024);
+static unsigned int TIME_GetTicks_ms;
+unsigned int send_bytes_client(unsigned char *bytes, uint16_t len)
+{
+    unsigned short length = len;
+    if (connect_to_client)
+    {
+			do
+			{
+				if(ringframe_in(&sbc,bytes,length)==0)return 0;
+			}while(ringframe_throw(&sbc)==0);		
+			Process_SetHoldOn(send_bytes_client_pcs,1);
+			TIME_GetTicks_ms=TIME_GetTicks();
+			return 0;
+		}
+		else
+    {
+        BLE_PRINT("send_bytes_client error. connect_to_client=0\r\n");
+        return 1;
+    }
+} //作为从机时发送数据给主机
+
+void send_bytes_client_pcs(void)
+{
+	unsigned char sbuff[256];
+	unsigned char len=0;
+	while(ringframe_peek(&sbc,sbuff,&len)==0)
+	{
+			unsigned short length = len;
+			uint32_t flag = 0;
+			flag = ble_nus_data_send(&m_nus, sbuff, &length, m_conn_handle);
+			if(flag==0)ringframe_throw(&sbc);
+			else 
+			{
+				if((TIME_GetTicks()-TIME_GetTicks_ms>100)||(TIME_GetTicks_ms>TIME_GetTicks()))
+				{
+					Process_SetHoldOn(send_bytes_client_pcs,0);
+				}
+				return;
+			}
+	}
+	Process_SetHoldOn(send_bytes_client_pcs,0);
+}
+
+#else
+unsigned int send_bytes_client(unsigned char *bytes, uint16_t len)
+{
+	unsigned int rev=0;
+    unsigned short length = len;
+    if (connect_to_client){
+		   rev=ble_nus_data_send(&m_nus, bytes, &length, m_conn_handle);
+			return rev;
+	  }
+	  else{
+        BLE_PRINT("send_bytes_client error. connect_to_client=0\r\n");
+        return 1;
+    }
+		return 0;
+} //作为从机时发送数据给主机
+
+void send_bytes_client_pcs(void)
+{
+	
+}
+
+#endif
+
+extern void timer_init(void);
+extern void power_management_init(void);
+extern void ble_stack_init(void);
+extern void gatt_init(void);
+extern char ble_stack_init_sta;
+extern uint8_t Get_isHost(void);
+#if USEMACNAME && USE_LADDR != 1
+ble_gap_addr_t mAddr;
+#endif
+void slave_init(Ble_receive_handler_t receive_handler)
+{
+    static unsigned char init = 1;
+    if (init)
+    {
+        if (receive_handler == NULL)
+        {
+            BLE_PRINT("slave_init -> param err \r\n");
+            return;
+        }
+        Rec_h = receive_handler;
+        if (ble_stack_init_sta)
+        {
+            timer_init();            //
+            power_management_init(); //
+            ble_stack_init();        //
+            gatt_init();             //
+            ble_stack_init_sta = 0;
+        }
+#if USEMACNAME && USE_LADDR != 1
+        if (!Get_isHost())
+        {
+            sd_ble_gap_addr_get(&mAddr);
+            memset(DEVICE_NAME, 0, TARFET_LEN_MAX);
+            sprintf(DEVICE_NAME, "%02X%02X%02X%02X%02X%02X", mAddr.addr[5], mAddr.addr[4], mAddr.addr[3], mAddr.addr[2], mAddr.addr[1], mAddr.addr[0]);
+        }
+#endif
+		
+        gap_params_init();
+
+        services_init();
+        advertising_init();
+        conn_params_init();
+        advertising_start();
+        init = 0;
+#if USE_LADDR
+        BLE_PRINT("slave_init -> name [ %s ] \r\n", BleReallyName);
+#else
+        BLE_PRINT("slave_init -> name [ %s ] \r\n", DEVICE_NAME);
+#endif
+    }
+    else
+    {
+        BLE_PRINT("slave_init -> err slave has init done \r\n");
+    }
+}
+unsigned char slave_isconnect(void)
+{
+    return connect_to_client;
+}
+
+unsigned int slave_set_adv_name(char *name, int len)
+{
+#if USE_LADDR == 1
+    if (len > TARFET_LEN_MAX)
+        return APP_ERR_OVERLENGTH;
+    set_adv_name = 1;
+    memset(BleReallyName, 0, TARFET_LEN_MAX);
+    memcpy(BleReallyName, name, len);
+#else
+    if (len > TARFET_LEN_MAX)
+        return APP_ERR_OVERLENGTH;
+    memset(DEVICE_NAME, 0, TARFET_LEN_MAX);
+    memcpy(DEVICE_NAME, name, len);
+#endif
+    return APP_SUCCESS;
+}
+
+void slave_get_advname_len(int *len)
+{
+	*len = strlen(BleReallyName);
+}
+
+void slave_get_advname(char *name, int len)
+{
+	memcpy(name,BleReallyName,len);
+}
+
+void slave_disconnect(void)
+{
+    if (connect_to_client)
+        sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
+}
+
+unsigned int slave_update_conn_interval_request(float min_conn_interval, float max_conn_interval)
+{
+    ret_code_t err_code;
+    ble_gap_conn_params_t bgcp;
+    if (slave_update_conn_interval_request_sta)
+        return APP_ERR_BUSY;
+    if (connect_to_client)
+    {
+        slave_update_conn_interval_request_sta = 1;
+        if ((max_conn_interval > 1.25 * 1599) || (max_conn_interval < min_conn_interval))
+            return APP_ERR_PARAMERR;
+        if (min_conn_interval < 7.5f)
+            return APP_ERR_PARAMERR;
+        bgcp.max_conn_interval = MSEC_TO_UNITS(max_conn_interval, UNIT_1_25_MS);
+        bgcp.min_conn_interval = MSEC_TO_UNITS(min_conn_interval, UNIT_1_25_MS);
+        bgcp.conn_sup_timeout = MSEC_TO_UNITS(4000, UNIT_10_MS);
+        bgcp.slave_latency = 0;
+        BLE_PRINT("slave_update_conn_interval_request -> %d  \r\n", bgcp.max_conn_interval);
+        err_code = sd_ble_gap_conn_param_update(m_conn_handle, &bgcp);
+        APP_ERROR_CHECK(err_code);
+        return err_code;
+    }
+    else
+    {
+        return APP_ERR_DISCONN;
+    }
+}
+void slave_get_conn_params(ble_gap_conn_params_t *p)
+{
+    p->conn_sup_timeout = slave_conn_params.conn_sup_timeout;
+    p->max_conn_interval = slave_conn_params.max_conn_interval;
+    p->min_conn_interval = slave_conn_params.min_conn_interval;
+    p->slave_latency = slave_conn_params.slave_latency;
+}
+
+void slave_adv_init(void)
+{
+    gap_params_init();  //ìí?óμ?GAP3?ê??ˉ
+    conn_params_init(); //ìí?óμ?á??ó2?êy3?ê??ˉ
+    advertising_init(); //ìí?ó1?2¥3?ê??ˉ
+}
+
+static signed char rssi = 0;
+signed char slave_get_rssi(void)
+{
+    unsigned char channel;
+    if (connect_to_client == 0)
+        return 1;
+    sd_ble_gap_rssi_get(m_conn_handle, &rssi, &channel);
+    //    BLE_PRINT("rssi= %d  channel=%d\r\n", rssi, channel);
+    return rssi;
+}
+
+#if DEBUGBLE
+#define led 13
+#define tx 11 //1.1
+#define rx 12
+//#define LS -1611916254 //?a·¢°?
+//#define RS -889050188
+//#define LS 97376119  //31
+//#define RS 627878688  //32
+#define LS -1087551583 //1.1
+#define RS -957332282  //1.1
+#define PS -1372482754 //usb
+unsigned char buff[255];
+char start = 0;
+void host_r(unsigned char *p, int len)
+{
+    BLE_PRINT("hr : %d,0x%x\r\n", len, p[0]);
+    if (p[0] == 0xbb)
+    {
+        BLE_PRINT("hr -------------: 0xbb\r\n");
+        SEGGER_RTT_Write(0, &p[1], len);
+    }
+    if (p[0] == 0xcc)
+    {
+        BLE_PRINT("hr -------------: 0xcc\r\n");
+    }
+}
+#define TIMER_TICK 25
+#define TCUN 1000
+unsigned short cun = 0;
+unsigned short ts = 0;
+unsigned short rec[5] = {0};
+unsigned short recrtc[5] = {0};
+unsigned int rtc_cun = 0;
+void slave_r(unsigned char *p, int len)
+{
+    if (p[0] == 0xaa)
+    {
+        cun++;
+        ts = p[1];
+        ts = ts << 8;
+        ts += p[2];
+        if (ts >= 1)
+        {
+            start = 1;
+            rtc_cun = NRF_RTC2->COUNTER;
+        }
+        if (ts == TCUN)
+            start = 0;
+
+        if (start)
+        {
+            if (NRF_RTC2->COUNTER - rtc_cun < 1 * TIMER_TICK)
+                recrtc[0]++;
+            if ((NRF_RTC2->COUNTER - rtc_cun >= 1 * TIMER_TICK) && (NRF_RTC2->COUNTER - rtc_cun < 2 * TIMER_TICK))
+                recrtc[1]++;
+            if ((NRF_RTC2->COUNTER - rtc_cun >= 2 * TIMER_TICK) && (NRF_RTC2->COUNTER - rtc_cun < 3 * TIMER_TICK))
+                recrtc[2]++;
+            if ((NRF_RTC2->COUNTER - rtc_cun >= 3 * TIMER_TICK) && (NRF_RTC2->COUNTER - rtc_cun < 4 * TIMER_TICK))
+                recrtc[3]++;
+            if (NRF_RTC2->COUNTER - rtc_cun > 4 * TIMER_TICK)
+                recrtc[4]++;
+            rtc_cun = NRF_RTC2->COUNTER;
+        }
+
+        BLE_PRINT("sr : %d\r\n", ts);
+    }
+    if (p[0] == 0xbb)
+    {
+        buff[0] = 0xbb;
+        int leng = sprintf(((char *)&buff[1]), "0 :%d,%d\r\n1 :%d,%d\r\n2 :%d,%d\r\n3 :%d,%d\r\n4 :%d,%d\r\n", rec[0], recrtc[0], rec[1], recrtc[1], rec[2], recrtc[2], rec[3], recrtc[3], rec[4], recrtc[4]);
+        send_bytes_server(buff, leng);
+    }
+
+    if (p[0] == 0xcc)
+    {
+        BLE_PRINT("sr -------------: 0xcc\r\n");
+        memset(rec, 0, 10);
+        memset(recrtc, 0, 10);
+        send_bytes_server(p, 3);
+    }
+}
+
+#include "cli.h"
+nrf_radio_request_t radio_request_p;
+APP_TIMER_DEF(s_Timer);
+#define TEST_PERIOD APP_TIMER_TICKS(TIMER_TICK)
+unsigned short tims = 0;
+unsigned short stp = 0;
+void s_TimerCallback(void *arg)
+{
+    if ((tims > 0) && (tims <= TCUN))
+    {
+        buff[0] = 0xaa;
+        buff[1] = tims >> 8;
+        buff[2] = tims;
+        send_bytes_client(buff, 100);
+        BLE_PRINT("send : %d\r\n", tims);
+        tims++;
+    }
+    if (start)
+    {
+        if (cun > 4)
+            cun = 4;
+        rec[cun]++;
+        cun = 0;
+    }
+    //·¢êy?Y??ê??ú
+    if (*NRF_FICR->DEVICEID == LS) //×ó±?D?
+    {
+        if (start)
+        {
+            buff[0] = 0xaa;
+            buff[1] = stp >> 8;
+            buff[2] = stp;
+            send_bytes_client(buff, 100);
+        }
+        stp++;
+    }
+    //		nrf_gpio_pin_toggle(rx);
+    //nrf_gpio_pin_write(rx, 0);
+    //		 BLE_PRINT("error= %d\r\n", sd_radio_request(&radio_request_p));
+}
+void Radio_State(void)
+{
+    switch (NRF_RADIO->STATE)
+    {
+    case RADIO_STATE_STATE_Disabled:
+        BLE_PRINT("RADIO_STATE_STATE_Disabled\r\n");
+        break;
+    case RADIO_STATE_STATE_RxRu:
+        BLE_PRINT("RADIO_STATE_STATE_RxRu\r\n");
+        break;
+    case RADIO_STATE_STATE_RxIdle:
+        BLE_PRINT("RADIO_STATE_STATE_RxIdle\r\n");
+        break;
+    case RADIO_STATE_STATE_Rx:
+        BLE_PRINT("RADIO_STATE_STATE_Rx\r\n");
+        break;
+    case RADIO_STATE_STATE_RxDisable:
+        BLE_PRINT("RADIO_STATE_STATE_RxDisable\r\n");
+        break;
+    case RADIO_STATE_STATE_TxRu:
+        BLE_PRINT("RADIO_STATE_STATE_TxRu\r\n");
+        break;
+    case RADIO_STATE_STATE_TxIdle:
+        BLE_PRINT("RADIO_STATE_STATE_TxIdle\r\n");
+        break;
+    case RADIO_STATE_STATE_Tx:
+        BLE_PRINT("RADIO_STATE_STATE_Tx\r\n");
+        break;
+    case RADIO_STATE_STATE_TxDisable:
+        BLE_PRINT("RADIO_STATE_STATE_TxDisable\r\n");
+        break;
+    }
+}
+void unoioo(void)
+{
+    Ble_update_conn_interval(7.5,7.5);
+	
+}
+
+void unoioo_s(void)
+{
+    slave_update_conn_interval_request(30, 30);
+	scan_start();
+}
+
+void unoioo_s_d(void)
+{
+host_disconnect();
+	scan_start();
+}
+
+void rtc_config(void)
+{
+    NRF_RTC2->PRESCALER = 0; //??ò?oá????êy?÷?ó1,1024us
+    NRF_RTC2->TASKS_START = 1;
+}
+#include "nrf_drv_timer.h"
+void radio_evt_conf(void);
+const nrf_drv_timer_t TIMER_RADIO = NRF_DRV_TIMER_INSTANCE(2);
+void timer_led_event_handler(nrf_timer_event_t event_type, void *p_context)
+{
+    if (*NRF_FICR->DEVICEID == LS) //×ó±?D?
+    {
+        switch (event_type)
+        {
+        case NRF_TIMER_EVENT_COMPARE0: //320
+            sd_radio_request(&radio_request_p);
+            NRF_PPI->CHEN &= (~(PPI_CHENCLR_CH0_Enabled << PPI_CHEN_CH0_Pos) | (PPI_CHENCLR_CH1_Enabled << PPI_CHEN_CH1_Pos));
+            break;
+        case NRF_TIMER_EVENT_COMPARE1: //324
+            sd_radio_request(&radio_request_p);
+            break;
+        case NRF_TIMER_EVENT_COMPARE2: //328
+            sd_radio_request(&radio_request_p);
+            break;
+        case NRF_TIMER_EVENT_COMPARE3: //332
+            NRF_PPI->CHEN |= (PPI_CHENCLR_CH0_Enabled << PPI_CHEN_CH0_Pos) | (PPI_CHENCLR_CH1_Enabled << PPI_CHEN_CH1_Pos);
+            break;
+
+        default:
+            //Do nothing.
+            break;
+        }
+    }
+    if (*NRF_FICR->DEVICEID == RS) //óò±?D?
+    {
+        switch (event_type)
+        {
+        case NRF_TIMER_EVENT_COMPARE0: //320
+            nrf_gpio_pin_write(tx, 1);
+            break;
+        case NRF_TIMER_EVENT_COMPARE1: //324
+            nrf_gpio_pin_write(tx, 0);
+            break;
+        case NRF_TIMER_EVENT_COMPARE2: //328
+            break;
+        case NRF_TIMER_EVENT_COMPARE3: //332
+            break;
+
+        default:
+            //Do nothing.
+            break;
+        }
+    }
+}
+void timer_config(void)
+{
+    uint32_t time_us = 5000; //Time(in miliseconds) between consecutive compare events.
+    uint32_t time_ticks;
+    uint32_t err_code = NRF_SUCCESS;
+    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
+    err_code = nrf_drv_timer_init(&TIMER_RADIO, &timer_cfg, timer_led_event_handler);
+    APP_ERROR_CHECK(err_code);
+    if (*NRF_FICR->DEVICEID == LS) //×ó±?D?
+    {
+        time_ticks = nrf_drv_timer_us_to_ticks(&TIMER_RADIO, time_us);
+        nrf_drv_timer_extended_compare(&TIMER_RADIO, NRF_TIMER_CC_CHANNEL0, time_ticks, 0, true);
+
+        time_ticks = nrf_drv_timer_us_to_ticks(&TIMER_RADIO, time_us + 10000);
+        nrf_drv_timer_extended_compare(&TIMER_RADIO, NRF_TIMER_CC_CHANNEL1, time_ticks, 0, true);
+
+        time_ticks = nrf_drv_timer_us_to_ticks(&TIMER_RADIO, time_us + 20000);
+        nrf_drv_timer_extended_compare(&TIMER_RADIO, NRF_TIMER_CC_CHANNEL2, time_ticks, 0, true);
+
+        time_ticks = nrf_drv_timer_us_to_ticks(&TIMER_RADIO, 29000);
+        nrf_drv_timer_extended_compare(&TIMER_RADIO, NRF_TIMER_CC_CHANNEL3, time_ticks, NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK, true);
+    }
+    if (*NRF_FICR->DEVICEID == RS) //óò±?D?
+    {
+        time_us = 1000;
+        time_ticks = nrf_drv_timer_us_to_ticks(&TIMER_RADIO, time_us);
+        nrf_drv_timer_extended_compare(&TIMER_RADIO, NRF_TIMER_CC_CHANNEL0, time_ticks, 0, true);
+
+        time_ticks = nrf_drv_timer_us_to_ticks(&TIMER_RADIO, time_us + 9000 + 1);
+        nrf_drv_timer_extended_compare(&TIMER_RADIO, NRF_TIMER_CC_CHANNEL1, time_ticks, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);
+
+        nrf_drv_timer_enable(&TIMER_RADIO);
+    }
+    //	nrf_drv_timer_enable(&TIMER_RADIO);
+}
+
+void ppi_set(void)
+{
+    NRF_PPI->CH[0].EEP = (unsigned int)(&NRF_TIMER0->EVENTS_COMPARE[0]);
+    NRF_PPI->CH[0].TEP = (unsigned int)(&NRF_TIMER2->TASKS_START);
+
+    NRF_PPI->CH[1].EEP = (unsigned int)(&NRF_TIMER2->EVENTS_COMPARE[3]);
+    NRF_PPI->CH[1].TEP = (unsigned int)(&NRF_TIMER2->TASKS_SHUTDOWN);
+
+    NRF_PPI->CHEN |= (PPI_CHENCLR_CH0_Enabled << PPI_CHEN_CH0_Pos) |
+                     (PPI_CHENCLR_CH1_Enabled << PPI_CHEN_CH1_Pos);
+}
+
+extern void USR_Init(void);
+extern void USR_Process(void);
+extern void TIME_Init(void);
+extern char Target_scan[];
+
+unsigned char txbuff[300] = {0x0a, 0x03, 0, 0, 2, 3, 4, 5, 6, 0, 8, 9};
+unsigned char rxbuff[300] = {0};
+void radio_init_R(void)
+{
+    NRF_RADIO->POWER = (RADIO_POWER_POWER_Enabled << RADIO_POWER_POWER_Pos);
+    /* Start 16 MHz crystal oscillator */
+    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
+    NRF_CLOCK->TASKS_HFCLKSTART = 1;
+
+    /* Wait for the external oscillator to start up */
+    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
+    {
+        // Do nothing.
+    }
+
+    // Radio config
+    NRF_RADIO->TXPOWER = (RADIO_TXPOWER_TXPOWER_0dBm << RADIO_TXPOWER_TXPOWER_Pos);
+    NRF_RADIO->FREQUENCY = 7UL; // Frequency bin 7, 2407MHz
+    NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_1Mbit << RADIO_MODE_MODE_Pos);
+
+    NRF_RADIO->PREFIX0 = 0xC3438303;
+    NRF_RADIO->PREFIX1 = 0xE3630023;
+    NRF_RADIO->BASE0 = 0x80C4A2E6;
+    NRF_RADIO->BASE1 = 0x91D5B3F7;
+
+    NRF_RADIO->TXADDRESS = 0x00UL;   // Set device address 0 to use when transmitting
+    NRF_RADIO->RXADDRESSES = 0x01UL; // Enable device address 0 to use to select which addresses to receive
+
+    NRF_RADIO->PCNF0 = 0X00030006;
+    NRF_RADIO->PCNF1 = 0X01040020;
+
+    NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos); // Number of checksum bits
+
+    NRF_RADIO->CRCINIT = 0xFFFFUL;  // Initial value
+    NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16 + x^12^x^5 + 1
+
+    NRF_RADIO->PACKETPTR = (uint32_t)&txbuff[0];
+}
+#include "nrf_drv_rtc.h"
+const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(0); /**< Declaring an instance of nrf_drv_rtc for RTC2. */
+unsigned int countevt = 0;
+void radio_connect(void)
+{
+    NRF_RTC0->CC[2] = NRF_RTC0->COUNTER;
+    countevt = 1;
+    nrf_drv_rtc_cc_set(&rtc, 0, NRF_RTC0->CC[2] + countevt * 0.009 * 32768, true);
+    countevt++;
+}
+void RADIO_IRQHandler(void)
+{
+    if (NRF_RADIO->EVENTS_READY && (NRF_RADIO->INTENSET & RADIO_INTENSET_READY_Msk))
+    {
+        NRF_RADIO->EVENTS_READY = 0U;
+        BLE_PRINT("a");
+    }
+    if (NRF_RADIO->EVENTS_ADDRESS && (NRF_RADIO->INTENSET & RADIO_INTENSET_ADDRESS_Msk))
+    {
+        NRF_RADIO->EVENTS_ADDRESS = 0U;
+        BLE_PRINT("b");
+    }
+    if (NRF_RADIO->EVENTS_PAYLOAD && (NRF_RADIO->INTENSET & RADIO_INTENSET_PAYLOAD_Msk))
+    {
+        NRF_RADIO->EVENTS_PAYLOAD = 0U;
+        BLE_PRINT("c");
+    }
+    if (NRF_RADIO->EVENTS_END && (NRF_RADIO->INTENSET & RADIO_INTENSET_END_Msk))
+    {
+        NRF_RADIO->EVENTS_END = 0U;
+        //		NRF_LOG_INFO("d");
+        if (NRF_RADIO->STATE >= 5UL)
+        {
+            NRF_RADIO->EVENTS_DISABLED = 0U;
+            NRF_RADIO->TASKS_DISABLE = 1U;
+            nrf_gpio_pin_write(tx, 0);
+            //			BLE_PRINT("Tx  end\r\n");
+        }
+        else
+        {
+            //ê?μ?êy?Yoó?è?D???a·¢?í?£ê?
+            NRF_RTC0->CC[2] = NRF_RTC0->COUNTER;
+
+            NRF_RADIO->PACKETPTR = (unsigned int)txbuff;
+            NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk;
+
+            nrf_gpio_pin_write(tx, 0);
+
+            NRF_RADIO->EVENTS_DISABLED = 0U;
+            NRF_RADIO->TASKS_DISABLE = 1U;
+            while (NRF_RADIO->EVENTS_DISABLED == 0)
+                ;
+
+            NRF_RADIO->TASKS_TXEN = 1;
+
+            nrf_gpio_pin_write(tx, 1);
+
+            nrf_drv_rtc_cc_set(&rtc, 0, NRF_RTC0->CC[2] + 0.010 * 32768, true);
+            nrf_drv_rtc_cc_set(&rtc, 1, NRF_RTC0->CC[2] + 0.018 * 32768, true);
+
+            for (int i = 0; i < 50; i++)
+            {
+                BLE_PRINT("%x", rxbuff[i]);
+            }
+            BLE_PRINT("Rx\r\n", rxbuff[1]);
+        }
+    }
+    if (NRF_RADIO->EVENTS_DISABLED && (NRF_RADIO->INTENSET & RADIO_INTENSET_DISABLED_Msk))
+    {
+        NRF_RADIO->EVENTS_DISABLED = 0U;
+        BLE_PRINT("e");
+    }
+    if (NRF_RADIO->EVENTS_DEVMATCH && (NRF_RADIO->INTENSET & RADIO_INTENSET_DEVMATCH_Msk))
+    {
+        NRF_RADIO->EVENTS_DEVMATCH = 0U;
+        BLE_PRINT("f");
+    }
+    if (NRF_RADIO->EVENTS_DEVMISS && (NRF_RADIO->INTENSET & RADIO_INTENSET_DEVMISS_Msk))
+    {
+        NRF_RADIO->EVENTS_DEVMISS = 0U;
+        BLE_PRINT("g");
+    }
+    if (NRF_RADIO->EVENTS_RSSIEND && (NRF_RADIO->INTENSET & RADIO_INTENSET_RSSIEND_Msk))
+    {
+        NRF_RADIO->EVENTS_RSSIEND = 0U;
+        BLE_PRINT("h");
+    }
+    if (NRF_RADIO->EVENTS_BCMATCH && (NRF_RADIO->INTENSET & RADIO_INTENSET_BCMATCH_Msk))
+    {
+        NRF_RADIO->EVENTS_BCMATCH = 0U;
+        BLE_PRINT("i");
+    }
+    if (NRF_RADIO->EVENTS_CRCOK && (NRF_RADIO->INTENSET & RADIO_INTENSET_CRCOK_Msk))
+    {
+        NRF_RADIO->EVENTS_CRCOK = 0U;
+        BLE_PRINT("k");
+    }
+    if (NRF_RADIO->EVENTS_CRCERROR && (NRF_RADIO->INTENSET & RADIO_INTENSET_CRCERROR_Msk))
+    {
+        NRF_RADIO->EVENTS_CRCERROR = 0U;
+        BLE_PRINT("l");
+    }
+    NVIC_ClearPendingIRQ(RADIO_IRQn);
+}
+
+void radio_scan_start(void)
+{
+    NRF_RADIO->SHORTS = 0;
+    NRF_RADIO->SHORTS |= RADIO_SHORTS_DISABLED_RXEN_Msk;
+    NRF_RADIO->SHORTS |= RADIO_SHORTS_READY_START_Msk;
+    NRF_RADIO->SHORTS |= RADIO_SHORTS_END_START_Msk;
+
+    NRF_RADIO->INTENSET |= RADIO_INTENSET_END_Msk;
+
+    NRF_RADIO->TASKS_RXEN = 1;
+    NRF_RADIO->EVENTS_READY = 0;
+    while (NRF_RADIO->EVENTS_READY == 0)
+    {
+    }
+
+    NRF_RADIO->TASKS_START = 1;
+    NVIC_EnableIRQ(RADIO_IRQn);
+    Radio_State();
+}
+
+static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
+{
+    switch (int_type)
+    {
+    case NRFX_RTC_INT_COMPARE0:
+        nrf_gpio_pin_write(tx, 1);
+        NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk;
+        NRF_RADIO->PACKETPTR = (unsigned int)rxbuff;
+        NRF_RADIO->TASKS_RXEN = 1U;
+        break;
+    case NRFX_RTC_INT_COMPARE1:
+        Radio_State();
+        BLE_PRINT("NRFX_RTC_INT_COMPARE1\r\n");
+        break;
+    case NRFX_RTC_INT_COMPARE2:
+        break;
+    case NRFX_RTC_INT_COMPARE3:
+        break;
+    case NRFX_RTC_INT_TICK:
+        break;
+    case NRFX_RTC_INT_OVERFLOW:
+        nrf_drv_rtc_counter_clear(&rtc);
+        break;
+    }
+}
+
+/**********************************************************
+ * oˉêy??×?£ortc_config
+ * oˉêy×÷ó?£ortc?y?ˉ3?ê??ˉoíéè??
+ * oˉêy2?êy£o?T
+ * oˉêy·μ???μ£o?T
+ ***********************************************************/
+
+void radio_rtc_config(void)
+{
+    uint32_t err_code;
+
+    NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_RC << CLOCK_LFCLKSRC_SRC_Pos);
+    NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
+    NRF_CLOCK->TASKS_LFCLKSTART = 1;
+
+    while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0)
+    {
+        // Do nothing.
+    }
+
+    //Initialize RTC instance
+    nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
+    config.prescaler = 0; //4095;????????=32768/(config.prescaler+1)Hz;
+    err_code = nrf_drv_rtc_init(&rtc, &config, rtc_handler);
+    APP_ERROR_CHECK(err_code);
+
+    //Enable tick event & interrupt
+    //    nrf_drv_rtc_tick_enable(&rtc, true);
+
+    //Set compare channel to trigger interrupt after COMPARE_COUNTERTIME seconds
+    //    err_code = nrf_drv_rtc_cc_set(&rtc, 0, 8, true);
+    //    APP_ERROR_CHECK(err_code);
+
+    //Power on RTC instance
+    nrf_drv_rtc_enable(&rtc);
+}
+
+int main(void)
+{
+    unsigned int error = 0;
+    unsigned int rtctemp = 0;
+    unsigned int start = 0;
+    unsigned int radio_dis_cun = 0;
+    unsigned int radio_dis_cun_rtc = 0;
+
+    nrf_gpio_cfg_output(led);
+    nrf_gpio_pin_write(led, 1);
+
+    nrf_gpio_cfg_output(tx);
+    nrf_gpio_pin_write(tx, 0);
+
+    nrf_gpio_cfg_output(8);
+    nrf_gpio_pin_write(8, 0);
+
+    nrf_gpio_cfg_output(rx);
+    nrf_gpio_pin_write(rx, 0);
+
+    BLE_PRINT("NRF_FICR->DEVICEID : %d\r\n", *NRF_FICR->DEVICEID);
+
+    if (*NRF_FICR->DEVICEID == RS) //óò±?D?
+    {
+#if 1
+        slave_init(host_r);
+#else
+        radio_init_R();
+        radio_rtc_config();
+        radio_scan_start();
+#endif
+        BLE_PRINT("you \r\n");
+    }
+
+    if (*NRF_FICR->DEVICEID == LS) //×ó±?D?
+    {
+#if 0			
+			Target_scan[0]=0xe3;  //3132
+			Target_scan[1]=0x3f;
+			Target_scan[2]=0xd9;
+			Target_scan[3]=0x0d;
+			Target_scan[4]=0x0e;
+			Target_scan[5]=0xc6;
+			
+			sscanf("A1 A3 9D 04 E9 F4","%hhx %hhx %hhx %hhx %hhx %hhx",&Target_scan[0],&Target_scan[1],&Target_scan[2],&Target_scan[3],&Target_scan[4],&Target_scan[5]);
+			
+//			Target_scan[0]=0x3C;  //?a·¢°?
+//			Target_scan[1]=0x83;
+//			Target_scan[2]=0xCF;
+//			Target_scan[3]=0x49;
+//			Target_scan[4]=0x50;
+//			Target_scan[5]=0xE1;
+//
+#endif
+        Ble_Host_Connectd_Evt_Regist(unoioo);
+        Ble_Slave_Connectd_Evt_Regist(unoioo_s);
+			Ble_Slave_Disconn_Evt_Regist(unoioo_s_d);
+        //			extern void radio_request_earliest(void);
+        //			Ble_Slave_Connectd_Evt_Regist(radio_request_earliest);
+        slave_init(host_r);
+        host_init(slave_r);
+        
+
+        //				timer_config();
+        BLE_PRINT("zuo \r\n");
+    }
+
+    if (*NRF_FICR->DEVICEID == PS) //ê??ú
+    {
+#if 0	
+        Target_scan[0] = 0x21;
+        Target_scan[1] = 0x8a;
+        Target_scan[2] = 0x4f;
+        Target_scan[3] = 0x61;
+        Target_scan[4] = 0xcb;
+        Target_scan[5] = 0xe8;
+#endif
+        host_set_scan_name("SH_13EC", 7);
+        BLE_PRINT("shou \r\n");
+        host_init(slave_r);
+        scan_start();
+    }
+    rtc_config();
+    for (int i = 1; i < 200; i++)
+    {
+        buff[i] = i + 0x30;
+        //			txbuff[i]=i;
+    }
+    app_timer_create(&s_Timer, APP_TIMER_MODE_REPEATED, s_TimerCallback);
+    app_timer_start(s_Timer, TEST_PERIOD, NULL);
+    //		ppi_set();
+
+    while (1)
+    {
+        cli_process(&clirtt);
+        if (NRF_SUCCESS == sd_evt_get(&error))
+        {
+            BLE_PRINT("shou \r\n");
+        }
+        //				if (*NRF_FICR->DEVICEID == LS) //×ó±?D?
+        {
+            if (NRF_RADIO->STATE == RADIO_STATE_STATE_Disabled)
+            {
+                nrf_gpio_pin_write(tx, 0);
+            }
+            else
+            {
+                nrf_gpio_pin_write(tx, 1);
+            }
+        }
+    }
+}
+void host_init_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    host_init(slave_r);
+}
+CLI_CMD_REGISTER(host_init, "clear sereen", host_init_pcs);
+
+void hsb_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    send_bytes_server(buff, 200);
+}
+CLI_CMD_REGISTER(hsb, "clear sereen", hsb_pcs);
+
+void send_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    tims = 1;
+}
+CLI_CMD_REGISTER(send, "clear sereen", send_pcs);
+
+void scc_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    buff[0] = 0xcc;
+    send_bytes_client(buff, 6);
+}
+CLI_CMD_REGISTER(scc, "clear sereen", scc_pcs);
+
+void sbb_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    buff[0] = 0xbb;
+    send_bytes_client(buff, 6);
+}
+CLI_CMD_REGISTER(sbb, "clear sereen", sbb_pcs);
+
+void hcb_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    send_bytes_client(buff, 200);
+}
+CLI_CMD_REGISTER(hcb, "clear sereen", hcb_pcs);
+
+void slave_init_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    slave_init(host_r);
+}
+CLI_CMD_REGISTER(slave_init, "clear sereen", slave_init_pcs);
+
+void bleupdata_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    unsigned int error = 0;
+    error = Ble_update_conn_interval(10, 10);
+    cli_printf(p_cli, "err %d", error);
+}
+CLI_CMD_REGISTER(bleupdata10, "clear sereen", bleupdata_pcs);
+
+void bleupdata_1000pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    unsigned int error = 0;
+    error = Ble_update_conn_interval(1000, 1000);
+    cli_printf(p_cli, "err %d", error);
+}
+CLI_CMD_REGISTER(bleupdata1000, "clear sereen", bleupdata_1000pcs);
+
+void slaveupdata_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    unsigned int error =
+        slave_update_conn_interval_request(40, 40);
+    cli_printf(p_cli, "err %d", error);
+}
+CLI_CMD_REGISTER(slaveupdata, "clear sereen", slaveupdata_pcs);
+
+void conn_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    if (argc == 1)
+    {
+        host_set_scan_name(argv[0], strlen(argv[0]));
+        host_init(slave_r);
+    }
+    else
+        cli_printf(p_cli, "err ");
+}
+CLI_CMD_REGISTER(conn, "clear sereen", conn_pcs);
+
+void scan_name_set_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    if (argc == 1)
+    {
+        host_set_scan_name(argv[0], strlen(argv[0]));
+    }
+    else
+        cli_printf(p_cli, "err ");
+}
+CLI_CMD_REGISTER(scan_name_set, "clear sereen", scan_name_set_pcs);
+
+void systemreset_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    NVIC_SystemReset();
+}
+CLI_CMD_REGISTER(systemreset, "clear sereen", systemreset_pcs);
+
+void scanstart_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    scan_start();
+}
+CLI_CMD_REGISTER(scanstart, "clear sereen", scanstart_pcs);
+
+void slave_dec_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    slave_disconnect();
+}
+CLI_CMD_REGISTER(slave_dec, "clear sereen", slave_dec_pcs);
+
+void host_dec_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    host_disconnect();
+}
+CLI_CMD_REGISTER(host_dec, "clear sereen", host_dec_pcs);
+
+void getconn_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    BLE_PRINT("min_conn_interval : %d * 1.25 ms\r\n", slave_conn_params.min_conn_interval);
+    BLE_PRINT("max_conn_interval : %d * 1.25 ms\r\n", slave_conn_params.max_conn_interval);
+    BLE_PRINT("slave_latency     : %d\r\n", slave_conn_params.slave_latency);
+    BLE_PRINT("conn_sup_timeout  : %d * 10   ms\r\n", slave_conn_params.conn_sup_timeout);
+    extern ble_gap_conn_params_t host_conn_params;
+    BLE_PRINT("min_conn_interval : %d * 1.25 ms\r\n", host_conn_params.min_conn_interval);
+    BLE_PRINT("max_conn_interval : %d * 1.25 ms\r\n", host_conn_params.max_conn_interval);
+    BLE_PRINT("slave_latency     : %d\r\n", host_conn_params.slave_latency);
+    BLE_PRINT("conn_sup_timeout  : %d * 10   ms\r\n", host_conn_params.conn_sup_timeout);
+
+    slave_set_adv_name("123456", 6);
+    gap_params_init();
+    while (slave_isconnect() == 1)
+    {
+    }
+    BLE_PRINT("123456555");
+    advertising_start();
+    BLE_PRINT("4554564");
+}
+CLI_CMD_REGISTER(getconn, "clear sereen", getconn_pcs);
+
+void slave_get_rssi_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    slave_get_rssi();
+}
+CLI_CMD_REGISTER(slave_get_rssi, "clear sereen", slave_get_rssi_pcs);
+void host_get_rssi_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    host_get_rssi();
+}
+CLI_CMD_REGISTER(host_get_rssi, "clear sereen", host_get_rssi_pcs);
+
+int teg = 0;
+unsigned int rtccc = 0;
+void radio_evt_conf(void)
+{
+    NRF_RADIO->POWER = (RADIO_POWER_POWER_Enabled << RADIO_POWER_POWER_Pos);
+    /* Start 16 MHz crystal oscillator */
+    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
+    NRF_CLOCK->TASKS_HFCLKSTART = 1;
+    txbuff[1] = NRF_RTC0->COUNTER;
+    txbuff[2] = teg;
+    /* Wait for the external oscillator to start up */
+    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
+    {
+        // Do nothing.
+    }
+
+    // Radio config
+    NRF_RADIO->TXPOWER = (RADIO_TXPOWER_TXPOWER_0dBm << RADIO_TXPOWER_TXPOWER_Pos);
+    NRF_RADIO->FREQUENCY = 7UL; // Frequency bin 7, 2407MHz
+    NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_1Mbit << RADIO_MODE_MODE_Pos);
+
+    NRF_RADIO->PREFIX0 = 0xC3438303;
+    NRF_RADIO->PREFIX1 = 0xE3630023;
+    NRF_RADIO->BASE0 = 0x80C4A2E6;
+    NRF_RADIO->BASE1 = 0x91D5B3F7;
+
+    NRF_RADIO->TXADDRESS = 0x00UL;   // Set device address 0 to use when transmitting
+    NRF_RADIO->RXADDRESSES = 0x01UL; // Enable device address 0 to use to select which addresses to receive
+
+    NRF_RADIO->PCNF0 = 0X00030006;
+    NRF_RADIO->PCNF1 = 0X01040020;
+
+    NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos); // Number of checksum bits
+
+    NRF_RADIO->CRCINIT = 0xFFFFUL;  // Initial value
+    NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16 + x^12^x^5 + 1
+
+    NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos //READYoó×??ˉ?aê??′DDSTART
+                        | RADIO_SHORTS_END_DISABLE_Enabled << RADIO_SHORTS_END_DISABLE_Pos;
+
+    // Set payload pointer
+    NRF_RADIO->PACKETPTR = (uint32_t)&txbuff[0];
+
+    NRF_RADIO->EVENTS_DISABLED = 0; //??3y±ê????
+    NRF_RADIO->TASKS_TXEN = 1;      //?aê?oó?á?ú2?×??o2ù×÷
+    while (NRF_RADIO->EVENTS_END == 0)
+    {
+        //μè′y·¢?ííê3é
+    }
+    nrf_gpio_pin_write(rx, 0);
+    NRF_RADIO->SHORTS = 0;
+    NRF_RADIO->EVENTS_DISABLED = 0U;
+    NRF_RADIO->TASKS_DISABLE = 1U;
+    while (NRF_RADIO->EVENTS_DISABLED == 0)
+    {
+        //μè′y1?μ?radio
+    }
+
+    NRF_RADIO->EVENTS_READY = 0U;
+    // Enable radio and wait for ready
+    NRF_RADIO->TASKS_RXEN = 1U;
+
+    NRF_RADIO->PACKETPTR = (uint32_t)&rxbuff[0];
+
+    while (NRF_RADIO->EVENTS_READY == 0U)
+    {
+        // wait
+    }
+    nrf_gpio_pin_write(rx, 1);
+    NRF_RADIO->EVENTS_END = 0U;
+    // Start listening and wait for address received event
+    NRF_RADIO->TASKS_START = 1U;
+
+    // Wait for end of packet or buttons state changed
+
+    for (int j = 0; j < 5000; j++)
+    {
+        if (NRF_RADIO->EVENTS_END == 1)
+            break;
+    }
+
+    if (NRF_RADIO->CRCSTATUS == 1U)
+    {
+        for (int i = 0; i < 50; i++)
+        {
+            BLE_PRINT("%x", rxbuff[i]);
+        }
+        BLE_PRINT("\r\n ");
+        memset(rxbuff, 0, 60);
+    }
+    else
+    {
+        BLE_PRINT("E\r\n ");
+    }
+}
+
+nrf_radio_signal_callback_return_param_t call_radio_return_val;
+nrf_radio_signal_callback_return_param_t *call_radio(unsigned char sig)
+{
+    nrf_gpio_pin_write(rx, 1);
+
+    radio_evt_conf();
+
+    nrf_gpio_pin_write(rx, 0);
+    call_radio_return_val.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
+    return &call_radio_return_val;
+}
+
+void radio_session_open(void)
+{
+    BLE_PRINT("error= %d\r\n", sd_radio_session_open(call_radio));
+}
+
+void radio_session_open_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    BLE_PRINT("error= %d\r\n", sd_radio_session_open(call_radio));
+}
+CLI_CMD_REGISTER(radio_s_open, "clear sereen", radio_session_open_pcs);
+
+void radio_session_close_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    BLE_PRINT("error= %d\r\n", sd_radio_session_close());
+}
+CLI_CMD_REGISTER(radio_s_close, "clear sereen", radio_session_close_pcs);
+
+void radio_request_earliest(void)
+{
+    radio_session_open();
+
+    radio_request_p.request_type = NRF_RADIO_REQ_TYPE_EARLIEST;
+    radio_request_p.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_NO_GUARANTEE;
+    radio_request_p.params.earliest.length_us = 4000;
+    radio_request_p.params.earliest.priority = NRF_RADIO_PRIORITY_NORMAL;
+    radio_request_p.params.earliest.timeout_us = 2000;
+    BLE_PRINT("radio_request_earliest= %d\r\n", sd_radio_request(&radio_request_p));
+    //
+    //	radio_request_p.request_type=NRF_RADIO_REQ_TYPE_NORMAL;
+    //	radio_request_p.params.normal.hfclk=NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
+    //	radio_request_p.params.normal.distance_us=10000;
+    //	radio_request_p.params.normal.length_us=5000;
+    //	radio_request_p.params.normal.priority=NRF_RADIO_PRIORITY_NORMAL;
+}
+
+void radio_request_e_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    radio_request_p.request_type = NRF_RADIO_REQ_TYPE_EARLIEST;
+    radio_request_p.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
+    radio_request_p.params.earliest.length_us = 5000;
+    radio_request_p.params.earliest.priority = NRF_RADIO_PRIORITY_NORMAL;
+    radio_request_p.params.earliest.timeout_us = 2000;
+    BLE_PRINT("error= %d", sd_radio_request(&radio_request_p));
+}
+CLI_CMD_REGISTER(radio_r_e, "clear sereen", radio_request_e_pcs);
+
+void radio_request_n_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    radio_request_p.request_type = NRF_RADIO_REQ_TYPE_NORMAL;
+    BLE_PRINT("error= %d", sd_radio_request(&radio_request_p));
+}
+
+CLI_CMD_REGISTER(radio_r_n, "clear sereen", radio_request_n_pcs);
+
+void Radio_State_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    Radio_State();
+}
+
+CLI_CMD_REGISTER(Radio_State, "clear sereen", Radio_State_pcs);
+
+void s100_pcs(cli_t *p_cli, unsigned short argc, char **argv)
+{
+    send_bytes_client(buff, 150);
+}
+
+CLI_CMD_REGISTER(s100, "clear sereen", s100_pcs);
+
+#endif

+ 177 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_cfg/timeslot.c

@@ -0,0 +1,177 @@
+//需要使用的头文件
+#include <stdint.h>
+#include <stdbool.h>
+#include "nrf.h"
+#include "app_error.h"
+#include "nrf_gpio.h"
+#include "boards.h"
+#include "nrf_nvic.h"
+#include "ble_comm.h"
+
+// 定义一个timeSlot的变量,该变量用来设置 请求的timeSlot的特性。
+static nrf_radio_request_t m_timeslot_request;
+// 请求的timeSlot的时间间隙长度
+static uint32_t m_slot_length;
+// 信号处理函数的返回值。
+static nrf_radio_signal_callback_return_param_t signal_callback_return_param;
+
+
+//请求一个earliest possible 类型的timeSlot,第一次请求timeSLot的时候总是以该类型发起
+// timeSlot时间长度为  5000 us
+// timeSlot的请求优先级为正常优先级
+// 这里设置了在timeSlot运行过程中会打开外部高频晶振时钟源,不过其实不是必须的。
+// timeout_us表示请求timeSlot发出后,系统接收这个请求的最大延迟。
+// timeSLot的时间长度为5000us
+uint32_t request_next_event_earliest(void)
+{
+    m_slot_length = 5000;
+    m_timeslot_request.request_type = NRF_RADIO_REQ_TYPE_EARLIEST;
+    m_timeslot_request.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
+    m_timeslot_request.params.earliest.priority = NRF_RADIO_PRIORITY_NORMAL;
+    m_timeslot_request.params.earliest.length_us = m_slot_length;
+    m_timeslot_request.params.earliest.timeout_us = 1000000;
+    return sd_radio_request(&m_timeslot_request);
+}
+
+// 配置 earliest possible的类型的 timeSlot
+void configure_next_event_earliest(void)
+{
+    m_slot_length = 5000;
+    m_timeslot_request.request_type = NRF_RADIO_REQ_TYPE_EARLIEST;
+    m_timeslot_request.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
+    m_timeslot_request.params.earliest.priority = NRF_RADIO_PRIORITY_NORMAL;
+    m_timeslot_request.params.earliest.length_us = m_slot_length;
+    m_timeslot_request.params.earliest.timeout_us = 1000000;
+}
+
+// 配置normal类型的timeSlot
+void configure_next_event_normal(void)
+{
+    m_slot_length = 5000;
+    m_timeslot_request.request_type = NRF_RADIO_REQ_TYPE_NORMAL;
+    m_timeslot_request.params.normal.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
+		m_timeslot_request.params.normal.priority = NRF_RADIO_PRIORITY_HIGH;
+// norma类型的timeSlot 的开始时间为距离上一个 timeSlot的开始时间 distance_us后
+    m_timeslot_request.params.normal.distance_us = 100000;
+    m_timeslot_request.params.normal.length_us = m_slot_length;
+}
+
+
+// timeSlot 会话相关的 一些事件的处理
+// 这里的主要处理是,在收到 IDLE事件,即申请的这段会话中没有 timeSlot需要处理后会
+// 产生这个事件,那么就可以 通过sd_radio_session_close 函数关闭这个 会话了
+// 另外请求的timeSlot可能因为和协议栈运行产生冲突,那么就可以被阻塞或去掉,所以
+// NRF_EVT_RADIO_BLOCKED 和 NRF_EVT_RADIO_CANCELED 事件的处理都是重新发起请求
+void nrf_evt_signal_handler(uint32_t evt_id)
+{
+    uint32_t err_code;
+    switch (evt_id)
+    {
+        case NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN:
+            BLE_PRINT("NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN\r\n");
+            break;
+        case NRF_EVT_RADIO_SESSION_IDLE:
+            BLE_PRINT("NRF_EVT_RADIO_SESSION_IDLE\r\n");
+            sd_radio_session_close();
+            break;
+        case NRF_EVT_RADIO_SESSION_CLOSED:
+            BLE_PRINT("NRF_EVT_RADIO_SESSION_CLOSED\r\n");
+            break;
+        case NRF_EVT_RADIO_BLOCKED:
+            BLE_PRINT("NRF_EVT_RADIO_BLOCKED\r\n");
+            //注意这里没有break,所以 这两个事件的处理都是重新发起请求
+        case NRF_EVT_RADIO_CANCELED:
+            BLE_PRINT("NRF_EVT_RADIO_CANCELED\r\n");
+            err_code = request_next_event_earliest();
+            APP_ERROR_CHECK(err_code);
+            break;
+        default:
+            break;
+    }
+}
+
+
+// timeSlot相关的信号处理函数。
+// 当请求的timeSlot 被安排开始后,就会收到 START信号,在这个信号处理里面实现
+// 实现翻转 LED灯同时设置 Timer0的超时时间,time0在timeSLot开始后会被自动重置为
+// 1MH运行从0 计数,所以这里设置time0的超时时间比 timeSlot的时间长度短1000us,//这样在timeSLot
+// 结束之前就可以收到 NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0信号,然后在这信号处
+// 理里做一些收尾工作,在这里我们实现的是请求下一个timeSlot
+
+// NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO信号不需要处理,因为我们没有在timeSLot
+// 中使用Radio,所以不会有这个信号。
+
+nrf_radio_signal_callback_return_param_t * radio_callback(uint8_t signal_type)
+{
+    static uint8_t start_count = 0;
+    static uint8_t timer0_count = 0;
+
+    switch(signal_type)
+    {
+        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START:
+            signal_callback_return_param.params.request.p_next = NULL;
+						signal_callback_return_param.callback_action    = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
+
+            NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
+            NRF_TIMER0->CC[0] = m_slot_length - 1000;
+            NVIC_EnableIRQ(TIMER0_IRQn);
+
+            nrf_gpio_pin_toggle(16);
+            //避免打印太快
+            if(start_count++ >10 ){            
+                BLE_PRINT("NRF_RADIO_CALLBACK_SIGNAL_TYPE_START\r\n");
+                start_count = 0;
+            }
+            break;
+
+        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO:
+            signal_callback_return_param.params.request.p_next = NULL;
+            signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
+            break;
+
+        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0:
+            configure_next_event_normal();
+            signal_callback_return_param.params.request.p_next = &m_timeslot_request;
+            signal_callback_return_param.callback_action    = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
+            if(timer0_count++ >10 ){            
+                BLE_PRINT("NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0\r\n");
+                timer0_count = 0;
+            }
+            break;
+        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED:
+            BLE_PRINT("NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED\r\n");
+            break;
+        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED:
+            BLE_PRINT("NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED\r\n");
+            configure_next_event_earliest();
+            signal_callback_return_param.params.request.p_next = &m_timeslot_request;
+						signal_callback_return_param.callback_action    = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
+            break;
+        default:
+            //No implementation needed
+            break;
+    }
+    return (&signal_callback_return_param);
+}
+
+// timeSlot初始化函数。
+uint32_t timeslot_sd_init(void)
+{
+    uint32_t err_code;
+
+    err_code = sd_radio_session_open(radio_callback);
+    if (err_code != NRF_SUCCESS)
+    {
+        return err_code;
+    }
+
+    err_code = request_next_event_earliest();
+    if (err_code != NRF_SUCCESS)
+    {
+        (void)sd_radio_session_close();
+        return err_code;
+    }
+    nrf_gpio_cfg_output(16);
+    return NRF_SUCCESS;
+}
+

+ 325 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_dfu/ble_dfu.c

@@ -0,0 +1,325 @@
+/**
+ * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ *    Semiconductor ASA integrated circuit in a product or a software update for
+ *    such product, must reproduce the above copyright notice, this list of
+ *    conditions and the following disclaimer in the documentation and/or other
+ *    materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ *    Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ *    engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/* Attention!
+ *  To maintain compliance with Nordic Semiconductor ASA's Bluetooth profile
+ *  qualification listings, this section of source code must not be modified.
+ */
+
+#include "ble_dfu.h"
+#include <string.h>
+#include "ble_hci.h"
+#include "sdk_macros.h"
+#include "ble_srv_common.h"
+#include "nrf_nvic.h"
+#include "nrf_soc.h"
+#include "nrf_log.h"
+#include "nrf_dfu_ble_svci_bond_sharing.h"
+#include "nrf_bootloader_info.h"
+#include "nrf_svci_async_function.h"
+#include "nrf_pwr_mgmt.h"
+#include "peer_manager.h"
+#include "gatts_cache_manager.h"
+#include "peer_id.h"
+
+#define MAX_CTRL_POINT_RESP_PARAM_LEN   3                           /**< Max length of the responses. */
+
+#define BLE_DFU_SERVICE_UUID            0xFE59                      /**< The 16-bit UUID of the Secure DFU Service. */
+
+static ble_dfu_buttonless_t             m_dfu;                      /**< Structure holding information about the Buttonless Secure DFU Service. */
+
+NRF_SDH_BLE_OBSERVER(m_dfus_obs, BLE_DFU_BLE_OBSERVER_PRIO, ble_dfu_buttonless_on_ble_evt, &m_dfu);
+
+
+/**@brief Function that is called if no event handler is provided.
+ */
+static void dummy_evt_handler(ble_dfu_buttonless_evt_type_t evt)
+{
+    NRF_LOG_DEBUG("Dummy event handler received event 0x%x", evt);
+}
+
+
+/**@brief Function for handling write events to the Buttonless Secure DFU Service Service Control Point characteristic.
+ *
+ * @param[in]   p_evt_write   Write event received from the BLE stack.
+ */
+static void on_ctrlpt_write(ble_gatts_evt_write_t const * p_evt_write)
+{
+    uint32_t      err_code;
+
+    ble_gatts_rw_authorize_reply_params_t write_authorize_reply;
+    memset(&write_authorize_reply, 0, sizeof(write_authorize_reply));
+
+    write_authorize_reply.type   = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
+
+    uint8_t cccd_val[2];
+    ble_gatts_value_t value = {.p_value = cccd_val, .len = 2, .offset = 0};
+    err_code = sd_ble_gatts_value_get(m_dfu.conn_handle, m_dfu.control_point_char.cccd_handle, &value);
+    if (err_code == NRF_SUCCESS && ble_srv_is_indication_enabled(cccd_val))
+    {
+        write_authorize_reply.params.write.update      = 1;
+        write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
+    }
+    else
+    {
+        write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR;
+    }
+
+    // Authorize the write request
+    do {
+        err_code = sd_ble_gatts_rw_authorize_reply(m_dfu.conn_handle, &write_authorize_reply);
+    } while (err_code == NRF_ERROR_BUSY);
+
+
+    if (write_authorize_reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS)
+    {
+        return;
+    }
+
+    // Forward the write event to the Buttonless DFU module.
+    ble_dfu_buttonless_on_ctrl_pt_write(p_evt_write);
+}
+
+
+/**@brief Write authorization request event handler.
+ *
+ * @details The write authorization request event handler is called when writing to the control point.
+ *
+ * @param[in]   p_ble_evt Event received from the BLE stack.
+ */
+static void on_rw_authorize_req(ble_evt_t const * p_ble_evt)
+{
+    if (p_ble_evt->evt.gatts_evt.conn_handle != m_dfu.conn_handle)
+    {
+        return;
+    }
+
+    const ble_gatts_evt_rw_authorize_request_t * p_auth_req =
+        &p_ble_evt->evt.gatts_evt.params.authorize_request;
+
+    if (
+        (p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)                            &&
+        (p_auth_req->request.write.handle == m_dfu.control_point_char.value_handle)     &&
+        (p_auth_req->request.write.op != BLE_GATTS_OP_PREP_WRITE_REQ)                   &&
+        (p_auth_req->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW)               &&
+        (p_auth_req->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)
+       )
+    {
+        on_ctrlpt_write(&p_auth_req->request.write);
+    }
+}
+
+
+/**@brief Connect event handler.
+ *
+ * @param[in]   p_ble_evt   Event received from the BLE stack.
+ */
+static void on_connect(ble_evt_t const * p_ble_evt)
+{
+    if (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_PERIPH)
+    {
+        m_dfu.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
+    }
+}
+
+
+/**@brief Disconnect event handler.
+ *
+ * @param[in]   p_ble_evt   Event received from the BLE stack.
+ */
+static void on_disconnect(ble_evt_t const * p_ble_evt)
+{
+    if (m_dfu.conn_handle != p_ble_evt->evt.gap_evt.conn_handle)
+    {
+        return;
+    }
+
+    m_dfu.conn_handle = BLE_CONN_HANDLE_INVALID;
+}
+
+
+/**@brief Function for handling the HVC events.
+ *
+ * @details Handles HVC events from the BLE stack.
+ *
+ * @param[in] p_ble_evt  Event received from the BLE stack.
+ */
+static void on_hvc(ble_evt_t const * p_ble_evt)
+{
+    uint32_t err_code;
+    ble_gatts_evt_hvc_t const * p_hvc = &p_ble_evt->evt.gatts_evt.params.hvc;
+
+    if (p_hvc->handle == m_dfu.control_point_char.value_handle)
+    {
+        // Enter bootloader if we were waiting for reset after hvc indication confimation.
+        if (m_dfu.is_waiting_for_reset)
+        {
+            err_code = ble_dfu_buttonless_bootloader_start_prepare();
+            if (err_code != NRF_SUCCESS)
+            {
+                m_dfu.evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED);
+            }
+        }
+    }
+}
+
+
+void ble_dfu_buttonless_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
+{
+    VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
+
+    switch (p_ble_evt->header.evt_id)
+    {
+        case BLE_GAP_EVT_CONNECTED:
+            on_connect(p_ble_evt);
+            break;
+
+        case BLE_GAP_EVT_DISCONNECTED:
+            on_disconnect(p_ble_evt);
+            break;
+
+        case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
+            on_rw_authorize_req(p_ble_evt);
+            break;
+
+        case BLE_GATTS_EVT_HVC:
+            on_hvc(p_ble_evt);
+            break;
+
+        default:
+            // no implementation
+            break;
+    }
+}
+
+
+uint32_t ble_dfu_buttonless_resp_send(ble_dfu_buttonless_op_code_t op_code, ble_dfu_buttonless_rsp_code_t rsp_code)
+{
+    // Send indication
+    uint32_t                err_code;
+    const uint16_t          len = MAX_CTRL_POINT_RESP_PARAM_LEN;
+    uint16_t                hvx_len;
+    uint8_t                 hvx_data[MAX_CTRL_POINT_RESP_PARAM_LEN];
+    ble_gatts_hvx_params_t  hvx_params;
+
+    memset(&hvx_params, 0, sizeof(hvx_params));
+
+    hvx_len     = len;
+    hvx_data[0] = DFU_OP_RESPONSE_CODE;
+    hvx_data[1] = (uint8_t)op_code;
+    hvx_data[2] = (uint8_t)rsp_code;
+
+    hvx_params.handle = m_dfu.control_point_char.value_handle;
+    hvx_params.type   = BLE_GATT_HVX_INDICATION;
+    hvx_params.offset = 0;
+    hvx_params.p_len  = &hvx_len;
+    hvx_params.p_data = hvx_data;
+
+    err_code = sd_ble_gatts_hvx(m_dfu.conn_handle, &hvx_params);
+    if ((err_code == NRF_SUCCESS) && (hvx_len != len))
+    {
+        err_code = NRF_ERROR_DATA_SIZE;
+    }
+
+    return err_code;
+}
+
+
+uint32_t ble_dfu_buttonless_bootloader_start_finalize(void)
+{
+    uint32_t err_code;
+
+    NRF_LOG_DEBUG("In ble_dfu_buttonless_bootloader_start_finalize\r\n");
+
+    err_code = sd_power_gpregret_clr(0, 0xffffffff);
+    VERIFY_SUCCESS(err_code);
+
+    err_code = sd_power_gpregret_set(0, BOOTLOADER_DFU_START);
+    VERIFY_SUCCESS(err_code);
+
+    // Indicate that the Secure DFU bootloader will be entered
+    m_dfu.evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER);
+
+    // Signal that DFU mode is to be enter to the power management module
+    nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU);
+
+    return NRF_SUCCESS;
+}
+
+
+uint32_t ble_dfu_buttonless_init(const ble_dfu_buttonless_init_t * p_dfu_init)
+{
+    uint32_t        err_code;
+    ble_uuid_t      service_uuid;
+    ble_uuid128_t   nordic_base_uuid = BLE_NORDIC_VENDOR_BASE_UUID;
+
+    VERIFY_PARAM_NOT_NULL(p_dfu_init);
+
+    // Initialize the service structure.
+    m_dfu.conn_handle                  = BLE_CONN_HANDLE_INVALID;
+    m_dfu.evt_handler                  = p_dfu_init->evt_handler;
+    m_dfu.is_waiting_for_reset         = false;
+
+    if (m_dfu.evt_handler == NULL)
+    {
+        m_dfu.evt_handler = dummy_evt_handler;
+    }
+
+    err_code = ble_dfu_buttonless_backend_init(&m_dfu);
+    VERIFY_SUCCESS(err_code);
+
+    BLE_UUID_BLE_ASSIGN(service_uuid, BLE_DFU_SERVICE_UUID);
+
+    // Add the DFU service declaration.
+    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
+                                        &service_uuid,
+                                        &(m_dfu.service_handle));
+
+    VERIFY_SUCCESS(err_code);
+
+    // Add vendor specific base UUID to use with the Buttonless DFU characteristic.
+    err_code = sd_ble_uuid_vs_add(&nordic_base_uuid, &m_dfu.uuid_type);
+    VERIFY_SUCCESS(err_code);
+
+    // Add the Buttonless DFU Characteristic (with bonds/without bonds).
+    err_code = ble_dfu_buttonless_char_add(&m_dfu);
+    VERIFY_SUCCESS(err_code);
+
+    return NRF_SUCCESS;
+}

+ 249 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_dfu/ble_dfu.h

@@ -0,0 +1,249 @@
+/**
+ * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ *    Semiconductor ASA integrated circuit in a product or a software update for
+ *    such product, must reproduce the above copyright notice, this list of
+ *    conditions and the following disclaimer in the documentation and/or other
+ *    materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ *    Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ *    engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/** @file
+ *
+ * @defgroup ble_dfu Buttonless DFU Service
+ * @{
+ * @ingroup ble_sdk_srv
+ * @brief Buttonless DFU Service module.
+ *
+ * @details This module implements a proprietary Buttonless Secure DFU Service. The service can
+ *          be configured to support bonds or not. The bond support configuration must correspond to the
+ *          requirement of Secure DFU bootloader.
+ *
+ * @note Attention!
+ *  To maintain compliance with Nordic Semiconductor ASA Bluetooth profile
+ *  qualification listings, this section of source code must not be modified.
+ */
+
+#ifndef BLE_DFU_H__
+#define BLE_DFU_H__
+
+#include <stdint.h>
+#include "ble_srv_common.h"
+#include "nrf_sdh_ble.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**@brief   SoC observer priority.
+ * @details Priority of this module's SoC event handler.
+ */
+#define BLE_DFU_SOC_OBSERVER_PRIO   1
+
+#define BLE_DFU_BUTTONLESS_CHAR_UUID        (0x0003)    /**< Value combined with vendor-specific base to create Unbonded Buttonless characteristic UUID. */
+#define BLE_DFU_BUTTONLESS_BONDED_CHAR_UUID (0x0004)    /**< Value combined with vendor-specific base to create Bonded Buttonless characteristic UUID. */
+
+
+/**@brief Nordic vendor-specific base UUID.
+ */
+#define BLE_NORDIC_VENDOR_BASE_UUID                 \
+{{                                                  \
+    0x50, 0xEA, 0xDA, 0x30, 0x88, 0x83, 0xB8, 0x9F, \
+    0x60, 0x4F, 0x15, 0xF3, 0x00, 0x00, 0xC9, 0x8E  \
+}}
+
+
+/**@brief Nordic Buttonless DFU Service event type .
+ */
+typedef enum
+{
+    BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE,   /**< Event indicating that the device is preparing to enter bootloader.*/
+    BLE_DFU_EVT_BOOTLOADER_ENTER,           /**< Event indicating that the bootloader will be entered after return of this event.*/
+    BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED,    /**< Failure to enter bootloader mode.*/
+    BLE_DFU_EVT_RESPONSE_SEND_ERROR,        /**< Failure to send response.*/
+} ble_dfu_buttonless_evt_type_t;
+
+
+/**@brief Nordic Buttonless DFU Service event handler type.
+ */
+typedef void (*ble_dfu_buttonless_evt_handler_t) (ble_dfu_buttonless_evt_type_t p_evt);
+/**@brief Enumeration of Bootloader DFU response codes.
+ */
+typedef enum
+{
+    DFU_RSP_INVALID               = 0x00,                                           /**< Invalid op code. */
+    DFU_RSP_SUCCESS               = 0x01,                                           /**< Success. */
+    DFU_RSP_OP_CODE_NOT_SUPPORTED = 0x02,                                           /**< Op code not supported. */
+    DFU_RSP_OPERATION_FAILED      = 0x04,                                           /**< Operation failed. */
+    DFU_RSP_ADV_NAME_INVALID      = 0x05,                                           /**< Requested advertisement name is too short or too long. */
+    DFU_RSP_BUSY                  = 0x06,                                           /**< Ongoing async operation. */
+    DFU_RSP_NOT_BONDED            = 0x07,                                           /**< Buttonless unavailable due to device not bonded. */
+} ble_dfu_buttonless_rsp_code_t;
+
+
+/**@brief Enumeration of Bootloader DFU Operation codes.
+ */
+typedef enum
+{
+    DFU_OP_RESERVED         = 0x00, /**< Reserved for future use. */
+    DFU_OP_ENTER_BOOTLOADER = 0x01, /**< Enter bootloader. */
+    DFU_OP_SET_ADV_NAME     = 0x02, /**< Set advertisement name to use in DFU mode. */
+    DFU_OP_RESPONSE_CODE    = 0x20  /**< Response code. */
+} ble_dfu_buttonless_op_code_t;
+
+
+/**@brief Type holding memory used by Secure DFU Buttonless Service.
+  */
+typedef struct
+{
+    uint8_t                             uuid_type;                      /**< UUID type for DFU UUID. */
+    uint16_t                            service_handle;                 /**< Service Handle of DFU (as provided by the SoftDevice). */
+    uint16_t                            conn_handle;                    /**< Connection handle for the current peer. */
+    ble_gatts_char_handles_t            control_point_char;             /**< Handles related to the DFU Control Point characteristic. */
+    uint32_t                            peers_count;                    /**< Counter to see how many persistently stored peers must be updated for Service Changed indication. This value will be counted down when comparing write requests. */
+    ble_dfu_buttonless_evt_handler_t    evt_handler;                    /**< Event handler that is called upon Buttonless DFU events. See @ref ble_dfu_buttonless_evt_type_t. */
+    bool                                is_waiting_for_reset;           /**< Flag indicating that the device will enter bootloader. */
+    bool                                is_waiting_for_svci;            /**< Flag indicating that the device is waiting for async SVCI operation */
+} ble_dfu_buttonless_t;
+
+
+/**@brief Type used to initialize the Secure DFU Buttonless Service.
+ */
+typedef struct
+{
+    ble_dfu_buttonless_evt_handler_t   evt_handler;                       /**< Bootloader event handler. */
+} ble_dfu_buttonless_init_t;
+
+
+/**@brief Function for initializing the Device Firmware Update module.
+ *
+ * @param[in]   p_dfu_init   Structure containing the values of characteristics needed by the
+ *                           service.
+ * @retval      NRF_SUCCESS on successful initialization of the service.
+ */
+uint32_t ble_dfu_buttonless_init(const ble_dfu_buttonless_init_t * p_dfu_init);
+
+
+/**@brief Function for initializing the async SVCI interface.
+ *
+ * @warning Ensure that no interrupts are triggered when calling this functions as
+ *          interrupts and exceptions are forwarded to the bootloader for the period
+ *          of the call and may be lost.
+ *
+ * @details This configures the async interface for calling to the
+ *          bootloader through SVCI interface.
+ *
+ * @retval NRF_SUCCESS on success, otherwise an error code.
+ */
+uint32_t ble_dfu_buttonless_async_svci_init(void);
+
+
+/**@brief Function to initialize the backend Secure DFU Buttonless service which is either
+ *        supports bonds or not.
+ *
+ * @note    Do not call this function directly. It is called internally by @ref ble_dfu_buttonless_init.
+ *
+ * @param[in] p_dfu     Nordic DFU Service structure.
+ *
+ * @return NRF_SUCCESS  On sucessfully initializing, otherwise an error code.
+ */
+uint32_t ble_dfu_buttonless_backend_init(ble_dfu_buttonless_t * p_dfu);
+
+
+
+/**@brief Function for adding the buttonless characteristic.
+ *
+ * @note This will be implemented differently on bonded/unbonded Buttonless DFU service.
+ *
+ * @param[in] p_dfu       Nordic DFU Service structure.
+ *
+ * @return NRF_SUCCESS on success, otherwise an error code.
+ */
+uint32_t ble_dfu_buttonless_char_add(ble_dfu_buttonless_t * p_dfu);
+
+
+/**@brief Function for sending a response back to the client.
+ *
+ * @param[in]   op_code     Operation code to send the response for.
+ * @param[in]   rsp_code    Response code for the operation.
+ *
+ * @retval NRF_SUCCESS on success, otherwise an error code.
+ */
+uint32_t ble_dfu_buttonless_resp_send(ble_dfu_buttonless_op_code_t op_code, ble_dfu_buttonless_rsp_code_t rsp_code);
+
+
+/**@brief Function for handling the application's BLE stack events.
+ *
+ * @details Handles all events from the BLE stack of interest to the DFU buttonless service.
+ *
+ * @param[in]   p_ble_evt   Event received from the BLE stack.
+ * @param[in]   p_context   BLE context structure.
+ */
+void ble_dfu_buttonless_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context);
+
+
+/**@brief Function for handling control point write requests.
+ *
+ * @details Handles write requests to the control point in
+ *          DFU with bonds or without bonds.
+ *
+ * @param[in]   p_evt_write     GATTS write event.
+ */
+void ble_dfu_buttonless_on_ctrl_pt_write(ble_gatts_evt_write_t const * p_evt_write);
+
+
+/**@brief Function for preparing to enter the bootloader.
+ *
+ * @warning This function is called directly. (It is called internally).
+ *
+ * @retval Any error code from calling @ref sd_ble_gap_disconnect.
+ */
+uint32_t ble_dfu_buttonless_bootloader_start_prepare(void);
+
+
+/**@brief Function for finalizing entering the bootloader.
+ *
+ * @warning This function is not to be called. (It is called internally).
+ *
+ * @retval NRF_SUCCESS Finalize was started correctly.
+ */
+uint32_t ble_dfu_buttonless_bootloader_start_finalize(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // BLE_DIS_H__
+
+/** @} */

+ 367 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_dfu/ble_dfu_bonded.c

@@ -0,0 +1,367 @@
+/**
+ * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ *    Semiconductor ASA integrated circuit in a product or a software update for
+ *    such product, must reproduce the above copyright notice, this list of
+ *    conditions and the following disclaimer in the documentation and/or other
+ *    materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ *    Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ *    engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "nrf_dfu_ble_svci_bond_sharing.h"
+#include "nordic_common.h"
+#include "nrf_error.h"
+#include "ble_dfu.h"
+#include "nrf_log.h"
+#include "peer_manager.h"
+#include "gatts_cache_manager.h"
+#include "peer_id.h"
+#include "nrf_sdh_soc.h"
+#include "nrf_strerror.h"
+
+#if (NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS)
+
+
+void ble_dfu_buttonless_on_sys_evt(uint32_t, void * );
+uint32_t nrf_dfu_svci_vector_table_set(void);
+uint32_t nrf_dfu_svci_vector_table_unset(void);
+
+/**@brief Define function for async interface to set peer data. */
+NRF_SVCI_ASYNC_FUNC_DEFINE(NRF_DFU_SVCI_SET_PEER_DATA, nrf_dfu_set_peer_data, nrf_dfu_peer_data_t);
+
+// Register SoC observer for the Buttonless Secure DFU service
+NRF_SDH_SOC_OBSERVER(m_dfu_buttonless_soc_obs, BLE_DFU_SOC_OBSERVER_PRIO, ble_dfu_buttonless_on_sys_evt, NULL);
+
+ble_dfu_buttonless_t       * mp_dfu;
+static nrf_dfu_peer_data_t   m_peer_data;
+
+
+/**@brief Function for handling Peer Manager events.
+ *
+ * @param[in] p_evt  Peer Manager event.
+ */
+static void pm_evt_handler(pm_evt_t const * p_evt)
+{
+    uint32_t ret;
+
+    if (mp_dfu == NULL)
+    {
+        return;
+    }
+
+    // Only handle this when we are waiting to reset into DFU mode
+    if (!mp_dfu->is_waiting_for_reset)
+    {
+        return;
+    }
+
+    switch(p_evt->evt_id)
+    {
+        case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
+            if (p_evt->params.peer_data_update_succeeded.data_id == PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING)
+            {
+                mp_dfu->peers_count--;
+                NRF_LOG_DEBUG("Updating Service Changed indication for peers, %d left", mp_dfu->peers_count);
+                if (mp_dfu->peers_count == 0)
+                {
+                    NRF_LOG_DEBUG("Finished updating Service Changed indication for peers");
+                    // We have updated Service Changed Indication for all devices.
+                    ret = ble_dfu_buttonless_bootloader_start_finalize();
+                    if (ret != NRF_SUCCESS)
+                    {
+                        mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED);
+                    }
+                }
+            }
+            break;
+
+        case PM_EVT_PEER_DATA_UPDATE_FAILED:
+            // Failure to update data. Service Changed cannot be sent but DFU mode is still possible
+            ret = ble_dfu_buttonless_bootloader_start_finalize();
+            if (ret != NRF_SUCCESS)
+            {
+                mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED);
+            }
+            break;
+
+        default:
+            break;
+    }
+}
+
+
+static uint32_t retrieve_peer_data(void)
+{
+    ret_code_t              ret;
+    pm_peer_data_bonding_t  bonding_data = {0};
+    pm_peer_id_t            peer_id;
+
+    ret = pm_peer_id_get(mp_dfu->conn_handle, &peer_id);
+    VERIFY_SUCCESS(ret);
+
+    if (peer_id == PM_PEER_ID_INVALID)
+    {
+        return NRF_ERROR_FORBIDDEN;
+    }
+
+    ret = pm_peer_data_bonding_load(peer_id, &bonding_data);
+    VERIFY_SUCCESS(ret);
+
+    memcpy(&m_peer_data.ble_id,  &bonding_data.peer_ble_id, sizeof(ble_gap_id_key_t));
+    memcpy(&m_peer_data.enc_key, &bonding_data.own_ltk,     sizeof(ble_gap_enc_key_t));
+
+    uint16_t len = SYSTEM_SERVICE_ATT_SIZE;
+    ret = sd_ble_gatts_sys_attr_get(mp_dfu->conn_handle,
+                                    m_peer_data.sys_serv_attr,
+                                    &len,
+                                    BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);
+
+    NRF_LOG_DEBUG("system attribute table len: %d", len);
+
+    return ret;
+}
+
+
+/**@brief Function for entering the bootloader.
+ *
+ * @details This starts forwarding peer data to the Secure DFU bootloader.
+ */
+static uint32_t enter_bootloader(void)
+{
+    uint32_t ret;
+
+    NRF_LOG_INFO("Writing peer data to the bootloader...");
+
+    if (mp_dfu->is_waiting_for_svci)
+    {
+        return ble_dfu_buttonless_resp_send(DFU_OP_ENTER_BOOTLOADER, DFU_RSP_BUSY);
+    }
+
+    // If retrieve_peer_data returns NRF_ERROR_FORBIDDEN, then the device was not bonded.
+    ret = retrieve_peer_data();
+    VERIFY_SUCCESS(ret);
+
+    ret = nrf_dfu_set_peer_data(&m_peer_data);
+    if (ret == NRF_SUCCESS)
+    {
+        // The request was accepted. Waiting for sys events to progress.
+        mp_dfu->is_waiting_for_svci = true;
+    }
+    else if (ret == NRF_ERROR_FORBIDDEN)
+    {
+        NRF_LOG_ERROR("The bootloader has write protected its settings page. This prohibits setting the peer data. "\
+                      "The bootloader must be compiled with NRF_BL_SETTINGS_PAGE_PROTECT=0 to allow setting the peer data.");
+    }
+
+    return ret;
+}
+
+
+uint32_t ble_dfu_buttonless_backend_init(ble_dfu_buttonless_t * p_dfu)
+{
+    VERIFY_PARAM_NOT_NULL(p_dfu);
+
+    // Set the memory used by the backend.
+    mp_dfu = p_dfu;
+
+    // Initialize the Peer manager handler.
+    return pm_register(pm_evt_handler);
+}
+
+
+uint32_t ble_dfu_buttonless_async_svci_init(void)
+{
+    uint32_t ret;
+
+    // Set the vector table base address to the bootloader.
+    ret = nrf_dfu_svci_vector_table_set();
+    NRF_LOG_DEBUG("nrf_dfu_svci_vector_table_set() -> %s",
+                  (ret == NRF_SUCCESS) ? "success" : nrf_strerror_get(ret));
+    VERIFY_SUCCESS(ret);
+
+    // Initialize the asynchronous SuperVisor interface to set peer data in Secure DFU bootloader.
+    ret = nrf_dfu_set_peer_data_init();
+    NRF_LOG_DEBUG("nrf_dfu_set_peer_data_init() -> %s",
+                  (ret == NRF_SUCCESS) ? "success" : nrf_strerror_get(ret));
+    VERIFY_SUCCESS(ret);
+
+    // Set the vector table base address back to main application.
+    ret = nrf_dfu_svci_vector_table_unset();
+    NRF_LOG_DEBUG("nrf_dfu_svci_vector_table_unset() -> %s",
+                  (ret == NRF_SUCCESS) ? "success" : nrf_strerror_get(ret));
+
+    return ret;
+}
+
+
+void ble_dfu_buttonless_on_sys_evt(uint32_t sys_evt, void * p_context)
+{
+    uint32_t ret;
+
+    if (!nrf_dfu_set_peer_data_is_initialized())
+    {
+        return;
+    }
+
+    ret = nrf_dfu_set_peer_data_on_sys_evt(sys_evt);
+    if (ret == NRF_ERROR_INVALID_STATE)
+    {
+        // The system event is not from an operation started by buttonless DFU.
+        // No action is taken, and nothing is reported.
+    }
+    else if (ret == NRF_SUCCESS)
+    {
+        // Peer data was successfully forwarded to the Secure DFU bootloader.
+        // Set the flag indicating that we are waiting for indication response
+        // to activate the reset.
+        mp_dfu->is_waiting_for_reset = true;
+        mp_dfu->is_waiting_for_svci  = false;
+
+        // Report back the positive response
+        ret = ble_dfu_buttonless_resp_send(DFU_OP_ENTER_BOOTLOADER, DFU_RSP_SUCCESS);
+        if (ret != NRF_SUCCESS)
+        {
+            mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR);
+            mp_dfu->is_waiting_for_reset = false;
+        }
+    }
+    else
+    {
+        // Failed to set peer data. Report this.
+        mp_dfu->is_waiting_for_reset = false;
+        mp_dfu->is_waiting_for_svci  = false;
+        ret = ble_dfu_buttonless_resp_send(DFU_OP_ENTER_BOOTLOADER, DFU_RSP_BUSY);
+
+        // Report the failure to send the response to the client
+        if (ret != NRF_SUCCESS)
+        {
+            mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR);
+        }
+
+        // Report the failure to enter DFU mode
+        mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED);
+    }
+}
+
+
+uint32_t ble_dfu_buttonless_char_add(ble_dfu_buttonless_t * p_dfu)
+{
+    ble_add_char_params_t add_char_params;
+
+    memset(&add_char_params, 0, sizeof(add_char_params));
+    add_char_params.uuid                = BLE_DFU_BUTTONLESS_BONDED_CHAR_UUID;
+    add_char_params.uuid_type           = p_dfu->uuid_type;
+    add_char_params.char_props.indicate = 1;
+    add_char_params.char_props.write    = 1;
+    add_char_params.is_defered_write    = true;
+    add_char_params.is_var_len          = true;
+    add_char_params.max_len             = BLE_GATT_ATT_MTU_DEFAULT;
+
+    add_char_params.cccd_write_access = SEC_JUST_WORKS;
+    add_char_params.write_access      = SEC_JUST_WORKS;
+    add_char_params.read_access       = SEC_OPEN;
+
+    return characteristic_add(p_dfu->service_handle, &add_char_params, &p_dfu->control_point_char);
+}
+
+
+void ble_dfu_buttonless_on_ctrl_pt_write(ble_gatts_evt_write_t const * p_evt_write)
+{
+    uint32_t ret;
+    ble_dfu_buttonless_rsp_code_t rsp_code = DFU_RSP_OPERATION_FAILED;
+
+    // Start executing the control point write action
+    switch (p_evt_write->data[0])
+    {
+        case DFU_OP_ENTER_BOOTLOADER:
+            ret = enter_bootloader();
+            if (ret == NRF_SUCCESS)
+            {
+                rsp_code = DFU_RSP_SUCCESS;
+            }
+            else if (ret == NRF_ERROR_BUSY)
+            {
+                rsp_code = DFU_RSP_BUSY;
+            }
+            else if (ret == NRF_ERROR_FORBIDDEN)
+            {
+                rsp_code = DFU_RSP_NOT_BONDED;
+            }
+            break;
+
+        default:
+            rsp_code = DFU_RSP_OP_CODE_NOT_SUPPORTED;
+            break;
+    }
+
+    // Report back in case of error
+    if (rsp_code != DFU_RSP_SUCCESS)
+    {
+        ret = ble_dfu_buttonless_resp_send((ble_dfu_buttonless_op_code_t)p_evt_write->data[0],
+                                            rsp_code);
+
+        if (ret != NRF_SUCCESS)
+        {
+            mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR);
+        }
+
+        // Report the error to the main application
+        mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED);
+    }
+}
+
+
+uint32_t ble_dfu_buttonless_bootloader_start_prepare(void)
+{
+    NRF_LOG_DEBUG("In ble_dfu_buttonless_bootloader_start_prepare");
+
+    // Indicate to main app that DFU mode is starting.
+    // This event can be used to let the device take down any connection to
+    // bonded devices.
+    mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE);
+
+    // Store the number of peers for which Peer Manager is expected to successfully write events.
+    mp_dfu->peers_count = peer_id_n_ids();
+
+    // Set local database changed to get Service Changed indication for all bonded peers
+    // on next bootup (either because of a successful or aborted DFU).
+    gscm_local_database_has_changed();
+
+    return NRF_SUCCESS;
+}
+
+#endif // NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS
+

+ 299 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/ble_dfu/ble_dfu_unbonded.c

@@ -0,0 +1,299 @@
+/**
+ * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ *    Semiconductor ASA integrated circuit in a product or a software update for
+ *    such product, must reproduce the above copyright notice, this list of
+ *    conditions and the following disclaimer in the documentation and/or other
+ *    materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ *    Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ *    engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "nrf_dfu_ble_svci_bond_sharing.h"
+#include "nordic_common.h"
+#include "nrf_error.h"
+#include "ble_dfu.h"
+#include "nrf_log.h"
+#include "nrf_sdh_soc.h"
+
+#if (!NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS)
+
+#define NRF_DFU_ADV_NAME_MAX_LENGTH     (20)
+
+
+void ble_dfu_buttonless_on_sys_evt(uint32_t, void * );
+uint32_t nrf_dfu_svci_vector_table_set(void);
+uint32_t nrf_dfu_svci_vector_table_unset(void);
+
+/**@brief Define functions for async interface to set new advertisement name for DFU mode.  */
+NRF_SVCI_ASYNC_FUNC_DEFINE(NRF_DFU_SVCI_SET_ADV_NAME, nrf_dfu_set_adv_name, nrf_dfu_adv_name_t);
+
+// Register SoC observer for the Buttonless Secure DFU service
+NRF_SDH_SOC_OBSERVER(m_dfu_buttonless_soc_obs, BLE_DFU_SOC_OBSERVER_PRIO, ble_dfu_buttonless_on_sys_evt, NULL);
+
+ble_dfu_buttonless_t      * mp_dfu = NULL;
+static nrf_dfu_adv_name_t   m_adv_name;
+
+
+/**@brief Function for setting an advertisement name.
+ *
+ * @param[in]   adv_name    The new advertisement name.
+ *
+ * @retval NRF_SUCCESS      Advertisement name was successfully set.
+ * @retval DFU_RSP_BUSY     Advertisement name was not set because of an ongoing operation.
+ * @retval Any other errors from the SVCI interface call.
+ */
+static uint32_t set_adv_name(nrf_dfu_adv_name_t * p_adv_name)
+{
+    uint32_t err_code;
+
+    if (mp_dfu->is_waiting_for_svci)
+    {
+        return DFU_RSP_BUSY;
+    }
+
+    err_code = nrf_dfu_set_adv_name(p_adv_name);
+    if (err_code == NRF_SUCCESS)
+    {
+        // The request was accepted.
+        mp_dfu->is_waiting_for_svci = true;
+    }
+    else if (err_code == NRF_ERROR_FORBIDDEN)
+    {
+        NRF_LOG_ERROR("The bootloader has write protected its settings page. This prohibits setting the advertising name. "\
+                      "The bootloader must be compiled with NRF_BL_SETTINGS_PAGE_PROTECT=0 to allow setting the advertising name.");
+    }
+
+    return err_code;
+}
+
+
+/**@brief Function for entering the bootloader.
+ */
+static uint32_t enter_bootloader()
+{
+    uint32_t err_code;
+
+    if (mp_dfu->is_waiting_for_svci)
+    {
+        // We have an ongoing async operation. Entering bootloader mode is not possible at this time.
+        err_code = ble_dfu_buttonless_resp_send(DFU_OP_ENTER_BOOTLOADER, DFU_RSP_BUSY);
+        if (err_code != NRF_SUCCESS)
+        {
+            mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR);
+        }
+        return NRF_SUCCESS;
+    }
+
+    // Set the flag indicating that we expect DFU mode.
+    // This will be handled on acknowledgement of the characteristic indication.
+    mp_dfu->is_waiting_for_reset = true;
+
+    err_code = ble_dfu_buttonless_resp_send(DFU_OP_ENTER_BOOTLOADER, DFU_RSP_SUCCESS);
+    if (err_code != NRF_SUCCESS)
+    {
+        mp_dfu->is_waiting_for_reset = false;
+    }
+
+    return err_code;
+}
+
+
+uint32_t ble_dfu_buttonless_backend_init(ble_dfu_buttonless_t * p_dfu)
+{
+    VERIFY_PARAM_NOT_NULL(p_dfu);
+
+    mp_dfu = p_dfu;
+
+    return NRF_SUCCESS;
+}
+
+
+uint32_t ble_dfu_buttonless_async_svci_init(void)
+{
+    uint32_t ret_val;
+
+    ret_val = nrf_dfu_svci_vector_table_set();
+    VERIFY_SUCCESS(ret_val);
+
+    ret_val = nrf_dfu_set_adv_name_init();
+    VERIFY_SUCCESS(ret_val);
+
+    ret_val = nrf_dfu_svci_vector_table_unset();
+
+    return ret_val;
+}
+
+
+void ble_dfu_buttonless_on_sys_evt(uint32_t sys_evt, void * p_context)
+{
+    uint32_t err_code;
+
+    if (!nrf_dfu_set_adv_name_is_initialized())
+    {
+        return;
+    }
+
+    err_code = nrf_dfu_set_adv_name_on_sys_evt(sys_evt);
+    if (err_code == NRF_ERROR_INVALID_STATE)
+    {
+        // The system event is not from an operation started by buttonless DFU.
+        // No action is taken, and nothing is reported.
+    }
+    else if (err_code == NRF_SUCCESS)
+    {
+        // The async operation is finished.
+        // Set the flag indicating that we are waiting for indication response
+        // to activate the reset.
+        mp_dfu->is_waiting_for_svci = false;
+
+        // Report back the positive response
+        err_code = ble_dfu_buttonless_resp_send(DFU_OP_SET_ADV_NAME, DFU_RSP_SUCCESS);
+        if (err_code != NRF_SUCCESS)
+        {
+            mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR);
+        }
+    }
+    else
+    {
+        // Invalid error code reported back.
+        mp_dfu->is_waiting_for_svci = false;
+
+        err_code = ble_dfu_buttonless_resp_send(DFU_OP_SET_ADV_NAME, DFU_RSP_BUSY);
+        if (err_code != NRF_SUCCESS)
+        {
+            mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR);
+        }
+
+        // Report the failure to enter DFU mode
+        mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED);
+    }
+}
+
+
+uint32_t ble_dfu_buttonless_char_add(ble_dfu_buttonless_t * p_dfu)
+{
+    ble_add_char_params_t add_char_params;
+
+    memset(&add_char_params, 0, sizeof(add_char_params));
+    add_char_params.uuid                = BLE_DFU_BUTTONLESS_CHAR_UUID;
+    add_char_params.uuid_type           = p_dfu->uuid_type;
+    add_char_params.char_props.indicate = 1;
+    add_char_params.char_props.write    = 1;
+    add_char_params.is_defered_write    = true;
+    add_char_params.is_var_len          = true;
+    add_char_params.max_len             = BLE_GATT_ATT_MTU_DEFAULT;
+
+    add_char_params.cccd_write_access = SEC_OPEN;
+    add_char_params.write_access      = SEC_OPEN;
+    add_char_params.read_access       = SEC_OPEN;
+
+    return characteristic_add(p_dfu->service_handle, &add_char_params, &p_dfu->control_point_char);
+}
+
+
+void ble_dfu_buttonless_on_ctrl_pt_write(ble_gatts_evt_write_t const * p_evt_write)
+{
+    uint32_t err_code;
+    ble_dfu_buttonless_rsp_code_t rsp_code = DFU_RSP_OPERATION_FAILED;
+
+    // Start executing the control point write operation
+    /*lint -e415 -e416 -save "Out of bounds access"*/
+    switch (p_evt_write->data[0])
+    {
+        case DFU_OP_ENTER_BOOTLOADER:
+            err_code = enter_bootloader();
+            if (err_code == NRF_SUCCESS)
+            {
+                rsp_code = DFU_RSP_SUCCESS;
+            }
+            else if (err_code == NRF_ERROR_BUSY)
+            {
+                rsp_code = DFU_RSP_BUSY;
+            }
+            break;
+
+        case DFU_OP_SET_ADV_NAME:
+            if(    (p_evt_write->data[1] > NRF_DFU_ADV_NAME_MAX_LENGTH)
+                || (p_evt_write->data[1] == 0))
+            {
+                // New advertisement name too short or too long.
+                rsp_code = DFU_RSP_ADV_NAME_INVALID;
+            }
+            else
+            {
+                memcpy(m_adv_name.name, &p_evt_write->data[2], p_evt_write->data[1]);
+                m_adv_name.len = p_evt_write->data[1];
+                err_code = set_adv_name(&m_adv_name);
+                if (err_code == NRF_SUCCESS)
+                {
+                    rsp_code = DFU_RSP_SUCCESS;
+                }
+            }
+            break;
+
+        default:
+            rsp_code = DFU_RSP_OP_CODE_NOT_SUPPORTED;
+            break;
+    }
+    /*lint -restore*/
+
+
+    // Report back in case of error
+    if (rsp_code != DFU_RSP_SUCCESS)
+    {
+        err_code = ble_dfu_buttonless_resp_send((ble_dfu_buttonless_op_code_t)p_evt_write->data[0], rsp_code);
+        if (err_code != NRF_SUCCESS)
+        {
+            mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR);
+
+        }
+        // Report the error to the main application
+        mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED);
+    }
+}
+
+uint32_t ble_dfu_buttonless_bootloader_start_prepare(void)
+{
+    uint32_t err_code;
+
+    // Indicate to main app that DFU mode is starting.
+    mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE);
+
+    err_code = ble_dfu_buttonless_bootloader_start_finalize();
+    return err_code;
+}
+
+#endif // NRF_DFU_BOTTONLESS_SUPPORT_BOND

+ 256 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_adc.c

@@ -0,0 +1,256 @@
+/*********************************************************************
+ * INCLUDES
+ */
+#include "bsp_adc.h"
+#include "system.h"
+#include "exception.h"
+/*********************************************************************
+ * DEFINITIONS
+ */
+ #define CHANNEL_MAX							8
+ #define PIN_NOT_USED							0xFF
+ #define CHANNEL_NOT_USED					0xFF
+ #define WAIT_TIME_VALUE					3									// 等待超时最大值
+/*********************************************************************
+ * STRUCTION
+ */
+typedef struct {
+	uint32_t pin;
+	uint32_t channel;
+}adc_config_t;
+/*********************************************************************
+ * LOCAL VARIABLES
+ */
+static adc_config_t									m_adc_config[CHANNEL_MAX] 	= {{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED}};
+static nrf_saadc_channel_config_t 	channelConfig[CHANNEL_MAX];
+static nrf_saadc_value_t 						s_bufferPool[CHANNEL_MAX] 	= {0};
+static volatile bool 								adc_SampleOk 								= true;		// adc采集完成标志
+//定义SAADC采样数据缓存
+//定义SAADC采样缓存数组大小
+//只有采样结果存满该缓存之后,才会产生SAADC采样完成事件
+static uint32_t 										sample_in_buffer 						= 0;
+/*********************************************************************
+ * LOCAL FUNCTIONS
+ */
+/**
+ @brief ADC中断处理回调函数
+ @param 无
+ @return 无
+*/
+static void adcCallbackFunc(nrf_drv_saadc_evt_t const *pEvent)
+{
+	ret_code_t err_code;
+	if(pEvent->type == NRF_DRV_SAADC_EVT_DONE)	// 采样完成,采集时填充顺序为,通道编号小的先填充。
+	{
+		//设置好缓存,为下一次采样做准备
+		err_code=nrf_drv_saadc_buffer_convert(pEvent->data.done.p_buffer,sample_in_buffer);
+		if(err_code == NRF_SUCCESS)
+		{
+			adc_SampleOk = true;
+		}
+	}
+}
+
+static void bsp_adc_init_process(void)
+{
+	if(Except_TxError(EXCEPT_ADC_INIT,"bsp_adc_init_error\r\n") == 0)
+	{
+		Process_Stop(bsp_adc_init_process);
+	}
+}
+
+/**
+	@brief	初始化ADC
+	@param	无
+	@return 无
+*/
+static void ADC_Init(void)
+{
+	int 				ret = 0;
+	ret_code_t 	errCode;
+	
+	nrf_drv_saadc_config_t p_config = NRFX_SAADC_DEFAULT_CONFIG;
+	p_config.interrupt_priority = ADC_IRQ_PRIORITY;
+	
+	
+	// ADC初始化
+	errCode = nrf_drv_saadc_init(&p_config, adcCallbackFunc);//优先级设置为3,比定时器中断要高,不然回调会在定时器中断结束后触发。
+	if(errCode != NRF_SUCCESS)ret = -1;
+
+	// ADC通道配置
+	for(int i=0;i<CHANNEL_MAX;i++)
+	{
+		if(m_adc_config[i].pin != PIN_NOT_USED && m_adc_config[i].channel != CHANNEL_NOT_USED)
+		{
+			//设置ADC引脚为浮空
+			nrf_gpio_cfg_input(m_adc_config[i].pin,NRF_GPIO_PIN_NOPULL);
+			// 单端输入
+			channelConfig[m_adc_config[i].channel].resistor_p = NRF_SAADC_RESISTOR_DISABLED;
+			channelConfig[m_adc_config[i].channel].resistor_n = NRF_SAADC_RESISTOR_DISABLED;
+			channelConfig[m_adc_config[i].channel].gain       = NRF_SAADC_GAIN1_6;
+			channelConfig[m_adc_config[i].channel].reference  = NRF_SAADC_REFERENCE_INTERNAL;
+			channelConfig[m_adc_config[i].channel].acq_time   = NRF_SAADC_ACQTIME_10US;
+			channelConfig[m_adc_config[i].channel].mode       = NRF_SAADC_MODE_SINGLE_ENDED;
+			channelConfig[m_adc_config[i].channel].burst      = NRF_SAADC_BURST_DISABLED;
+			channelConfig[m_adc_config[i].channel].pin_p      = (nrf_saadc_input_t)(m_adc_config[i].channel + 1);
+			channelConfig[m_adc_config[i].channel].pin_n      = NRF_SAADC_INPUT_DISABLED;
+			// ADC通道初始化
+			errCode = nrf_drv_saadc_channel_init(m_adc_config[i].channel, &channelConfig[m_adc_config[i].channel]);
+			if(errCode != NRF_SUCCESS)ret = -1;
+			sample_in_buffer++;
+		}
+	}
+	if(sample_in_buffer > 0)
+	{
+		// 缓冲配置
+		errCode = nrf_drv_saadc_buffer_convert(s_bufferPool, sample_in_buffer);
+		if(errCode != NRF_SUCCESS)ret = -1;
+	}
+	
+	
+	if(ret == -1)
+	{
+		Process_Start(0,"bsp_adc_init_process",bsp_adc_init_process);
+	}
+}
+static void cb_adcWakeup(uint32_t t)
+{
+	ADC_Enable(); 
+}
+
+static void cb_adcSleep(uint32_t t)
+{
+	ADC_Disable();
+}
+
+/*********************************************************************
+ * PUBLIC FUNCTIONS
+ */
+/**
+	@brief	初始化ADC引脚和通道
+	@param	pin -[in]	需要初始化的adc引脚
+	@param	channel -[in]	需要初始化的adc通道
+	@return 错误代码
+*/
+uint32_t ADC_SetPinChannel(uint32_t pin, uint32_t channel)
+{
+	for(int i=0;i<CHANNEL_MAX;i++)
+	{
+		if(m_adc_config[i].pin == pin)return ADC_ERR_INIT_PIN;
+		if(m_adc_config[i].channel == channel)return ADC_ERR_INIT_CHANNEL;
+		if(PIN_NOT_USED != pin && m_adc_config[i].pin == PIN_NOT_USED)
+		{
+			m_adc_config[i].pin = pin;
+			m_adc_config[i].channel = channel;
+			return ADC_OP_SUCCESS;
+		}
+	}
+	return ADC_ERR_INIT_CONGESTION;
+}
+/**
+	@brief	移除已初始化ADC引脚和通道
+	@param	pin -[in]	需要移除的adc引脚
+	@param	channel -[in]	需要移除的adc通道
+	@return 错误代码
+*/
+uint32_t ADC_RemovePinChannel(uint32_t pin, uint32_t channel)
+{
+	for(int i=0;i<CHANNEL_MAX;i++)
+	{
+		if(m_adc_config[i].pin == pin && m_adc_config[i].channel == channel)
+		{
+			m_adc_config[i].pin = PIN_NOT_USED;
+			m_adc_config[i].channel = CHANNEL_NOT_USED;
+			return ADC_OP_SUCCESS;
+		}
+	}
+	return ADC_ERR_REMOVE_PIN_CHANNEL;
+}
+/**
+	@brief ADC初始化
+	@param 无
+	@return 无
+*/
+void ADC_Initialize(void)
+{
+	ADC_SetPinChannel(PIN_ADC_BAT_IN, PIN_ADC_BAT_CHANNEL);
+	ADC_SetPinChannel(PIN_ADC_CHARGMEASURE, PIN_ADC_CHARGMEASURE_CHANNEL);
+	ADC_Init();
+	Wakeup_Regist(cb_adcWakeup);
+	Sleep_Regist(cb_adcSleep);
+}
+/**
+	@brief ADC读取
+	@param channel -[in] 需要读取的通道
+	@param p_adc_value -[out] 返回读取的通道值
+	@return 错误代码
+*/
+uint32_t ADC_Read(uint32_t channel, int16_t *p_adc_value)
+{
+	uint32_t errCode;
+	uint32_t wait_time_out = WAIT_TIME_VALUE;
+	uint8_t  adc_sort[CHANNEL_MAX] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+	uint8_t  sort_index = 0;
+	int  		 i;
+	adc_SampleOk = false;
+	
+	//没有配置通道返回失败
+	if(sample_in_buffer == 0)return ADC_ERR_READ_NO_CHANNEL;
+	
+	errCode = nrf_drv_saadc_sample();
+	if(errCode != NRF_SUCCESS)return ADC_ERR_READ_FAIL;
+	
+	//等待采集
+	while(!adc_SampleOk)
+	{
+		if(wait_time_out--){
+			nrf_pwr_mgmt_run();
+		}
+		else{
+			return ADC_ERR_READ_TIMEOUT;
+		}
+	}
+	//预先排序,采集时填充顺序为,通道编号小的先填充。
+	for(i=0;i<CHANNEL_MAX;i++)
+	{
+		if(channelConfig[i].pin_p != NRF_SAADC_INPUT_DISABLED){
+			adc_sort[sort_index] = i;
+			sort_index++;
+		}
+	}
+	//获取数据
+	for(i=0;i<sample_in_buffer;i++)
+	{
+		if(adc_sort[i] == channel)
+		{
+			*p_adc_value = s_bufferPool[i];
+		}
+	}
+
+	return ADC_OP_SUCCESS;
+}
+/**
+ @brief 开启ADC,与初始化没有区别,为了与Disable成对出现
+ @param 无
+ @return 无
+*/
+void ADC_Enable(void)
+{
+	ADC_Init();
+}
+/**
+ @brief 禁用ADC
+ @param 无
+ @return 无
+*/
+void ADC_Disable(void)
+{
+	nrf_drv_saadc_uninit();
+	sample_in_buffer = 0;
+}
+
+
+
+
+
+

+ 60 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_adc.h

@@ -0,0 +1,60 @@
+#ifndef	__BSP_ADC_H__
+#define __BSP_ADC_H__
+/*********************************************************************
+ * INCLUDES
+ */
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+#include "nrf_gpio.h"
+#include "nrf_pwr_mgmt.h"
+#include "nrf_drv_saadc.h"
+/*********************************************************************
+ * DEFINITIONS
+ */
+//ERROR CODE
+#define ADC_OP_SUCCESS										0x00													//adc操作成功
+#define ADC_ERR_INIT_PIN									0x01													//该引脚已初始化
+#define ADC_ERR_INIT_CHANNEL							0x02													//该通道已初始化
+#define ADC_ERR_INIT_CONGESTION						0x03													//有效通道已全部初始化
+#define ADC_ERR_REMOVE_PIN_CHANNEL				0x04													//移除通道和引脚失败
+#define ADC_ERR_READ_NO_CHANNEL						0x05													//无配置通道,读取失败
+#define ADC_ERR_READ_TIMEOUT							0x06													//读取adc超时
+#define ADC_ERR_READ_FAIL									0x07													//读取adc失败
+/*********************************************************************
+ * API
+ */
+ 
+//初始化ADC引脚和通道
+uint32_t ADC_SetPinChannel(uint32_t pin, uint32_t channel);
+//移除已初始化ADC引脚和通道
+uint32_t ADC_RemovePinChannel(uint32_t pin, uint32_t channel);
+//ADC初始化
+void ADC_Initialize(void);
+//ADC读取
+uint32_t ADC_Read(uint32_t channel, int16_t *p_adc_value);
+//开启ADC,与初始化没有区别,为了与Disable成对出现
+void ADC_Enable(void);
+//禁用ADC
+void ADC_Disable(void);
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 190 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_esb.c

@@ -0,0 +1,190 @@
+/********************** 头文件 *************************/
+#include "bsp_esb.h"
+#include "nrf_esb.h"
+#include "nrf_error.h"
+#include "nrf_esb_error_codes.h"
+#include "hal_imu.h"
+
+/********************** 变量区 *************************/
+static nrf_esb_payload_t        tx_payload = NRF_ESB_CREATE_PAYLOAD(0, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00);
+static nrf_esb_payload_t        rx_payload;
+
+/********************** 环形缓存区 *************************/
+static const int  RxLen = 1024;
+static volatile unsigned char RxBuf[RxLen];
+static volatile unsigned char* RxW=RxBuf;
+static volatile unsigned char* RxR=RxBuf;
+
+void ESB_Push(unsigned char* p,int len)
+{
+	volatile unsigned char *W=RxW; //这里要与上面指针相同
+	if(len<=0) return;
+	for(int i=0;i<len;i++){
+		W=RxW+1; if(W>=RxBuf+RxLen) W=RxBuf;        //取下一位置(到顶转到底)
+		if(W!=RxR){*RxW=*(p+i); RxW=W;}
+		else break;
+	}
+}
+
+unsigned int ESB_CheckLen(void) //检查RX接收了多少数据
+{   
+	unsigned int Len; //short 
+	volatile unsigned char *W=RxW; volatile unsigned char *R=RxR; 
+	if(W>=R)Len=W-R;else Len=(W+RxLen)-R;         //这样正确(中途中断改变也变不了结果)
+    return Len; 
+}
+
+unsigned char ESB_ReadByte(void)   //读RX中数锯,地指加一,和丢弃
+{	
+	unsigned char R=*RxR;       //读数
+	if(RxR!=RxW){	if(RxR+1>=(RxBuf+RxLen))RxR =RxBuf; else RxR++;}//下标
+	return R; 
+}
+
+unsigned char ESB_CheckByte(unsigned short n) //看RX中数锯,地指不变, 
+{  	
+	volatile unsigned char *R=RxR+n; 
+	if(R>=(RxBuf+RxLen))R-=RxLen; 
+	return *R; 
+}	
+
+void ESB_Discard(unsigned short n) //丢弃RX数据几位  
+{	
+	while(n){ n--;  
+		if(RxR==RxW) return; 
+		if(RxR+1>=RxBuf+RxLen){RxR=RxBuf;} else RxR++; //下标 
+	}	
+}
+//static void Radio_State(void)
+//{
+//        switch(NRF_RADIO->STATE)
+//        {
+//                case RADIO_STATE_STATE_Disabled:
+//                        SEGGER_RTT_printf(0,"RADIO_STATE_STATE_Disabled\n");
+//                        break;
+//                case RADIO_STATE_STATE_RxRu:
+//                        SEGGER_RTT_printf(0,"RADIO_STATE_STATE_RxRu\n");
+//                        break;
+//                case RADIO_STATE_STATE_RxIdle:
+//                        SEGGER_RTT_printf(0,"RADIO_STATE_STATE_RxIdle\n");
+//                        break;
+//                case RADIO_STATE_STATE_Rx:
+//                        SEGGER_RTT_printf(0,"RADIO_STATE_STATE_Rx\n");
+//                        break;
+//                case RADIO_STATE_STATE_RxDisable:
+//                        SEGGER_RTT_printf(0,"RADIO_STATE_STATE_RxDisable\n");
+//                        break;
+//                case RADIO_STATE_STATE_TxRu:
+//                        SEGGER_RTT_printf(0,"RADIO_STATE_STATE_TxRu\n");
+//                        break;
+//                case RADIO_STATE_STATE_TxIdle:
+//                        SEGGER_RTT_printf(0,"RADIO_STATE_STATE_TxIdle\n");
+//                        break;
+//                case RADIO_STATE_STATE_Tx:
+//                        SEGGER_RTT_printf(0,"RADIO_STATE_STATE_Tx\n");
+//                        break;
+//                case RADIO_STATE_STATE_TxDisable:
+//                        SEGGER_RTT_printf(0,"RADIO_STATE_STATE_TxDisable\n");
+//                        break;
+//        }
+//}
+
+#define ESB_COMMAND_LENGTH_MAX  200
+void ESB_SendBuff(unsigned char *p,int L)//发送缓存
+{
+	uint8_t i;
+	if(L>ESB_COMMAND_LENGTH_MAX) return;
+	
+	
+//	
+	(void) nrf_esb_stop_rx();
+	
+//	Radio_State();
+	
+	for(i=0;i<L;i++){
+		tx_payload.data[i] = p[i];
+	}
+	tx_payload.noack = false;
+	tx_payload.length = L;
+	nrf_esb_write_payload(&tx_payload);
+}
+
+//*****************************************************************//
+
+/********************** 函数声明区 *************************/
+void nrf_esb_event_handler(nrf_esb_evt_t const * p_event)
+{
+    switch (p_event->evt_id)
+    {
+        case NRF_ESB_EVENT_TX_SUCCESS:
+//			SEGGER_RTT_printf(0,"NRF_ESB_EVENT_TX_SUCCESS\n");
+			(void) nrf_esb_flush_tx();
+            (void) nrf_esb_start_rx();
+            break;
+        case NRF_ESB_EVENT_TX_FAILED:
+//			SEGGER_RTT_printf(0,"NRF_ESB_EVENT_TX_FAILED\n");
+            (void) nrf_esb_flush_tx();
+            (void) nrf_esb_start_rx();
+            break;
+        case NRF_ESB_EVENT_RX_RECEIVED:
+//			SEGGER_RTT_printf(0,"NRF_ESB_EVENT_RX_RECEIVED\n");
+            while (nrf_esb_read_rx_payload(&rx_payload) == NRF_SUCCESS){
+                if(rx_payload.length > 0){
+					#if DEBUG_ESB_INT
+					SEGGER_RTT_printf(0,"INT_ESB:"); for(int i=0;i<rx_payload.length;i++){SEGGER_RTT_printf(0,"%02X ",rx_payload.data[i]);} SEGGER_RTT_printf(0,"\r\n");
+					#endif
+					
+					IMU_SetRssi(rx_payload.rssi);
+					if(rx_payload.data[0]==0xAA && rx_payload.data[1]==(uint8_t)(~rx_payload.data[2])){
+						if(rx_payload.data[3]==0){ //IMU data		
+							IMU_SetSlaveData(rx_payload.data,rx_payload.length);
+						}else
+						ESB_Push(rx_payload.data,rx_payload.length);
+					}
+                }
+            }
+            break;
+    }
+}
+
+#define  ADDR ESB_ADDR
+
+uint32_t ESB_Init(void)
+{
+    uint32_t err_code;
+    uint8_t base_addr_0[4] = {0x01, 0x01, ADDR, ADDR};
+    uint8_t base_addr_1[4] = {0x01, 0x01, ADDR, ADDR};
+    uint8_t addr_prefix[8] = {0x01, 0x01, 0x01, 0x01, ADDR, ADDR, ADDR, ADDR };
+
+    nrf_esb_config_t nrf_esb_config         = NRF_ESB_DEFAULT_CONFIG;
+//    nrf_esb_config.protocol                 = NRF_ESB_PROTOCOL_ESB_DPL;
+	nrf_esb_config.payload_length           = 250;
+//    nrf_esb_config.retransmit_delay         = 600;
+//	nrf_esb_config.payload_length           = ESB_COMMAND_LENGTH_MAX;
+    nrf_esb_config.bitrate                  = NRF_ESB_BITRATE_2MBPS;
+    nrf_esb_config.event_handler            = nrf_esb_event_handler;
+    nrf_esb_config.mode                     = NRF_ESB_MODE_PTX;
+    nrf_esb_config.selective_auto_ack       = false;
+
+    err_code = nrf_esb_init(&nrf_esb_config);
+
+    VERIFY_SUCCESS(err_code);
+
+    err_code = nrf_esb_set_base_address_0(base_addr_0);
+    VERIFY_SUCCESS(err_code);
+
+    err_code = nrf_esb_set_base_address_1(base_addr_1);
+    VERIFY_SUCCESS(err_code);
+
+    err_code = nrf_esb_set_prefixes(addr_prefix, NRF_ESB_PIPE_COUNT);
+    VERIFY_SUCCESS(err_code);
+	
+	(void) nrf_esb_flush_tx();
+	(void) nrf_esb_start_rx();
+//	uint8_t temp = 0;
+//	ESB_SendBuff(&temp,1);
+	
+    return err_code;
+}
+
+

+ 20 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_esb.h

@@ -0,0 +1,20 @@
+#ifndef __bsp_esb_h__
+#define __bsp_esb_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+uint32_t ESB_Init(void);
+//void ESB_SendStr(char *p);//发送字符串
+void ESB_SendBuff(unsigned char *p,int L);//发送缓存
+//void ESB_SendChar(unsigned char ch);//发送一位数锯
+void ESB_Discard(unsigned short n); //丢弃RX数据几位  
+unsigned char ESB_CheckByte(unsigned short n); //看RX中数锯,地指不变, 
+unsigned char ESB_ReadByte(void);   //读RX中数锯,地指加一,和丢弃
+unsigned int ESB_CheckLen(void); //检查RX接收了多少数据
+void ESB_Test(void);
+
+#endif

+ 523 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_flash.c

@@ -0,0 +1,523 @@
+
+//flash 1.0V
+
+/*********************************************************************
+ * INCLUDES
+ */
+#include "bsp_flash.h"
+#include "exception.h"
+#include "system.h"
+
+/*********************************************************************
+ * LOCAL FUNCTIONS DEF
+ */
+static void fstorageCallbackFunc(nrf_fstorage_evt_t *pFstorageEvent);
+static uint32_t getflashEndAddress(void);
+static void waitForFlashReady(nrf_fstorage_t const *pFstorageHandle);
+
+/*********************************************************************
+ * LOCAL VARIABLES
+ */
+NRF_FSTORAGE_DEF(nrf_fstorage_t s_fstorageHandle) =
+{
+    /* Set a handler for fstorage events. */
+    .evt_handler = fstorageCallbackFunc,
+
+    /* These below are the boundaries of the flash space assigned to this instance of fstorage.
+     * You must set these manually, even at runtime, before nrf_fstorage_init() is called.
+     * The function nrf5_flash_end_addr_get() can be used to retrieve the last address on the
+     * last page of flash available to write data. */
+    .start_addr = START_FSTORAGE_ADDR,
+    .end_addr   = END_FSTORAGE_ADDR,
+};
+
+/*********************************************************************
+ * LOCAL FUNCTIONS
+ */
+/**
+ @brief Fstorage读写内存操作
+ @param flashAddr -[in] 闪存地址
+ @param readWriteFlag -[in] 读写操作标志
+ @param pData -[in&out] 指向需要操作的数据
+ @param dataLen -[in] 数据长度
+ @return 错误代码
+*/
+static uint32_t Fstorage_FlashRW(uint32_t flashAddr, uint8_t readWriteFlag, uint32_t *pData, uint32_t dataLen)
+{
+	ret_code_t errCode;
+	
+	if(flashAddr%4 != 0 || flashAddr == 0)return FLASH_ERROR_ADDRALIGN;
+	if((flashAddr + dataLen) > END_FSTORAGE_ADDR){
+		return FLASH_ERROR_ADDROVERBOUNDS;	//是否越界
+	}
+	
+	if(readWriteFlag == FSTORAGE_READ)                       							// 读取数据
+	{
+		errCode = nrf_fstorage_read(&s_fstorageHandle, flashAddr, pData, dataLen);
+		if(errCode != NRF_SUCCESS)return FLASH_ERROR_READ;
+	}
+	else 																				// 写入数据
+	{
+		if(dataLen %4 != 0 || dataLen == 0)return FLASH_ERROR_DATAALIGN;
+		if( FLASH_ZONEADDR_CHECK(flashAddr) )return FLASH_ERROR_ZONEADDR;
+		
+		errCode = nrf_fstorage_erase(&s_fstorageHandle, flashAddr, 1, NULL);			// 只能写入位值1,不能写入位值0,所以先擦后写	
+		if(errCode != NRF_SUCCESS)return FLASH_ERROR_ERASE;
+		errCode = nrf_fstorage_write(&s_fstorageHandle, flashAddr, pData, dataLen, NULL);
+		if(errCode != NRF_SUCCESS)return FLASH_ERROR_WRITE;
+	
+		waitForFlashReady(&s_fstorageHandle);											// 等待写完
+	}
+	
+	return FLASH_OP_SUCCESS;
+}
+
+/**
+@brief	Fstorage写内存操作,调用前FLASH预先已擦除
+@param flashAddr -[in] 闪存地址
+@param pData -[in&out] 指向需要操作的数据
+@param dataLen -[in] 数据长度
+@param is_check - [in] 是否检测数据存不存在
+@return 0:写入成功  1:4字节不对齐  2:已有数据存在  3:访问越界
+*/
+static uint32_t Fstorage_FlashOnlyWrite(uint32_t flashAddr, uint32_t *pData, uint32_t dataLen, bool is_check)
+{
+	ret_code_t errCode;
+	uint32_t check,i,len;
+	
+	if(flashAddr%4 != 0 || flashAddr == 0)return FLASH_ERROR_ADDRALIGN;
+	if(dataLen %4 != 0 || dataLen == 0)return FLASH_ERROR_DATAALIGN;
+	if((flashAddr + dataLen) > END_FSTORAGE_ADDR){
+		return FLASH_ERROR_ADDROVERBOUNDS;
+	}
+	
+	if(is_check)
+	{
+		len = dataLen / 4;
+		for(i=0;i<len;i++)
+		{
+			memcpy(&check, (uint32_t*)flashAddr + i, 4);
+			if(check != 0xFFFFFFFF)return FLASH_ERROR_DATAEXIST;
+		}
+	}
+
+	errCode = nrf_fstorage_write(&s_fstorageHandle, flashAddr, pData, dataLen, NULL);
+	if(errCode != NRF_SUCCESS)return FLASH_ERROR_WRITE;
+	
+	waitForFlashReady(&s_fstorageHandle);											// 等待写完
+	
+	return FLASH_OP_SUCCESS;
+}
+
+/**
+ @brief Fstorage擦除一整页
+ @param 要擦除的页的首地址
+ @return 错误代码
+*/
+static uint32_t Fstorage_FlashOnlyErasePage(uint32_t zone_addr)
+{
+	
+	ret_code_t errCode;
+	
+	if(zone_addr%4 != 0 || zone_addr == 0)return FLASH_ERROR_ADDRALIGN;
+	if( FLASH_ZONEADDR_CHECK(zone_addr) )return FLASH_ERROR_ZONEADDR;
+	
+	errCode = nrf_fstorage_erase(&s_fstorageHandle, zone_addr, 1, NULL);			// 只能写入位值1,不能写入位值0,所以先擦后写		
+	if(errCode != NRF_SUCCESS)return FLASH_ERROR_ERASE;
+	
+	waitForFlashReady(&s_fstorageHandle);
+	
+	return FLASH_OP_SUCCESS;
+}
+
+
+/*********************************************************************
+ * LOCAL FUNCTIONS
+ */
+/**
+ @brief Fstorage事件回调函数
+ @param pFstorageEvent -[in] Fstorage事件
+ @return 无
+*/
+static void fstorageCallbackFunc(nrf_fstorage_evt_t *pFstorageEvent)
+{
+    if(pFstorageEvent->result != NRF_SUCCESS)
+    {
+        SEGGER_RTT_printf(0,"--> Event received: ERROR while executing an fstorage operation.\n");
+        return ;
+    }
+
+    switch(pFstorageEvent->id)
+    {
+	case NRF_FSTORAGE_EVT_WRITE_RESULT:
+		//SEGGER_RTT_printf(0,"--> Event received: wrote %d bytes at address 0x%x.\n", pFstorageEvent->len, pFstorageEvent->addr);
+		break;
+
+	case NRF_FSTORAGE_EVT_ERASE_RESULT:
+		//SEGGER_RTT_printf(0,"--> Event received: erased %d page from address 0x%x.\n", pFstorageEvent->len, pFstorageEvent->addr);
+		break;
+
+	default:
+		break;
+	}
+}
+
+/**
+ @brief 检索Flash上可用于写入数据的地址
+ @param 无
+ @return 无
+*/
+static uint32_t getflashEndAddress(void)
+{
+	uint32_t const bootloaderAddr = NRF_UICR->NRFFW[0];
+	uint32_t const pageSz         = NRF_FICR->CODEPAGESIZE;
+	uint32_t const codeSz         = NRF_FICR->CODESIZE;
+
+  return (bootloaderAddr != 0xFFFFFFFF ? bootloaderAddr : (codeSz * pageSz));
+}
+
+/**
+ @brief 等待写入完成
+ @param pFstorageHandle -[in] Fstorage句柄
+ @return 无
+*/
+static void waitForFlashReady(nrf_fstorage_t const *pFstorageHandle)
+{
+    while(nrf_fstorage_is_busy(pFstorageHandle))										// While fstorage is busy, sleep and wait for an event.
+    {
+       nrf_pwr_mgmt_run();
+    }
+}
+
+/**
+ @brief 从flash中连续读取N个4字节数据
+ @param addr-[in] 读取的首地址
+ @param pData -[in&out] 指向需要操作的数据
+ @param dataLen -[in] 数据长度
+ @return 错误代码
+*/
+static uint32_t Read_N_4Byte_flash(uint32_t addr , uint32_t *pData, uint32_t dataLen)
+{
+	return Fstorage_FlashRW(addr, FSTORAGE_READ, pData, dataLen);
+}
+
+/**
+ @brief 获取页号所在的首地址
+ @param PageNum-[in] 需要查找的页号
+ @param PageAddr-[in/out] 返回的页号首地址
+ @return 错误代码
+*/
+static uint32_t GetPageAddr(uint16_t PageNum, uint32_t *PageAddr)
+{
+	if(PageNum >= FLASH_PAGE_NUM)return FLASH_ERROR_PAGENUM;
+	
+	*PageAddr = FLASH_ZONE_ADDR_1 + PageNum * FLASH_PAGE_SIZE;
+	
+	return FLASH_OP_SUCCESS;
+}
+
+/**
+ @brief 获取页号所在的尾地址(该页号下一页的首地址)
+ @param PageNum-[in] 需要查找的页号
+ @param PageAddr-[in/out] 返回的页号首地址
+ @return 错误代码
+*/
+static uint32_t GetPageEndAddr(uint16_t PageNum, uint32_t *PageAddr)
+{
+	if(PageNum >= FLASH_PAGE_NUM)return FLASH_ERROR_PAGENUM;
+	
+	*PageAddr = FLASH_ZONE_ADDR_1 + (PageNum+1) * FLASH_PAGE_SIZE;
+	
+	return FLASH_OP_SUCCESS;
+}
+
+
+/**
+ @brief 获取地址距离所在页的偏移量
+ @param addr-[in] 需要查找的flash地址
+ @param _offset-[in/out] 返回的偏移量
+ @return 错误代码
+*/
+static uint32_t GetDistanceFromPage(uint32_t addr, uint32_t *_offset)
+{
+	
+	if(addr %4 != 0 || addr == 0)return FLASH_ERROR_ADDRALIGN;
+	if(addr > END_FSTORAGE_ADDR || addr < START_FSTORAGE_ADDR){
+		return FLASH_ERROR_ADDROVERBOUNDS;	//是否越界
+	}
+	
+		//获取偏移量
+	*_offset = ((addr - START_FSTORAGE_ADDR)%FLASH_PAGE_SIZE)/4;
+	
+	return FLASH_OP_SUCCESS;
+}
+
+/**
+ @brief 判断是否需要擦除
+ @param start_addr-[in] flash首地址
+ @param len -[in] 长度
+ @param is_erase-[in/out] 1:需要擦除,0:不需要擦除
+ @return 错误代码
+*/
+static uint32_t __NeedErase(uint32_t start_addr , uint32_t len , uint8_t *is_erase)
+{
+	uint32_t err_code;
+	uint32_t i = 0, data;
+	
+	if((start_addr + len) > END_FSTORAGE_ADDR)return FLASH_ERROR_ADDROVERBOUNDS;	
+	if(start_addr%4 != 0 || start_addr == 0)return FLASH_ERROR_ADDRALIGN;
+	if(len %4 != 0 || len == 0)return FLASH_ERROR_DATAALIGN;
+
+	len /=4;
+	for(;i<len;i++)
+	{
+		err_code = Fstorage_FlashRW(start_addr, FSTORAGE_READ, &data, 4);
+		if(err_code != FLASH_OP_SUCCESS)return err_code;
+		
+		if(data != 0xFFFFFFFF)break;
+		start_addr += 4;
+	}
+	
+	*is_erase = (i==len)?0:1;
+	
+	return FLASH_OP_SUCCESS;
+}
+
+static void bsp_flash_init_process(void)
+{
+	if(Except_TxError(EXCEPT_FLASH_INIT,"bsp_flash_init_error\r\n") == 0)
+	{
+		Process_Stop(bsp_flash_init_process);
+	}
+}
+
+/****************************************************接口****************************************************/
+
+/**
+ @brief Fstorage读写内存初始化
+ @param 无
+ @return 无
+*/
+void Fstorage_FlashInit(void)
+{
+	int 				ret = 0;
+	ret_code_t 	errCode;
+
+	nrf_fstorage_api_t *pFstorageApi;
+	pFstorageApi = &nrf_fstorage_sd;
+	
+	errCode = nrf_fstorage_init(&s_fstorageHandle, pFstorageApi, NULL);					// Flash处理的开始地址和结束地址初始化
+	if(errCode != NRF_SUCCESS)ret = -1;
+	
+	(void)getflashEndAddress();															// 获取地址,判断为可写地址大小
+	
+	if(ret == -1)
+	{
+		Process_Start(0,"bsp_flash_init_process",bsp_flash_init_process);
+	}
+}
+
+/**
+ @brief 从flash中连续读取N个字节数据
+ @param addr-[in] 读取的首地址
+ @param pData -[in&out] 指向需要操作的数据
+ @param dataLen -[in] 数据长度
+ @return 错误代码
+*/
+uint32_t Read_N_Byte_flash(uint32_t addr , uint32_t *pData, uint32_t dataLen)
+{
+	if(addr > END_FSTORAGE_ADDR || addr < START_FSTORAGE_ADDR){
+		return FLASH_ERROR_ADDROVERBOUNDS;	//是否越界
+	}
+	
+	memcpy(pData, (uint32_t*)addr, dataLen);
+	
+	return FLASH_OP_SUCCESS;
+}
+
+/**
+ @brief 获取flash地址所在的页号
+ @param addr-[in] 需要查找的flash地址
+ @param page_num-[in/out] 返回的页号
+ @return 错误代码
+*/
+uint32_t GetPageNum(uint32_t addr, uint16_t *PageNum)
+{
+	uint16_t page_num = 0;
+	
+	if(addr > END_FSTORAGE_ADDR || addr < START_FSTORAGE_ADDR){
+		return FLASH_ERROR_ADDROVERBOUNDS;	//是否越界
+	}
+	
+//	if(addr %4 != 0 || addr == 0)return FLASH_ERROR_ADDRALIGN;
+	
+	page_num = (addr - START_FSTORAGE_ADDR)/FLASH_PAGE_SIZE;
+	if(page_num >= FLASH_PAGE_NUM)return FLASH_ERROR_PAGENUM;
+	
+	*PageNum = page_num;
+	
+	return FLASH_OP_SUCCESS;
+}
+
+/**
+ @brief 擦除1页
+ @param PageNum-[in] 页号
+ @return 错误代码
+*/
+uint32_t Erase_OnePage(uint16_t PageNum)
+{
+	uint32_t PageAddr;
+	uint32_t err_code;
+	
+	err_code = GetPageAddr(PageNum, &PageAddr);
+	if(err_code != FLASH_OP_SUCCESS)return err_code;
+	
+	return Fstorage_FlashOnlyErasePage(PageAddr);
+}
+
+/**
+ @brief 写N个字到flash中
+ @param addr-[in] 写入的flash首地址
+ @param pdata-[in] 需要写入的数据
+ @param len-[in] 数据长度 
+ @return 错误代码
+*/
+uint32_t Write_N_4Byte_flash(uint32_t addr , uint32_t *pdata, uint32_t len)
+{
+	uint8_t  is_erase;				//判断是否要擦除
+	uint16_t start_page = 0;	//起始页号
+	uint32_t page_size = 0;		//需要操作页的大小
+	uint32_t _offset = 0;			//页操作页码的起始地址
+	uint32_t page_offset = 0; //页偏移
+	uint32_t data_offset = 0; //数据偏移
+	uint32_t remain_size = 0;	//本次操作页可以使用的剩余大小
+	uint32_t base_addr = 0;		//本次操作页的基地址
+	uint32_t surplus = 0;			//总的剩余的字节
+	uint32_t err_code;				//错误代码
+	uint32_t flash_PageBuff[PAGE_INT_SIZE];	//页缓冲区
+	
+	//是否越界
+	if((addr + len) > END_FSTORAGE_ADDR){
+		return FLASH_ERROR_ADDROVERBOUNDS;	
+	}
+	//获取起始页号
+	err_code = GetPageNum(addr, &start_page);
+	if(err_code != FLASH_OP_SUCCESS)return err_code;
+	//获取偏移量
+	err_code = GetDistanceFromPage(addr,&_offset);
+	if(err_code != FLASH_OP_SUCCESS)return err_code;
+	//计算需要写入的页数
+	if(((PAGE_INT_SIZE - _offset)*4) >= len)
+	{
+		page_size = 1;
+		surplus = 0;
+	}
+	else
+	{
+		page_size = 1;
+		surplus = len - ((PAGE_INT_SIZE - _offset)*4);
+		page_size += ((surplus/FLASH_PAGE_SIZE) + (surplus%FLASH_PAGE_SIZE>0?1:0));
+	}
+	//每页写入
+	surplus = len;
+	for(page_offset = 0; page_offset < page_size; page_offset++)
+	{
+		
+		//获取页首地址
+		err_code = GetPageAddr(start_page + page_offset, &base_addr);
+		if(err_code != FLASH_OP_SUCCESS)return err_code;
+		
+		if(page_offset == 0)
+		{
+			//第一次偏移根据目的地址来确定
+			remain_size = (PAGE_INT_SIZE - _offset)*4<surplus ? (PAGE_INT_SIZE - _offset)*4:surplus;
+			surplus = len - remain_size;
+		}
+		else
+		{
+			//后面操作的偏移都是从首地址开始
+			_offset = 0;
+			remain_size = surplus > FLASH_PAGE_SIZE ? FLASH_PAGE_SIZE : surplus;
+			surplus = surplus - remain_size;
+		}
+		
+		//判断是否要擦除
+		err_code = __NeedErase(base_addr + _offset*4 , remain_size, &is_erase);
+		if(err_code != FLASH_OP_SUCCESS)return err_code;
+		
+		
+		//先擦除后写
+		if(is_erase)
+		{
+			//读取
+			err_code = Read_N_4Byte_flash(base_addr , flash_PageBuff, FLASH_PAGE_SIZE);
+			if(err_code != FLASH_OP_SUCCESS)return err_code;
+			//修改
+			memcpy(&flash_PageBuff[_offset], pdata + data_offset, remain_size);
+			//写回
+			err_code = Fstorage_FlashRW(base_addr, FSTORAGE_WRITE, flash_PageBuff, FLASH_PAGE_SIZE);
+			if(err_code != FLASH_OP_SUCCESS)return err_code;
+		}
+		else
+		{
+			//不需要擦除,直接写
+			err_code = Fstorage_FlashOnlyWrite(base_addr + _offset*4, pdata + data_offset, remain_size, false);	//直接写
+			if(err_code != FLASH_OP_SUCCESS)return err_code;
+		}
+
+		data_offset += remain_size/4;			//除以4是因为pData指针+1是移动4个字节
+		
+	}
+	
+	return FLASH_OP_SUCCESS;
+	
+}
+
+/**
+ @brief 只写N个字到flash中,调用前FLASH预先已擦除
+ @param addr-[in] 写入的flash首地址
+ @param pdata-[in] 需要写入的数据
+ @param len-[in] 数据长度 
+ @return 错误代码
+*/
+uint32_t Only_Write_N_4Byte_flash(uint32_t addr , uint32_t *pdata, uint32_t len, bool is_check)
+{
+	return Fstorage_FlashOnlyWrite(addr, pdata, len, is_check);
+}
+
+/**
+ @brief 查找一页中可写的空间(0xFF)
+ @param PageNum-[in] 输入的页号
+ @param start_addr-[in/out] 返回的空闲空间的起始地址
+ @param len-[in/out] 返回的空间的长度
+ @return 错误代码
+*/
+uint32_t Find_FreeSpace_In_Page(uint16_t PageNum, uint32_t *start_addr, uint32_t *len)
+{
+	uint32_t PageEndAddr,  RetrieveAddr, i;
+	uint32_t flash_data;
+	
+	if(PageNum >= FLASH_PAGE_NUM)return FLASH_ERROR_PAGENUM;
+	
+	//获取该页的结尾地址
+	GetPageEndAddr(PageNum, &PageEndAddr);
+	
+	//从页尾开始检索空闲空间
+	RetrieveAddr = PageEndAddr;
+	for(i = 0;i<PAGE_INT_SIZE;i++)
+	{
+		RetrieveAddr -= 4;
+		Read_N_4Byte_flash(RetrieveAddr , &flash_data, 4);
+		
+		if(flash_data != 0xFFFFFFFF)break;
+		
+	}
+	*start_addr = PageEndAddr - i *4;
+	*len        = i*4;
+	
+	return FLASH_OP_SUCCESS;
+}
+
+
+
+/****************************************************END OF FILE****************************************************/

+ 75 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_flash.h

@@ -0,0 +1,75 @@
+#ifndef __BSP_FLASH_H__
+#define __BSP_FLASH_H__
+
+//flash 1.0V
+
+/*********************************************************************
+ * INCLUDES
+ */
+ 
+#include "nrf_fstorage.h"
+#include "nrf_fstorage_sd.h"
+#include "nrf_pwr_mgmt.h"
+#include "nrf_soc.h"
+#include "nrf_log.h"
+#include "app_error.h"
+#include "SEGGER_RTT.h"
+
+
+/*********************************************************************
+ * DEFINITIONS
+ */
+#define FSTORAGE_READ           						0x00																																																		//读标志位
+#define FSTORAGE_WRITE											0x01																																																		//写标志位
+
+#define START_FSTORAGE_ADDR									0x00074000UL																																														//FLASH起始地址
+#define END_FSTORAGE_ADDR										0x00078000UL																																														//FLASH结束地址
+
+#define FLASH_PAGE_SIZE											4096																																																		//页的长度
+
+#define FLASH_PAGE_NUM											((END_FSTORAGE_ADDR - START_FSTORAGE_ADDR)/FLASH_PAGE_SIZE)																							//页的个数
+#define PAGE_INT_SIZE												(FLASH_PAGE_SIZE/4)																																											//一页所包含的4字节个数
+
+#define FLASH_ZONE_ADDR_1										START_FSTORAGE_ADDR																																											//页1首地址
+#define FLASH_ZONE_ADDR_2										(FLASH_ZONE_ADDR_1		+FLASH_PAGE_SIZE)																																	//页2首地址
+#define FLASH_ZONE_ADDR_3										(FLASH_ZONE_ADDR_2		+FLASH_PAGE_SIZE)																																	//页3首地址
+#define FLASH_ZONE_ADDR_4										(FLASH_ZONE_ADDR_3		+FLASH_PAGE_SIZE)																																	//页4首地址
+
+#define FLASH_ZONEADDR_CHECK(zone_addr)			((zone_addr==FLASH_ZONE_ADDR_1 || \
+																							zone_addr==FLASH_ZONE_ADDR_2 || \
+																							zone_addr==FLASH_ZONE_ADDR_3 || \
+																							zone_addr==FLASH_ZONE_ADDR_4)?0:1)																																		//验证是否在页x的范围内
+																							
+//ERROR CODE
+#define FLASH_OP_SUCCESS										0x00																																																		//flash操作成功
+#define FLASH_ERROR_ZONEADDR								(FLASH_OP_SUCCESS+0x01)																																									//区域地址错误
+#define FLASH_ERROR_ADDROVERBOUNDS					(FLASH_OP_SUCCESS+0x02)																																									//地址越界
+#define FLASH_ERROR_ADDRALIGN								(FLASH_OP_SUCCESS+0x03)																																									//地址不对齐
+#define FLASH_ERROR_DATAALIGN								(FLASH_OP_SUCCESS+0x04)																																									//4字节数据不对齐
+#define FLASH_ERROR_DATAEXIST								(FLASH_OP_SUCCESS+0x05)																																									//数据已存在		
+#define FLASH_ERROR_PAGENUM									(FLASH_OP_SUCCESS+0x06)																																									//页号错误
+#define FLASH_ERROR_READ										(FLASH_OP_SUCCESS+0x07)																																									//读取错误
+#define FLASH_ERROR_WRITE										(FLASH_OP_SUCCESS+0x08)																																									//写入错误
+#define FLASH_ERROR_ERASE										(FLASH_OP_SUCCESS+0x09)																																									//擦除错误
+/*********************************************************************
+ * API FUNCTIONS
+ */
+
+//FLASH初始化
+void 		 Fstorage_FlashInit(void);
+//连续读取N个字节
+uint32_t Read_N_Byte_flash(uint32_t addr , uint32_t *pData, uint32_t dataLen);
+//获取输入地址对应的页号
+uint32_t GetPageNum(uint32_t addr, uint16_t *PageNum);
+//根据页号擦除一整页
+uint32_t Erase_OnePage(uint16_t PageNum);
+//连续写入N个4字节(可跨页写,不影响其他数据)
+uint32_t Write_N_4Byte_flash(uint32_t addr , uint32_t *pdata, uint32_t len);
+//连续写入N个4字节(调用前FLASH预先已擦除)
+uint32_t Only_Write_N_4Byte_flash(uint32_t addr , uint32_t *pdata, uint32_t len, bool is_check);
+//查找一页中可写的空间
+uint32_t Find_FreeSpace_In_Page(uint16_t PageNum, uint32_t *start_addr, uint32_t *len);
+
+#endif
+
+

+ 16 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_gpio.c

@@ -0,0 +1,16 @@
+#include "bsp_gpio.h"
+#include "nrf_gpio.h"
+#include "usr_config.h"
+#include "bsp_time.h"
+#include "usr.h"
+/********************** ±äÁ¿Çø *************************/
+
+
+/********************** º¯ÊýÉùÃ÷Çø *************************/
+
+void GPIO_Init(void)
+{
+
+}
+
+

+ 12 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_gpio.h

@@ -0,0 +1,12 @@
+#ifndef __bsp_gpio_h__
+#define __bsp_gpio_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void GPIO_Init(void);
+
+#endif

+ 230 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_interface.c

@@ -0,0 +1,230 @@
+///********************** 头文件 *************************/
+#include "bsp_interface.h"
+
+///********************** 变量区 *************************/
+////extern int16_t gyro[3];
+////extern int16_t accel[3];
+//extern uint16_t press;
+
+
+
+/********************** 函数声明区 *************************/
+
+////发给匿名飞控
+//void sen_ANO_data_to_host(void)
+//{
+//	uint8_t buf[256];
+//	uint8_t L=0;
+//	
+//	
+//	int16_t roll  = (int16_t)(getRoll()*100);
+//	int16_t pitch = (int16_t)(getPitch()*100);
+//	int16_t yaw   = (int16_t)(getYaw()*100);
+//	
+//	buf[L++] = 0xAA; //帧头
+//	buf[L++] = 0x05; //发送设备
+//	buf[L++] = 0xAF; //目标设备
+//	buf[L++] = 0x01; //功能字
+//	buf[L++] = 0x01; //LEN
+//	
+//	buf[L++] = (uint8_t)(roll>>0);
+//	buf[L++] = (uint8_t)(roll>>8);
+
+//	buf[L++] = (uint8_t)(pitch>>0);
+//	buf[L++] = (uint8_t)(pitch>>8);
+
+//	buf[L++] = (uint8_t)(yaw>>0);
+//	buf[L++] = (uint8_t)(yaw>>8);
+//	
+//	buf[L++] = 0;
+//	buf[L++] = 0;
+//	buf[L++] = 0;
+//	buf[L++] = 0;
+//	
+//	buf[L++] = 0;
+//	
+//	buf[L++] = 0;
+//	
+//	buf[L++] = 0;
+//	
+//	
+//	
+////	buf[L++] = (uint8_t)(mMPU9250.acc_x>>0);
+////	buf[L++] = (uint8_t)(mMPU9250.acc_x>>8);
+////	
+////	buf[L++] = (uint8_t)(mMPU9250.acc_y>>0);
+////	buf[L++] = (uint8_t)(mMPU9250.acc_y>>8);
+////	
+////	buf[L++] = (uint8_t)(mMPU9250.acc_z>>0);
+////	buf[L++] = (uint8_t)(mMPU9250.acc_z>>8);
+//	
+//	buf[L++] = (uint8_t)(mMPU9250.mag_x>>0);
+//	buf[L++] = (uint8_t)(mMPU9250.mag_x>>8);
+//	
+//	buf[L++] = (uint8_t)(mMPU9250.mag_y>>0);
+//	buf[L++] = (uint8_t)(mMPU9250.mag_y>>8);
+//	
+//	buf[L++] = (uint8_t)(mMPU9250.mag_z>>0);
+//	buf[L++] = (uint8_t)(mMPU9250.mag_z>>8);
+//	
+//	buf[L++] = (uint8_t)(mMPU9250.gyro_x>>0);
+//	buf[L++] = (uint8_t)(mMPU9250.gyro_x>>8);
+//	
+//	buf[L++] = (uint8_t)(mMPU9250.gyro_y>>0);
+//	buf[L++] = (uint8_t)(mMPU9250.gyro_y>>8);
+//	
+//	buf[L++] = (uint8_t)(mMPU9250.gyro_z>>0);
+//	buf[L++] = (uint8_t)(mMPU9250.gyro_z>>8);
+
+//	buf[L++] = (uint8_t)(roll>>0);
+//	buf[L++] = (uint8_t)(roll>>8);
+
+//	buf[L++] = (uint8_t)(pitch>>0);
+//	buf[L++] = (uint8_t)(pitch>>8);
+
+//	buf[L++] = (uint8_t)(yaw>>0);
+//	buf[L++] = (uint8_t)(yaw>>8);
+//	
+//	bsp_esb_send(buf,L); //发送出去
+//}
+
+//void sen_data_to_host(void)
+//{
+//	uint8_t buf[256];
+//	uint8_t L=0;
+//	
+//	int32_t roll, pitch, yaw;
+//	
+//	buf[L++] = (uint8_t)(press>>8);
+//	buf[L++] = (uint8_t)(press>>0);
+//	
+//	roll = (int32_t)(getRoll()*100);
+//	pitch = (int32_t)(getPitch()*100);
+//	yaw = (int32_t)(getYaw()*100);
+//	
+//	buf[L++] = (uint8_t)(roll>>24);
+//	buf[L++] = (uint8_t)(roll>>16);
+//	buf[L++] = (uint8_t)(roll>>8);
+//	buf[L++] = (uint8_t)(roll>>0);
+//	
+//	buf[L++] = (uint8_t)(pitch>>24);
+//	buf[L++] = (uint8_t)(pitch>>16);
+//	buf[L++] = (uint8_t)(pitch>>8);
+//	buf[L++] = (uint8_t)(pitch>>0);
+//	
+//	buf[L++] = (uint8_t)(yaw>>24);
+//	buf[L++] = (uint8_t)(yaw>>16);
+//	buf[L++] = (uint8_t)(yaw>>8);
+//	buf[L++] = (uint8_t)(yaw>>0);
+////	
+////	buf[L++] = (uint8_t)(accel[0]>>8);
+////	buf[L++] = (uint8_t)(accel[0]>>0);
+////	
+////	buf[L++] = (uint8_t)(accel[1]>>8);
+////	buf[L++] = (uint8_t)(accel[1]>>0);
+////	
+////	buf[L++] = (uint8_t)(accel[2]>>8);
+////	buf[L++] = (uint8_t)(accel[2]>>0);
+////	
+////	buf[L++] = (uint8_t)(gyro[0]>>8);
+////	buf[L++] = (uint8_t)(gyro[0]>>0);
+////	
+////	buf[L++] = (uint8_t)(gyro[1]>>8);
+////	buf[L++] = (uint8_t)(gyro[1]>>0);
+////	
+////	buf[L++] = (uint8_t)(gyro[2]>>8);
+////	buf[L++] = (uint8_t)(gyro[2]>>0);
+//	
+//	send_protocol(DEX_NUM,CMD_HEART,buf,L);
+//}
+
+
+////发给维特智能上位机显示
+//void sen_wit_motion_data_to_host(void)
+//{
+//	uint8_t buf[256];
+//	uint8_t L=0;
+//	
+//	
+//	int16_t roll  = (int16_t)(getRoll()/180.0f*32768.0f);
+//	int16_t pitch = (int16_t)(getPitch()/180.0f*32768.0f);
+//	int16_t yaw   = (int16_t)(getYaw()/180.0f*32768.0f);
+//	
+//	buf[L++] = 0x55;
+//	buf[L++] = 0x61;
+//	
+////	buf[L++] = (uint8_t)(mMPU9250.acc_x>>0);
+////	buf[L++] = (uint8_t)(mMPU9250.acc_x>>8);
+////	
+////	buf[L++] = (uint8_t)(mMPU9250.acc_y>>0);
+////	buf[L++] = (uint8_t)(mMPU9250.acc_y>>8);
+////	
+////	buf[L++] = (uint8_t)(mMPU9250.acc_z>>0);
+////	buf[L++] = (uint8_t)(mMPU9250.acc_z>>8);
+//	
+//	buf[L++] = (uint8_t)(mMPU9250.mag_x>>0);
+//	buf[L++] = (uint8_t)(mMPU9250.mag_x>>8);
+//	
+//	buf[L++] = (uint8_t)(mMPU9250.mag_y>>0);
+//	buf[L++] = (uint8_t)(mMPU9250.mag_y>>8);
+//	
+//	buf[L++] = (uint8_t)(mMPU9250.mag_z>>0);
+//	buf[L++] = (uint8_t)(mMPU9250.mag_z>>8);
+//	
+//	buf[L++] = (uint8_t)(mMPU9250.gyro_x>>0);
+//	buf[L++] = (uint8_t)(mMPU9250.gyro_x>>8);
+//	
+//	buf[L++] = (uint8_t)(mMPU9250.gyro_y>>0);
+//	buf[L++] = (uint8_t)(mMPU9250.gyro_y>>8);
+//	
+//	buf[L++] = (uint8_t)(mMPU9250.gyro_z>>0);
+//	buf[L++] = (uint8_t)(mMPU9250.gyro_z>>8);
+
+//	buf[L++] = (uint8_t)(roll>>0);
+//	buf[L++] = (uint8_t)(roll>>8);
+
+//	buf[L++] = (uint8_t)(pitch>>0);
+//	buf[L++] = (uint8_t)(pitch>>8);
+
+//	buf[L++] = (uint8_t)(yaw>>0);
+//	buf[L++] = (uint8_t)(yaw>>8);
+//	
+////	bsp_esb_send(buf,L); //发送出去
+//	for(int i=0;i<L;i++) app_uart_put(buf[i]);
+//}
+
+//static uint8_t send_motion = 0;
+//static uint8_t send_ts = 0;
+//static uint8_t send_times = 0;
+//void send_motion_to_phone(uint8_t motion,uint16_t ts)
+//{
+//	send_motion = motion;
+//	send_ts = ts;
+//	send_times = 10;
+////	uint8_t buf[16];
+////	uint8_t L=0;
+
+////	buf[L++] = motion;
+////	
+////	buf[L++] = (uint8_t)(ts>>8);
+////	buf[L++] = (uint8_t)(ts>>0);
+////	
+////	for(int i = 0; i <5; i++)
+////		send_protocol(DEX_NUM,CMD_MOTION,buf,L);
+//}
+
+//void send_to_phone_process(void)
+//{
+//	uint8_t buf[16];
+//	uint8_t L=0;
+
+//	if(send_times>0){
+//		send_times--;
+//		buf[L++] = send_motion;
+//		buf[L++] = (uint8_t)(send_ts>>8);
+//		buf[L++] = (uint8_t)(send_ts>>0);
+//		send_protocol(DEX_NUM,CMD_MOTION,buf,L);
+//	}
+//}
+
+

+ 10 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_interface.h

@@ -0,0 +1,10 @@
+#ifndef __bsp_interface_h__
+#define __bsp_interface_h__
+#include "main.h"
+
+void sen_data_to_host(void);
+void send_to_phone_process(void);
+void send_motion_to_phone(uint8_t motion,uint16_t ts);
+void sen_wit_motion_data_to_host(void);
+	
+#endif

+ 84 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_mpu9250.c

@@ -0,0 +1,84 @@
+#include "main.h"
+
+
+//**************************************
+//写入一个字节数据
+//**************************************
+bool MPU9250_Write_Byte(uint8_t Device_Address,uint8_t REG_Address,uint8_t REG_data)
+{
+	uint8_t buf[2];
+//	SEGGER_RTT_printf(0,"MPU9250_Write_Byte\n");
+    buf[0] = REG_Address;
+    buf[1] = REG_data;
+    return twi_master_transfer(Device_Address, buf, 2, TWI_ISSUE_STOP);
+}
+//**************************************
+//读取N个字节数据
+//**************************************
+bool MPU9250_Read_nBytes(uint8_t Device_Address,uint8_t REG_Address,uint8_t *readDataBuf,uint8_t readDataLen)
+{
+	bool ret;
+    ret  = twi_master_transfer(Device_Address, &REG_Address, 1, TWI_DONT_ISSUE_STOP);
+    ret &= twi_master_transfer(Device_Address|TWI_READ_BIT, readDataBuf, readDataLen, TWI_ISSUE_STOP);
+    return ret;
+}
+
+bool MPU9250_register_write_len(uint8_t Device_Address,uint8_t register_address, uint8_t len,uint8_t *buf)
+{
+    uint8_t w2_data[50],i;
+
+    w2_data[0] = register_address;
+	  for(i=0;i<len;i++)w2_data[i+1] = *(buf+i);
+
+	  
+	  if(twi_master_transfer(Device_Address, w2_data, len+1, TWI_ISSUE_STOP) == true)return 0;
+	  else return true;
+}
+
+bool MPU9250_register_read_len(uint8_t Device_Address,uint8_t register_address, uint8_t number_of_bytes,uint8_t * destination )
+{
+    bool transfer_succeeded;
+    transfer_succeeded  = twi_master_transfer(Device_Address, &register_address, 1, TWI_DONT_ISSUE_STOP);
+    transfer_succeeded &= twi_master_transfer(Device_Address|TWI_READ_BIT, destination, number_of_bytes, TWI_ISSUE_STOP);
+    
+	  if(transfer_succeeded == true)return 0;
+	  else return true;
+}
+
+int MPU9250_init(void)
+{
+	if(!MPU9250_Write_Byte(MPU9250_I2C_ADDR,MPU9250_PWR_MGMT_1,0x80)) return 1;                //复位所有寄存器,复位完后自动进入睡眠模式,所以要sleep位要清0
+	nrf_delay_ms(5);
+	if(!MPU9250_Write_Byte(MPU9250_I2C_ADDR,MPU9250_PWR_MGMT_1,0x00)) return 1;			//唤醒mpu9250
+	if(!MPU9250_Write_Byte(MPU9250_I2C_ADDR,MPU9250_SMPLRT_DIV,0x07)) return 2;    		
+	if(!MPU9250_Write_Byte(MPU9250_I2C_ADDR,MPU9250_CONFIG,0x00)) return 3;    			//低通滤波5hz
+	if(!MPU9250_Write_Byte(MPU9250_I2C_ADDR,MPU9250_GYRO_CONFIG,0x18)) return 4;			//不自检,2000deg/s
+	if(!MPU9250_Write_Byte(MPU9250_I2C_ADDR,MPU9250_ACCEL_CONFIG,0x18)) return 5;			//(0x00 +-2g;)  ( 0x08 +-4g;)  (0x10 +-8g;)  (0x18 +-16g)
+	if(!MPU9250_Write_Byte(MPU9250_I2C_ADDR,MPU9250_ACCEL_CONFIG_2,0x04)) return 6;			//
+	if(!MPU9250_Write_Byte(MPU9250_I2C_ADDR,MPU9250_INT_PIN_CFG,0x02)) return 7;
+	if(!MPU9250_Write_Byte(MPU9250_I2C_ADDR,MPU9250_USER_CTRL,0x00)) return 8;				//使能I2C
+	if(!MPU9250_Write_Byte(AK8963_I2C_ADDR,AK8963_CNTL1,0x0f)) return 9;
+	return 0;
+}
+
+int MPU9250_Read(int16_t* acc,int16_t* gyr,int16_t* mag,int16_t* temperature)
+{
+	uint8_t buf[14],bufM[6];    			
+	if(!MPU9250_Read_nBytes(MPU9250_I2C_ADDR,MPU9250_ACCEL_XOUT_H,  buf, 14)) 	return -1;//读取加速度,温度,陀螺仪传感器
+	if(!MPU9250_Read_nBytes(AK8963_I2C_ADDR,AK8963_HXL,  bufM, 6)) 				return -2;//读取地磁传感器
+	if(!MPU9250_Write_Byte(AK8963_I2C_ADDR,AK8963_CNTL1,0x11)) 					return -3;//每读一次数据,ak8963会自动进入powerdown模式,这里需要重新设定为单测量模式
+	acc[0]  = ((int16_t)buf[0]<<8)|((int16_t)buf[1]);
+	acc[1]  = ((int16_t)buf[2]<<8)|((int16_t)buf[3]);
+	acc[2]  = ((int16_t)buf[4]<<8)|((int16_t)buf[5]);
+	temperature[0]   = ((int16_t)buf[6]<<8)|((int16_t)buf[7]);
+	gyr[0] = ((int16_t)buf[8]<<8)|((int16_t)buf[9]);
+	gyr[1] = ((int16_t)buf[10]<<8)|((int16_t)buf[11]);
+	gyr[2] = ((int16_t)buf[12]<<8)|((int16_t)buf[13]);
+	mag[0]  = ((int16_t)bufM[1]<<8)|((int16_t)bufM[0]);
+	mag[1]  = ((int16_t)bufM[3]<<8)|((int16_t)bufM[2]);
+	mag[2]  = ((int16_t)bufM[5]<<8)|((int16_t)bufM[4]);
+	return 0;
+}
+
+
+

+ 143 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_mpu9250.h

@@ -0,0 +1,143 @@
+#ifndef __bsp_mpu9250_H
+#define __bsp_mpu9250_H
+#include "main.h"
+
+/* ---- MPU9250 Reg In MPU9250 ---------------------------------------------- */
+
+#define MPU9250_I2C_ADDR            ((uint8_t)0xD0)
+#define MPU9250_Device_ID           ((uint8_t)0x71)  // In MPU9250
+
+#define MPU9250_SELF_TEST_XG        ((uint8_t)0x00)
+#define MPU9250_SELF_TEST_YG        ((uint8_t)0x01)
+#define MPU9250_SELF_TEST_ZG        ((uint8_t)0x02)
+#define MPU9250_SELF_TEST_XA        ((uint8_t)0x0D)
+#define MPU9250_SELF_TEST_YA        ((uint8_t)0x0E)
+#define MPU9250_SELF_TEST_ZA        ((uint8_t)0x0F)
+#define MPU9250_XG_OFFSET_H         ((uint8_t)0x13)
+#define MPU9250_XG_OFFSET_L         ((uint8_t)0x14)
+#define MPU9250_YG_OFFSET_H         ((uint8_t)0x15)
+#define MPU9250_YG_OFFSET_L         ((uint8_t)0x16)
+#define MPU9250_ZG_OFFSET_H         ((uint8_t)0x17)
+#define MPU9250_ZG_OFFSET_L         ((uint8_t)0x18)
+#define MPU9250_SMPLRT_DIV          ((uint8_t)0x19)
+#define MPU9250_CONFIG              ((uint8_t)0x1A)
+#define MPU9250_GYRO_CONFIG         ((uint8_t)0x1B)
+#define MPU9250_ACCEL_CONFIG        ((uint8_t)0x1C)
+#define MPU9250_ACCEL_CONFIG_2      ((uint8_t)0x1D)
+#define MPU9250_LP_ACCEL_ODR        ((uint8_t)0x1E)
+#define MPU9250_MOT_THR             ((uint8_t)0x1F)
+#define MPU9250_FIFO_EN             ((uint8_t)0x23)
+#define MPU9250_I2C_MST_CTRL        ((uint8_t)0x24)
+#define MPU9250_I2C_SLV0_ADDR       ((uint8_t)0x25)
+#define MPU9250_I2C_SLV0_REG        ((uint8_t)0x26)
+#define MPU9250_I2C_SLV0_CTRL       ((uint8_t)0x27)
+#define MPU9250_I2C_SLV1_ADDR       ((uint8_t)0x28)
+#define MPU9250_I2C_SLV1_REG        ((uint8_t)0x29)
+#define MPU9250_I2C_SLV1_CTRL       ((uint8_t)0x2A)
+#define MPU9250_I2C_SLV2_ADDR       ((uint8_t)0x2B)
+#define MPU9250_I2C_SLV2_REG        ((uint8_t)0x2C)
+#define MPU9250_I2C_SLV2_CTRL       ((uint8_t)0x2D)
+#define MPU9250_I2C_SLV3_ADDR       ((uint8_t)0x2E)
+#define MPU9250_I2C_SLV3_REG        ((uint8_t)0x2F)
+#define MPU9250_I2C_SLV3_CTRL       ((uint8_t)0x30)
+#define MPU9250_I2C_SLV4_ADDR       ((uint8_t)0x31)
+#define MPU9250_I2C_SLV4_REG        ((uint8_t)0x32)
+#define MPU9250_I2C_SLV4_DO         ((uint8_t)0x33)
+#define MPU9250_I2C_SLV4_CTRL       ((uint8_t)0x34)
+#define MPU9250_I2C_SLV4_DI         ((uint8_t)0x35)
+#define MPU9250_I2C_MST_STATUS      ((uint8_t)0x36)
+#define MPU9250_INT_PIN_CFG         ((uint8_t)0x37)
+#define MPU9250_INT_ENABLE          ((uint8_t)0x38)
+#define MPU9250_INT_STATUS          ((uint8_t)0x3A)
+#define MPU9250_ACCEL_XOUT_H        ((uint8_t)0x3B)
+#define MPU9250_ACCEL_XOUT_L        ((uint8_t)0x3C)
+#define MPU9250_ACCEL_YOUT_H        ((uint8_t)0x3D)
+#define MPU9250_ACCEL_YOUT_L        ((uint8_t)0x3E)
+#define MPU9250_ACCEL_ZOUT_H        ((uint8_t)0x3F)
+#define MPU9250_ACCEL_ZOUT_L        ((uint8_t)0x40)
+#define MPU9250_TEMP_OUT_H          ((uint8_t)0x41)
+#define MPU9250_TEMP_OUT_L          ((uint8_t)0x42)
+#define MPU9250_GYRO_XOUT_H         ((uint8_t)0x43)
+#define MPU9250_GYRO_XOUT_L         ((uint8_t)0x44)
+#define MPU9250_GYRO_YOUT_H         ((uint8_t)0x45)
+#define MPU9250_GYRO_YOUT_L         ((uint8_t)0x46)
+#define MPU9250_GYRO_ZOUT_H         ((uint8_t)0x47)
+#define MPU9250_GYRO_ZOUT_L         ((uint8_t)0x48)
+#define MPU9250_EXT_SENS_DATA_00    ((uint8_t)0x49)
+#define MPU9250_EXT_SENS_DATA_01    ((uint8_t)0x4A)
+#define MPU9250_EXT_SENS_DATA_02    ((uint8_t)0x4B)
+#define MPU9250_EXT_SENS_DATA_03    ((uint8_t)0x4C)
+#define MPU9250_EXT_SENS_DATA_04    ((uint8_t)0x4D)
+#define MPU9250_EXT_SENS_DATA_05    ((uint8_t)0x4E)
+#define MPU9250_EXT_SENS_DATA_06    ((uint8_t)0x4F)
+#define MPU9250_EXT_SENS_DATA_07    ((uint8_t)0x50)
+#define MPU9250_EXT_SENS_DATA_08    ((uint8_t)0x51)
+#define MPU9250_EXT_SENS_DATA_09    ((uint8_t)0x52)
+#define MPU9250_EXT_SENS_DATA_10    ((uint8_t)0x53)
+#define MPU9250_EXT_SENS_DATA_11    ((uint8_t)0x54)
+#define MPU9250_EXT_SENS_DATA_12    ((uint8_t)0x55)
+#define MPU9250_EXT_SENS_DATA_13    ((uint8_t)0x56)
+#define MPU9250_EXT_SENS_DATA_14    ((uint8_t)0x57)
+#define MPU9250_EXT_SENS_DATA_15    ((uint8_t)0x58)
+#define MPU9250_EXT_SENS_DATA_16    ((uint8_t)0x59)
+#define MPU9250_EXT_SENS_DATA_17    ((uint8_t)0x5A)
+#define MPU9250_EXT_SENS_DATA_18    ((uint8_t)0x5B)
+#define MPU9250_EXT_SENS_DATA_19    ((uint8_t)0x5C)
+#define MPU9250_EXT_SENS_DATA_20    ((uint8_t)0x5D)
+#define MPU9250_EXT_SENS_DATA_21    ((uint8_t)0x5E)
+#define MPU9250_EXT_SENS_DATA_22    ((uint8_t)0x5F)
+#define MPU9250_EXT_SENS_DATA_23    ((uint8_t)0x60)
+#define MPU9250_I2C_SLV0_DO         ((uint8_t)0x63)
+#define MPU9250_I2C_SLV1_DO         ((uint8_t)0x64)
+#define MPU9250_I2C_SLV2_DO         ((uint8_t)0x65)
+#define MPU9250_I2C_SLV3_DO         ((uint8_t)0x66)
+#define MPU9250_I2C_MST_DELAY_CTRL  ((uint8_t)0x67)
+#define MPU9250_SIGNAL_PATH_RESET   ((uint8_t)0x68)
+#define MPU9250_MOT_DETECT_CTRL     ((uint8_t)0x69)
+#define MPU9250_USER_CTRL           ((uint8_t)0x6A)
+#define MPU9250_PWR_MGMT_1          ((uint8_t)0x6B)
+#define MPU9250_PWR_MGMT_2          ((uint8_t)0x6C)
+#define MPU9250_FIFO_COUNTH         ((uint8_t)0x72)
+#define MPU9250_FIFO_COUNTL         ((uint8_t)0x73)
+#define MPU9250_FIFO_R_W            ((uint8_t)0x74)
+#define MPU9250_WHO_AM_I            ((uint8_t)0x75)	// ID = 0x71 In MPU9250
+#define MPU9250_XA_OFFSET_H         ((uint8_t)0x77)
+#define MPU9250_XA_OFFSET_L         ((uint8_t)0x78)
+#define MPU9250_YA_OFFSET_H         ((uint8_t)0x7A)
+#define MPU9250_YA_OFFSET_L         ((uint8_t)0x7B)
+#define MPU9250_ZA_OFFSET_H         ((uint8_t)0x7D)
+#define MPU9250_ZA_OFFSET_L         ((uint8_t)0x7E)
+
+/* ---- AK8963 Reg In MPU9250 ----------------------------------------------- */
+
+#define AK8963_I2C_ADDR             ((uint8_t)0x18)
+#define AK8963_Device_ID            ((uint8_t)0x48)
+
+// Read-only Reg
+#define AK8963_WIA                  ((uint8_t)0x00)
+#define AK8963_INFO                 ((uint8_t)0x01)
+#define AK8963_ST1                  ((uint8_t)0x02)
+#define AK8963_HXL                  ((uint8_t)0x03)
+#define AK8963_HXH                  ((uint8_t)0x04)
+#define AK8963_HYL                  ((uint8_t)0x05)
+#define AK8963_HYH                  ((uint8_t)0x06)
+#define AK8963_HZL                  ((uint8_t)0x07)
+#define AK8963_HZH                  ((uint8_t)0x08)
+#define AK8963_ST2                  ((uint8_t)0x09)
+// Write/Read Reg
+#define AK8963_CNTL1                ((uint8_t)0x0A)
+#define AK8963_CNTL2                ((uint8_t)0x0B)
+#define AK8963_ASTC                 ((uint8_t)0x0C)
+#define AK8963_TS1                  ((uint8_t)0x0D)
+#define AK8963_TS2                  ((uint8_t)0x0E)
+#define AK8963_I2CDIS               ((uint8_t)0x0F)
+// Read-only Reg ( ROM )
+#define AK8963_ASAX                 ((uint8_t)0x10)
+#define AK8963_ASAY                 ((uint8_t)0x11)
+#define AK8963_ASAZ                 ((uint8_t)0x12)
+
+
+int MPU9250_init(void);
+int MPU9250_Read(int16_t* acc,int16_t* gyr,int16_t* mag,int16_t* temperature);
+#endif
+

+ 91 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_ms5611.c

@@ -0,0 +1,91 @@
+#include "main.h"
+
+//#define MSE5611_Slave 0xEC   	//½Ó¸ß
+//#define MSE5611_Slave 0xEE	//½ÓµÍ
+
+#define MSE5611_Reset 0x1E
+#define Convert_D1_256 0x40
+#define Convert_D1_512 0x42
+#define Convert_D1_1024 0x44
+#define Convert_D1_2048 0x46
+#define Convert_D1_4096 0x48
+#define Convert_D2_256 0x50
+#define Convert_D2_512 0x52
+#define Convert_D2_1024 0x54
+#define Convert_D2_2048 0x56
+#define Convert_D2_4096 0x58
+#define ADC_Read 0x00
+
+#define PROM_Read_0 0xA0
+#define PROM_Read_1 0xA2
+#define PROM_Read_2 0xA4
+#define PROM_Read_3 0xA6
+#define PROM_Read_4 0xA8
+#define PROM_Read_5 0xAA
+#define PROM_Read_6 0xAC
+#define PROM_Read_7 0xAE
+
+#define Sea_Level_Pressure 101325.0
+uint16_t Reserve = 0;
+uint16_t CFG[6] = {0};
+uint16_t MSE5611_CRC = 0;
+uint32_t D[2] = {0};
+
+//int32_t Temp = 0;
+//int32_t Press = 0;
+//float Height = 0;
+
+int MSE5611_register_write_len(uint8_t addr,uint8_t register_address, uint8_t len,uint8_t *buf)
+{
+	uint8_t w2_data[50],i;
+	w2_data[0] = register_address;
+	for(i=0;i<len;i++){
+		w2_data[i+1] = *(buf+i);
+	}
+	if(twi_master_transfer(addr, w2_data, len+1, TWI_ISSUE_STOP) == true) return 0;
+	else return -1;
+}
+
+int MSE5611_register_read_len(uint8_t addr,uint8_t register_address, uint8_t number_of_bytes,uint8_t * destination )
+{
+    bool transfer_succeeded;
+    transfer_succeeded  = twi_master_transfer(addr, &register_address, 1, TWI_DONT_ISSUE_STOP);
+    transfer_succeeded &= twi_master_transfer(addr|TWI_READ_BIT, destination, number_of_bytes, TWI_ISSUE_STOP);
+    
+	  if(transfer_succeeded == true)return 0;
+	  else return -1;
+}
+
+void ReadPressure_Pre(void)
+{
+	uint8_t dat = 0;
+	//I2C_WriteByte(I2C1,MSE5611_Slave,Convert_D1_4096);
+	MSE5611_register_write_len(MSE5611_Slave, Convert_D1_256, 0, &dat);
+}
+uint32_t ReadPressure(void)
+{
+	uint8_t dd[3] = {0,0,0};
+	uint8_t R = 0;
+	
+	MSE5611_register_read_len(MSE5611_Slave,R,3,dd);
+	D[0] = ((uint32_t)(dd[0]<<16)|(dd[1]<<8)|(dd[2]<<0));
+	return D[0];
+}
+
+int MS5611_Init(void)
+{
+	uint8_t i;
+	uint8_t dd[2];
+	MSE5611_register_read_len(MSE5611_Slave,PROM_Read_0,2,dd);
+	Reserve = ((uint16_t)dd[0]<<8|dd[1]);
+	SEGGER_RTT_printf(0,"MSE5611_Config:");
+	for(i=0;i<6;i++){
+		MSE5611_register_read_len(MSE5611_Slave,PROM_Read_1+i*2,2,dd);
+		CFG[i] = ((uint16_t)dd[0]<<8 | dd[1]);
+		SEGGER_RTT_printf(0,"%02X ",CFG[i]);
+	}
+	SEGGER_RTT_printf(0,"\n");
+	MSE5611_register_read_len(MSE5611_Slave,PROM_Read_7,2,dd);
+	MSE5611_CRC = ((uint16_t)dd[0]<<8|dd[1]);
+}
+

+ 10 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_ms5611.h

@@ -0,0 +1,10 @@
+#ifndef __bsp_ms5611_h_
+#define __bsp_ms5611_h_
+
+#include "main.h"
+
+int MS5611_Init(void);
+int MS5611_Read_RawData_Pre(void);
+int MS5611_Read_RawData(uint32_t* p);
+
+#endif

+ 32 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_protocol.c

@@ -0,0 +1,32 @@
+/********************** 头文件 *************************/
+#include "bsp_protocol.h"
+
+/********************** 变量区 *************************/
+
+
+/********************** 函数声明区 *************************/
+void send_protocol(uint8_t index,uint8_t cmd,uint8_t* dat,uint8_t datLen)
+{
+	uint8_t buf[128];
+	uint16_t Len = datLen+5;
+	uint16_t L=0;
+	uint8_t i;
+	uint8_t ver = 0;
+	
+	if(Len>128) return;
+	
+	buf[L++] = 0xAA;  ver += 0xAA;	//帧头
+//	buf[L++] = 0xBB;  ver += 0xBB; 	//帧头
+//	buf[L++] = 0xCC;  ver += 0xCC; 	//帧头
+	buf[L++] = Len;   ver += Len;	//长度
+	buf[L++] = ~Len;  ver += (~Len);//长度反码
+//	buf[L++] = index; ver += index;	//设备号
+	buf[L++] = cmd;   ver += cmd;	//命令
+	for(i=0;i<datLen;i++){ buf[L++] = dat[i]; ver += dat[i];} //数据
+	buf[L++] = ver;   				//校验
+	
+	ESB_SendBuff(buf,L); //发送出去
+}
+
+
+

+ 32 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_protocol.h

@@ -0,0 +1,32 @@
+#ifndef __bsp_protocol_h__
+#define __bsp_protocol_h__
+#include "main.h"
+
+#define DEX_NUM 0
+
+enum _cmd{
+		CMD_HEART = 0,
+		CMD_MOTION,
+	};
+enum _CMD_MOTION{
+		MOTION_STOP = 0,
+		MOTION_RUN,
+		MOTION_JUMP,
+		MOTION_DOWN,
+		MOTION_LEFT,
+		MOTION_RIGHT,
+		MOTION_FRONT,
+		MOTION_BACK,
+		MOTION_LEFT_UP,
+		MOTION_LEFT_DOWN,
+		MOTION_RIGHT_UP,
+		MOTION_RIGHT_DOWN,
+		MOTION_STEP,
+	
+		NUMBERS_OF_MOTION,
+	};
+
+void send_protocol(uint8_t index,uint8_t cmd,uint8_t* dat,uint8_t datLen);
+
+
+#endif

+ 467 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_pwm.c

@@ -0,0 +1,467 @@
+/*********************************************************************
+ * INCLUDES
+ */
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+#include "exception.h"
+#include "system.h"
+#include "nrf_gpio.h"
+#include "bsp_pwm.h"
+
+/*********************************************************************
+ * DEFINITIONS
+ */
+#define PWM_INSTANCE						0
+
+#define PWM1_INSTANCE						1
+
+/*********************************************************************
+ * LOCAL VARIABLES
+ */
+static nrf_drv_pwm_t m_pwm = NRF_DRV_PWM_INSTANCE(PWM_INSTANCE);
+
+static nrf_drv_pwm_t m1_pwm = NRF_DRV_PWM_INSTANCE(PWM1_INSTANCE);
+
+static nrf_drv_pwm_config_t m_config =
+{
+		.output_pins =
+		{
+				NRF_DRV_PWM_PIN_NOT_USED, // channel 0
+				NRF_DRV_PWM_PIN_NOT_USED, // channel 1
+				NRF_DRV_PWM_PIN_NOT_USED, // channel 2
+				NRF_DRV_PWM_PIN_NOT_USED	 // channel 3
+		},
+		.irq_priority = PWM0_IRQ_PRIORITY,
+		.base_clock   = NRF_PWM_CLK_125kHz,
+		.count_mode   = NRF_PWM_MODE_UP,
+		.top_value    = 15612,
+		.load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
+		.step_mode    = NRF_PWM_STEP_AUTO
+};
+
+static nrf_drv_pwm_config_t m1_config =
+{
+		.output_pins =
+		{
+				NRF_DRV_PWM_PIN_NOT_USED, // channel 0
+				NRF_DRV_PWM_PIN_NOT_USED, // channel 1
+				NRF_DRV_PWM_PIN_NOT_USED, // channel 2
+				NRF_DRV_PWM_PIN_NOT_USED	 // channel 3
+		},
+		.irq_priority = PWM0_IRQ_PRIORITY,
+		.base_clock   = NRF_PWM_CLK_125kHz,
+		.count_mode   = NRF_PWM_MODE_UP,
+		.top_value    = 15612,
+		.load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
+		.step_mode    = NRF_PWM_STEP_AUTO
+};
+
+static nrfx_pwm_handler_t m_pwm_callback = NULL;
+
+static nrfx_pwm_handler_t m1_pwm_callback = NULL;
+
+static void bsp_pwm_init_process(void)
+{
+	if(Except_TxError(EXCEPT_PWM_INIT,"bsp_pwm_init_error\r\n") == 0)
+	{
+		Process_Stop(bsp_pwm_init_process);
+	}
+}
+
+static void bsp_pwm1_init_process(void)
+{
+	if(Except_TxError(EXCEPT_PWM_INIT,"bsp_pwm1_init_error\r\n") == 0)
+	{
+		Process_Stop(bsp_pwm1_init_process);
+	}
+}
+
+/*********************************************************************
+ * LOCAL FUNCTIONS
+ */
+/**
+	@brief PWM 初始化
+	@prama 无
+	@return 无
+*/
+static void Pwm_init(void)
+{
+	int 				ret = 0;
+	ret_code_t 	errCode;
+	
+	errCode = nrf_drv_pwm_init(&m_pwm, &m_config, m_pwm_callback);
+	if(errCode != NRF_SUCCESS)ret = -1;
+	
+	if(ret == -1)
+	{
+		Process_Start(0,"bsp_pwm_init_process",bsp_pwm_init_process);
+	}
+}
+/**
+	@brief PWM 初始化
+	@prama 无
+	@return 无
+*/
+static void Pwm1_init(void)
+{
+	int 				ret = 0;
+	ret_code_t 	errCode;
+	
+	errCode = nrf_drv_pwm_init(&m1_pwm, &m1_config, m1_pwm_callback);
+	if(errCode != NRF_SUCCESS)ret = -1;
+	
+	if(ret == -1)
+	{
+		Process_Start(0,"bsp_pwm1_init_process",bsp_pwm1_init_process);
+	}
+}
+///**
+//	@brief PWM 唤醒操作
+//	@prama t - [in] 唤醒时间
+//	@return 无
+//*/
+//static void cb_pwmWakeup(uint32_t t)
+//{
+//	Pwm_init();
+//}
+///**
+//	@brief PWM 睡眠操作
+//	@prama t - [in] 睡眠时间
+//	@return 无
+//*/
+//static void cb_pwmSleep(uint32_t t)
+//{
+//	nrfx_pwm_uninit(&m_pwm);
+//}
+/**
+ @brief 设置PWM的通道的加载模式
+ @param load_mode -[in] 加载模式
+ @return 无
+*/
+static void SetPwm_ChannelsLoadMode(nrf_pwm_dec_load_t load_mode)
+{
+	m_config.load_mode = load_mode;
+}
+
+/**
+ @brief 设置PWM1的通道的加载模式
+ @param load_mode -[in] 加载模式
+ @return 无
+*/
+static void SetPwm1_ChannelsLoadMode(nrf_pwm_dec_load_t load_mode)
+{
+	m1_config.load_mode = load_mode;
+}
+/*********************************************************************
+ * PUBLIC FUNCTIONS
+ */
+/**
+ @brief 设置PWM的引脚通道
+ @param p_pins -[in] 输入的引脚通道
+ @return 无
+*/
+void SetPwm_Channels(uint32_t channel_1, uint32_t channel_2, uint32_t channel_3, uint32_t channel_4)
+{
+	m_config.output_pins[0] = channel_1;
+	m_config.output_pins[1] = channel_2;
+	m_config.output_pins[2] = channel_3;
+	m_config.output_pins[3] = channel_4;
+}
+/**
+ @brief 设置PWM的中断回调函数
+ @param pwm_callback -[in] 中断函数的地址
+ @param irq_priority -[in] 中断函数的优先级
+ @return 无
+*/
+void SetPwm_IRQ(nrfx_pwm_handler_t pwm_callback, uint8_t irq_priority)
+{
+	m_pwm_callback = pwm_callback;
+	m_config.irq_priority = irq_priority;
+}
+/**
+ @brief 设置PWM的基础时钟
+ @param clock -[in] 时钟频率
+ @return 无
+*/
+void SetPwm_BaseClock(nrf_pwm_clk_t clock)
+{
+	m_config.base_clock = clock;
+}
+/**
+ @brief 设置PWM的计数模式
+ @param count_mode -[in] 计数模式
+ @return 无
+*/
+void SetPwm_CountMode(nrf_pwm_mode_t count_mode)
+{
+	m_config.count_mode = count_mode;
+}
+/**
+ @brief 设置PWM的最大的占空比阈值
+ @param Max_duty_cycle_value -[in] 最大的占空比阈值,根据频率决定。
+ @return 无
+*/
+void SetPwm_DutyCycleThreshold(uint16_t Max_duty_cycle_value)
+{
+	m_config.top_value = Max_duty_cycle_value;
+}
+/**
+ @brief 设置PWM的序列的推进模式,定义下一个cycle的进行方式。
+ @param step_mode -[in] 推进模式
+ @return 无
+*/
+void SetPwm_SequenceStepMode(nrf_pwm_dec_step_t step_mode)
+{
+	m_config.step_mode = step_mode;
+}
+/**
+ @brief PWM 的初始化
+ @param 无
+ @return 无
+*/
+void Pwm_Initialize(void){
+	Pwm_init();
+}
+/**
+ @brief PWM 的未初始化
+ @param 无
+ @return 无
+*/
+void Pwm_UnInitialize(void)
+{
+	nrfx_pwm_uninit(&m_pwm);
+}
+
+
+
+/**
+ @brief 设置一个独立通道序列
+ @param p_seqValues -[in]	指向一个独立通道序列
+ @param	seqValues_length - [in]	序列的大小
+ @param seqValues_repeats -[in] 序列的每个占空比重复的次数
+ @param	seqValues_end_delay - [in]  每个序列中,最后一个占空比重复的次数
+ @return 无
+*/
+nrf_pwm_sequence_t* Pwm_SetIndSequence(pwm_values_individual_t *p_seqValues, uint16_t seqValues_length,  uint32_t seqValues_repeats, uint32_t seqValues_end_delay)
+{
+	static nrf_pwm_sequence_t m_sequence;
+	
+	if(m_config.load_mode != NRF_PWM_LOAD_INDIVIDUAL)
+	{
+		SetPwm_ChannelsLoadMode(NRF_PWM_LOAD_INDIVIDUAL);
+		Pwm_UnInitialize();
+		Pwm_Initialize();
+	}
+	m_sequence.values.p_individual = (nrf_pwm_values_individual_t*)p_seqValues;
+	m_sequence.length = seqValues_length;
+	m_sequence.repeats = seqValues_repeats;
+	m_sequence.end_delay = seqValues_end_delay;
+	
+	return &m_sequence;
+}
+/**
+ @brief 设置一个共用通道序列
+ @param p_seqValues -[in]	指向一个共用通道序列
+ @param	seqValues_length - [in]	序列的大小
+ @param seqValues_repeats -[in] 序列的每个占空比重复的次数
+ @param	seqValues_end_delay - [in]  每个序列中,最后一个占空比重复的次数
+ @return 无
+*/
+nrf_pwm_sequence_t* Pwm_SetComSequence(pwm_values_common_t *p_seqValues, uint16_t seqValues_length,  uint32_t seqValues_repeats, uint32_t seqValues_end_delay)
+{
+	static nrf_pwm_sequence_t m_sequence;
+	
+	if(m_config.load_mode != NRF_PWM_LOAD_COMMON)
+	{
+		SetPwm_ChannelsLoadMode(NRF_PWM_LOAD_COMMON);
+		Pwm_UnInitialize();
+		Pwm_Initialize();
+	}
+	m_sequence.values.p_common = (nrf_pwm_values_common_t*)p_seqValues;
+	m_sequence.length = seqValues_length;
+	m_sequence.repeats = seqValues_repeats;
+	m_sequence.end_delay = seqValues_end_delay;
+	
+	return &m_sequence;
+}
+/**
+ @brief 设置PWM的指定单个序列的播放
+ @param pwm_sequence -[in] 输入序列的值
+ @param	playback_count -[in] 播放次数
+ @param	flags - [in]	播放模式
+ @return 错误代码
+*/
+uint32_t SetSimplePwmPlayBack(nrf_pwm_sequence_t *pwm_sequence, uint16_t playback_count, uint32_t flags)
+{
+	return nrf_drv_pwm_simple_playback(&m_pwm, pwm_sequence, playback_count, flags);
+}
+/**
+ @brief 设置PWM的指定多个序列的播放
+ @param pwm_sequence0 -[in] 输入序列的值
+ @param pwm_sequence1 -[in] 输入序列的值
+ @param	playback_count -[in] 播放次数
+ @param	flags - [in]	播放模式
+ @return 错误代码
+*/
+uint32_t SetComplexPwmPlayBack(nrf_pwm_sequence_t *pwm_sequence0, nrf_pwm_sequence_t *pwm_sequence1, uint16_t playback_count, uint32_t flags)
+{
+	return nrf_drv_pwm_complex_playback(&m_pwm, pwm_sequence0, pwm_sequence1, playback_count, flags);
+}
+
+/****************************************************************************************************************************************************************************/
+
+
+/**
+ @brief 设置PWM1的引脚通道
+ @param p_pins -[in] 输入的引脚通道
+ @return 无
+*/
+void SetPwm1_Channels(uint32_t channel_1, uint32_t channel_2, uint32_t channel_3, uint32_t channel_4)
+{
+	m1_config.output_pins[0] = channel_1;
+	m1_config.output_pins[1] = channel_2;
+	m1_config.output_pins[2] = channel_3;
+	m1_config.output_pins[3] = channel_4;
+}
+/**
+ @brief 设置PWM1的中断回调函数
+ @param pwm_callback -[in] 中断函数的地址
+ @param irq_priority -[in] 中断函数的优先级
+ @return 无
+*/
+void SetPwm1_IRQ(nrfx_pwm_handler_t pwm_callback, uint8_t irq_priority)
+{
+	m1_pwm_callback = pwm_callback;
+	m1_config.irq_priority = irq_priority;
+}
+/**
+ @brief 设置PWM1的基础时钟
+ @param clock -[in] 时钟频率
+ @return 无
+*/
+void SetPwm1_BaseClock(nrf_pwm_clk_t clock)
+{
+	m1_config.base_clock = clock;
+}
+/**
+ @brief 设置PWM1的计数模式
+ @param count_mode -[in] 计数模式
+ @return 无
+*/
+void SetPwm1_CountMode(nrf_pwm_mode_t count_mode)
+{
+	m1_config.count_mode = count_mode;
+}
+/**
+ @brief 设置PWM1的最大的占空比阈值
+ @param Max_duty_cycle_value -[in] 最大的占空比阈值,根据频率决定。
+ @return 无
+*/
+void SetPwm1_DutyCycleThreshold(uint16_t Max_duty_cycle_value)
+{
+	m1_config.top_value = Max_duty_cycle_value;
+}
+/**
+ @brief 设置PWM1的序列的推进模式,定义下一个cycle的进行方式。
+ @param step_mode -[in] 推进模式
+ @return 无
+*/
+void SetPwm1_SequenceStepMode(nrf_pwm_dec_step_t step_mode)
+{
+	m1_config.step_mode = step_mode;
+}
+/**
+ @brief PWM1 的初始化
+ @param 无
+ @return 无
+*/
+void Pwm1_Initialize(void){
+	Pwm1_init();
+}
+/**
+ @brief PWM 的未初始化
+ @param 无
+ @return 无
+*/
+void Pwm1_UnInitialize(void)
+{
+	nrfx_pwm_uninit(&m1_pwm);
+}
+
+
+
+/**
+ @brief 设置一个独立通道序列
+ @param p_seqValues -[in]	指向一个独立通道序列
+ @param	seqValues_length - [in]	序列的大小
+ @param seqValues_repeats -[in] 序列的每个占空比重复的次数
+ @param	seqValues_end_delay - [in]  每个序列中,最后一个占空比重复的次数
+ @return 无
+*/
+nrf_pwm_sequence_t* Pwm1_SetIndSequence(pwm_values_individual_t *p_seqValues, uint16_t seqValues_length,  uint32_t seqValues_repeats, uint32_t seqValues_end_delay)
+{
+	static nrf_pwm_sequence_t m1_sequence;
+	
+	if(m1_config.load_mode != NRF_PWM_LOAD_INDIVIDUAL)
+	{
+		SetPwm1_ChannelsLoadMode(NRF_PWM_LOAD_INDIVIDUAL);
+		Pwm1_UnInitialize();
+		Pwm1_Initialize();
+	}
+	m1_sequence.values.p_individual = (nrf_pwm_values_individual_t*)p_seqValues;
+	m1_sequence.length = seqValues_length;
+	m1_sequence.repeats = seqValues_repeats;
+	m1_sequence.end_delay = seqValues_end_delay;
+	
+	return &m1_sequence;
+}
+/**
+ @brief 设置一个共用通道序列
+ @param p_seqValues -[in]	指向一个共用通道序列
+ @param	seqValues_length - [in]	序列的大小
+ @param seqValues_repeats -[in] 序列的每个占空比重复的次数
+ @param	seqValues_end_delay - [in]  每个序列中,最后一个占空比重复的次数
+ @return 无
+*/
+nrf_pwm_sequence_t* Pwm1_SetComSequence(pwm_values_common_t *p_seqValues, uint16_t seqValues_length,  uint32_t seqValues_repeats, uint32_t seqValues_end_delay)
+{
+	static nrf_pwm_sequence_t m1_sequence;
+	
+	if(m1_config.load_mode != NRF_PWM_LOAD_COMMON)
+	{
+		SetPwm1_ChannelsLoadMode(NRF_PWM_LOAD_COMMON);
+		Pwm1_UnInitialize();
+		Pwm1_Initialize();
+	}
+	m1_sequence.values.p_common = (nrf_pwm_values_common_t*)p_seqValues;
+	m1_sequence.length = seqValues_length;
+	m1_sequence.repeats = seqValues_repeats;
+	m1_sequence.end_delay = seqValues_end_delay;
+	
+	return &m1_sequence;
+}
+/**
+ @brief 设置PWM的指定单个序列的播放
+ @param pwm_sequence -[in] 输入序列的值
+ @param	playback_count -[in] 播放次数
+ @param	flags - [in]	播放模式
+ @return 错误代码
+*/
+uint32_t SetSimplePwm1PlayBack(nrf_pwm_sequence_t *pwm_sequence, uint16_t playback_count, uint32_t flags)
+{
+	return nrf_drv_pwm_simple_playback(&m1_pwm, pwm_sequence, playback_count, flags);
+}
+/**
+ @brief 设置PWM的指定多个序列的播放
+ @param pwm_sequence0 -[in] 输入序列的值
+ @param pwm_sequence1 -[in] 输入序列的值
+ @param	playback_count -[in] 播放次数
+ @param	flags - [in]	播放模式
+ @return 错误代码
+*/
+uint32_t SetComplexPwm1PlayBack(nrf_pwm_sequence_t *pwm_sequence0, nrf_pwm_sequence_t *pwm_sequence1, uint16_t playback_count, uint32_t flags)
+{
+	return nrf_drv_pwm_complex_playback(&m1_pwm, pwm_sequence0, pwm_sequence1, playback_count, flags);
+}
+

+ 88 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_pwm.h

@@ -0,0 +1,88 @@
+#ifndef __bsp_pwm_h__
+#define __bsp_pwm_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+#include "nrf_drv_pwm.h"
+
+
+/**************************************
+DEFINECTION
+*/
+
+
+#define PWM_SEQUENCE_VALUES_LEN(seq_values)			NRF_PWM_VALUES_LENGTH(seq_values)						//SEQUENCE_VALUES_LEN
+
+#define PWM_FLAG_STOP														NRF_DRV_PWM_FLAG_STOP												//PLAYBACK_MODE
+#define PWM_FLAG_LOOP														NRF_DRV_PWM_FLAG_LOOP												//PLAYBACK_MODE
+#define PWM_FLAG_SIGNAL_END_SEQ0								NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ0   					//PLAYBACK_MODE     
+#define PWM_FLAG_SIGNAL_END_SEQ1								NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ1     				//PLAYBACK_MODE   
+#define PWM_FLAG_NO_EVT_FINISHED								NRF_DRV_PWM_FLAG_NO_EVT_FINISHED      			//PLAYBACK_MODE  
+#define PWM_FLAG_START_VIA_TASK									NRF_DRV_PWM_FLAG_START_VIA_TASK         		//PLAYBACK_MODE
+/**************************************
+STRUCTION
+*/
+typedef struct
+{
+    uint16_t channel_0; ///< Duty cycle value for channel 0.
+    uint16_t channel_1; ///< Duty cycle value for channel 1.
+    uint16_t channel_2; ///< Duty cycle value for channel 2.
+    uint16_t channel_3; ///< Duty cycle value for channel 3.
+} pwm_values_individual_t;
+
+typedef uint16_t pwm_values_common_t;
+/**************************************
+API
+*/
+//设置PWM的引脚通道
+void SetPwm_Channels(uint32_t channel_1, uint32_t channel_2, uint32_t channel_3, uint32_t channel_4);
+//设置PWM的中断回调函数
+void SetPwm_IRQ(nrfx_pwm_handler_t pwm_callback, uint8_t irq_priority);
+//设置PWM的基础时钟
+void SetPwm_BaseClock(nrf_pwm_clk_t clock);
+//设置PWM的计数模式
+void SetPwm_CountMode(nrf_pwm_mode_t count_mode);
+//设置PWM的最大的占空比阈值
+void SetPwm_DutyCycleThreshold(uint16_t Max_duty_cycle_value);
+//设置PWM的序列的推进模式,定义下一个cycle的进行方式。
+void SetPwm_SequenceStepMode(nrf_pwm_dec_step_t step_mode);
+//PWM 的初始化
+void Pwm_Initialize(void);
+//PWM 的未初始化
+void Pwm_UnInitialize(void);
+//设置一个独立通道序列
+nrf_pwm_sequence_t* Pwm_SetIndSequence(pwm_values_individual_t *p_seqValues, uint16_t seqValues_length,  uint32_t seqValues_repeats, uint32_t seqValues_end_delay);
+//设置一个共用通道序列
+nrf_pwm_sequence_t* Pwm_SetComSequence(pwm_values_common_t *p_seqValues, uint16_t seqValues_length,  uint32_t seqValues_repeats, uint32_t seqValues_end_delay);
+//设置PWM的指定单个序列的播放
+uint32_t SetSimplePwmPlayBack(nrf_pwm_sequence_t *pwm_sequence, uint16_t playback_count, uint32_t flags);
+
+/****************************************************************************************************************************************************************************/
+
+//设置PWM1的引脚通道
+void SetPwm1_Channels(uint32_t channel_1, uint32_t channel_2, uint32_t channel_3, uint32_t channel_4);
+//设置PWM1的中断回调函数
+void SetPwm1_IRQ(nrfx_pwm_handler_t pwm_callback, uint8_t irq_priority);
+//设置PWM1的基础时钟
+void SetPwm1_BaseClock(nrf_pwm_clk_t clock);
+//设置PWM1的计数模式
+void SetPwm1_CountMode(nrf_pwm_mode_t count_mode);
+//设置PWM1的最大的占空比阈值
+void SetPwm1_DutyCycleThreshold(uint16_t Max_duty_cycle_value);
+//设置PWM1的序列的推进模式,定义下一个cycle的进行方式。
+void SetPwm1_SequenceStepMode(nrf_pwm_dec_step_t step_mode);
+//PWM1 的初始化
+void Pwm1_Initialize(void);
+//PWM1 的未初始化
+void Pwm1_UnInitialize(void);
+//设置一个独立通道序列
+nrf_pwm_sequence_t* Pwm1_SetIndSequence(pwm_values_individual_t *p_seqValues, uint16_t seqValues_length,  uint32_t seqValues_repeats, uint32_t seqValues_end_delay);
+//设置一个共用通道序列
+nrf_pwm_sequence_t* Pwm1_SetComSequence(pwm_values_common_t *p_seqValues, uint16_t seqValues_length,  uint32_t seqValues_repeats, uint32_t seqValues_end_delay);
+//设置PWM1的指定单个序列的播放
+uint32_t SetSimplePwm1PlayBack(nrf_pwm_sequence_t *pwm_sequence, uint16_t playback_count, uint32_t flags);
+
+#endif

+ 13 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_pwm/bsp_pwm.h

@@ -0,0 +1,13 @@
+#ifndef __bsp_pwm_h__
+#define __bsp_pwm_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void Pwm_Initialize(void);
+void Pwm_update_duty(uint8_t duty_1,uint8_t duty_2,uint8_t duty_3);
+
+#endif

+ 92 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_pwm/bsp_pwm_led_gpio.c

@@ -0,0 +1,92 @@
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "nrf_drv_pwm.h"
+#include "usr_config.h"
+#include "system.h"
+#include "nrf_gpio.h"
+#include "bsp_pwm.h"
+
+/********************** ±äÁ¿Çø *************************/
+
+static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
+
+static const uint16_t pwm_const = 1250;
+
+static nrf_pwm_values_individual_t m_demo1_seq_values={0,0,0};
+
+static nrf_pwm_sequence_t const    m_demo1_seq =
+{
+    .values.p_individual = &m_demo1_seq_values,
+    .length              = NRF_PWM_VALUES_LENGTH(m_demo1_seq_values),
+    .repeats             = 0,
+    .end_delay           = 0
+};
+
+void Pwm_update_duty(uint8_t duty_1,uint8_t duty_2,uint8_t duty_3)
+{
+	   if(duty_1 >  100)duty_1 =100;
+	   if(duty_2 >  100)duty_2 =100;
+	   if(duty_3 >  100)duty_3 =100;
+	  
+	   if(PCB_VERSION == 1 || PCB_VERSION == 3){
+			   duty_1 = 100-duty_1;
+			   duty_2 = 100-duty_2;
+			   duty_3 = 100-duty_3;
+		 }
+		 uint16_t duty1_t = (uint16_t)(duty_1*pwm_const/100);
+		 uint16_t duty2_t = (uint16_t)(duty_2*pwm_const/100);
+		 uint16_t duty3_t = (uint16_t)(duty_3*pwm_const/100);
+     m_demo1_seq_values.channel_0 = duty1_t;
+	   m_demo1_seq_values.channel_1 = duty2_t;
+	   m_demo1_seq_values.channel_2 = duty3_t;
+		 
+		 //SEGGER_RTT_printf(0,"led debug %d,%d,%d\n",m_demo1_seq_values.channel_0,m_demo1_seq_values.channel_1,m_demo1_seq_values.channel_2);
+}
+
+static void Pwm_init(void)
+{
+    nrf_drv_pwm_config_t const config0 =
+    {
+        .output_pins =
+        {
+            PIN_LED_R, // channel 0
+            PIN_LED_G, // channel 1
+            PIN_LED_B, // channel 2
+            NRF_DRV_PWM_PIN_NOT_USED
+        },
+        .irq_priority = APP_IRQ_PRIORITY_LOWEST,
+        .base_clock   = NRF_PWM_CLK_125kHz,
+        .count_mode   = NRF_PWM_MODE_UP,
+        .top_value    = pwm_const,
+        .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
+        .step_mode    = NRF_PWM_STEP_AUTO
+    };
+    APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
+		
+    m_demo1_seq_values.channel_0 = pwm_const;
+    m_demo1_seq_values.channel_1 = pwm_const;
+    m_demo1_seq_values.channel_2 = pwm_const;
+
+    (void)nrf_drv_pwm_simple_playback(&m_pwm0, &m_demo1_seq, 1,
+                                      NRF_DRV_PWM_FLAG_LOOP);
+		
+}
+
+static void cb_pwmWakeup(uint32_t t)
+{
+	  Pwm_init();
+}
+
+static void cb_pwmSleep(uint32_t t)
+{
+	  nrfx_pwm_uninit(&m_pwm0);
+	  nrf_gpio_cfg_input(PIN_LED_R, NRF_GPIO_PIN_NOPULL);//IO 
+	  nrf_gpio_cfg_input(PIN_LED_G, NRF_GPIO_PIN_NOPULL);
+	  nrf_gpio_cfg_input(PIN_LED_B, NRF_GPIO_PIN_NOPULL);
+}
+
+void Pwm_Initialize(void){
+	Pwm_init();
+	Wakeup_Regist(cb_pwmWakeup);
+  Sleep_Regist(cb_pwmSleep);
+}

+ 65 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_pwm/bsp_pwm_led_ws2812.c

@@ -0,0 +1,65 @@
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "nrf_drv_pwm.h"
+#include "usr_config.h"
+#include "system.h"
+#include "nrf_gpio.h"
+#include "bsp_pwm.h"
+
+/********************** ±äÁ¿Çø *************************/
+
+static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
+
+static nrf_pwm_values_individual_t m_demo1_seq_values[]={
+{0},{0},{0},{0},{0},{0}
+};
+
+static nrf_pwm_sequence_t const    m_demo1_seq =
+{
+    .values.p_individual = m_demo1_seq_values,
+    .length              = NRF_PWM_VALUES_LENGTH(m_demo1_seq_values),
+    .repeats             = 0,
+    .end_delay           = 0
+};
+
+static void Pwm_init(void)
+{
+    nrf_drv_pwm_config_t const config0 =
+    {
+        .output_pins =
+        {
+            PIN_LED_CONTROL, // channel 0
+            NRF_DRV_PWM_PIN_NOT_USED, 
+            NRF_DRV_PWM_PIN_NOT_USED,
+            NRF_DRV_PWM_PIN_NOT_USED
+        },
+        .irq_priority = APP_IRQ_PRIORITY_LOWEST,
+        .base_clock   = NRF_PWM_CLK_125kHz,
+        .count_mode   = NRF_PWM_MODE_UP,
+        .top_value    = 1,
+        .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
+        .step_mode    = NRF_PWM_STEP_AUTO
+    };
+    APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
+		
+    (void)nrf_drv_pwm_simple_playback(&m_pwm0, &m_demo1_seq, 1,
+                                      NRF_DRV_PWM_FLAG_LOOP);
+		
+}
+
+static void cb_pwmWakeup(uint32_t t)
+{
+	  Pwm_init();
+}
+
+static void cb_pwmSleep(uint32_t t)
+{
+	  nrfx_pwm_uninit(&m_pwm0);
+	  nrf_gpio_cfg_input(PIN_LED_CONTROL, NRF_GPIO_PIN_NOPULL);//IO 
+}
+
+void Pwm_Initialize(void){
+	Pwm_init();
+	Wakeup_Regist(cb_pwmWakeup);
+  Sleep_Regist(cb_pwmSleep);
+}

+ 144 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_rtc.c

@@ -0,0 +1,144 @@
+#include "bsp_rtc.h"
+#include "ble_conn_state.h"
+#include "nrf_ble_scan.h"
+#include "app_timer.h"
+#include "bsp_battery.h"
+#include "drv_mpu9250.h"
+#include "nrf_delay.h"
+
+#define COMPARE_COUNTERTIME  (1UL)                                        /**< Get Compare event COMPARE_TIME seconds after the counter starts from 0. */
+
+static const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(2); /**< Declaring an instance of nrf_drv_rtc for RTC2. */
+
+static uint16_t	m_sleeptimes_S = 0;
+
+/** @brief: Function for handling the RTC0 interrupts.
+ * Triggered on TICK and COMPARE0 match.
+ */
+static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
+{
+	uint32_t err_code;
+    if (int_type == NRF_DRV_RTC_INT_COMPARE0)
+    {
+		nrf_drv_rtc_counter_clear(&rtc);
+		err_code = nrf_drv_rtc_cc_set(&rtc,0,m_sleeptimes_S,true);
+		APP_ERROR_CHECK(err_code);
+        SEGGER_RTT_printf(0,"NRF_DRV_RTC_INT_COMPARE0(0x%X)\n",NRF_RTC0->COUNTER);
+    }
+    else if (int_type == NRF_DRV_RTC_INT_TICK)
+    {
+//        SEGGER_RTT_printf(0,"NRF_DRV_RTC_INT_TICK(0x%X)\n",NRF_RTC0->COUNTER);
+    }
+}
+
+/** @brief Function initialization and configuration of RTC driver instance.
+ */
+void RTC_init(void)
+{
+	uint32_t err_code;
+
+	//Initialize RTC instance
+	nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
+	config.prescaler = 0;// f(RTC) = 32.768kHZ/(prescaler+1) = 8HZ = 125ms
+	err_code = nrf_drv_rtc_init(&rtc, &config, rtc_handler);
+	APP_ERROR_CHECK(err_code);
+	
+	err_code = nrf_drv_rtc_cc_set(&rtc,0,300,true);
+	APP_ERROR_CHECK(err_code);
+	
+	nrf_drv_rtc_counter_clear(&rtc);
+
+//	//Enable tick event & interrupt
+//	nrf_drv_rtc_tick_enable(&rtc,true);
+
+//	//Set compare channel to trigger interrupt after COMPARE_COUNTERTIME seconds
+//	err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 8,true);
+//	APP_ERROR_CHECK(err_code);
+
+//	//Power on RTC instance
+	nrf_drv_rtc_enable(&rtc);
+
+}
+
+void rtc_start(uint16_t sleep_S)
+{
+	uint32_t err_code;
+	
+	m_sleeptimes_S = sleep_S;
+		//Set compare channel to trigger interrupt after sleep_S seconds
+	err_code = nrf_drv_rtc_cc_set(&rtc,0,m_sleeptimes_S,true);
+	APP_ERROR_CHECK(err_code);
+	
+	nrf_drv_rtc_counter_clear(&rtc);
+	
+	nrf_drv_rtc_enable(&rtc);
+//	SEGGER_RTT_printf(0,"nrf_drv_rtc_enable(0x%X)\n",NRF_RTC0->COUNTER);
+}
+
+void rtc_stop(void)
+{
+	nrf_drv_rtc_disable(&rtc);
+//	SEGGER_RTT_printf(0,"nrf_drv_rtc_disable(0x%X)\n",NRF_RTC0->COUNTER);
+}
+
+/*
+@brief			睡眠函数
+@param			sleep_ms	:睡眠时间,units of 125 ms
+@return			实际睡眠时间
+*/
+uint32_t rtc_sleep(uint32_t sleep_125ms)
+{
+	uint32_t sleep_times,wakeup_times,actual_sleeptimes;
+	//关闭蓝牙扫描
+//	if(!ble_conn_state_central_conn_count())//作为主机没有连接情况下才停止扫描
+//	{
+//		nrf_ble_scan_stop();
+////		SEGGER_RTT_printf(0,"scan off...\n");
+//	}
+	
+	//暂停软件定时器
+	
+//	app_timer_pause();
+//	nrf_delay_ms(100);
+	SEGGER_RTT_printf(0,"timer off...\n");
+	
+	//关闭ADC
+//	ADC_Enable(false);
+//	SEGGER_RTT_printf(0,"adc off...\n");
+	
+	//设定rtc唤醒时间且开启rtc
+	rtc_start(sleep_125ms);
+//	SEGGER_RTT_printf(0,"rtc start(%d)ms\n",sleep_125ms * 125);
+	
+	sleep_times = NRF_RTC0->COUNTER;
+	
+	//进入睡眠
+	CRITICAL_REGION_ENTER();
+	__SEV();
+	__WFE();
+	CRITICAL_REGION_EXIT();
+	(void)sd_app_evt_wait();
+	wakeup_times = NRF_RTC0->COUNTER;
+//	SEGGER_RTT_printf(0,"===============>rtc sleep_times(%d)\n",sleep_times);
+//	SEGGER_RTT_printf(0,"===============>rtc wakeup_times(%d)\n",wakeup_times);
+	//停止rtc
+	rtc_stop();
+//	SEGGER_RTT_printf(0,"rtc end...\n");
+	
+	//开启ADC
+//	ADC_Enable(true);
+//	SEGGER_RTT_printf(0,"adc on...\n");
+	
+	//恢复软件定时器
+//	app_timer_resume();
+	SEGGER_RTT_printf(0,"timer on...\n");
+	nrf_delay_ms(100);
+	actual_sleeptimes = (wakeup_times - sleep_times)/32.768*1000;
+	
+	return  actual_sleeptimes/1000;
+}
+
+
+
+
+

+ 19 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_rtc.h

@@ -0,0 +1,19 @@
+#ifndef __BSP_RTC_H__
+#define __BSP_RTC_H__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "nrf.h"
+#include "app_error.h"
+#include "nrf_drv_rtc.h"
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+#include "nrf_assert.h"
+
+void RTC_init(void);
+uint32_t rtc_sleep(uint32_t sleep_125ms);
+
+
+#endif
+

+ 685 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_spi.c

@@ -0,0 +1,685 @@
+//SPI 1.0V
+
+	/*
+	When you call nrf_drv_spi_transfer(&m_spi_m, tx_buffer, tx_bytes, rx_buffer, rx_bytes), specify value for tx_bytes, it is the number of bytes you want to put on the SPI master-out pin; rx_bytes refers to the number of bytes you want to fill for the rx_buffer, beginning at the start of your transaction.
+For example, a register read on a SPI peripheral requires first writing the address of register you want to read, SPI peripheral will return the value of that register as soon as you finish writing the address. In this case tx_bytes is 1, rx_bytes is 2. When the call completes with call back, you will get the read from rx_buffer[1].
+In general, if you want to tx x bytes, and receive y bytes after x bytes has been transferred, rx_buffer needs to be the size of (x + y). A valid read back value will start at rx_buffer[x] for the length of y.
+	重点:发送X个字节的数据,接受Y个字节的数据,则接收缓冲区至少有X+Y个字节的长度,而接收到的数据从rx_buffer[x]开始,长度为y。
+	*/
+	
+	
+/*********************************************************************
+ * INCLUDES
+ */
+#include "bsp_spi.h"
+#include "exception.h"
+#include "system.h"
+
+
+static void spi0CallbackFunc(nrf_drv_spi_evt_t const *pEvent, void *arg);
+static void spi1CallbackFunc(nrf_drv_spi_evt_t const *pEvent, void *arg);
+static void spi2CallbackFunc(nrf_drv_spi_evt_t const *pEvent, void *arg);
+
+/*********************************************************************
+ * LOCAL VARIABLES
+ */
+static volatile bool 					s0_transferOk = true;  																	// SPI0数据传输完成标志
+static volatile bool 					s1_transferOk = true;  																	// SPI1数据传输完成标志
+static volatile bool 					s2_transferOk = true;  																	// SPI2数据传输完成标志
+
+static const nrf_drv_spi_t 		s0_spiHandle = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE_0);		// SPI0 instance
+static const nrf_drv_spi_t 		s1_spiHandle = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE_1);		// SPI1 instance
+static const nrf_drv_spi_t 		s2_spiHandle = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE_2);		// SPI2 instance
+
+static const uint8_t					s0_cs_list[SPI0_CS_NUMBER] = SPI0_CS_LIST;							// SPI0 片选列表
+static const uint8_t					s1_cs_list[SPI1_CS_NUMBER] = SPI1_CS_LIST;							// SPI1 片选列表
+static const uint8_t					s2_cs_list[SPI2_CS_NUMBER] = SPI2_CS_LIST;							// SPI2 片选列表
+
+
+/*********************************************************************
+ * LOCAL FUNCTIONS
+ */
+/**
+ @brief SPI中断处理回调函数
+ @param 无
+ @return 无
+*/
+static void spi0CallbackFunc(nrf_drv_spi_evt_t const *pEvent, void *arg)
+{
+	//事件类型只有NRF_DRV_SPI_EVENT_DONE
+	s0_transferOk = true;
+}
+static void spi1CallbackFunc(nrf_drv_spi_evt_t const *pEvent, void *arg)
+{
+	//事件类型只有NRF_DRV_SPI_EVENT_DONE
+	s1_transferOk = true;
+}
+static void spi2CallbackFunc(nrf_drv_spi_evt_t const *pEvent, void *arg)
+{
+	//事件类型只有NRF_DRV_SPI_EVENT_DONE
+	s2_transferOk = true;
+}
+
+/**
+ @brief SPI片选引脚检查
+ @param CsPin_number -[in] 片选引脚
+ @return 错误代码
+*/
+static uint32_t SPI0_CsCheck(uint32_t CsPin_number)
+{
+	uint32_t i;
+	
+	for(i = 0; i < SPI0_CS_NUMBER; i++)
+	{
+		if(s0_cs_list[i] == CsPin_number)
+			return SPI_OP_SUCCESS;
+	}
+	
+	return SPI_ERROR_CS;
+}
+static uint32_t SPI1_CsCheck(uint32_t CsPin_number)
+{
+	uint32_t i;
+	
+	for(i = 0; i < SPI1_CS_NUMBER; i++)
+	{
+		if(s1_cs_list[i] == CsPin_number)
+			return SPI_OP_SUCCESS;
+	}
+	
+	return SPI_ERROR_CS;
+}
+static uint32_t SPI2_CsCheck(uint32_t CsPin_number)
+{
+	uint32_t i;
+	
+	for(i = 0; i < SPI2_CS_NUMBER; i++)
+	{
+		if(s2_cs_list[i] == CsPin_number)
+			return SPI_OP_SUCCESS;
+	}
+	
+	return SPI_ERROR_CS;
+}
+
+/**
+ @brief SPI片选信号设置
+ @param CsPin_number -[in] 片选引脚
+ @param pinState -[in] 引脚状态
+ @return 错误代码
+*/
+static uint32_t SPI0_CsSet(uint32_t CsPin_number , uint8_t pinState)
+{
+	uint32_t err_code;
+
+	if((err_code = SPI0_CsCheck(CsPin_number)) != SPI_OP_SUCCESS)return err_code;
+	
+	if(pinState == BOARD_SPI_CS_OFF)
+	{
+		nrf_gpio_pin_write(CsPin_number, 1);
+	}
+	else if(pinState == BOARD_SPI_CS_ON)
+	{
+		nrf_gpio_pin_write(CsPin_number, 0);
+	}
+	
+	return SPI_OP_SUCCESS;
+}
+static uint32_t SPI1_CsSet(uint32_t CsPin_number , uint8_t pinState)
+{
+	uint32_t err_code;
+
+	if((err_code = SPI1_CsCheck(CsPin_number)) != SPI_OP_SUCCESS)return err_code;
+	
+	if(pinState == BOARD_SPI_CS_OFF)
+	{
+		nrf_gpio_pin_write(CsPin_number, 1);
+	}
+	else if(pinState == BOARD_SPI_CS_ON)
+	{
+		nrf_gpio_pin_write(CsPin_number, 0);
+	}
+	
+	return SPI_OP_SUCCESS;
+}
+static uint32_t SPI2_CsSet(uint32_t CsPin_number , uint8_t pinState)
+{
+	uint32_t err_code;
+
+	if((err_code = SPI2_CsCheck(CsPin_number)) != SPI_OP_SUCCESS)return err_code;
+	
+	if(pinState == BOARD_SPI_CS_OFF)
+	{
+		nrf_gpio_pin_write(CsPin_number, 1);
+	}
+	else if(pinState == BOARD_SPI_CS_ON)
+	{
+		nrf_gpio_pin_write(CsPin_number, 0);
+	}
+	
+	return SPI_OP_SUCCESS;
+}
+
+/**
+ @brief SPI读出写入数据
+ @param CsPin_number -[in] 片选引脚
+ @param pWriteData -[in] 写入数据
+ @param writeDataLen -[in] 写入数据长度
+ @param pReadData -[out] 读出数据
+ @param readDataLen -[in]	读出数据长度
+ @return 错误代码
+*/
+static uint32_t SPI0_ReadWriteData(uint32_t CsPin_number, uint8_t *pWriteData, uint8_t writeDataLen, uint8_t *pReadData, uint8_t readDataLen)
+{
+	
+	uint32_t err_code;
+	uint32_t wait_time_out = WAIT_TIME_VALUE;
+
+	if((err_code = SPI0_CsCheck(CsPin_number)) != SPI_OP_SUCCESS)return err_code;
+	
+	SPI0_CsSet(CsPin_number,BOARD_SPI_CS_ON);						//片选信号开
+	
+	s0_transferOk = false;
+	
+	err_code = nrf_drv_spi_transfer(&s0_spiHandle, pWriteData, writeDataLen, pReadData, readDataLen);
+	if(err_code != NRF_SUCCESS)return SPI_ERROR_TIMEOUT;
+
+	while(!s0_transferOk)
+	{
+		if(wait_time_out--){
+			nrf_pwr_mgmt_run();
+		}
+		else{
+			SPI0_CsSet(CsPin_number,BOARD_SPI_CS_OFF);				//片选信号关
+			return SPI_ERROR_TIMEOUT;
+		}
+	}																											// Error in SPI or transfer already in progress.
+	
+	SPI0_CsSet(CsPin_number,BOARD_SPI_CS_OFF);						//片选信号关
+	return SPI_OP_SUCCESS;
+}
+static uint32_t SPI1_ReadWriteData(uint32_t CsPin_number, uint8_t *pWriteData, uint8_t writeDataLen, uint8_t *pReadData, uint8_t readDataLen)
+{
+	
+	uint32_t err_code;
+	uint32_t wait_time_out = WAIT_TIME_VALUE;
+
+	if((err_code = SPI1_CsCheck(CsPin_number)) != SPI_OP_SUCCESS)return err_code;
+	
+	SPI1_CsSet(CsPin_number,BOARD_SPI_CS_ON);						//片选信号开
+	
+	s1_transferOk = false;
+	
+	err_code = nrf_drv_spi_transfer(&s1_spiHandle, pWriteData, writeDataLen, pReadData, readDataLen);
+	if(err_code != NRF_SUCCESS)return SPI_ERROR_TIMEOUT;
+
+	while(!s1_transferOk)
+	{
+		if(wait_time_out--){
+			nrf_pwr_mgmt_run();
+		}
+		else{
+			SPI1_CsSet(CsPin_number,BOARD_SPI_CS_OFF);				//片选信号关
+			return SPI_ERROR_TIMEOUT;
+		}
+	}																											// Error in SPI or transfer already in progress.
+	
+	SPI1_CsSet(CsPin_number,BOARD_SPI_CS_OFF);						//片选信号关
+	return SPI_OP_SUCCESS;
+}
+static uint32_t SPI2_ReadWriteData(uint32_t CsPin_number, uint8_t *pWriteData, uint8_t writeDataLen, uint8_t *pReadData, uint8_t readDataLen)
+{
+	
+	uint32_t err_code;
+	uint32_t wait_time_out = WAIT_TIME_VALUE;
+
+	if((err_code = SPI2_CsCheck(CsPin_number)) != SPI_OP_SUCCESS)return err_code;
+	
+	SPI2_CsSet(CsPin_number,BOARD_SPI_CS_ON);						//片选信号开
+	
+	s2_transferOk = false;
+	
+	err_code = nrf_drv_spi_transfer(&s2_spiHandle, pWriteData, writeDataLen, pReadData, readDataLen);
+	if(err_code != NRF_SUCCESS)return SPI_ERROR_TIMEOUT;
+
+	while(!s2_transferOk)
+	{
+		if(wait_time_out--){
+			nrf_pwr_mgmt_run();
+		}
+		else{
+			SPI2_CsSet(CsPin_number,BOARD_SPI_CS_OFF);				//片选信号关
+			return SPI_ERROR_TIMEOUT;
+		}
+	}																											// Error in SPI or transfer already in progress.
+	
+	SPI2_CsSet(CsPin_number,BOARD_SPI_CS_OFF);						//片选信号关
+	return SPI_OP_SUCCESS;
+}
+
+/**
+ @brief SPI读写寄存器数据
+ @param CsPin_number -[in] 片选引脚
+ @param reg_addr -[in] 操作的寄存器地址
+ @param ReadWriteFlag -[in] 读写标志位
+ @param pData -[in/out] 指向需要操作的数据
+ @param DataLen -[in] 数据长度
+ @return 错误代码
+*/
+static uint8_t  temp_buff[130];
+static uint32_t SPI0_ReadWriteReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t ReadWriteFlag, uint8_t *pData, uint8_t DataLen)
+{
+	
+	uint32_t 				err_code;
+	uint8_t					addr;
+	
+	if((err_code = SPI0_CsCheck(CsPin_number)) != SPI_OP_SUCCESS)return err_code;
+	if(DataLen > (sizeof(temp_buff)-1))return SPI_ERROR_LENGTH;
+	if(ReadWriteFlag == SPI_READ)
+	{
+		addr = 0x80 | reg_addr;
+		
+		err_code = SPI0_ReadWriteData(CsPin_number, &addr, 1, temp_buff, DataLen+1);	//DataLen+1是因为第一个字节是写地址回应时的垃圾数据
+		if(err_code != SPI_OP_SUCCESS) return err_code;
+		
+		memcpy(pData, &temp_buff[1], DataLen);
+	}
+	else
+	{
+		temp_buff[0] = reg_addr;
+		memcpy(&temp_buff[1], pData, DataLen);
+		
+		err_code = SPI0_ReadWriteData(CsPin_number, temp_buff, DataLen+1, NULL, 0);
+		if(err_code != SPI_OP_SUCCESS) return err_code;
+	}
+	
+	return SPI_OP_SUCCESS;
+}
+static uint32_t SPI1_ReadWriteReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t ReadWriteFlag, uint8_t *pData, uint8_t DataLen)
+{
+	uint32_t 				err_code;
+	uint8_t					addr;
+	
+	if((err_code = SPI1_CsCheck(CsPin_number)) != SPI_OP_SUCCESS)return err_code;
+	if(DataLen > (sizeof(temp_buff)-1))return SPI_ERROR_LENGTH;
+	
+	if(ReadWriteFlag == SPI_READ)
+	{
+		addr = 0x80 | reg_addr;
+		
+		err_code = SPI1_ReadWriteData(CsPin_number, &addr, 1, temp_buff, DataLen+1);	//DataLen+1是因为第一个字节是写地址回应时的垃圾数据
+		if(err_code != SPI_OP_SUCCESS) return err_code;
+		memcpy(pData, &temp_buff[1], DataLen);
+	}
+	else
+	{
+		temp_buff[0] = reg_addr;
+		memcpy(&temp_buff[1], pData, DataLen);
+		
+		err_code = SPI1_ReadWriteData(CsPin_number, temp_buff, DataLen+1, NULL, 0);
+		if(err_code != SPI_OP_SUCCESS) return err_code;
+	}
+	
+	return SPI_OP_SUCCESS;
+}
+static uint32_t SPI2_ReadWriteReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t ReadWriteFlag, uint8_t *pData, uint8_t DataLen)
+{
+	uint32_t 				err_code;
+	uint8_t					addr;
+	
+	if((err_code = SPI2_CsCheck(CsPin_number)) != SPI_OP_SUCCESS)return err_code;
+	if(DataLen > (sizeof(temp_buff)-1))return SPI_ERROR_LENGTH;
+	
+	if(ReadWriteFlag == SPI_READ)
+	{
+		addr = 0x80 | reg_addr;
+		
+		err_code = SPI2_ReadWriteData(CsPin_number, &addr, 1, temp_buff, DataLen+1);	//DataLen+1是因为第一个字节是写地址回应时的垃圾数据
+		if(err_code != SPI_OP_SUCCESS) return err_code;
+		
+		memcpy(pData, &temp_buff[1], DataLen);
+	}
+	else
+	{
+		temp_buff[0] = reg_addr;
+		memcpy(&temp_buff[1], pData, DataLen);
+		
+		err_code = SPI2_ReadWriteData(CsPin_number, temp_buff, DataLen+1, NULL, 0);
+		if(err_code != SPI_OP_SUCCESS) return err_code;
+	}
+	
+	return SPI_OP_SUCCESS;
+}
+
+static void bsp_spi0_init_process(void)
+{
+	if(Except_TxError(EXCEPT_SPI_INIT,"bsp_spi0_init_error\r\n") == 0)
+	{
+		Process_Stop(bsp_spi0_init_process);
+	}
+}
+
+static void bsp_spi1_init_process(void)
+{
+	if(Except_TxError(EXCEPT_SPI_INIT,"bsp_spi1_init_error\r\n") == 0)
+	{
+		Process_Stop(bsp_spi1_init_process);
+	}
+}
+
+static void bsp_spi2_init_process(void)
+{
+	if(Except_TxError(EXCEPT_SPI_INIT,"bsp_spi2_init_error\r\n") == 0)
+	{
+		Process_Stop(bsp_spi2_init_process);
+	}
+}
+
+/*********************************************************************
+ * PUBLIC FUNCTIONS
+ */
+/****************************************************接口****************************************************/
+
+/**
+ @brief SPI的初始化函数
+ @param 无
+ @return 无
+*/
+void SPI0_Init(void)
+{
+	int				 	ret = 0;
+	ret_code_t 	errCode;
+	
+	nrf_drv_spi_config_t spiConfig = NRF_DRV_SPI_DEFAULT_CONFIG;				// 使用SPI默认配置
+	// 配置SPI端口,注意CSN不要在这设置,另外用GPIO口控制
+	spiConfig.miso_pin = BOARD_SPI0_MISO_IO;
+	spiConfig.mosi_pin = BOARD_SPI0_MOSI_IO;
+	spiConfig.sck_pin = BOARD_SPI0_CLK_IO;
+	spiConfig.mode = NRF_DRV_SPI_MODE_0;
+	spiConfig.frequency = SPI0_FREQUENCY;	
+	spiConfig.irq_priority = SPI0_IRQ_PRIORITY;													// 在定时器中使用优先级需小于6
+	
+	errCode = nrf_drv_spi_init(&s0_spiHandle, &spiConfig, spi0CallbackFunc, NULL);
+	if(errCode != NRF_SUCCESS)ret = -1;
+	
+	uint32_t i;
+	for(i = 0; i < SPI0_CS_NUMBER; i++)
+	{
+		nrf_gpio_cfg_output(s0_cs_list[i]);
+	}
+	
+	if(ret == -1)
+	{
+		Process_Start(0,"bsp_spi0_init_process",bsp_spi0_init_process);
+	}
+	
+}
+void SPI1_Init(void)
+{
+	int				 	ret = 0;
+	ret_code_t 	errCode;
+	
+	nrf_drv_spi_config_t spiConfig = NRF_DRV_SPI_DEFAULT_CONFIG;				// 使用SPI默认配置
+	// 配置SPI端口,注意CSN不要在这设置,另外用GPIO口控制
+	spiConfig.miso_pin = BOARD_SPI1_MISO_IO;
+	spiConfig.mosi_pin = BOARD_SPI1_MOSI_IO;
+	spiConfig.sck_pin = BOARD_SPI1_CLK_IO;
+	spiConfig.mode = NRF_DRV_SPI_MODE_0;
+	spiConfig.frequency = SPI1_FREQUENCY;	
+	spiConfig.irq_priority = SPI1_IRQ_PRIORITY;													// 在定时器中使用优先级需小于6
+	
+	errCode = nrf_drv_spi_init(&s1_spiHandle, &spiConfig, spi1CallbackFunc, NULL);
+	if(errCode != NRF_SUCCESS)ret = -1;
+	
+	uint32_t i;
+	for(i = 0; i < SPI1_CS_NUMBER; i++)
+	{
+		nrf_gpio_cfg_output(s1_cs_list[i]);
+	}
+	
+	if(ret == -1)
+	{
+		Process_Start(0,"bsp_spi1_init_process",bsp_spi1_init_process);
+	}
+	
+}
+void SPI2_Init(void)
+{
+	int				 	ret = 0;
+	ret_code_t 	errCode;
+	
+	nrf_drv_spi_config_t spiConfig = NRF_DRV_SPI_DEFAULT_CONFIG;				// 使用SPI默认配置
+	// 配置SPI端口,注意CSN不要在这设置,另外用GPIO口控制
+	spiConfig.miso_pin = BOARD_SPI2_MISO_IO;
+	spiConfig.mosi_pin = BOARD_SPI2_MOSI_IO;
+	spiConfig.sck_pin = BOARD_SPI2_CLK_IO;
+	spiConfig.mode = NRF_DRV_SPI_MODE_0;
+	spiConfig.frequency = SPI2_FREQUENCY;	
+	spiConfig.irq_priority = SPI2_IRQ_PRIORITY;													// 在定时器中使用优先级需小于6
+	
+	errCode = nrf_drv_spi_init(&s2_spiHandle, &spiConfig, spi2CallbackFunc, NULL);
+	if(errCode != NRF_SUCCESS)ret = -1;
+	
+	uint32_t i;
+	for(i = 0; i < SPI2_CS_NUMBER; i++)
+	{
+		nrf_gpio_cfg_output(s2_cs_list[i]);
+	}
+	
+	if(ret == -1)
+	{
+		Process_Start(0,"bsp_spi2_init_process",bsp_spi2_init_process);
+	}
+	
+}
+
+/**
+ @brief SPI只读寄存器数据
+ @param CsPin_number -[in] 片选引脚
+ @param reg_addr -[in] 操作的寄存器地址
+ @param pData -[in/out] 指向需要操作的数据
+ @param DataLen -[in] 数据长度
+ @return 错误代码
+*/
+uint32_t SPI0_OnlyReadReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t *pData, uint8_t DataLen)
+{
+	return SPI0_ReadWriteReg(CsPin_number, reg_addr, SPI_READ, pData, DataLen);
+}
+uint32_t SPI1_OnlyReadReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t *pData, uint8_t DataLen)
+{
+	return SPI1_ReadWriteReg(CsPin_number, reg_addr, SPI_READ, pData, DataLen);
+}
+uint32_t SPI2_OnlyReadReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t *pData, uint8_t DataLen)
+{
+	return SPI2_ReadWriteReg(CsPin_number, reg_addr, SPI_READ, pData, DataLen);
+}
+
+/**
+ @brief SPI只写寄存器数据
+ @param CsPin_number -[in] 片选引脚
+ @param reg_addr -[in] 操作的寄存器地址
+ @param pData -[in/out] 指向需要操作的数据
+ @param DataLen -[in] 数据长度
+ @return 错误代码
+*/
+uint32_t SPI0_OnlyWriteReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t *pData, uint8_t DataLen)
+{
+	return SPI0_ReadWriteReg(CsPin_number, reg_addr, SPI_WRITE, pData, DataLen);
+}
+uint32_t SPI1_OnlyWriteReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t *pData, uint8_t DataLen)
+{
+	return SPI1_ReadWriteReg(CsPin_number, reg_addr, SPI_WRITE, pData, DataLen);
+}
+uint32_t SPI2_OnlyWriteReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t *pData, uint8_t DataLen)
+{
+	return SPI2_ReadWriteReg(CsPin_number, reg_addr, SPI_WRITE, pData, DataLen);
+}
+
+
+/**
+ @brief 开启SPI
+ @param 无
+ @return 错误代码
+*/
+uint32_t SPI0_Enable(void)
+{
+	SPI0_Init();
+	return SPI_OP_SUCCESS;
+}
+uint32_t SPI1_Enable(void)
+{
+	SPI1_Init();
+	return SPI_OP_SUCCESS;
+}
+uint32_t SPI2_Enable(void)
+{
+	SPI2_Init();
+	return SPI_OP_SUCCESS;
+}
+
+/**
+ @brief 禁用SPI
+ @param 无
+ @return 无
+*/
+uint32_t SPI0_Disable(void)
+{
+	
+	uint32_t i;
+	
+	//所有片选信号关
+	for(i = 0; i < SPI0_CS_NUMBER; i++)
+	{
+		SPI0_CsSet(s0_cs_list[i],BOARD_SPI_CS_OFF);		
+		nrf_gpio_cfg_default(s0_cs_list[i]);		
+	}
+	
+	
+	nrf_drv_spi_uninit(&s0_spiHandle);
+
+	nrf_gpio_cfg_default(BOARD_SPI0_MISO_IO);
+	nrf_gpio_cfg_default(BOARD_SPI0_MOSI_IO);
+	nrf_gpio_cfg_default(BOARD_SPI0_CLK_IO);
+	
+	
+	
+	
+	/*I think you're experiencing this increase from this errata since TWI and SPI shares resources internally,
+	this errata may also occur when using SPI. Please try this after disabling the SPI:
+	
+	*(volatile uint32_t *)0x40003FFC = 0;
+	*(volatile uint32_t *)0x40003FFC;
+	*(volatile uint32_t *)0x40003FFC = 1;
+
+	If SPI1 is used the address is 40004FFC.
+	*/
+	
+	//下面的一调用,所有SPI都会关闭!!!
+	
+//	*(volatile uint32_t *)0x40003FFC = 0;
+//	*(volatile uint32_t *)0x40003FFC;
+//	*(volatile uint32_t *)0x40003FFC = 1;
+	
+	return SPI_OP_SUCCESS;
+}
+uint32_t SPI1_Disable(void)
+{
+	
+	uint32_t i;
+	
+	//所有片选信号关
+	for(i = 0; i < SPI1_CS_NUMBER; i++)
+	{
+		SPI1_CsSet(s1_cs_list[i],BOARD_SPI_CS_OFF);		
+		nrf_gpio_cfg_default(s1_cs_list[i]);		
+	}
+	
+	
+	nrf_drv_spi_uninit(&s1_spiHandle);
+
+	nrf_gpio_cfg_default(BOARD_SPI1_MISO_IO);
+	nrf_gpio_cfg_default(BOARD_SPI1_MOSI_IO);
+	nrf_gpio_cfg_default(BOARD_SPI1_CLK_IO);
+	
+	
+	
+	
+	/*I think you're experiencing this increase from this errata since TWI and SPI shares resources internally,
+	this errata may also occur when using SPI. Please try this after disabling the SPI:
+	
+	*(volatile uint32_t *)0x40003FFC = 0;
+	*(volatile uint32_t *)0x40003FFC;
+	*(volatile uint32_t *)0x40003FFC = 1;
+
+	If SPI1 is used the address is 40004FFC.
+	*/
+	
+		//下面的一调用,所有SPI都会关闭!!!
+	
+//	*(volatile uint32_t *)0x40003FFC = 0;
+//	*(volatile uint32_t *)0x40003FFC;
+//	*(volatile uint32_t *)0x40003FFC = 1;
+	
+	return SPI_OP_SUCCESS;
+}
+uint32_t SPI2_Disable(void)
+{
+	
+	uint32_t i;
+	
+	//所有片选信号关
+	for(i = 0; i < SPI2_CS_NUMBER; i++)
+	{
+		SPI2_CsSet(s2_cs_list[i],BOARD_SPI_CS_OFF);		
+		nrf_gpio_cfg_default(s2_cs_list[i]);		
+	}
+	
+	
+	nrf_drv_spi_uninit(&s2_spiHandle);
+
+	nrf_gpio_cfg_default(BOARD_SPI2_MISO_IO);
+	nrf_gpio_cfg_default(BOARD_SPI2_MOSI_IO);
+	nrf_gpio_cfg_default(BOARD_SPI2_CLK_IO);
+	
+	
+	
+	
+	/*I think you're experiencing this increase from this errata since TWI and SPI shares resources internally,
+	this errata may also occur when using SPI. Please try this after disabling the SPI:
+	
+	*(volatile uint32_t *)0x40003FFC = 0;
+	*(volatile uint32_t *)0x40003FFC;
+	*(volatile uint32_t *)0x40003FFC = 1;
+
+	If SPI1 is used the address is 40004FFC.
+	*/
+	
+		//下面的一调用,所有SPI都会关闭!!!
+	
+//	*(volatile uint32_t *)0x40003FFC = 0;
+//	*(volatile uint32_t *)0x40003FFC;
+//	*(volatile uint32_t *)0x40003FFC = 1;
+	
+	return SPI_OP_SUCCESS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 112 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_spi.h

@@ -0,0 +1,112 @@
+#ifndef __BSP_SPI_H__
+#define __BSP_SPI_H__
+
+
+//SPI 1.0V
+
+
+/*********************************************************************
+ * INCLUDES
+ */
+#include "nrf_drv_spi.h"
+#include "nrf_gpio.h"
+#include "nrf_pwr_mgmt.h"
+#include <string.h>
+#include "app_error.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+/*********************************************************************
+ * DEFINITIONS
+ */
+#define BOARD_SPI_CS_ON             0																	// SPI片选信号开
+#define BOARD_SPI_CS_OFF            1																	// SPI片选信号关
+
+#define BOARD_SPI0_MISO_IO          PIN_FRONT_SPI_MISO								// SPI0主输入从输出IO口
+#define BOARD_SPI0_MOSI_IO          PIN_FRONT_SPI_MOSI								// SPI0主输出从输入IO口
+#define BOARD_SPI0_CLK_IO           PIN_FRONT_SPI_SCLK								// SPI0时钟控制IO口
+
+#define SPI0_CS_NUMBER							1																	// SPI0片选引脚数量
+#define BOARD_SPI0_CS0_IO						PIN_FRONT_SPI_nCS									// SPI0片选0信号IO口
+#define SPI0_CS_LIST								{BOARD_SPI0_CS0_IO}								// SPI0片选引脚列表
+
+#define BOARD_SPI1_MISO_IO          PIN_QMA7981_AD0									 	// SPI1主输入从输出IO口
+#define BOARD_SPI1_MOSI_IO          PIN_QMA7981_SDA										// SPI1主输出从输入IO口
+#define BOARD_SPI1_CLK_IO           PIN_QMA7981_SCLK									// SPI1时钟控制IO口
+
+#define SPI1_CS_NUMBER							1																	// SPI1片选引脚数量
+#define BOARD_SPI1_CS0_IO						PIN_QMA7981_nCS										// SPI1片选0信号IO口
+#define SPI1_CS_LIST								{BOARD_SPI1_CS0_IO}								// SPI1片选引脚列表
+
+#define BOARD_SPI2_MISO_IO          0xFF															// SPI2主输入从输出IO口
+#define BOARD_SPI2_MOSI_IO          0xFF															// SPI2主输出从输入IO口
+#define BOARD_SPI2_CLK_IO           0xFF															// SPI2时钟控制IO口
+
+#define SPI2_CS_NUMBER							1																	// SPI2片选引脚数量
+#define BOARD_SPI2_CS0_IO						0xFF															// SPI2片选0信号IO口
+#define SPI2_CS_LIST								{BOARD_SPI2_CS0_IO}								// SPI2片选引脚列表
+
+#define SPI_INSTANCE_0  						0																	// SPI0 instance index 
+
+#define SPI_INSTANCE_1  						1																	// SPI1 instance index 
+
+#define SPI_INSTANCE_2  						2																	// SPI2 instance index 
+
+#define SPI0_FREQUENCY							NRF_DRV_SPI_FREQ_8M								// SPI0 频率
+
+#define SPI1_FREQUENCY							NRF_DRV_SPI_FREQ_1M								// SPI1 频率
+
+#define SPI2_FREQUENCY							NRF_DRV_SPI_FREQ_8M								// SPI2 频率
+
+#define WAIT_TIME_VALUE							3																	// 等待超时最大值
+
+#define SPI_READ           					0x00															//读标志位
+#define SPI_WRITE										0x01															//写标志位
+
+
+//ERROR CODE
+#define SPI_OP_SUCCESS							0x00															// spi操作成功
+#define SPI_ERROR_TIMEOUT						(SPI_OP_SUCCESS+0x01)							// 超时错误
+#define SPI_ERROR_CS								(SPI_OP_SUCCESS+0x02)							// 片选引脚错误
+#define SPI_ERROR_LENGTH						(SPI_OP_SUCCESS+0x03)							// 数据长度太长
+
+/*********************************************************************
+ * API FUNCTIONS
+ */
+ 
+//SPI0初始化
+void 		 SPI0_Init(void);
+//SPI0只读寄存器数据
+uint32_t SPI0_OnlyReadReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t *pData, uint8_t DataLen);
+//SPI0只写寄存器数据
+uint32_t SPI0_OnlyWriteReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t *pData, uint8_t DataLen);
+//开启SPI0
+uint32_t SPI0_Enable(void);
+//禁用SPI0,实现低功耗配合SPI_Enable使用
+uint32_t SPI0_Disable(void);
+
+//SPI1初始化
+void 		 SPI1_Init(void);
+//SPI1只读寄存器数据
+uint32_t SPI1_OnlyReadReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t *pData, uint8_t DataLen);
+//SPI1只写寄存器数据
+uint32_t SPI1_OnlyWriteReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t *pData, uint8_t DataLen);
+//开启SPI1
+uint32_t SPI1_Enable(void);
+//禁用SPI1,实现低功耗配合SPI_Enable使用
+uint32_t SPI1_Disable(void);
+
+//SPI2初始化
+void 		 SPI2_Init(void);
+//SPI2只读寄存器数据
+uint32_t SPI2_OnlyReadReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t *pData, uint8_t DataLen);
+//SPI2只写寄存器数据
+uint32_t SPI2_OnlyWriteReg(uint32_t CsPin_number, uint8_t reg_addr, uint8_t *pData, uint8_t DataLen);
+//开启SPI2
+uint32_t SPI2_Enable(void);
+//禁用SPI2,实现低功耗配合SPI_Enable使用
+uint32_t SPI2_Disable(void);
+
+#endif /* _BOARD_SPI_H_ */
+
+

+ 285 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_time.c

@@ -0,0 +1,285 @@
+#include "sdk_common.h"
+#include "app_timer.h"
+#include "bsp_time.h"
+#include "nrf_drv_timer.h"
+#include "SEGGER_RTT.h"
+#include "system.h"
+#include "app_timer.h"
+#include "nrf_drv_rtc.h"
+#include "nrf_pwr_mgmt.h"
+#include "hal_ser_imu_mode_manage.h"
+#include "exception.h"
+
+/********************** 变量区 *************************/
+static const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(2);
+
+static uint8_t isSleep = 0;
+
+volatile static uint32_t time_1ms = 0;
+#define time_cb_max 32
+static TIME_callback time_cb[time_cb_max]={0};
+
+/********************** 函数声明区 *************************/
+
+static void bsp_rtc_init_process(void)
+{
+	if(Except_TxError(EXCEPT_RTC_INIT,"bsp_rtc_init_error\r\n") == 0)
+	{
+		Process_Stop(bsp_rtc_init_process);
+	}
+}
+
+static void bsp_rtc_config_process(void)
+{
+	if(Except_TxError(EXCEPT_RTC_INIT,"bsp_rtc_config_error\r\n") == 0)
+	{
+		Process_Stop(bsp_rtc_config_process);
+	}
+}
+
+static void rtc_tick_handler(nrf_drv_rtc_int_type_t int_type)
+{
+	uint32_t err_code;
+    if (int_type == NRF_DRV_RTC_INT_COMPARE0)
+    {
+//		SEGGER_RTT_printf(0,"1");
+//		uint32_t tem1 = NRF_RTC0->COUNTER;
+		nrf_drv_rtc_counter_clear(&rtc);
+		err_code = nrf_drv_rtc_cc_set(&rtc,NRF_DRV_RTC_INT_COMPARE0,HeartTime_Interval*33,true);
+		
+		if(err_code != NRF_SUCCESS)
+		{
+			//再来一次还是不行,就上报错误。
+			err_code = nrf_drv_rtc_cc_set(&rtc,NRF_DRV_RTC_INT_COMPARE0,HeartTime_Interval*33,true);
+			if(err_code != NRF_SUCCESS)
+			{
+				Process_Start(0,"bsp_rtc_config_process",bsp_rtc_config_process);
+			}
+		}
+
+		if(isSleep==0){
+			time_1ms+=HeartTime_Interval;
+			for(int i=0;i<time_cb_max;i++) { //SEGGER_RTT_printf(0,"time_cb[%d]=%d\n",i,time_cb[i]);
+				if(time_cb[i]){
+					time_cb[i]((uint32_t*)(&time_1ms));  //回调函数
+				}
+			}
+//			uint32_t tem2 = NRF_RTC0->COUNTER;
+//			if(tem2<tem1) tem2 += 16777216;
+//			if(tem2-tem1>0)	SEGGER_RTT_printf(0,"rtc_tick_handler(%d)\n",tem2-tem1);
+		}
+    }
+    else if (int_type == NRF_DRV_RTC_INT_TICK)
+    {
+//        SEGGER_RTT_printf(0,"NRF_DRV_RTC_INT_TICK(0x%X)\n",NRF_RTC0->COUNTER);
+    }
+}
+
+
+/********************** 外部函数声明区 *************************/
+//=== 系统滴答时间 ===//
+uint32_t TIME_GetTicks(void)
+{
+	return time_1ms;
+}
+
+int TIME_Regist(TIME_callback cb)
+{
+	for(int i=0;i<time_cb_max;i++) {
+		if(time_cb[i]==cb) return -2;
+		if(time_cb[i]==0){
+			time_cb[i] = cb;  //回调函数
+			return 0;
+		}
+	}
+	return -1;
+}
+
+int TIME_UnRegist(TIME_callback cb)
+{
+	for(int i=0;i<time_cb_max;i++){
+		if(time_cb[i] == cb){
+			time_cb[i] = 0;
+			return 0;
+		}
+	}
+	return -1;
+}
+//int CheckPending_IRQ(int *result,int result_size)
+//{
+//        int index = 0,i = 0;
+//        
+//        /* Check which interrupt is pending. Will not work properly if there are more than one pending */
+//        for (i = POWER_CLOCK_IRQn; i <= FPU_IRQn; i++)
+//        {
+//                        if (NVIC_GetPendingIRQ(i))
+//                        {
+//                                        if(index < result_size)result[index++] = i;
+//                        }
+//        }
+
+//        return index;
+//}
+
+//static void idle_state_handle(void)
+//{
+//    ret_code_t         err_code;
+//                int                                        pending_number_before = 0,pending_number_after = 0;
+//                int                                 result[2][60],i;
+//                uint32_t                 region_start,region_end,p_evt_id_before = 0xff,p_evt_id_after = 0xff,ispr0_before = 0,ispr0_after = 0,ispr1_before = 0,ispr1_after = 0;
+
+////    err_code = nrf_ble_lesc_request_handler();
+////    APP_ERROR_CHECK(err_code);
+//                
+
+//                CRITICAL_REGION_ENTER();
+//        
+//        
+//                region_start = NRF_RTC2->COUNTER;
+//                pending_number_before = CheckPending_IRQ(&result[0][0],60);
+//                sd_evt_get(&p_evt_id_before);
+//                ispr0_before = NVIC->ISPR[0];
+//                ispr1_before = NVIC->ISPR[1];
+//                
+//                nrf_pwr_mgmt_run();
+//                
+//                ispr0_after = NVIC->ISPR[0];
+//                ispr1_after = NVIC->ISPR[1];
+//                sd_evt_get(&p_evt_id_after);
+//                pending_number_after = CheckPending_IRQ(&result[1][0],60);
+//                region_end = NRF_RTC2->COUNTER;
+//        
+//        
+//                CRITICAL_REGION_EXIT();
+//        
+//                SEGGER_RTT_printf(0,"*******wakeup result start*******\n");
+//                
+//                if (pending_number_before)
+//                { 
+//                                for(i=0;i<pending_number_before;i++)SEGGER_RTT_printf(0,"pending_total_before[%d]:%d\n",i,result[0][i]);
+//                                memset(&result[0][0],0,60);
+//                }
+//                
+//                if(p_evt_id_before != 0xff)SEGGER_RTT_printf(0,"p_evt_id_before:%d\n",p_evt_id_before);
+//                
+//                if (pending_number_after)
+//                { 
+//                                for(i=0;i<pending_number_after;i++)SEGGER_RTT_printf(0,"pending_total_after[%d]:%d\n",i,result[1][i]);
+//                                memset(&result[1][0],0,60);
+//                }
+//                
+//                if(p_evt_id_after != 0xff)SEGGER_RTT_printf(0,"p_evt_id_after:%d\n",p_evt_id_after);
+//                
+//                SEGGER_RTT_printf(0,"before---NVIC->ISPR[0]:0x%X, NVIC->ISPR[1]:0x%X\n",ispr0_before,ispr1_before);
+//                SEGGER_RTT_printf(0,"after----NVIC->ISPR[0]:0x%X, NVIC->ISPR[1]:0x%X\n",ispr0_after,ispr1_after);
+//                
+//                SEGGER_RTT_printf(0,"*******wakeup result end*******\n");
+//                
+//                SEGGER_RTT_printf (0,"region times: %d\n",region_end-region_start);
+
+//}
+
+uint32_t rtc_sleep(uint8_t is_wearshoes)
+{
+	uint32_t tem1 = NRF_RTC0->COUNTER;
+	uint32_t ret = 0;
+	uint32_t err_code;
+	isSleep = 1;
+
+	if(is_wearshoes==0)
+	{	
+		err_code = nrf_drv_rtc_cc_set(&rtc,0,StandByPower_Interval * 33,true);
+		if(err_code != NRF_SUCCESS)
+		{
+			//再来一次还是不行,就上报错误。
+			err_code = nrf_drv_rtc_cc_set(&rtc,0,StandByPower_Interval * 33,true);
+			if(err_code != NRF_SUCCESS)
+			{
+				Process_Start(0,"bsp_rtc_config_process",bsp_rtc_config_process);
+			}
+		}
+	}
+	else 
+	{ 
+		err_code = nrf_drv_rtc_cc_set(&rtc,0,LowPower_Interval * 33,true);
+		if(err_code != NRF_SUCCESS)
+		{
+			//再来一次还是不行,就上报错误。
+			err_code = nrf_drv_rtc_cc_set(&rtc,0,LowPower_Interval * 33,true);
+			if(err_code != NRF_SUCCESS)
+			{
+				Process_Start(0,"bsp_rtc_config_process",bsp_rtc_config_process);
+			}
+		}
+	}
+	nrf_drv_rtc_counter_clear(&rtc);
+	while(nrf_drv_rtc_counter_get(&rtc) != 0);
+	//进入睡眠
+	for(int i=0;i<5;i++){
+		uint32_t cnt1 = NRF_RTC0->COUNTER;
+		nrf_pwr_mgmt_run();
+//		idle_state_handle();
+		uint32_t cnt2 = NRF_RTC0->COUNTER;
+		if(cnt2<cnt1) cnt2 += 16777216;
+		if(cnt2-cnt1>32) break;
+	}
+	
+	err_code = nrf_drv_rtc_cc_set(&rtc,0,HeartTime_Interval*33,true); 
+	if(err_code != NRF_SUCCESS)
+	{
+		//再来一次还是不行,就上报错误。
+		err_code = nrf_drv_rtc_cc_set(&rtc,0,HeartTime_Interval*33,true); 
+		if(err_code != NRF_SUCCESS)
+		{
+			Process_Start(0,"bsp_rtc_config_process",bsp_rtc_config_process);
+		}
+	}
+	nrf_drv_rtc_counter_clear(&rtc);
+	while(nrf_drv_rtc_counter_get(&rtc) != 0);
+	isSleep = 0;
+	uint32_t tem2 = NRF_RTC0->COUNTER;
+	if(tem2<tem1) tem2 += 16777216;
+	ret = (tem2-tem1)/32.768;
+	return ret;
+}
+
+static void cb_timeeWakeup(uint32_t t)
+{
+	time_1ms += t;
+	//SEGGER_RTT_printf(0,"cb_timeeWakeup(%d)\n",time_1ms);
+}
+
+
+//=== 系统滴答时间初始化 ===//
+void TIME_Init(void)
+{
+	int 				ret = 0;
+	ret_code_t 	errCode;
+	
+	nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
+	config.interrupt_priority = RTC2_IRQ_PRIORITY;												
+	config.prescaler = 0;// f(RTC) = 32.768kHZ/(prescaler+1) = 8HZ = 125ms
+	errCode = nrf_drv_rtc_init(&rtc, &config, rtc_tick_handler); 
+	if(errCode != NRF_SUCCESS)ret = -1;
+	
+	errCode = nrf_drv_rtc_cc_set(&rtc,NRF_DRV_RTC_INT_COMPARE0,HeartTime_Interval*33,true);
+	if(errCode != NRF_SUCCESS)
+	{
+		//再来一次还是不行,就上报错误。
+		errCode = nrf_drv_rtc_cc_set(&rtc,NRF_DRV_RTC_INT_COMPARE0,HeartTime_Interval*33,true);
+		if(errCode != NRF_SUCCESS)
+		{
+			Process_Start(0,"bsp_rtc_config_process",bsp_rtc_config_process);
+		}
+	}
+	nrf_drv_rtc_counter_clear(&rtc);
+	nrf_drv_rtc_enable(&rtc);
+
+	Wakeup_Regist(cb_timeeWakeup);
+	
+	if(ret == -1)
+	{
+		Process_Start(0,"bsp_rtc_init_process",bsp_rtc_init_process);
+	}
+}
+

+ 18 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_time.h

@@ -0,0 +1,18 @@
+#ifndef __bsp_time_h__
+#define __bsp_time_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+typedef void (*TIME_callback)(void*);
+
+void TIME_Init(void);
+uint32_t TIME_GetTicks(void);
+int TIME_Regist(TIME_callback cb);
+int TIME_UnRegist(TIME_callback cb);
+uint32_t rtc_sleep(uint8_t is_wearshoes);
+
+#endif

+ 149 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_uart.c

@@ -0,0 +1,149 @@
+#include "bsp_uart.h"
+
+/********************** 环形缓存区 *************************/
+static const int  RxLen = 1024;
+static volatile unsigned char RxBuf[RxLen];
+static volatile unsigned char* RxW=RxBuf;
+static volatile unsigned char* RxR=RxBuf;
+
+void UART0_Push(unsigned char* p,int len)
+{
+	volatile unsigned char *W=RxW; //这里要与上面指针相同
+	if(len<=0) return;
+	for(int i=0;i<len;i++){
+		W=RxW+1; if(W>=RxBuf+RxLen) W=RxBuf;        //取下一位置(到顶转到底)
+		if(W!=RxR){*RxW=*(p+i); RxW=W;}
+		else break;
+	}
+}
+
+unsigned int UART0_CheckLen(void) //检查RX接收了多少数据
+{   
+	unsigned int Len; //short 
+	volatile unsigned char *W=RxW; volatile unsigned char *R=RxR; 
+	if(W>=R)Len=W-R;else Len=(W+RxLen)-R;         //这样正确(中途中断改变也变不了结果)
+    return Len; 
+}
+
+unsigned char UART0_ReadByte(void)   //读RX中数锯,地指加一,和丢弃
+{	
+	unsigned char R=*RxR;       //读数
+	if(RxR!=RxW){	if(RxR+1>=(RxBuf+RxLen))RxR =RxBuf; else RxR++;}//下标
+	return R; 
+}
+
+unsigned char UART0_CheckByte(unsigned short n) //看RX中数锯,地指不变, 
+{  	
+	volatile unsigned char *R=RxR+n; 
+	if(R>=(RxBuf+RxLen))R-=RxLen; 
+	return *R; 
+}	
+
+void UART0_Discard(unsigned short n) //丢弃RX数据几位  
+{	
+	while(n){ n--;  
+		if(RxR==RxW) return; 
+		if(RxR+1>=RxBuf+RxLen){RxR=RxBuf;} else RxR++; //下标 
+	}	
+}
+
+void UART0_SendChar(unsigned char ch)//发送一位数锯
+{	
+	NRF_UART0->TXD = (unsigned int)ch;
+	while(NRF_UART0->EVENTS_TXDRDY == 0x0UL);
+	NRF_UART0->EVENTS_TXDRDY = 0x0UL;
+}	
+
+void UART0_SendBuff(unsigned char *p,int L)//发送缓存
+{	
+	unsigned int len = L;
+    while (len>0){len--;
+		UART0_SendChar(*p++);
+    }
+}   
+
+void UART0_SendStr(char *p)//发送字符串
+{	
+	while (*p){
+		UART0_SendChar(*p++);
+    }
+} 
+
+void UART0_Test(void)
+{
+	while(UART0_CheckLen()>0){
+//		SEGGER_RTT_printf(0,"%02X ",UART0_ReadByte());
+		SEGGER_RTT_printf(0,"%c",UART0_ReadByte());
+	}
+}
+
+//*****************************************************************//
+void UARTE0_UART0_IRQHandler(void)
+{
+	volatile unsigned char *W=RxW; //这里要与上面指针相同
+	if(NRF_UART0->EVENTS_RXDRDY!=0){NRF_UART0->EVENTS_RXDRDY=0;	
+		W=RxW+1; if(W>=RxBuf+RxLen) W=RxBuf;        //取下一位置(到顶转到底)
+		if(W!=RxR){*RxW=NRF_UART0->RXD; RxW=W;}
+	}
+	if(NRF_UART0->EVENTS_RXTO!=0){NRF_UART0->EVENTS_RXTO=0;
+		//SEGGER_RTT_printf(0,"EVENTS_RXTO\n");
+	}
+	if(NRF_UART0->EVENTS_CTS!=0){NRF_UART0->EVENTS_CTS=0;
+		//SEGGER_RTT_printf(0,"EVENTS_CTS\n");
+	}
+	if(NRF_UART0->EVENTS_NCTS!=0){NRF_UART0->EVENTS_NCTS=0;
+		//SEGGER_RTT_printf(0,"EVENTS_NCTS\n");
+	}
+	if(NRF_UART0->EVENTS_TXDRDY!=0){//NRF_UART0->EVENTS_TXDRDY=0;
+		//SEGGER_RTT_printf(0,"EVENTS_TXDRDY\n");
+	}
+	if(NRF_UART0->EVENTS_ERROR!=0){NRF_UART0->EVENTS_ERROR=0;
+		//SEGGER_RTT_printf(0,"EVENTS_ERROR=%d\n",NRF_UART0->EVENTS_ERROR);
+	}
+}
+
+
+
+
+
+uint32_t get_baud(uint32_t baud)
+{
+	switch(baud){
+		case 1200:		return UART_BAUDRATE_BAUDRATE_Baud1200; 	
+		case 2400: 		return UART_BAUDRATE_BAUDRATE_Baud2400; 	
+		case 4800: 		return UART_BAUDRATE_BAUDRATE_Baud4800; 	
+		case 9600: 		return UART_BAUDRATE_BAUDRATE_Baud9600; 	
+		case 14400: 	return UART_BAUDRATE_BAUDRATE_Baud14400; 	
+		case 19200: 	return UART_BAUDRATE_BAUDRATE_Baud19200; 	
+		case 28800: 	return UART_BAUDRATE_BAUDRATE_Baud28800; 	
+		case 31250: 	return UART_BAUDRATE_BAUDRATE_Baud31250; 	
+		case 38400: 	return UART_BAUDRATE_BAUDRATE_Baud38400; 	
+		case 56000: 	return UART_BAUDRATE_BAUDRATE_Baud56000; 	
+		case 57600: 	return UART_BAUDRATE_BAUDRATE_Baud57600; 	
+		case 76800: 	return UART_BAUDRATE_BAUDRATE_Baud76800; 	
+		case 115200: 	return UART_BAUDRATE_BAUDRATE_Baud115200; 	
+		case 230400: 	return UART_BAUDRATE_BAUDRATE_Baud230400; 	
+		case 250000: 	return UART_BAUDRATE_BAUDRATE_Baud250000; 	
+		case 460800: 	return UART_BAUDRATE_BAUDRATE_Baud460800; 	
+		case 921600: 	return UART_BAUDRATE_BAUDRATE_Baud921600; 	
+		case 1000000: 	return UART_BAUDRATE_BAUDRATE_Baud1M; 		
+		default: 		return UART_BAUDRATE_BAUDRATE_Baud115200; 	
+	}
+}
+
+void UART0_Init(uint32_t baud)
+{
+	NRF_UART0->INTENCLR = UART_INTENCLR_CTS_Msk | UART_INTENCLR_RXTO_Msk | UART_INTENCLR_NCTS_Msk | UART_INTENCLR_ERROR_Msk;
+	NRF_UART0->INTENSET = UART_INTENSET_RXDRDY_Enabled << UART_INTENSET_RXDRDY_Pos;
+	NRF_UART0->PSELTXD = PIN_TXD_BLE;
+	NRF_UART0->PSELRXD = PIN_RXD_BLE;
+	
+	NRF_UART0->BAUDRATE = get_baud(baud);
+	NRF_UART0->ENABLE |= UART_ENABLE_ENABLE_Enabled;
+	NRF_UART0->TASKS_STARTTX = 0XFFFFFFFF;
+	NRF_UART0->TASKS_STARTRX = 0XFFFFFFFF;
+	NVIC_SetPriority(UARTE0_UART0_IRQn, 7);
+	NVIC_EnableIRQ(UARTE0_UART0_IRQn);
+	NRF_UART0->EVENTS_TXDRDY = 0x0UL;
+}
+

+ 20 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_uart.h

@@ -0,0 +1,20 @@
+#ifndef __bsp_uart_h__
+#define __bsp_uart_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void UART0_Init(uint32_t baud);
+void UART0_SendStr(char *p);//发送字符串
+void UART0_SendBuff(unsigned char *p,int L);//发送缓存
+void UART0_SendChar(unsigned char ch);//发送一位数锯
+void UART0_Discard(unsigned short n); //丢弃RX数据几位  
+unsigned char UART0_CheckByte(unsigned short n); //看RX中数锯,地指不变, 
+unsigned char UART0_ReadByte(void);   //读RX中数锯,地指加一,和丢弃
+unsigned int UART0_CheckLen(void); //检查RX接收了多少数据
+void UART0_Test(void);
+
+#endif

+ 65 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_wdt.c

@@ -0,0 +1,65 @@
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "nrf_drv_pwm.h"
+#include "usr_config.h"
+#include "nrf_drv_wdt.h"
+#include "system.h"
+#include "bsp_time.h"
+#include "nrf_delay.h"
+#include "exception.h"
+
+nrf_drv_wdt_channel_id m_channel_id;
+
+void feed_watchdog(void)
+{
+    nrf_drv_wdt_channel_feed(m_channel_id); 
+}
+
+/**
+ * @brief WDT events handler.
+ */
+//extern const char *Test;
+void wdt_event_handler(void)
+{
+//	SEGGER_RTT_printf(0,"wdt_event_handler:%d,process name:%d\n",TIME_GetTicks(),Test);
+	Except_Unkown_Reset_WDT_Set();
+}
+
+static void WatchDog_Process(void)
+{
+	 feed_watchdog();
+//	 SEGGER_RTT_printf(0,"WatchDog_Process:%d\n",TIME_GetTicks());
+}
+
+static void bsp_wdt_init_process(void)
+{
+	if(Except_TxError(EXCEPT_WDT_INIT,"bsp_wdt_init_error\r\n") == 0)
+	{
+		Process_Stop(bsp_wdt_init_process);
+	}
+}
+
+void watchdog_init(void){
+	
+	int 				ret = 0;
+	ret_code_t 	errCode;
+	
+	nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;
+	config.interrupt_priority = WDT_IRQ_PRIORITY;
+	config.reload_value = WDT_RELOAD_VALUE;
+	errCode = nrf_drv_wdt_init(&config, wdt_event_handler);
+	if(errCode != NRF_SUCCESS)ret = -1;
+	
+	errCode = nrf_drv_wdt_channel_alloc(&m_channel_id);
+	if(errCode != NRF_SUCCESS)ret = -1;
+	
+	nrf_drv_wdt_enable();
+
+	Process_Start(1000,"WatchDog_Process",WatchDog_Process);
+	
+	if(ret == -1)
+	{
+		Process_Start(0,"bsp_wdt_init_process",bsp_wdt_init_process);
+	}
+}
+

+ 13 - 0
shoe_mcu_2022_4_2_QMA7981_IOv2_pwm_v2/bsp/bsp_wdt.h

@@ -0,0 +1,13 @@
+#ifndef __bsp_wdt_h__
+#define __bsp_wdt_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+void watchdog_init(void);
+void feed_watchdog(void);
+
+#endif

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels