zhengxuelong 2 years ago
parent
commit
d53091eed9
100 changed files with 13852 additions and 0 deletions
  1. 52 0
      sotfware/03_Test/myTest_templet-20220722/.gitignore
  2. BIN
      sotfware/03_Test/myTest_templet-20220722/Picture/Down.png
  3. BIN
      sotfware/03_Test/myTest_templet-20220722/Picture/Hotkey.png
  4. BIN
      sotfware/03_Test/myTest_templet-20220722/Picture/config.png
  5. 26 0
      sotfware/03_Test/myTest_templet-20220722/README.md
  6. 137 0
      sotfware/03_Test/myTest_templet-20220722/app/app_Calibration.c
  7. 19 0
      sotfware/03_Test/myTest_templet-20220722/app/app_Calibration.h
  8. 488 0
      sotfware/03_Test/myTest_templet-20220722/app/app_ImuCalibration.c
  9. 13 0
      sotfware/03_Test/myTest_templet-20220722/app/app_ImuCalibration.h
  10. 171 0
      sotfware/03_Test/myTest_templet-20220722/app/app_baseinfo.c
  11. 15 0
      sotfware/03_Test/myTest_templet-20220722/app/app_baseinfo.h
  12. 15 0
      sotfware/03_Test/myTest_templet-20220722/app/app_charge/app_charge.h
  13. 139 0
      sotfware/03_Test/myTest_templet-20220722/app/app_charge/app_charge_NoPowerEnPin.c
  14. 58 0
      sotfware/03_Test/myTest_templet-20220722/app/app_client.c
  15. 16 0
      sotfware/03_Test/myTest_templet-20220722/app/app_client.h
  16. 54 0
      sotfware/03_Test/myTest_templet-20220722/app/app_client_dataupdate.c
  17. 15 0
      sotfware/03_Test/myTest_templet-20220722/app/app_client_dataupdate.h
  18. 96 0
      sotfware/03_Test/myTest_templet-20220722/app/app_client_infomation.c
  19. 16 0
      sotfware/03_Test/myTest_templet-20220722/app/app_client_infomation.h
  20. 155 0
      sotfware/03_Test/myTest_templet-20220722/app/app_client_step.c
  21. 18 0
      sotfware/03_Test/myTest_templet-20220722/app/app_client_step.h
  22. 208 0
      sotfware/03_Test/myTest_templet-20220722/app/app_config.c
  23. 12 0
      sotfware/03_Test/myTest_templet-20220722/app/app_config.h
  24. 197 0
      sotfware/03_Test/myTest_templet-20220722/app/app_connect_manage.c
  25. 12 0
      sotfware/03_Test/myTest_templet-20220722/app/app_connect_manage.h
  26. 70 0
      sotfware/03_Test/myTest_templet-20220722/app/app_err.c
  27. 25 0
      sotfware/03_Test/myTest_templet-20220722/app/app_err.h
  28. 810 0
      sotfware/03_Test/myTest_templet-20220722/app/app_flash.c
  29. 144 0
      sotfware/03_Test/myTest_templet-20220722/app/app_flash.h
  30. 149 0
      sotfware/03_Test/myTest_templet-20220722/app/app_game.c
  31. 17 0
      sotfware/03_Test/myTest_templet-20220722/app/app_game.h
  32. 99 0
      sotfware/03_Test/myTest_templet-20220722/app/app_host.c
  33. 26 0
      sotfware/03_Test/myTest_templet-20220722/app/app_host.h
  34. 38 0
      sotfware/03_Test/myTest_templet-20220722/app/app_losspack.c
  35. 17 0
      sotfware/03_Test/myTest_templet-20220722/app/app_losspack.h
  36. 156 0
      sotfware/03_Test/myTest_templet-20220722/app/app_math.c
  37. 15 0
      sotfware/03_Test/myTest_templet-20220722/app/app_math.h
  38. 55 0
      sotfware/03_Test/myTest_templet-20220722/app/app_organ.c
  39. 12 0
      sotfware/03_Test/myTest_templet-20220722/app/app_organ.h
  40. 223 0
      sotfware/03_Test/myTest_templet-20220722/app/app_ota - 副本.c
  41. 195 0
      sotfware/03_Test/myTest_templet-20220722/app/app_ota.c
  42. 13 0
      sotfware/03_Test/myTest_templet-20220722/app/app_ota.h
  43. 132 0
      sotfware/03_Test/myTest_templet-20220722/app/app_overturn.c
  44. 14 0
      sotfware/03_Test/myTest_templet-20220722/app/app_overturn.h
  45. 237 0
      sotfware/03_Test/myTest_templet-20220722/app/app_pair.c
  46. 18 0
      sotfware/03_Test/myTest_templet-20220722/app/app_pair.h
  47. 13 0
      sotfware/03_Test/myTest_templet-20220722/app/app_power/app_power.h
  48. 65 0
      sotfware/03_Test/myTest_templet-20220722/app/app_power/app_power_NoPowerEnPin.c
  49. 559 0
      sotfware/03_Test/myTest_templet-20220722/app/app_self_checking.c
  50. 27 0
      sotfware/03_Test/myTest_templet-20220722/app/app_self_checking.h
  51. 119 0
      sotfware/03_Test/myTest_templet-20220722/app/app_step.c
  52. 14 0
      sotfware/03_Test/myTest_templet-20220722/app/app_step.h
  53. 48 0
      sotfware/03_Test/myTest_templet-20220722/app/app_switchimu.c
  54. 19 0
      sotfware/03_Test/myTest_templet-20220722/app/app_switchimu.h
  55. 120 0
      sotfware/03_Test/myTest_templet-20220722/ble_cfg/ble_comm.h
  56. 699 0
      sotfware/03_Test/myTest_templet-20220722/ble_cfg/cli.c
  57. 100 0
      sotfware/03_Test/myTest_templet-20220722/ble_cfg/cli.h
  58. 593 0
      sotfware/03_Test/myTest_templet-20220722/ble_cfg/cli_vt100.h
  59. 180 0
      sotfware/03_Test/myTest_templet-20220722/ble_cfg/dtalige.c
  60. 602 0
      sotfware/03_Test/myTest_templet-20220722/ble_cfg/host.c
  61. 46 0
      sotfware/03_Test/myTest_templet-20220722/ble_cfg/queue.c
  62. 76 0
      sotfware/03_Test/myTest_templet-20220722/ble_cfg/queue.h
  63. 82 0
      sotfware/03_Test/myTest_templet-20220722/ble_cfg/ringframe.c
  64. 62 0
      sotfware/03_Test/myTest_templet-20220722/ble_cfg/ringframe.h
  65. 1615 0
      sotfware/03_Test/myTest_templet-20220722/ble_cfg/slave.c
  66. 177 0
      sotfware/03_Test/myTest_templet-20220722/ble_cfg/timeslot.c
  67. 325 0
      sotfware/03_Test/myTest_templet-20220722/ble_dfu/ble_dfu.c
  68. 249 0
      sotfware/03_Test/myTest_templet-20220722/ble_dfu/ble_dfu.h
  69. 367 0
      sotfware/03_Test/myTest_templet-20220722/ble_dfu/ble_dfu_bonded.c
  70. 299 0
      sotfware/03_Test/myTest_templet-20220722/ble_dfu/ble_dfu_unbonded.c
  71. 232 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_adc.c
  72. 59 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_adc.h
  73. 190 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_esb.c
  74. 20 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_esb.h
  75. 506 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_flash.c
  76. 72 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_flash.h
  77. 16 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_gpio.c
  78. 12 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_gpio.h
  79. 230 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_interface.c
  80. 10 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_interface.h
  81. 84 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_mpu9250.c
  82. 143 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_mpu9250.h
  83. 91 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_ms5611.c
  84. 10 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_ms5611.h
  85. 32 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_protocol.c
  86. 32 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_protocol.h
  87. 234 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_pwm.c
  88. 63 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_pwm.h
  89. 13 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_pwm/bsp_pwm.h
  90. 92 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_pwm/bsp_pwm_led_gpio.c
  91. 65 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_pwm/bsp_pwm_led_ws2812.c
  92. 144 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_rtc.c
  93. 19 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_rtc.h
  94. 206 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_time.c
  95. 18 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_time.h
  96. 149 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_uart.c
  97. 20 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_uart.h
  98. 44 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_wdt.c
  99. 14 0
      sotfware/03_Test/myTest_templet-20220722/bsp/bsp_wdt.h
  100. 179 0
      sotfware/03_Test/myTest_templet-20220722/bsp/nrfx_prs.c

+ 52 - 0
sotfware/03_Test/myTest_templet-20220722/.gitignore

@@ -0,0 +1,52 @@
+# Prerequisites
+*.d
+
+# Object files
+*.o
+*.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
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Kernel Module Compile Results
+*.mod*
+*.cmd
+.tmp_versions/
+modules.order
+Module.symvers
+Mkfile.old
+dkms.conf

BIN
sotfware/03_Test/myTest_templet-20220722/Picture/Down.png


BIN
sotfware/03_Test/myTest_templet-20220722/Picture/Hotkey.png


BIN
sotfware/03_Test/myTest_templet-20220722/Picture/config.png


+ 26 - 0
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
+
+
+

+ 15 - 0
sotfware/03_Test/myTest_templet-20220722/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
+
+

+ 139 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_charge/app_charge_NoPowerEnPin.c

@@ -0,0 +1,139 @@
+#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_err.h"
+#include "app_charge.h"
+#include "app_flash.h"
+#include "hal_battery.h"
+#include "hal_ble_uart0.h"
+#include "ble_comm.h"
+#include "hal_mt.h"
+
+/************************ 函数声明 ***********************************/
+void app_charge_Process(void);
+void cb_BLE_Client_T_CHARGE(void* handle);
+
+/************************ 变量 ***********************************/
+static uint8_t app_charge_state = BLE_Client_T_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)
+{
+	app_charge_Vol_Send(BLE_CHAR_VOL); //共享充电电量
+	
+	uint32_t ch = nrf_gpio_pin_read(PIN_CHARGING);
+	
+//		SEGGER_RTT_printf(0,"charge state:%d\n",ch);
+	if(!ch){	//没充电
+		if(app_charge_state!=BLE_Client_T_CHARGE_PULLOUT){ SEGGER_RTT_printf(0,"charge out...\n");
+			app_charge_state = BLE_Client_T_CHARGE_PULLOUT;
+			Process_SetHoldOn(app_charge_Process,0);
+			LED_Stop(LED_CHARGE);
+			send_charge();
+		}
+		return;
+	}
+	//进入充电状态
+	uint8_t ble_connect =0;
+	if(mFlash.isHost){
+		 ble_connect = host_isconnect();
+	}
+	else{
+		 ble_connect = slave_isconnect();
+	}
+	
+	if(ble_connect && GetBatteryPersent()>=100 && OtherShoesVol>=100){	//充满
+		if(app_charge_state!=BLE_Client_T_CHARGE_DONE){ SEGGER_RTT_printf(0,"charge done:%d...\n",OtherShoesVol);
+			app_charge_state = BLE_Client_T_CHARGE_DONE;
+			Process_SetHoldOn(app_charge_Process,1);
+			LED_Start(LED_CHARGE,COLOR_GREEN);
+			send_charge();
+		}
+	}else{	//正在充电
+		if(app_charge_state!=BLE_Client_T_CHARGE_INSERT){ SEGGER_RTT_printf(0,"charge in...\n");
+			app_charge_state = BLE_Client_T_CHARGE_INSERT;
+			Process_SetHoldOn(app_charge_Process,1);
+			LED_Start(LED_CHARGE,COLOR_ORANGE);
+			send_charge();
+			MT_Run(100);
+			char buf[16];
+			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);
+		}
+	}
+}
+
+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(100,"app_charge",app_charge_Process);
+	app_charge_Process();
+}
+
+

+ 58 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_client.c

@@ -0,0 +1,58 @@
+#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 "app_client_infomation.h"
+#include "app_client_dataupdate.h"
+#include "hal_mode_manage.h"
+
+ //>> 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
+			if(mFlash.isHost)
+				  app_host_GetClientInfo(); //申请设备基本信息
+		  else
+				  app_client_infomation_Send();
+			break;}
+		case BLE_Client_R_UPDATE_DATA:{
+			//>> 1(设备数据)
+			//<< 1(子命令): 左鞋电量(1)+左鞋温度(1)+左鞋压力(4)+左鞋步数(4)+右鞋电量(1)+右鞋温度(1)+右鞋压力(4)+右鞋步数(4)
+			if(mFlash.isHost)
+				app_host_GetClientData(20);
+			else
+				app_client_DataUpdate_Send();
+			break;}
+		case BLE_Client_R_UPDATE_STEPNUM:{
+			//>> 2(查询步数): 包序号[0全部](2)
+			//<< 2(查询步数): +开始时间ms(8)+包的数量(2)+包序号(2)+每小时步数(4)+...
+			if(HAL_MODE_REALSTEP != hal_mode_get())app_client_SendStep(target);
+			break;}
+		case BLE_Client_R_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;
+	}
+}
+
+void app_client_Initialize(void)
+{
+	BLE_Client_Rx_Regist(BLE_UPDATE,cb_BLE_Client_R_UPDATE);
+	app_client_step_Initialize();
+}

+ 16 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_client.h

@@ -0,0 +1,16 @@
+#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);
+
+#endif
+
+
+

+ 54 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_client_dataupdate.c

@@ -0,0 +1,54 @@
+#include "system.h"
+#include "app_client_dataupdate.h"
+#include "hal_ble_client.h"
+#include "app_flash.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "app_host.h"
+#include "app_step.h"
+#include "hal_battery.h"
+#include "hal_imu.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; 
+
+//	SEGGER_RTT_printf(0,"temperature=%d\n",temperature);
+//	SEGGER_RTT_printf(0,"press=%d\n",press);
+	
+	//子命令
+	buf[L++] = BLE_Client_T_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);
+}

+ 15 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_client_dataupdate.h

@@ -0,0 +1,15 @@
+#ifndef __app_client_dataupdate_h__
+#define __app_client_dataupdate_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_DataUpdate_Send(void);
+
+#endif
+
+
+

+ 96 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_client_infomation.c

@@ -0,0 +1,96 @@
+#include "system.h"
+#include "app_client_infomation.h"
+#include "app_flash.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "app_host.h"
+#include "app_step.h"
+#include "hal_ble_client.h"
+#include "ble_gap.h"
+
+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_Client_T_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)((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);
+	
+	//右鞋mac地址
+	for(int i=0;i<6;i++) buf[L++] = mFlash.mClient.macAddr[i];
+	
+	//右鞋硬件版本
+	//buf[L++] = (uint8_t)(mFlash.mClient.hardVersion>>8);
+	//buf[L++] = (uint8_t)(mFlash.mClient.hardVersion>>0);
+	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);
+	
+	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_Client_T_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)((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);
+	
+	//右鞋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)(mFlash.mClient.hardVersion>>8);
+	//buf[L++] = (uint8_t)(mFlash.mClient.hardVersion>>0);
+	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);
+	
+	BLE_Client_Tx_Send(0,BLE_UPDATE,buf,L);
+}
+

+ 16 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_client_infomation.h

@@ -0,0 +1,16 @@
+#ifndef __app_client_infomation_h__
+#define __app_client_infomation_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_infomation_Send(void);
+void app_client_infomation_Send_defineName(uint8_t name[],uint8_t lenth);
+
+#endif
+
+
+

+ 155 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_client_step.c

@@ -0,0 +1,155 @@
+#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 uint32_t timeCNT = 0;
+
+static uint8_t isScan = 0;
+uint8_t app_client_step_GetIsScan(void)
+{
+	return isScan;
+}
+
+static void app_client_step_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;
+//	SEGGER_RTT_printf(0,"timeCNT(%d)(%d)\n",timeCNT,sec);
+	
+	if(sec>=60*60-10) isScan = 1;
+	if(sec>=60*60){ 
+		SEGGER_RTT_printf(0,"====>1 hour:%d,%d,%d\n",timeCNT,sec,TIME_GetTicks()/1000);
+		timeCNT = 0;
+		Flash_SaveStep();
+		Flash_SaveInfomation();
+		isScan = 0;
+	}
+}
+
+/************************ 删除步数 ***************************/
+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];
+	Flash_DeleteAllStep();
+	
+}
+
+/************************ 发送步数 ***************************/
+#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_Client_T_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,"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_Client_T_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);
+}

+ 18 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_client_step.h

@@ -0,0 +1,18 @@
+#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);
+
+#endif
+
+
+

+ 208 - 0
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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

+ 197 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_connect_manage.c

@@ -0,0 +1,197 @@
+#include "app_connect_manage.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_mode_manage.h"
+#include "ble_comm.h"
+#include "app_flash.h"
+#include "app_charge.h"
+#include "app_ota.h"
+#include "app_err.h"
+#include "hal_ble_client.h"
+#include "hal_ble_host.h"
+#include "hal_led.h"
+
+/********************** 变量区 *************************/
+
+/********************** 函数声明区 *************************/
+extern uint8_t app_client_step_GetIsScan(void);
+
+BLE_Client_Tx_t mBLE_Client_T_CONNET_R = {
+	.n = 10,
+	.t = 500,
+	.cb = 0,
+};
+
+
+
+#if BLE_LED_TEST_ENANBLE
+static uint8_t connect_LED_FlashFlag =0;
+
+static BLE_Host_Tx_t mBLE_Host_T_CONNET_R = {
+	.n = 3,
+	.t = 100,
+	.cb = 0,
+};
+
+static void app_connect_LED_Flash(void)
+{
+	static uint8_t cnt = 0;
+	static uint8_t state = 0;
+
+//	SEGGER_RTT_printf(0,"=======>app_connect_LED_Flash:%d\n",TIME_GetTicks());
+	switch(state){
+		case 0:
+				Process_SetHoldOn(app_connect_LED_Flash,1);
+				LED_Start(LED_CONNECT,COLOR_BLUE);
+				state = 1;
+			break;
+		case 1:
+				state = 0;
+				if(++cnt >= 3){ cnt = 0;
+					LED_Stop(LED_CONNECT);
+					Process_SetHoldOn(app_connect_LED_Flash,0);
+					Process_Stop(app_connect_LED_Flash);
+					connect_LED_FlashFlag =0;
+//					SEGGER_RTT_printf(0,"=======>out app_connect_LED_Flash\n");
+				}
+				else LED_Start(LED_CONNECT,COLOR_BLACK);
+			  break;
+		default:state=0;break;
+	}
+	
+}
+
+void cb_BLE_Client_R_CONNET_LED(void* handle)
+{
+	if(0 == connect_LED_FlashFlag){
+	  Process_Start(200,"connect_LED",app_connect_LED_Flash);
+		SEGGER_RTT_printf(0,"====================>cb_BLE_Client_R_CONNET_LED\n");
+		connect_LED_FlashFlag =1;
+	}
+}
+
+
+#endif
+
+void app_connect_LED_Process(void)
+{
+	static uint8_t ResportCs_Flag = 0;
+	if(slave_isconnect()){
+		if(host_isconnect()){ 
+        if(0 == ResportCs_Flag){			
+					ResportCs_Flag = 1;
+					BLE_Client_Tx_Send(&mBLE_Client_T_CONNET_R,BLE_CONNET_R,&ResportCs_Flag,1);
+					#if BLE_LED_TEST_ENANBLE
+					BLE_Host_Tx_Send(&mBLE_Host_T_CONNET_R,BLE_CONNET_LED,&flashLED,1);
+					Process_Start(200,"connect_LED",app_connect_LED_Flash);
+					#endif
+					SEGGER_RTT_printf(0,"====================>BLE_Host_T_CONNET_LED\n");
+				}
+		}
+		else if(ResportCs_Flag > 0)ResportCs_Flag = 0;
+	}
+	else if(ResportCs_Flag>0)ResportCs_Flag = 0;
+}
+
+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");
+//	else slave_update_conn_interval_request(100,100);
+//	Process_Start(200," ",cb_Slave_Connect_LED);
+}
+
+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_Client_T_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_Client_T_CHARGE_PULLOUT)){
+					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){ app_err_Set(ERR_NUM_CONNET,1);
+					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(mFlash.isHost){
+						if(hal_mode_get() == HAL_MODE_GAME){//游戏模式下更新连接间隔
+								if(ble_con_int !=2 && update_temp <= 60){
+									if(APP_SUCCESS ==  Ble_update_conn_interval(7.5,7.5)){
+										ble_con_int =2;
+										update_temp  =0;
+									}
+									else ++update_temp;
+								}
+						}else{
+								if(ble_con_int !=1 && update_temp <= 60){
+									if(APP_SUCCESS ==  Ble_update_conn_interval(100,100)){
+										ble_con_int =1;
+										update_temp =0;
+									}
+									else update_temp++;
+								}
+						}
+			 }
+			
+				if(app_client_step_GetIsScan()==0&&slave_isconnect()==0&&(app_charge_Getstate()==BLE_Client_T_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;
+		}
+}
+
+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);
+	#if BLE_LED_TEST_ENANBLE
+	
+	BLE_Client_Rx_Regist(BLE_CONNET_LED,cb_BLE_Client_R_CONNET_LED);
+	#endif
+}
+
+

+ 12 - 0
sotfware/03_Test/myTest_templet-20220722/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

+ 70 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_err.c

@@ -0,0 +1,70 @@
+#include "app_err.h"
+#include "usr_config.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_ble_client.h"
+#include "hal_ble_host.h"
+#include "nrf_delay.h"
+#include "app_flash.h"
+#include "hal_imu.h"
+#include "ble_comm.h"
+#include "app_error.h"
+#include "app_client_infomation.h"
+
+#include "app_util_platform.h"
+#include "nrf_strerror.h"
+#include "hal_flash.h"
+
+/********************** 函数声明区 *************************/
+
+static uint8_t errDex = 0;
+static uint8_t errTab[ERR_NUM_OF_T];
+
+//错误回调
+void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
+{
+	  Flash_SaveLog(id,pc,info);
+		SEGGER_RTT_printf(0,"app_error_fault_handler,System reset\n");
+		nrf_gpio_cfg_output(PIN_RESET_PIN); 	nrf_gpio_pin_write(PIN_RESET_PIN,0);
+}
+
+void app_err_Set(uint8_t errNum,uint8_t errTimes)
+{
+	if(errNum>=ERR_NUM_OF_T) return;
+	errTab[errNum] = errTimes;
+}
+
+void app_err_Process(void)
+{
+	for(int i=0;i<ERR_NUM_OF_T;i++){
+		if(errTab[i]>0){ errTab[i]--;
+			uint8_t buf[16];
+			uint8_t L=0;
+			L=0;
+			buf[L++] = errDex;	//0左鞋1右鞋
+			buf[L++] = i;		  	//错误编号
+			BLE_Client_Tx_Send(0,BLE_ERR,buf,L);
+		}
+	}
+	static uint8_t timflag=0;
+	timflag++;
+	if(timflag>=5){ timflag =0;
+		if(1 == mFlash.mFlashLog.Errorflag)app_client_infomation_Send_defineName(mFlash.mFlashLog.logData,strlen((const char *)mFlash.mFlashLog.logData));
+	}
+}
+
+void cb_BLE_Host_R_ERR(void* handle)
+{
+	BLE_Host_Rx_t* target = handle;
+	BLE_Client_Tx_Send(0,BLE_ERR,target->pDat,target->datLen);
+}
+
+void app_err_Init(void)
+{
+	if(mFlash.isHost==0) errDex = 1;
+	memset(errTab,0,sizeof(errTab));
+	Process_Start(3000,"app_err",app_err_Process);
+	BLE_Host_Rx_Regist(BLE_ERR,cb_BLE_Host_R_ERR);
+}
+
+

+ 25 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_err.h

@@ -0,0 +1,25 @@
+#ifndef __app_err_h__
+#define __app_err_h__
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+
+enum {	//错误编号
+	ERR_NUM_NONE = 0,	//留
+	ERR_NUM_FLASH,		//FLASH错误
+	ERR_NUM_IMU_LSM6DS3TR,		//IMU 6轴错误
+	ERR_NUM_IMU_QMC6310,	//地磁计错误
+	ERR_NUM_GAME,		//游戏模式错误
+	ERR_NUM_CONNET,		//连接右鞋错误
+	ERR_NUM_LOG,      //日志打印
+	ERR_NUM_OF_T,	//命令连续用此值
+};
+
+
+void app_err_Init(void);
+void app_err_Set(uint8_t errNum,uint8_t errCode);
+
+#endif

+ 810 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_flash.c

@@ -0,0 +1,810 @@
+#include "app_flash.h"
+#include "bsp_wdt.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;
+	
+	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));
+	
+	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);
+		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");
+			app_err_Set(ERR_NUM_FLASH,1);
+			ret = 1;
+			return;
+		}
+		SEGGER_RTT_printf(0,"System reset...\n",*addr_R);
+		#if WATCHDOG_ENANBLE
+		for(uint8_t i =0;i<6;i++){
+			nrf_delay_ms(500);
+			feed_watchdog();
+		}
+		#else
+		  nrf_delay_ms(3000);
+	  #endif
+		NVIC_SystemReset();
+	}
+	if(ret==0){
+		SEGGER_RTT_printf(0,"Flash_GetInfomation(&mFlash)\n");
+		SEGGER_RTT_printf(0,"Flash_GetInfomation(&mFlash):%d \n",Flash_GetInfomation(&mFlash));
+		SEGGER_RTT_printf(0,"Flash_GetInfomation(&mBackup):%d \n",Flash_GetBackup(&mBackup));
+		
+//		SEGGER_RTT_printf(0,">>>>>>>>>add:%02x,add1:%02x,add2:%02x,add3:%02x,add4:%02x,add5:%02x\r\n",mFlash.add,mFlash.add2,mFlash.add3,mFlash.add4,mFlash.add5);
+//		mFlash.add = 0x11;
+//		mFlash.add2 = 0x22;
+//		mFlash.add3 = 0x33;
+//		mFlash.add4 = 0x44;
+//		SEGGER_RTT_printf(0,"Flash_SaveInfomation():%d\n",Flash_SaveInfomation());
+	}
+	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);
+	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_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);
+		}
+
+		
+//		while(1)
+//		{
+//			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);
+//			nrf_delay_ms(1000);
+//			feed_watchdog();
+//		}
+		
+		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);
+	//获取最新的帧
+	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;
+	//校验数据
+	Flash_t	crc_buf;//单纯做一个缓冲区
+	memset(&crc_buf,0,sizeof(crc_buf));
+	char *buf = (char*)&crc_buf;
+	//获取成员head ~ m_struct_size
+//	SEGGER_RTT_printf(0,"1:sizeof(crc_buf):%d temp_flash.m_struct_size - sizeof(temp_flash.tail_crc16)-sizeof(temp_flash.m_struct_size)-pad_len:%d\n",sizeof(crc_buf),temp_flash.m_struct_size - sizeof(temp_flash.tail_crc16)-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;
+	uint32_t 				zone_bytes;
+	FlashBackup_t	 	temp_backup;
+	int32_t  				offset;
+	uint16_t 				crc;
+	uint8_t					tail_h;
+	
+	memset(&temp_backup,0,sizeof(temp_backup));
+	
+	err_code = Zone_GetByteSize(backup_zone, &zone_bytes);
+	if(err_code != ZONE_OP_SUCCESS)return err_code;
+	
+	//从区域尾开始找起,找到最新的帧尾
+	for(offset = zone_bytes - 1; offset >= 0; offset--)
+	{
+		err_code = Zone_Read(backup_zone + offset, (uint32_t*)&tail_h, 1);
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+		
+		if(tail_h == FLASH_TAIL_H)break;
+	}
+	//重新获取crc16校验码
+	mBackup.tail_crc16 = 0;
+	mBackup.m_struct_size = sizeof(mBackup);
+	mBackup.head = FLASH_HEAD;
+	crc = CalCrc(0, (char*)&mBackup, sizeof(mBackup));//计算得到的16位CRC校验码
+	mBackup.tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc;
+	//写入
+	if(offset < 0){	//意味着整个区域是干净的,直接写开头。
+		err_code = Zone_Write(backup_zone, (uint32_t*)&mBackup, sizeof(mBackup));
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+//		SEGGER_RTT_printf(0,"write zone all clear,mBackup.tail_crc16:0x%x\r\n",mBackup.tail_crc16);
+	}else{
+		//这里要偏移才能对齐成员
+		offset++;		
+		//获取最新的帧尾
+		err_code = Zone_Read(backup_zone + offset - sizeof(temp_backup.tail_crc16), (uint32_t*)&temp_backup.tail_crc16, sizeof(temp_backup.tail_crc16));
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+		//获取最新的帧长度
+		err_code = Zone_Read(backup_zone + offset - sizeof(temp_backup.tail_crc16) - sizeof(temp_backup.m_struct_size) , (uint32_t*)&temp_backup.m_struct_size, sizeof(temp_backup.m_struct_size));
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+		//因为结构体强制4字节对齐缘故,所以tail_crc16未必是真实存储的帧尾,后面可能带一些数据为0的填充字节。所以要做校准。
+//		uint32_t pad_len = temp_backup.m_struct_size - ((uint32_t)&temp_backup.tail_crc16 + sizeof(temp_backup.tail_crc16) - (uint32_t)&temp_backup.head);
+		
+		
+		uint32_t pad_len = 0;
+		SEGGER_RTT_printf(0,"save back up info_zone:0x%x offset:%d pad_len:%d temp_backup.m_struct_size:%d\n",info_zone,offset,pad_len,temp_backup.m_struct_size);
+		if(offset + pad_len < temp_backup.m_struct_size)pad_len = temp_backup.m_struct_size - offset;
+		err_code = Zone_Read(info_zone + offset + pad_len - temp_backup.m_struct_size, (uint32_t*)&temp_backup.head, sizeof(temp_backup.head));
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+//		SEGGER_RTT_printf(0,">>>>>>p_head:0x%x,addr:0x%x\n",temp_backup.head,info_zone + offset + pad_len - temp_backup.m_struct_size);
+		while(temp_backup.head != FLASH_HEAD){
+			pad_len++;
+			err_code = Zone_Read(info_zone + offset + pad_len - temp_backup.m_struct_size, (uint32_t*)&temp_backup.head, sizeof(temp_backup.head));
+			if(err_code != ZONE_OP_SUCCESS)return err_code;
+//			SEGGER_RTT_printf(0,">>>>>>p_head:0x%x,addr:0x%x\n",temp_backup.head,info_zone + offset + pad_len - temp_backup.m_struct_size);
+//			nrf_delay_ms(5);
+		}
+		
+		
+		
+		
+		err_code = Zone_Write(backup_zone + offset + pad_len, (uint32_t*)&mBackup, sizeof(mBackup));
+//		if(err_code == ZONE_OP_SUCCESS)SEGGER_RTT_printf(0,"write zone forward ,mBackup.tail_crc16:0x%x\r\n",mBackup.tail_crc16);
+		if(err_code != ZONE_OP_SUCCESS){	//如果写失败了
+			//擦除该区域
+			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));
+			if(err_code != ZONE_OP_SUCCESS)return err_code;
+//			SEGGER_RTT_printf(0,"write zone all erase ,mBackup.tail_crc16:0x%x\r\n",mBackup.tail_crc16);
+		}
+	}
+	
+	return ZONE_OP_SUCCESS;
+}
+
+/**
+ @brief 获取备份信息
+ @param 无
+ @return 错误代码
+*/
+uint32_t Flash_GetBackup(FlashBackup_t *pbackup)
+{
+	uint32_t 				err_code;
+	uint32_t 				zone_bytes;
+	FlashBackup_t	 	temp_backup;
+	int32_t  				offset;
+	uint16_t 				crc;
+	uint8_t					tail_h;
+	
+	memset(&temp_backup,0,sizeof(temp_backup));
+	
+	err_code = Zone_GetByteSize(backup_zone, &zone_bytes);
+	if(err_code != ZONE_OP_SUCCESS)return err_code;
+	
+	//从区域尾开始找起,找到最新的帧尾
+	for(offset = zone_bytes - 1; offset >= 0; offset--)
+	{
+		err_code = Zone_Read(backup_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(pbackup,0,sizeof(FlashBackup_t));
+		pbackup->head = FLASH_HEAD;
+		pbackup->m_struct_size = sizeof(FlashBackup_t);				//这里是包括填充字节的
+		crc = CalCrc(0, (char*)pbackup, sizeof(FlashBackup_t));//计算得到的16位CRC校验码,这里注意,有可能会将填充的字节也拿来做运算
+		pbackup->tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc;		//这里最后才加,是因为不知道填充字节的个数
+//		SEGGER_RTT_printf(0,"read zone all clear,pbackup->tail_crc16:0x%x\r\n",pbackup->tail_crc16);
+		return ZONE_OP_SUCCESS;
+	}
+	//这里要偏移才能对齐成员
+	offset++;		
+	//获取最新的帧尾
+	err_code = Zone_Read(backup_zone + offset - sizeof(temp_backup.tail_crc16), (uint32_t*)&temp_backup.tail_crc16, sizeof(temp_backup.tail_crc16));
+	if(err_code != ZONE_OP_SUCCESS)return err_code;
+	//获取最新的帧长度
+	err_code = Zone_Read(backup_zone + offset - sizeof(temp_backup.tail_crc16) - sizeof(temp_backup.m_struct_size) , (uint32_t*)&temp_backup.m_struct_size, sizeof(temp_backup.m_struct_size));
+	if(err_code != ZONE_OP_SUCCESS)return err_code;
+	//因为结构体强制4字节对齐缘故,所以tail_crc16未必是真实存储的帧尾,后面可能带一些数据为0的填充字节。所以要做校准。
+//	uint32_t pad_len = temp_backup.m_struct_size - ((uint32_t)&temp_backup.tail_crc16 + sizeof(temp_backup.tail_crc16) - (uint32_t)&temp_backup.head);
+	
+	
+		uint32_t pad_len = 0;
+		SEGGER_RTT_printf(0,"back up info_zone:0x%x offset:%d pad_len:%d temp_backup.m_struct_size:%d\n",info_zone,offset,pad_len,temp_backup.m_struct_size);
+		if(offset + pad_len < temp_backup.m_struct_size)pad_len = temp_backup.m_struct_size - offset;
+		err_code = Zone_Read(info_zone + offset + pad_len - temp_backup.m_struct_size, (uint32_t*)&temp_backup.head, sizeof(temp_backup.head));
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+//		SEGGER_RTT_printf(0,">>>>>>p_head:0x%x,addr:0x%x\n",temp_backup.head,info_zone + offset + pad_len - temp_backup.m_struct_size);
+		while(temp_backup.head != FLASH_HEAD){
+			pad_len++;
+			err_code = Zone_Read(info_zone + offset + pad_len - temp_backup.m_struct_size, (uint32_t*)&temp_backup.head, sizeof(temp_backup.head));
+			if(err_code != ZONE_OP_SUCCESS)return err_code;
+//			SEGGER_RTT_printf(0,">>>>>>p_head:0x%x,addr:0x%x\n",temp_backup.head,info_zone + offset + pad_len - temp_backup.m_struct_size);
+//			nrf_delay_ms(5);
+		}
+	
+	
+	
+	
+//	SEGGER_RTT_printf(0,"read pad_len 0x%x\r\n",pad_len);
+	//获取最新的帧
+	err_code = Zone_Read(backup_zone + offset + pad_len - temp_backup.m_struct_size , (uint32_t*)&temp_backup, temp_backup.m_struct_size - sizeof(temp_backup.tail_crc16)-sizeof(temp_backup.m_struct_size)-pad_len);
+	if(err_code != ZONE_OP_SUCCESS)return err_code;
+	//校验数据
+	FlashBackup_t	crc_buf;//单纯做一个缓冲区
+	memset(&crc_buf,0,sizeof(crc_buf));
+	char *buf = (char*)&crc_buf;
+	//获取成员head ~ m_struct_size
+	memcpy(buf,&temp_backup,temp_backup.m_struct_size - sizeof(temp_backup.tail_crc16)-sizeof(temp_backup.m_struct_size)-pad_len);
+	memcpy(buf + temp_backup.m_struct_size - sizeof(temp_backup.tail_crc16)-sizeof(temp_backup.m_struct_size)-pad_len,(uint32_t*)&temp_backup.m_struct_size,sizeof(temp_backup.m_struct_size));
+	//计算得到的16位CRC校验码
+	crc = CalCrc(0, buf, temp_backup.m_struct_size);
+	
+	
+	if(crc == (temp_backup.tail_crc16 & 0xFFFF)){
+//		SEGGER_RTT_printf(0,"read crc success :0x%x 0x%x \r\n",crc,temp_backup.tail_crc16 & 0xFFFF);
+		temp_backup.head = FLASH_HEAD;
+		temp_backup.m_struct_size = sizeof(temp_backup);
+		temp_backup.tail_crc16 = 0;
+		crc = CalCrc(0, (char*)&temp_backup, sizeof(temp_backup));//计算得到的16位CRC校验码
+		temp_backup.tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc;
+		*pbackup = temp_backup;//校验通过
+	}
+	else{
+		//校验没通过
+//		SEGGER_RTT_printf(0,"read crc fail :0x%x 0x%x \r\n",crc,temp_backup.tail_crc16 & 0xFFFF);
+		memset(pbackup,0,sizeof(FlashBackup_t));
+		pbackup->head = FLASH_HEAD;
+		pbackup->m_struct_size = sizeof(FlashBackup_t);
+		crc = CalCrc(0, (char*)pbackup, sizeof(FlashBackup_t));//计算得到的16位CRC校验码
+		pbackup->tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc;
+		err_code = Zone_Erase(backup_zone);
+		if(err_code != ZONE_OP_SUCCESS)return err_code;
+	}
+	
+	
+	return ZONE_OP_SUCCESS;
+}
+
+/**
+ @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");
+}
+
+

+ 144 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_flash.h

@@ -0,0 +1,144 @@
+#ifndef __APP_FLASH_H__
+#define __APP_FLASH_H__
+/*************************************
+ *INCLUDES
+ */
+#include "hal_flash.h"
+#include "app_step.h"
+#include "app_err.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];
+	uint16_t 	hardVersion;
+	uint16_t 	sotfVersion;
+	uint8_t 	isConfig;
+	/*此处加新的成员*/
+	uint32_t	m_struct_size;			//结构体自身大小	
+	uint32_t	tail_crc16;					//crc16校准只能做成员 head ~ m_struct_size,因为未知的填充字节原因,tail_crc16和未知填充字节(默认为0)都为0好计算。
+}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;
+	uint16_t 	hardVersion;
+	uint16_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;
+	struct __attribute__((packed,aligned(4))){
+		uint32_t	except_data_back_mag : 1;
+		uint32_t	except_data_front_acc : 1;
+		uint32_t	except_data_front_gry : 1;
+		uint32_t	except_data_front_mag : 1;
+		uint32_t	except_data_charge : 1;
+		uint32_t	except_mode_suspend_overflow : 1;
+		uint32_t	except_number_of_exist : 8;
+	}exception;		
+	/*此处加新的成员*/
+	
+//	uint8_t      add;
+//	uint8_t      add2;
+//	uint8_t      add3;
+//	uint8_t      add4;	
+//	uint32_t     add5;
+	///////////
+	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_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
sotfware/03_Test/myTest_templet-20220722/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 "app_err.h"
+#include "hal_mode_manage.h"
+
+#if GAMEDATA_TO_RAWDATA
+uint8_t gamedata_to_rawdata = 0;
+#endif
+
+/********************** 函数声明区 *************************/
+
+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_mode_set(HAL_MODE_GAME);
+		game_manager.GameModeHeartCnt =0;
+	}else{
+		hal_mode_set(HAL_MODE_NORMAL);
+	}
+	
+	#if GAMEDATA_TO_RAWDATA
+	if(game_manager.isGameMode == 2){
+		gamedata_to_rawdata = 1;
+	}else if(game_manager.isGameMode == 0){
+		gamedata_to_rawdata = 0;
+	}
+	#endif
+	
+	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_mode_get() == HAL_MODE_GAME){
+		SEGGER_RTT_printf(0,"game_manager.GameModeHeartCnt:%d\r\n",game_manager.GameModeHeartCnt);
+		if(game_manager.GameModeHeartCnt++ >= 5){
+			 game_manager.isGameMode = 0;
+			 hal_mode_set(HAL_MODE_NORMAL);
+			 BLE_Host_Tx_Send(0,BLE_GAMEMODE,&game_manager.isGameMode,1); 
+		}
+	}
+}
+
+static void app_game_Process(void)
+{
+	#if GAME_ENANBLE
+	
+	if(slave_isconnect())hal_mode_set(HAL_MODE_GAME);
+
+  #else
+		   
+	static uint8_t errCnt = 0;
+	uint8_t clientMode = 0;
+	
+	if(hal_mode_get() != HAL_MODE_GAME){
+		 if(1 == game_manager.isGameMode){
+			  hal_mode_set(HAL_MODE_GAME);
+			  errCnt = 0;
+		 }
+		 if(game_manager.clientCnt >0 && mFlash.isHost){
+				clientMode = 0;
+				BLE_Host_Tx_Send(0,BLE_GAMEMODE,&clientMode,1);
+		 }
+	}
+	else{//游戏模式
+		 
+			if(mFlash.isHost){//管理右鞋状态
+					 if(host_isconnect()){
+						 if(0 == game_manager.clientCnt){
+								clientMode = 1;
+								BLE_Host_Tx_Send(0,BLE_GAMEMODE,&clientMode,1);
+								if(++errCnt >= 10){
+									SEGGER_RTT_printf(0,"ERR_NUM_GAME app_game_Process\r\n");
+									app_err_Set(ERR_NUM_GAME,1);
+								}
+						 }
+						 else if(errCnt>0) errCnt = 0;
+						 game_manager.right_discnt =0;
+					 }
+					 else{
+						 if(game_manager.right_discnt++ >10 && gamedata_to_rawdata == 0){//与右鞋断开10秒后,退出游戏模式
+							  game_manager.isGameMode = 0;
+							  hal_mode_set(HAL_MODE_NORMAL);
+						 }
+					 }
+					
+			 }
+			
+			if(0 == game_manager.isGameMode){
+					hal_mode_set(HAL_MODE_NORMAL);//收到退出游戏指令,退出游戏模式 
+				  if(mFlash.isHost){
+					   clientMode = 0;
+					   BLE_Host_Tx_Send(0,BLE_GAMEMODE,&clientMode,1);
+					}
+			}
+			
+			 //与主机断开5秒后,退出游戏模式
+			 if(!slave_isconnect()){
+					if(game_manager.client_discnt++ >5){
+						game_manager.isGameMode = 0;
+						hal_mode_set(HAL_MODE_NORMAL);
+					}
+			 }else game_manager.client_discnt =0;
+					
+	}
+
+	if(game_manager.clientCnt>0) game_manager.clientCnt--;
+	
+	#endif
+
+	
+}
+
+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);
+}
+
+

+ 17 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_game.h

@@ -0,0 +1,17 @@
+#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);
+
+#if GAMEDATA_TO_RAWDATA
+extern uint8_t gamedata_to_rawdata;
+#endif
+
+#endif

+ 99 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_host.c

@@ -0,0 +1,99 @@
+#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_infomation.h"
+#include "app_client_dataupdate.h"
+#include "hal_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_Host_T_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 = 20,
+	.t = 500,
+	.cb = 0,
+};
+
+void app_host_GetClientData(uint8_t temp)
+{//AA 06 F9 A1 01 4B
+	static uint8_t buf=BLE_Host_T_UPDATE_DATA;
+	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_Host_R_UPDATE_BASEINFO:{
+			//<< 0(子命令): 设备型号(64)+左鞋蓝牙地址(6)+硬件版本(2)+软件版本(2)+右鞋蓝牙地址(6)+硬件版本(6)+软件版本(2)
+			uint8_t L = SHOES_NAME_LEN+6;
+			for(int i=0;i<6;i++) mFlash.mClient.macAddr[i] = target->pDat[i+SHOES_NAME_LEN+1];
+			mFlash.mClient.hardVersion = ((uint16_t)target->pDat[L]<<8)|((uint16_t)target->pDat[L+1]<<0);
+			mFlash.mClient.sotfVersion = ((uint16_t)target->pDat[L+2]<<8)|((uint16_t)target->pDat[L+3]<<0);
+			app_client_infomation_Send();
+			break;}
+		case BLE_Host_R_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;
+	}
+}
+
+static void app_host_Process(void)
+{
+	static uint8_t cnt =0;
+	if(host_isconnect()){
+		if(HAL_MODE_GAME == hal_mode_get()){
+			 if(cnt++ >= 3){
+				  cnt =0;
+				  app_host_GetClientData(1);
+			 }
+		}
+		else app_host_GetClientData(1);
+	}
+}
+
+void app_host_Initialize(void)
+{
+	if(mFlash.isHost==1){
+		BLE_Host_Rx_Regist(BLE_UPDATE,cb_BLE_Host_R_UPDATE);
+		Process_Start(3000,"app_host",app_host_Process);
+	}
+}
+

+ 26 - 0
sotfware/03_Test/myTest_templet-20220722/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
+
+
+

+ 38 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_losspack.c

@@ -0,0 +1,38 @@
+#include "app_losspack.h"
+#include "bsp_time.h"
+#include "app_flash.h"
+#include "system.h"
+#include "hal_ble_client.h"
+#include "ble_comm.h"
+
+
+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);
+}
+
+
+
+
+

+ 17 - 0
sotfware/03_Test/myTest_templet-20220722/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
+
+
+

+ 156 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_math.c

@@ -0,0 +1,156 @@
+#include "app_math.h"
+#include "bsp_time.h"
+#include "system.h"
+#include "hal_imu.h"
+#include "hal_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"
+
+static int16_t 	acc_front[IMU_BUFF_SIZE][3];
+static int16_t  gry_front[IMU_BUFF_SIZE][3];
+static int16_t	mag6310_front[IMU_BUFF_SIZE][3];
+
+static int16_t	mag6310_back[3];
+static int32_t	timestamp_front[IMU_BUFF_SIZE];
+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;
+	}
+	
+	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;
+		
+		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(void)
+{
+	int16_t 				group_num = 0;
+	
+	//游戏模式
+	if(hal_mode_get() == HAL_MODE_GAME){
+		
+//			CHECK_TIMECONSUMING_START;
+		
+		rssi = 0-host_get_rssi();
+		group_num = IMU_Get_Front_Data_Num();
+		for(int i=0;i<group_num;i++){
+			IMU_Get_Front_Data(i, gry_front[i], acc_front[i], mag6310_front[i], &timestamp_front[i]);
+//			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);
+		}
+		
+		IMU_Get_Back_Data(mag6310_back);
+		
+		if(mFlash.isHost){
+				process_imu_data_front(group_num);
+			}else if(Slave_Get7_5ms_interval()){
+				process_imu_data_front(group_num);
+			}
+			
+//			CHECK_TIMECONSUMING_END;
+	}else{
+	 //将状态重设为0
+	 IMU_STATUS = 0;
+	 set_pdr_status();
+	}
+			 
+	
+	//实时计步模式
+	if(hal_mode_get() == HAL_MODE_REALSTEP){
+		rssi = 0-host_get_rssi();
+		group_num = IMU_Get_Front_Data_Num();
+		for(int i=0;i<group_num;i++)IMU_Get_Front_Data(i, gry_front[i], acc_front[i], mag6310_front[i], &timestamp_front[i]);
+		IMU_Get_Back_Data(mag6310_back);
+		 
+		if(app_switchimu_GetGameModeLsm() == USED_FRONT_LSM){
+//			SEGGER_RTT_printf(0,"app_switchimu_GetGameModeLsm() == USED_FRONT_LSM\r\n");
+			if(RealTimeStep((int16_t*)mag6310_front, (int16_t*)mag6310_back, (int16_t*)acc_front)){
+				 mFlash.mStep.stepCur[0]++;
+			}
+				
+		}else if(app_switchimu_GetGameModeLsm() == USED_CENTER_LSM){
+//			SEGGER_RTT_printf(0,"app_switchimu_GetGameModeLsm() == USED_CENTER_LSM\r\n");
+			if(RealTimeStep((int16_t*)mag6310_front, (int16_t*)mag6310_back, (int16_t*)acc_front)){
+				 mFlash.mStep.stepCur[0]++;
+			}
+		}			 
+	}
+}
+
+static void app_math_DailyStep_Process(void)
+{
+	int16_t 	acc[3];
+	int16_t		mag6310[3];
+	 
+	if(hal_mode_get() == HAL_MODE_NORMAL){
+
+		for(int i=0; i < IMU_Get_Front_Data_Num(); i++)
+		{
+			IMU_Get_Front_Data(i, NULL, acc, mag6310, NULL);
+			//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,"curren step:%d\r\n",mFlash.mStep.stepCur[0]);
+				  break;
+			}
+		}
+	}
+}
+
+//static void hal_stepSaveTest_process(void){
+//	mFlash.mStep.stepCur[0]++;
+////	Flash_SaveStep();
+//	SEGGER_RTT_printf(0,"hal step Save one minute:step %d\r\n",mFlash.mStep.stepCur[0]);
+//}
+
+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);
+//	if(mFlash.isHost)Process_Start(10000,"hal_stepSaveTest",hal_stepSaveTest_process);
+}
+
+
+
+
+
+
+
+
+

+ 15 - 0
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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

+ 223 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_ota - 副本.c

@@ -0,0 +1,223 @@
+#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"
+
+static ble_gap_addr_t mAddr;
+static uint32_t isOTA=0;
+static uint8_t isHostOTA=0;
+
+static volatile uint8_t m_ready_for_reset = 0;
+
+static bool app_shutdown_handler(nrf_pwr_mgmt_evt_t event)
+{
+    switch (event){
+        case NRF_PWR_MGMT_EVT_PREPARE_DFU:
+			switch(m_ready_for_reset){
+				case 0:
+						m_ready_for_reset =1;
+						return false;
+				case 1:
+						return false;
+				default:
+						break;
+			}
+            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_clear_flash(void)
+{
+	uint32_t temp =0;
+	if(1 == m_ready_for_reset){
+		memset((uint8_t*)(&mFlash),0xFF,sizeof(Flash_t));
+		temp = Flash_SaveInfomation();
+		SEGGER_RTT_printf(0,"------>clear all flash...%d,\n",temp);
+		m_ready_for_reset =2;
+	}
+	else if(2 == m_ready_for_reset){
+		nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_CONTINUE);
+	} 
+}
+
+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;
+				m_ready_for_reset =0;
+				SEGGER_RTT_printf(0,"------>left out to dfu\n");
+			}
+			else{
+				if(slave_isconnect()==0){
+					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
+			
+			
+			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",app_ota_sendleftstate);
+	number =10;
+	left_dfu_state = *target->pDat;
+//	BLE_Client_Tx_Send(0,BLE_DFU,target->pDat,1);	//发送到手机
+}
+
+/*********************** 接收手机命令 ************************/
+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;
+		 Flash_SaveBackup();
+		 Flash_SaveInfomation();
+		 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",app_ota_Process);
+	Process_Start(500,"app_ota_clear_flash",app_ota_clear_flash);
+	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
+	
+	
+}
+
+

+ 195 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_ota.c

@@ -0,0 +1,195 @@
+#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"
+
+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){
+					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
+			
+			
+			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",app_ota_sendleftstate);
+	number =10;
+	left_dfu_state = *target->pDat;
+}
+
+/*********************** 接收手机命令 ************************/
+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;
+		 Flash_SaveBackup();
+		 Flash_SaveInfomation();
+		 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",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
sotfware/03_Test/myTest_templet-20220722/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

+ 132 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_overturn.c

@@ -0,0 +1,132 @@
+#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_imu.h"
+#include "hal_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];
+		static uint32_t cnt = 0;
+					
+		if(hal_mode_get() == HAL_MODE_NORMAL) return;//停止状态
+					
+		//获取最新一组前脚加速度
+		if(IMU_Get_Front_Data_Num() >= 1)IMU_Get_Front_Data(IMU_Get_Front_Data_Num()-1, NULL, acc, NULL, NULL);
+	 
+//		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];
+		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(hal_mode_get() == HAL_MODE_STANDBY) return;//走路状态
+			
+		//获取最新一组前脚加速度
+		if(IMU_Get_Front_Data_Num() >= 1)IMU_Get_Front_Data(IMU_Get_Front_Data_Num()-1, NULL, acc, NULL, NULL);
+//     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
sotfware/03_Test/myTest_templet-20220722/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
+
+

+ 237 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_pair.c

@@ -0,0 +1,237 @@
+/*********************************************************************
+ * 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"
+
+/*********************************************************************
+* LOCAL DEFINETION
+*/
+
+/*********************************************************************
+* LOCAL VARIABLES
+*/
+static ble_gap_addr_t mAddr;
+static uint16_t isConfig = 0;
+/*********************************************************************
+* LOCAL FUNCTIONS
+*/
+
+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);
+}
+
+#define PAIR_TIMES								50					//配对次数
+void app_pair_Process(void)
+{
+	static uint8_t flag = 0;
+	if(app_charge_Getstate()!=BLE_Client_T_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(isConfig<PAIR_TIMES){ isConfig++;
+			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(isConfig>0) isConfig = 0;
+	}
+}
+
+#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];
+	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_Initialize(PIN_TXD_BLE,UART0_INVALID_PIN,UART_HZ);
+	for(int i=0; i < 10; i++){
+	UART0_Config_Send(UART0_T_CONFIG_ACK);//应答主机申请
+	}
+	UART0_Initialize(UART0_INVALID_PIN,PIN_RXD_BLE,UART_HZ);
+	
+	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]);
+	#if BLUE_LED_TEST_ENANBLE
+	Process_Start(0,"config_LED",app_config_LED);
+	#endif
+	
+	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,LED_SMALL_ENABLE);
+}
+
+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 = PAIR_TIMES+1;			//已配对,停止配对发送
+	
+	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]);
+	#if BLUE_LED_TEST_ENANBLE
+	Process_Start(0,"config_LED",app_config_LED);
+	#endif
+	
+	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,LED_SMALL_ENABLE);
+}
+
+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);
+}
+
+ 
+
+
+
+
+

+ 18 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_pair.h

@@ -0,0 +1,18 @@
+#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"
+
+
+
+
+void app_pair_Init(void);
+
+#endif
+
+

+ 13 - 0
sotfware/03_Test/myTest_templet-20220722/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

+ 65 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_power/app_power_NoPowerEnPin.c

@@ -0,0 +1,65 @@
+#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_dataupdate.h"
+#include "hal_ble_uart0.h"
+#include "hal_led.h"
+#include "lsm6ds3tr_c.h"
+#include "hal_imu.h"
+#include "app_math.h"
+
+/********************** 变量区 *************************/
+
+/********************** 函数声明区 *************************/
+void PWR_Off(void)
+{
+		UART0_unInit(PIN_TXD_BLE,PIN_RXD_BLE);
+	  LED_Close_Enforce();
+	  Battery_Enable(false);
+	
+		IMU_PowerOffProcess();
+
+		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(1 == (Battery_BatteryIs_0() && app_charge_Getstate()==BLE_Client_T_CHARGE_PULLOUT)){
+		SEGGER_RTT_printf(0,"BatteryPersent:%d\n",GetBatteryPersent());
+		SEGGER_RTT_printf(0,"power off...\n");
+		//保存数据到flash
+		Flash_SaveStep();
+		Flash_SaveInfomation();
+//		MT_Run(1000);
+		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);
+}
+
+

+ 559 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_self_checking.c

@@ -0,0 +1,559 @@
+#include "app_self_checking.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"
+#include "app_charge.h"
+#include "hal_imu.h"
+#include "nrf_gpio.h"
+#include "hal_battery.h"
+#include "hal_ble_uart0.h"
+#include "hal_led.h"
+#include "ble_comm.h"
+#include "tool.h"
+#include "hal_mode_manage.h"
+#include "app_flash.h"
+#include "exception.h"
+
+#define TEST_SUCCESS													0																					//测试成功
+#define TEST_FAIL															1																					//测试失败
+#define TEST_UNKNOWN													2																					//测试未知
+
+#define TEST_ITEMS														4																					//非人工测试项数(前脚传感器、后脚传感器、电量、充电电流)
+
+#define ENTER_SELF_CHECK											1																					//进入自检标志位
+#define QUITE_SELF_CHECK											0																					//退出自检标志位
+
+#define TEST_RESULT_LED_SUCCESS_GREEN					0
+#define TEST_RESULT_LED_ERR_RED								(TEST_RESULT_LED_SUCCESS_GREEN+0x01)
+#define TEST_RESULT_LED_ERR_BLUE							(TEST_RESULT_LED_SUCCESS_GREEN+0x02)
+#define TEST_RESULT_LED_ERR_PURPLE						(TEST_RESULT_LED_SUCCESS_GREEN+0x03)
+#define TEST_RESULT_LED_ERR_YELLOW						(TEST_RESULT_LED_SUCCESS_GREEN+0x04)
+#define TEST_RESULT_LED_ERR_WHITE							(TEST_RESULT_LED_SUCCESS_GREEN+0x05)
+
+#define APP_SELF_CHECKING_PROCESS_CYCLE				10																				//线程周期,单位ms
+
+#define APP_SELF_CHECKING_READY_PROCESS_CYCLE	50																				//线程周期,单位ms
+
+#define DISPLAY_TEST_RESULT_LED_TIME					1000																			//用灯显示测试结果的时间,单位ms
+
+#define DISPLAY_TEST_RESULT_CONTINUE_TIME			3000																			//显示测试结果的总时间,单位ms
+
+#define	SELF_CHECK_RECIVE_ORDER_TIMES					1																					//允许接受到的自检指令最大次数
+
+#define BATTERY_TEST_VALUE										2500																			//电池必须大于2.5V,否则算异常
+
+#define BATTERY_CHARGE_CHANGE_VALUE						80																				//自检前和自检期间的充电电压变化值,单位mv
+
+#define TRIGGER_MONITOR_ACC_Z									1500																			//触发数据监测的加速度Z轴
+
+#define ENTER_MONITOR_TIME										(10000/StandByPower_Interval)							//进入数据监测所需时间(10S)
+
+#define MONITOR_DURATION_TIME									(60000/FullPower_Interval)								//数据监测至少需要维持的时间
+
+static uint8_t  self_check_state = QUITE_SELF_CHECK;
+
+static uint8_t  self_check_result_buff[TEST_ITEMS];
+
+static uint8_t	self_check_recive_order_times = 0;																			//允许接受到的自检指令最大次数
+
+static int16_t	before_check_charge_vol = 0;																						//自检前的充电电压
+
+static uint32_t	enter_monitor_times = ENTER_MONITOR_TIME;																//进入数据监测所需时间
+
+static uint8_t	enter_monitor_flag	=	0;																								//进入数据监测标志位
+
+static uint32_t	monitor_duration	=	MONITOR_DURATION_TIME;															//数据监测至少需要维持的时间
+
+/*-----------------以下属于数据监测线程的相关函数----------------------------*/
+//监测前脚传感器数据(acc + gry + mag)
+static void monitor_except_front_acc_gry_mag(int16_t *monitor_acc, int16_t *monitor_gry, int16_t *monitor_mag)
+{
+	#define MONITOR_FRONT_ACC_SUM	5
+	#define MONITOR_FRONT_GRY_SUM	5
+	#define MONITOR_FRONT_MAG_SUM	5
+	
+	static uint8_t	gry_err_sum, acc_err_sum, mag_err_sum;
+	static int16_t 	last_gry[3], last_acc[3], last_mag[3];
+//	SEGGER_RTT_printf(0,"front last_gry[0]=%d, last_gry[1]=%d, last_gry[2]=%d\r\n",last_gry[0],last_gry[1],last_gry[2]);
+//	SEGGER_RTT_printf(0,"front last_acc[0]=%d, last_acc[1]=%d, last_acc[2]=%d\r\n",last_acc[0],last_acc[1],last_acc[2]);
+//	SEGGER_RTT_printf(0,"front last_mag[0]=%d, last_mag[1]=%d, last_mag[2]=%d\r\n",last_mag[0],last_mag[1],last_mag[2]);
+	if(monitor_gry != NULL){
+		if(last_gry[0] == monitor_gry[0] && last_gry[1] == monitor_gry[1] && last_gry[2] == monitor_gry[2]){
+			gry_err_sum++;
+//			SEGGER_RTT_printf(0,"==>front gry_err_sum=%d\r\n",gry_err_sum);
+			if(gry_err_sum >= MONITOR_FRONT_GRY_SUM){
+				Except_SaveExceptype(EXCEPT_DATA_FRONT_GRY);
+			}
+		}else{
+			gry_err_sum = 0;
+		}
+		last_gry[0] = monitor_gry[0];
+		last_gry[1] = monitor_gry[1];
+		last_gry[2] = monitor_gry[2];
+	}
+
+	if(monitor_acc != NULL){
+		if(last_acc[0] == monitor_acc[0] && last_acc[1] == monitor_acc[1] && last_acc[2] == monitor_acc[2]){
+			acc_err_sum++;
+//			SEGGER_RTT_printf(0,"==>front acc_err_sum=%d\r\n",acc_err_sum);
+			if(acc_err_sum >= MONITOR_FRONT_ACC_SUM){
+				Except_SaveExceptype(EXCEPT_DATA_FRONT_ACC);
+			}
+		}else{
+			acc_err_sum = 0;
+		}
+		last_acc[0] = monitor_acc[0];
+		last_acc[1] = monitor_acc[1];
+		last_acc[2] = monitor_acc[2];
+	}
+	
+	if(monitor_mag != NULL){
+		if(last_mag[0] == monitor_mag[0] && last_mag[1] == monitor_mag[1] && last_mag[2] == monitor_mag[2]){
+			mag_err_sum++;
+//			SEGGER_RTT_printf(0,"==>front mag_err_sum=%d\r\n",mag_err_sum);
+			if(mag_err_sum >= MONITOR_FRONT_MAG_SUM){
+				Except_SaveExceptype(EXCEPT_DATA_FRONT_MAG);
+			}
+		}else{
+			mag_err_sum = 0;
+		}
+		last_mag[0] = monitor_mag[0];
+		last_mag[1] = monitor_mag[1];
+		last_mag[2] = monitor_mag[2];
+	}
+}
+//监测后脚传感器数据(mag)		
+static void monitor_except_back_mag(int16_t *monitor_mag)
+{
+	#define MONITOR_BACK_MAG_SUM	5
+	
+	static uint8_t mag_err_sum;
+	static int16_t last_mag[3];
+//	SEGGER_RTT_printf(0,"back last_mag[0]=%d, last_mag[1]=%d, last_mag[2]=%d\r\n",last_mag[0],last_mag[1],last_mag[2]);
+	if(monitor_mag != NULL){
+		if(last_mag[0] == monitor_mag[0] && last_mag[1] == monitor_mag[1] && last_mag[2] == monitor_mag[2]){
+			mag_err_sum++;
+//			SEGGER_RTT_printf(0,"==>back mag_err_sum=%d\r\n",mag_err_sum);
+			if(mag_err_sum >= MONITOR_BACK_MAG_SUM){
+				Except_SaveExceptype(EXCEPT_DATA_BACK_MAG);
+			}
+		}else{
+			mag_err_sum = 0;
+		}
+		last_mag[0] = monitor_mag[0];
+		last_mag[1] = monitor_mag[1];
+		last_mag[2] = monitor_mag[2];
+	}
+}
+
+void app_self_checking_monitor_Process(void)
+{
+	int16_t 					group_num = 0;
+	int16_t 					front_acc[3];
+	int16_t						front_gry[3];
+	int16_t						front_mag[3];
+	int16_t						back_mag[3];
+	static uint32_t 	tim =0;
+	
+	if(!IMU_IsNoSignal())return;		//配置期间不处理
+	
+	switch(hal_mode_get())
+	{
+		case HAL_MODE_SELF_CHECK:	
+		if(monitor_duration > 0 && enter_monitor_flag)monitor_duration--;
+		
+		//用于测试,人为添加错误,判断逻辑是否正确。
+//		static uint8_t test1 = 1;
+//		if(test1){
+//			Except_SaveExceptype(EXCEPT_DATA_FRONT_MAG);
+//			test1 = 0;
+//		}
+		
+		case HAL_MODE_GAME:
+		case HAL_MODE_REALSTEP:																									// 游戏模式 + 实时计步模式 + 自检模式
+			if(TIME_GetTicks()-tim>=FullPower_Interval){tim = TIME_GetTicks();
+				group_num = IMU_Get_Front_Data_Num();
+				for(int i=0;i<group_num;i++){
+					IMU_Get_Front_Data(i, front_gry, front_acc, front_mag, NULL);
+					monitor_except_front_acc_gry_mag(front_acc, front_gry, front_mag);//监测前脚传感器数据(acc + gry + mag)
+				}
+				IMU_Get_Back_Data(back_mag);
+				monitor_except_back_mag(back_mag);																	//监测后脚传感器数据(mag)	
+			}	
+			break;
+			
+		case HAL_MODE_STANDBY:																									// 待机模式
+			if(TIME_GetTicks()-tim>=StandByPower_Interval){tim = TIME_GetTicks();
+				group_num = IMU_Get_Front_Data_Num();
+				for(int i=0;i<group_num;i++){
+					IMU_Get_Front_Data(i, NULL, front_acc, NULL, NULL);
+					monitor_except_front_acc_gry_mag(front_acc, NULL, NULL);					//监测前脚传感器数据(acc)
+				}
+			}
+			break;
+		
+		case HAL_MODE_NORMAL:																										// 正常模式
+			if(TIME_GetTicks()-tim>=LowPower_Interval){tim = TIME_GetTicks();
+				group_num = IMU_Get_Front_Data_Num();
+				for(int i=0;i<group_num;i++){
+					IMU_Get_Front_Data(i, NULL, front_acc, front_mag, NULL);
+					monitor_except_front_acc_gry_mag(front_acc, NULL, front_mag);			//监测前脚传感器数据(acc + mag)
+				}
+			}
+			break;
+			
+		default:
+			break;
+	}
+	
+}
+
+/*-----------------以下属于自检流程线程的相关函数----------------------------*/
+//人工测试(电机、指示灯)
+static void app_self_checking_artificial(void)								
+{
+	uint32_t 				temp_result = 0;
+	static uint8_t 	state = 0;
+	static uint32_t display_times = 0;
+	
+	switch(state){
+		case 0:
+			Process_SetHoldOn(app_self_checking_artificial,1);
+			//测试电机是否正常
+//			MT_Run(100);
+			//显示其余的非人工测试结果
+			for(int i=0;i<TEST_ITEMS;i++)temp_result +=self_check_result_buff[i];
+//			SEGGER_RTT_printf(0,"temp_result=%d\n",temp_result);
+			if(temp_result == TEST_SUCCESS){																			//如果全部测试通过
+				LED_Start(LED_SELF_CHECK,COLOR_GREEN);
+				nrf_gpio_pin_write(PIN_LED_RUN,LED_SMALL_ENABLE);
+				Process_UpdatePeroid(app_self_checking_artificial,DISPLAY_TEST_RESULT_LED_TIME);
+				state = 1;
+				break;
+			}else{																																//没有全部通过
+				static uint8_t loop = 0;
+				if(self_check_result_buff[loop++] != TEST_SUCCESS){
+					switch(loop)
+					{
+						case TEST_RESULT_LED_ERR_RED:
+							if(self_check_result_buff[loop-1] != TEST_UNKNOWN)LED_Start(LED_SELF_CHECK,COLOR_RED);
+							else LED_Start(LED_SELF_CHECK,COLOR_WHITE);
+						break;
+						case TEST_RESULT_LED_ERR_BLUE:
+							if(self_check_result_buff[loop-1] != TEST_UNKNOWN)LED_Start(LED_SELF_CHECK,COLOR_BLUE);
+							else LED_Start(LED_SELF_CHECK,COLOR_WHITE);
+						break;
+						case TEST_RESULT_LED_ERR_PURPLE:
+							if(self_check_result_buff[loop-1] != TEST_UNKNOWN)LED_Start(LED_SELF_CHECK,COLOR_PURPLE);
+							else LED_Start(LED_SELF_CHECK,COLOR_WHITE);
+						break;
+						case TEST_RESULT_LED_ERR_YELLOW:
+							if(self_check_result_buff[loop-1] != TEST_UNKNOWN)LED_Start(LED_SELF_CHECK,COLOR_YELLOW);
+							else LED_Start(LED_SELF_CHECK,COLOR_WHITE);
+						break;				
+					}
+					Process_UpdatePeroid(app_self_checking_artificial,DISPLAY_TEST_RESULT_LED_TIME);
+				}else{
+					Process_UpdatePeroid(app_self_checking_artificial,0);						//通过的某项就跳过等待时间。
+				}
+				if(loop == TEST_ITEMS){
+					loop = 0;
+					state = 1;
+				}
+			}
+			break;
+		case 1:
+			for(int i=0;i<TEST_ITEMS;i++)temp_result +=self_check_result_buff[i];
+			temp_result = (temp_result == 0) ? DISPLAY_TEST_RESULT_LED_TIME : (temp_result * DISPLAY_TEST_RESULT_LED_TIME);//跑完一次case0的时间
+			if((temp_result * ++display_times) <= DISPLAY_TEST_RESULT_CONTINUE_TIME){
+				state = 0;
+				break;
+			}
+			display_times = 0;
+			Process_UpdatePeroid(app_self_checking_artificial,0);
+			LED_Stop(LED_SELF_CHECK);
+			nrf_gpio_pin_write(PIN_LED_RUN,LED_SMALL_DISABLE);
+			state = 0;
+			Process_SetHoldOn(app_self_checking_artificial,0);
+			Process_Stop(app_self_checking_artificial);
+			break;
+		default:state=0;Process_UpdatePeroid(app_self_checking_artificial,0);break;
+	}
+	
+}
+
+//测试前脚IMU和地磁是否正常
+static void app_checking_front_sensor(uint8_t *check_result)
+{
+	int16_t 	acc_front[3];
+	int16_t  	gry_front[3];
+	int16_t		mag6310_front[3];
+	int32_t		timestamp_front;
+
+	for(int i=0; i < IMU_Get_Front_Data_Num(); i++)
+	{
+		
+		IMU_Get_Front_Data(i, gry_front, acc_front, mag6310_front, &timestamp_front);
+		
+		if( (gry_front[0] == 0 && gry_front[1] == 0 && gry_front[2] == 0) || \
+				(acc_front[0] == 0 && acc_front[1] == 0 && acc_front[2] == 0) || \
+				(mag6310_front[0] == 0 && mag6310_front[1] == 0 && mag6310_front[2] == 0) ||
+				(timestamp_front == 0))
+		{
+			*check_result = TEST_FAIL;
+		}
+		else if(mFlash.exception.except_data_front_acc || mFlash.exception.except_data_front_gry || mFlash.exception.except_data_front_mag){
+			*check_result = TEST_FAIL;
+		}
+		else if(monitor_duration)*check_result = TEST_UNKNOWN;
+	}
+}
+
+//测试后脚地磁是否正常
+static void app_checking_back_sensor(uint8_t *check_result)
+{
+	static int16_t	mag6310_back[3];
+	
+	IMU_Get_Back_Data(mag6310_back);
+	if(mag6310_back[0] == 0 && mag6310_back[1] == 0 && mag6310_back[2] == 0)*check_result = TEST_FAIL;
+	else if(mFlash.exception.except_data_back_mag)*check_result = TEST_FAIL;
+	else if(monitor_duration)*check_result = TEST_UNKNOWN;
+}
+
+//测试电量检测是否正常
+static void app_checking_bat(uint8_t *check_result)
+{
+	int16_t cur_vol;
+	int16_t	bat;
+	
+	cur_vol = ADC_RESULT_IN_MILLI_VOLTS(ADC_GetValue(PIN_ADC_CHARGMEASURE_CHANNEL));
+	bat = ADC_RESULT_IN_MILLI_VOLTS(ADC_GetValue(PIN_ADC_BAT_CHANNEL))*5/3;
+//	SEGGER_RTT_printf(0,"app_checking_bat cur_vol:%d  before_check_charge_vol:%d  cur_vol-before_check_charge_vol:%d\r\n",cur_vol,before_check_charge_vol,cur_vol-before_check_charge_vol);
+	//电池小于2.5V或充电电压变化小于阈值且电池电压大于4V
+	if(bat <= BATTERY_TEST_VALUE || ((cur_vol-before_check_charge_vol)<BATTERY_CHARGE_CHANGE_VALUE && bat > 4000))*check_result = TEST_FAIL;
+	else if(monitor_duration)*check_result = TEST_UNKNOWN;
+}
+
+//测试充电电流是否正常
+static void app_checking_charge(uint8_t *check_result)
+{
+	int16_t cur_vol;
+	
+	cur_vol = ADC_GetValue(PIN_ADC_CHARGMEASURE_CHANNEL);
+	cur_vol = ADC_RESULT_IN_MILLI_VOLTS(cur_vol);
+//	SEGGER_RTT_printf(0,"app_checking_charge cur_vol:%d  before_check_charge_vol:%d  cur_vol-before_check_charge_vol:%d\r\n",cur_vol,before_check_charge_vol,cur_vol-before_check_charge_vol);
+	//当电池电量满了,不充电(经测试,哪怕电量满了,充电电压也有10+mv)
+	//当电池电量没满,充电(经测试,电量没满的充电电压跟电池电压有关,最小充电电压100+mv)	
+	if((cur_vol-before_check_charge_vol)<BATTERY_CHARGE_CHANGE_VALUE)*check_result = TEST_FAIL;
+	else if(monitor_duration)*check_result = TEST_UNKNOWN;
+}
+
+//发送非人工检测结果,只有在插上充电时,才配置串口
+static void app_self_check_send_result(uint8_t *buf, uint8_t datalen)
+{
+	uint32_t txd,rxd;
+	UART0_GetPinConfig(&txd, &rxd);
+	UART0_Initialize(PIN_TXD_BLE,PIN_RXD_BLE,UART_HZ);
+	for(int i=0;i<10;i++)
+	{
+		UART0_Tx_Send(0,UART0_T_SELF_CHECK_ACK,buf,datalen);
+	}
+	UART0_Initialize(txd,rxd,UART_HZ);
+}
+//触发自检配置用于监测数据变化,不需要通过串口发送结果。
+static void app_self_checking_monitor_trigger(void)
+{
+	static uint32_t 	tim =0;
+	
+	if(TIME_GetTicks()-tim>=StandByPower_Interval){tim = TIME_GetTicks();
+		int16_t front_acc[3];
+		if(IMU_Get_Front_Data_Num() >= 1)IMU_Get_Front_Data(IMU_Get_Front_Data_Num()-1, NULL, front_acc, NULL, NULL);
+//		SEGGER_RTT_printf(0,"front_acc[0]=%d\r,front_acc[1]=%d\r,front_acc[2]=%d\r\n",front_acc[0],front_acc[1],front_acc[2]);
+		if(front_acc[2] >= TRIGGER_MONITOR_ACC_Z){
+			if(enter_monitor_times == 0){
+				if(hal_mode_get() != HAL_MODE_SELF_CHECK){
+					hal_mode_set(HAL_MODE_SELF_CHECK);		//维持一段时间,开启自检模式
+					enter_monitor_flag = 1;
+				}
+				enter_monitor_times = ENTER_MONITOR_TIME;
+			}else{
+				enter_monitor_times--;
+			}
+		}else{
+			enter_monitor_times = ENTER_MONITOR_TIME;
+			if(enter_monitor_flag && self_check_state != ENTER_SELF_CHECK){
+				enter_monitor_flag = 0;
+				if(hal_mode_get() != HAL_MODE_NORMAL)hal_mode_set(HAL_MODE_NORMAL);					//关闭自检模式
+			}
+		}				
+	}
+
+}
+
+void app_self_checking_Process(void)
+{
+	static uint8_t wait_times = 20 + 1;					// 预防IMU初始化失败,重复几次才初始化成功的情况,所以等待时间为初始化失败上限+1
+	
+	//触发自检配置用于监测数据变化,不需要通过串口发送结果。
+	if(hal_mode_get() == HAL_MODE_SELF_CHECK || hal_mode_get() == HAL_MODE_STANDBY)app_self_checking_monitor_trigger();
+	//触发自检配置用于自检流程,需要通过串口发送结果。
+	if(self_check_state == ENTER_SELF_CHECK){
+		
+		if(wait_times-- != 0)return;
+		
+		wait_times = 20 + 1;
+	
+		memset(self_check_result_buff,TEST_SUCCESS,TEST_ITEMS);
+		
+		if(app_charge_Getstate()!=BLE_Client_T_CHARGE_PULLOUT){
+			//如果插上充电,测试充电电流是否正常
+			app_checking_charge(&self_check_result_buff[3]);
+		}
+		
+		if(hal_mode_get() == HAL_MODE_SELF_CHECK){
+			//测试前脚IMU和地磁是否正常
+			app_checking_front_sensor(&self_check_result_buff[0]);
+		}else{
+			//前脚传感器损坏
+			self_check_result_buff[0] = TEST_FAIL;
+		}
+		
+		//测试后脚地磁是否正常
+		app_checking_back_sensor(&self_check_result_buff[1]);
+		
+		//测试电量检测是否正常
+		app_checking_bat(&self_check_result_buff[2]);
+
+		
+		//发送非人工检测结果,只有在插上充电时,才配置串口
+		if(app_charge_Getstate()!=BLE_Client_T_CHARGE_PULLOUT){
+			app_self_check_send_result(self_check_result_buff, TEST_ITEMS);
+		}
+		
+		//关闭自检模式
+		hal_mode_set(HAL_MODE_NORMAL);
+		self_check_state = QUITE_SELF_CHECK;
+		
+//		self_check_result_buff[0] = TEST_FAIL;
+//		self_check_result_buff[1] = TEST_FAIL;
+//		self_check_result_buff[2] = TEST_FAIL;
+//		self_check_result_buff[3] = TEST_FAIL;
+		
+//		self_check_result_buff[0] = TEST_SUCCESS;
+//		self_check_result_buff[1] = TEST_SUCCESS;
+//		self_check_result_buff[2] = TEST_SUCCESS;
+//		self_check_result_buff[3] = TEST_SUCCESS;
+		
+		for(int j=0; j <TEST_ITEMS; j++ ){
+			SEGGER_RTT_printf(0,"=================>self_check_result_buff[%d] = %d\r\n",j,self_check_result_buff[j]);
+		}
+		
+		//开启需要人工去测试的线程
+		Process_Start(0,"app_self_checking_artificial",app_self_checking_artificial);																								
+
+	}else if(app_charge_Getstate()==BLE_Client_T_CHARGE_PULLOUT){
+		//更新可接受的自检指令最大次数
+		self_check_recive_order_times = SELF_CHECK_RECIVE_ORDER_TIMES;
+		//用于判断充电芯片和电池是否断线
+		int16_t	temp_vol = ADC_RESULT_IN_MILLI_VOLTS(ADC_GetValue(PIN_ADC_CHARGMEASURE_CHANNEL));
+		before_check_charge_vol = before_check_charge_vol > temp_vol ? temp_vol : before_check_charge_vol;	
+	}
+	
+//	//地磁触发自检
+//	else if((IMU_GetCurrentMode() == STATE_LOW_POWER_MODE) && app_charge_Getstate()!=BLE_Client_T_CHARGE_PULLOUT){
+//		int16_t mag[3];
+//		if(IMU_Get_Front_Data_Num() >= 1)IMU_Get_Front_Data(IMU_Get_Front_Data_Num()-1, NULL, NULL, mag, NULL);
+//		int32_t front_mag_norm;
+//		front_mag_norm  = (int32_t)(sqrt((float) (mag[0] * mag[0] + mag[1] * mag[1] + mag[2] * mag[2])));
+////			SEGGER_RTT_printf(0,"front_mag_norm=%d\r\n",front_mag_norm);
+//		if(front_mag_norm>=20000){
+//			hal_mode_set(HAL_MODE_SELF_CHECK);						//开机,开启自检模式
+//			self_check_state = ENTER_SELF_CHECK;
+//		}
+//	}
+	
+//		//上电5秒触发自检
+//		static uint32_t 	tim2 =0;
+//		if(TIME_GetTicks()-tim2>=5000){tim2 = TIME_GetTicks();
+//			static int time_test_check=1;
+//			if(time_test_check){
+//				hal_mode_set(HAL_MODE_SELF_CHECK);						//开机,开启自检模式
+//				self_check_state = ENTER_SELF_CHECK;
+//				time_test_check=0;
+//			}
+//		}
+
+	
+//	//用于测量充电电压、电池电压、电量百分比
+//	int16_t bat;
+//	int16_t	vol;
+//	if(app_charge_Getstate()!=BLE_Client_T_CHARGE_PULLOUT){
+//		bat = ADC_GetValue(PIN_ADC_BAT_CHANNEL);
+//		bat = ADC_RESULT_IN_MILLI_VOLTS(bat)*5/3;
+//		SEGGER_RTT_printf(0,"charge!!! %d %d %d\r\n",before_check_charge_vol,bat,GetBatteryPersent());
+//	}else{
+//		bat = ADC_GetValue(PIN_ADC_BAT_CHANNEL);
+//		bat = ADC_RESULT_IN_MILLI_VOLTS(bat)*5/3;
+//		SEGGER_RTT_printf(0,"no charge!!! %d %d %d\r\n",before_check_charge_vol,bat,GetBatteryPersent());
+//	}
+
+}
+
+void app_self_checking_ready_Process(void)
+{
+	char advname_buf[100];
+	int adv_len;
+	
+	if(app_charge_Getstate()!=BLE_Client_T_CHARGE_PULLOUT && self_check_recive_order_times){
+		slave_get_advname_len(&adv_len);
+		slave_get_advname(advname_buf, adv_len);
+		uint32_t txd,rxd;
+		UART0_GetPinConfig(&txd, &rxd);
+		UART0_Initialize(PIN_TXD_BLE,UART0_INVALID_PIN,UART_HZ);
+		UART0_Tx_Send(0,UART0_T_SELF_CHECK_RDY,(uint8_t*)advname_buf,adv_len);
+//		SEGGER_RTT_printf(0,"advname_buf:%s  len:%d\n",advname_buf,adv_len);
+		UART0_Initialize(txd,rxd,UART_HZ);
+	}
+}
+
+void cb_UART0_R_SELF_CHECK_ASK(void* handle)
+{
+	if(self_check_recive_order_times){
+		hal_mode_set(HAL_MODE_SELF_CHECK);							//串口接收自检指令,开启自检模式
+		self_check_state = ENTER_SELF_CHECK;		
+		self_check_recive_order_times--;
+	}
+}
+
+void app_self_checking_Init(void)
+{
+	UART0_Rx_Regist(UART0_R_SELF_CHECK_ASK,cb_UART0_R_SELF_CHECK_ASK);
+	Process_Start(0,"app_self_checking_monitor_Process",app_self_checking_monitor_Process);
+	Process_Start(APP_SELF_CHECKING_PROCESS_CYCLE,"app_self_checking_Process",app_self_checking_Process);
+	Process_Start(APP_SELF_CHECKING_READY_PROCESS_CYCLE,"app_self_checking_ready_Process",app_self_checking_ready_Process);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 27 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_self_checking.h

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

+ 119 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_step.c

@@ -0,0 +1,119 @@
+#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_mode_manage.h"
+#include "ble_comm.h"
+
+static uint8_t realStepMode = 0;      //是否为实时计步模式
+static uint32_t realStepCur_L = 0;      //左鞋步数记录点
+static uint32_t realStepAdd_R = 0;      //右鞋步数
+static uint32_t realStepTimCnt = 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];
+}
+
+//左鞋实时计步发送
+void app_step_RealSendProcess(void)
+{
+	if(HAL_MODE_REALSTEP == hal_mode_get() && slave_isconnect()>0){
+		uint8_t buf[8];
+		uint8_t L = 0;
+		buf[L++] = BLE_Client_R_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]:%d,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_MODE_REALSTEP == hal_mode_get()){
+			if(slave_isconnect()==0){//与手机断开连接
+				if(realStepTimCnt>0){ realStepTimCnt = 0; //从机在发步数
+					uint8_t mod = BLE_Client_R_REALTIMESTEP_HANDUP;
+					hal_mode_set(HAL_MODE_NORMAL);
+					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_Client_R_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);
+//		  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_Client_R_REALTIMESTEP_ENTER)hal_mode_set(HAL_MODE_REALSTEP);
+	else if(cmd==BLE_Client_R_REALTIMESTEP_EXIT)hal_mode_set(HAL_MODE_NORMAL);
+	
+	BLE_Host_Tx_Send(0,BLE_REALTIMESTEP,&cmd,1);
+	
+	if(cmd==BLE_Client_R_REALTIMESTEP_ENTER && realStepMode==BLE_Client_R_REALTIMESTEP_EXIT)
+			realStepCur_L = mFlash.mStep.stepCur[0]; //重新计数
+	realStepMode = cmd;
+}
+
+void app_step_Init(void)
+{
+	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
sotfware/03_Test/myTest_templet-20220722/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

+ 48 - 0
sotfware/03_Test/myTest_templet-20220722/app/app_switchimu.c

@@ -0,0 +1,48 @@
+#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
sotfware/03_Test/myTest_templet-20220722/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
+
+
+

+ 120 - 0
sotfware/03_Test/myTest_templet-20220722/ble_cfg/ble_comm.h

@@ -0,0 +1,120 @@
+#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"
+
+// <<< 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 1
+#endif
+#if BLE_PRINTF
+#define BLE_PRINT(...) SEGGER_RTT_printf(0, __VA_ARGS__)
+#else
+#define BLE_PRINT(...) ;
+#endif
+#define APP_ERR_BASE 0
+
+
+enum
+{
+	APP_SUCCESS = APP_ERR_BASE,
+	APP_ERR_DISCONN,
+	APP_ERR_CONNECTED,
+	APP_ERR_PARAMERR,
+	APP_ERR_OVERLENGTH,
+	APP_ERR_BUSY,
+};
+
+void err(int err_num);
+
+typedef void (*Ble_receive_handler_t)(unsigned char *, int);
+typedef void (*Ble_evt_cb)(void);
+unsigned int send_bytes_server(uint8_t *bytes, uint16_t len);
+unsigned int send_bytes_client(unsigned char *bytes, uint16_t len);
+void host_init(Ble_receive_handler_t receive_handler);
+void slave_init(Ble_receive_handler_t receive_handler);
+unsigned char slave_isconnect(void);
+unsigned char host_isconnect(void);
+unsigned int host_set_scan_name(char *name, int len);
+unsigned int slave_set_adv_name(char *name, int len);
+void slave_get_advname_len(int *len);
+void slave_get_advname(char *name, int len);
+
+int Ble_Host_Connectd_Evt_Regist(Ble_evt_cb cb);
+int Ble_Host_Disconn_Evt_Regist(Ble_evt_cb cb);
+int Ble_Slave_Connectd_Evt_Regist(Ble_evt_cb cb);
+int Ble_Slave_Disconn_Evt_Regist(Ble_evt_cb cb);
+
+unsigned int Ble_update_conn_interval(float min_conn_interval, float max_conn_interval);
+unsigned int slave_update_conn_interval_request(float min_conn_interval, float max_conn_interval);
+
+void advertising_stop(void);
+void advertising_start(void);
+
+void scan_start(void);
+//关掉扫描直接调用  void nrf_ble_scan_stop(void);
+
+uint8_t Slave_Get7_5ms_interval(void);
+void slave_disconnect(void);
+void host_disconnect(void);
+
+void slave_get_conn_params(ble_gap_conn_params_t *p);
+void host_get_conn_params(ble_gap_conn_params_t *p);
+
+void slave_adv_init(void);
+
+signed char slave_get_rssi(void);
+signed char host_get_rssi(void);
+
+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);
+void IMU_Rec_data(uint8_t* pdat,uint8_t len);
+void IMU_Dtalige(void);
+
+void send_bytes_client_pcs(void);
+#endif

+ 699 - 0
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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__ */
+

+ 180 - 0
sotfware/03_Test/myTest_templet-20220722/ble_cfg/dtalige.c

@@ -0,0 +1,180 @@
+#include "ble_comm.h"
+#include "vl53l1.h"
+#include "tool.h"
+#include "app_game.h"
+
+
+//WAITRIGHT==1 时,无论右鞋数据包是否丢失,左鞋数据包都上传,不等待
+#define WAITRIGHT 1
+
+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_8, QUEUE_MODE_OVERFLOW);
+QUEUE_DEF(IMU_Hal_t, IMU_DAT_S_queue, size_8, QUEUE_MODE_OVERFLOW);
+
+#define UNION_PACK {\
+										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);	\
+}
+
+
+
+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);
+        }
+				else if(ph->element_count > 0)
+				{
+					#if GAMEDATA_TO_RAWDATA
+					if(gamedata_to_rawdata){
+						UNION_PACK
+					}else{
+						queue_out(ph, &outp->h);
+					}
+					#else
+					queue_out(ph, &outp->h);
+					#endif			
+				}
+        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++;			
+									
+//										#if WAITRIGHT //右鞋数据包丢失,左鞋数据包存在,发送左鞋数据包和右鞋(上一个相同的数据包)			
+//										UNION_PACK
+//										#else
+//										queue_out(ph, &outp->h);
+//										#endif
+
+
+										#if GAMEDATA_TO_RAWDATA
+										if(gamedata_to_rawdata){
+											UNION_PACK
+										}else{
+											queue_out(ph, &outp->h);
+										}
+										#else
+										queue_out(ph, &outp->h);
+										#endif
+										
+										if (R_timestamp_re == outp->h.ts)
+										{
+												UNION_PACK
+												break;
+										}
+										if (ph->element_count <= 0)
+										{
+												sta = 0;
+												break;
+										}
+								} while (1);
+						}
+						else
+						{
+								UNION_PACK
+						}
+				}	
+        break;
+    }
+}
+
+void IMU_Dtalige(void)
+{
+		IMU_dtalige(&temp_IMU_DAT, &IMU_DAT_H_queue, &IMU_DAT_S_queue, integrate_left_right);
+}
+
+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);;
+		queue_in(&IMU_DAT_S_queue,&rev_s);	
+	}
+}
+
+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)
+{
+
+	process_motion(time_stamp, _acc, _gry, front_mag, back_mag, _rssi);
+	
+	get_foot_data(rev.imubuff,&rev.imubuff_len);
+	
+	rev.ts++;		
+
+	if(IS_HOST)
+	{
+		queue_in(&IMU_DAT_H_queue,&rev);
+	}
+	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);
+	}
+}
+
+
+
+
+
+
+
+
+
+

+ 602 - 0
sotfware/03_Test/myTest_templet-20220722/ble_cfg/host.c

@@ -0,0 +1,602 @@
+#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);
+}
+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](); //回调函数
+        }
+    }
+}
+
+#if BleNameHoldOn_ENANBLE
+uint8_t SaveFlashFlag_holdOn =0;
+#endif
+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;
+//				gpio_mt_run(500);
+        // 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;
+
+    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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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)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
sotfware/03_Test/myTest_templet-20220722/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 

+ 1615 - 0
sotfware/03_Test/myTest_templet-20220722/ble_cfg/slave.c

@@ -0,0 +1,1615 @@
+#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;
+//			  gpio_mt_run(500);
+        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 short length = len;
+    if (connect_to_client)
+    {
+		ble_nus_data_send(&m_nus, bytes, &length, m_conn_handle);
+	}
+	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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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

+ 232 - 0
sotfware/03_Test/myTest_templet-20220722/bsp/bsp_adc.c

@@ -0,0 +1,232 @@
+/*********************************************************************
+ * INCLUDES
+ */
+#include "bsp_adc.h"
+#include "system.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);
+		APP_ERROR_CHECK(err_code);
+		adc_SampleOk = true;
+	}
+}
+/**
+	@brief	初始化ADC
+	@param	无
+	@return 无
+*/
+static void ADC_Init(void)
+{
+	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,比定时器中断要高,不然回调会在定时器中断结束后触发。
+	APP_ERROR_CHECK(errCode);
+	// 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]);
+			APP_ERROR_CHECK(errCode);
+			sample_in_buffer++;
+		}
+	}
+	if(sample_in_buffer > 0)
+	{
+		// 缓冲配置
+		errCode = nrf_drv_saadc_buffer_convert(s_bufferPool, sample_in_buffer);
+		APP_ERROR_CHECK(errCode);
+	}
+}
+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_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();
+	APP_ERROR_CHECK(errCode);
+	//等待采集
+	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;
+}
+
+
+
+
+
+

+ 59 - 0
sotfware/03_Test/myTest_templet-20220722/bsp/bsp_adc.h

@@ -0,0 +1,59 @@
+#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超时								
+/*********************************************************************
+ * 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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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

+ 506 - 0
sotfware/03_Test/myTest_templet-20220722/bsp/bsp_flash.c

@@ -0,0 +1,506 @@
+
+//flash 1.0V
+
+/*********************************************************************
+ * INCLUDES
+ */
+#include "bsp_flash.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);
+		APP_ERROR_CHECK(errCode);
+	}
+	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,所以先擦后写		
+		errCode = nrf_fstorage_write(&s_fstorageHandle, flashAddr, pData, dataLen, NULL);
+		APP_ERROR_CHECK(errCode);
+	
+		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);
+	APP_ERROR_CHECK(errCode);
+	
+	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,所以先擦后写		
+	APP_ERROR_CHECK(errCode);
+	
+	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;
+}
+
+/****************************************************接口****************************************************/
+
+/**
+ @brief Fstorage读写内存初始化
+ @param 无
+ @return 无
+*/
+void Fstorage_FlashInit(void)
+{
+	ret_code_t errCode;
+
+	nrf_fstorage_api_t *pFstorageApi;
+	pFstorageApi = &nrf_fstorage_sd;
+	
+	errCode = nrf_fstorage_init(&s_fstorageHandle, pFstorageApi, NULL);					// Flash处理的开始地址和结束地址初始化
+	APP_ERROR_CHECK(errCode);
+	
+	(void)getflashEndAddress();															// 获取地址,判断为可写地址大小
+}
+
+/**
+ @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****************************************************/

+ 72 - 0
sotfware/03_Test/myTest_templet-20220722/bsp/bsp_flash.h

@@ -0,0 +1,72 @@
+#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)																																									//页号错误
+/*********************************************************************
+ * 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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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

+ 234 - 0
sotfware/03_Test/myTest_templet-20220722/bsp/bsp_pwm.c

@@ -0,0 +1,234 @@
+/*********************************************************************
+ * INCLUDES
+ */
+#include "sdk_common.h"
+#include "SEGGER_RTT.h"
+#include "usr_config.h"
+#include "system.h"
+#include "nrf_gpio.h"
+#include "bsp_pwm.h"
+
+/*********************************************************************
+ * DEFINITIONS
+ */
+#define PWM_INSTANCE						0
+
+/*********************************************************************
+ * LOCAL VARIABLES
+ */
+static nrf_drv_pwm_t m_pwm = NRF_DRV_PWM_INSTANCE(PWM_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 nrfx_pwm_handler_t m_pwm_callback = NULL;
+
+/*********************************************************************
+ * LOCAL FUNCTIONS
+ */
+/**
+	@brief PWM 初始化
+	@prama 无
+	@return 无
+*/
+static void Pwm_init(void)
+{
+	APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm, &m_config, m_pwm_callback));
+}
+///**
+//	@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;
+}
+/*********************************************************************
+ * 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);
+}
+

+ 63 - 0
sotfware/03_Test/myTest_templet-20220722/bsp/bsp_pwm.h

@@ -0,0 +1,63 @@
+#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);
+
+#endif

+ 13 - 0
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
+

+ 206 - 0
sotfware/03_Test/myTest_templet-20220722/bsp/bsp_time.c

@@ -0,0 +1,206 @@
+#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_imu.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 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); APP_ERROR_CHECK(err_code);
+		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); APP_ERROR_CHECK(err_code);}
+	else { err_code = nrf_drv_rtc_cc_set(&rtc,0,LowPower_Interval * 33,true); APP_ERROR_CHECK(err_code);}
+	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); APP_ERROR_CHECK(err_code);
+	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)
+{
+	uint32_t err_code;
+	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
+	err_code = nrf_drv_rtc_init(&rtc, &config, rtc_tick_handler); APP_ERROR_CHECK(err_code);
+	
+	err_code = nrf_drv_rtc_cc_set(&rtc,NRF_DRV_RTC_INT_COMPARE0,HeartTime_Interval*33,true); APP_ERROR_CHECK(err_code);
+	nrf_drv_rtc_counter_clear(&rtc);
+	nrf_drv_rtc_enable(&rtc);
+
+//	Wakeup_Regist(cb_timeeWakeup);
+}
+

+ 18 - 0
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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
sotfware/03_Test/myTest_templet-20220722/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

+ 44 - 0
sotfware/03_Test/myTest_templet-20220722/bsp/bsp_wdt.c

@@ -0,0 +1,44 @@
+#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"
+
+#if WATCHDOG_ENANBLE
+nrf_drv_wdt_channel_id m_channel_id;
+
+void feed_watchdog(void)
+{
+    nrf_drv_wdt_channel_feed(m_channel_id); 
+}
+
+/**
+ * @brief WDT events handler.
+ */
+void wdt_event_handler(void)
+{
+	SEGGER_RTT_printf(0,"wdt_event_handler:%d\n",TIME_GetTicks());
+}
+
+static void WatchDog_Process(void)
+{
+	 feed_watchdog();
+//	 SEGGER_RTT_printf(0,"WatchDog_Process:%d\n",TIME_GetTicks());
+}
+
+void watchdog_init(void){
+	  uint32_t err_code;
+    nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;
+		config.interrupt_priority = WDT_IRQ_PRIORITY;
+		config.reload_value = WDT_RELOAD_VALUE;
+    err_code = nrf_drv_wdt_init(&config, wdt_event_handler);
+    APP_ERROR_CHECK(err_code);
+    err_code = nrf_drv_wdt_channel_alloc(&m_channel_id);
+    APP_ERROR_CHECK(err_code);
+    nrf_drv_wdt_enable();
+	
+	  Process_Start(1000,"WatchDog_Process",WatchDog_Process);
+}
+#endif

+ 14 - 0
sotfware/03_Test/myTest_templet-20220722/bsp/bsp_wdt.h

@@ -0,0 +1,14 @@
+#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"
+
+#if WATCHDOG_ENANBLE
+void watchdog_init(void);
+void feed_watchdog(void);
+#endif
+#endif

+ 179 - 0
sotfware/03_Test/myTest_templet-20220722/bsp/nrfx_prs.c

@@ -0,0 +1,179 @@
+/**
+ * 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 <nrfx.h>
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+#include "nrfx_prs.h"
+
+#define NRFX_LOG_MODULE PRS
+#include <nrfx_log.h>
+
+#define LOG_FUNCTION_EXIT(level, ret_code)            \
+    NRFX_LOG_##level("Function: %s, error code: %s.", \
+        __func__,                                     \
+        NRFX_LOG_ERROR_STRING_GET(ret_code))
+
+
+typedef struct {
+    nrfx_irq_handler_t handler;
+    bool               acquired;
+} prs_box_t;
+
+#ifndef USE_REGISTER_UART
+#define PRS_BOX_DEFINE(n)                                                    \
+    static prs_box_t m_prs_box_##n = { .handler = NULL, .acquired = false }; \
+    void nrfx_prs_box_##n##_irq_handler(void)                                                                                                   \
+    {                                                                        \
+        NRFX_ASSERT(m_prs_box_##n.handler);                                  \
+        m_prs_box_##n.handler();                                             \
+    }
+#else
+#define PRS_BOX_DEFINE(n)                                                    \
+    static prs_box_t m_prs_box_##n = { .handler = NULL, .acquired = false }; 
+#endif     
+	
+//#define PRS_BOX_DEFINE(n)                                                    \
+//    static prs_box_t m_prs_box_##n = { .handler = NULL, .acquired = false }; \
+//    void nrfx_prs_box_##n##_irq_handler(void)                                \
+//    {                                                                        \
+//        NRFX_ASSERT(m_prs_box_##n.handler);                                  \
+//        m_prs_box_##n.handler();                                             \
+//    }
+
+#if defined(NRFX_PRS_BOX_0_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_0_ENABLED)
+PRS_BOX_DEFINE(0)
+#endif
+#if defined(NRFX_PRS_BOX_1_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_1_ENABLED)
+PRS_BOX_DEFINE(1)
+#endif
+#if defined(NRFX_PRS_BOX_2_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_2_ENABLED)
+PRS_BOX_DEFINE(2)
+#endif
+#if defined(NRFX_PRS_BOX_3_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_3_ENABLED)
+PRS_BOX_DEFINE(3)
+#endif
+#if defined(NRFX_PRS_BOX_4_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_4_ENABLED)
+PRS_BOX_DEFINE(4)
+#endif
+
+
+static prs_box_t * prs_box_get(void const * p_base_addr)
+{
+#if !defined(IS_PRS_BOX)
+#define IS_PRS_BOX(n, p_base_addr)  ((p_base_addr) == NRFX_PRS_BOX_##n##_ADDR)
+#endif
+
+#if defined(NRFX_PRS_BOX_0_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_0_ENABLED)
+    if (IS_PRS_BOX(0, p_base_addr)) { return &m_prs_box_0; }
+    else
+#endif
+#if defined(NRFX_PRS_BOX_1_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_1_ENABLED)
+    if (IS_PRS_BOX(1, p_base_addr)) { return &m_prs_box_1; }
+    else
+#endif
+#if defined(NRFX_PRS_BOX_2_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_2_ENABLED)
+    if (IS_PRS_BOX(2, p_base_addr)) { return &m_prs_box_2; }
+    else
+#endif
+#if defined(NRFX_PRS_BOX_3_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_3_ENABLED)
+    if (IS_PRS_BOX(3, p_base_addr)) { return &m_prs_box_3; }
+    else
+#endif
+#if defined(NRFX_PRS_BOX_4_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_4_ENABLED)
+    if (IS_PRS_BOX(4, p_base_addr)) { return &m_prs_box_4; }
+    else
+#endif
+    {
+        return NULL;
+    }
+}
+
+nrfx_err_t nrfx_prs_acquire(void       const * p_base_addr,
+                            nrfx_irq_handler_t irq_handler)
+{
+    NRFX_ASSERT(p_base_addr);
+
+    nrfx_err_t ret_code;
+
+    prs_box_t * p_box = prs_box_get(p_base_addr);
+    if (p_box != NULL)
+    {
+        bool busy = false;
+
+        NRFX_CRITICAL_SECTION_ENTER();
+        if (p_box->acquired)
+        {
+            busy = true;
+        }
+        else
+        {
+            p_box->handler  = irq_handler;
+            p_box->acquired = true;
+        }
+        NRFX_CRITICAL_SECTION_EXIT();
+
+        if (busy)
+        {
+            ret_code = NRFX_ERROR_BUSY;
+            LOG_FUNCTION_EXIT(WARNING, ret_code);
+            return ret_code;
+        }
+    }
+
+    ret_code = NRFX_SUCCESS;
+    LOG_FUNCTION_EXIT(INFO, ret_code);
+    return ret_code;
+}
+
+void nrfx_prs_release(void const * p_base_addr)
+{
+    NRFX_ASSERT(p_base_addr);
+
+    prs_box_t * p_box = prs_box_get(p_base_addr);
+    if (p_box != NULL)
+    {
+        p_box->handler  = NULL;
+        p_box->acquired = false;
+    }
+}
+
+
+#endif // NRFX_CHECK(NRFX_PRS_ENABLED)

Some files were not shown because too many files changed in this diff