yang преди 2 години
ревизия
5a4b198fa6
променени са 100 файла, в които са добавени 9817 реда и са изтрити 0 реда
  1. 92 0
      app/A01_DOOR/A01_DOOR_example.c
  2. 26 0
      app/A01_DOOR/BUILD.gn
  3. 23 0
      app/A01_DOOR/include/DOOR.h
  4. 99 0
      app/A01_DOOR/src/DOOR.c
  5. 83 0
      app/A02_MQ5/A02_MQ5.c
  6. 25 0
      app/A02_MQ5/BUILD.gn
  7. 32 0
      app/A02_MQ5/include/MQ5.h
  8. 144 0
      app/A02_MQ5/src/MQ5.c
  9. 193 0
      app/A03_MAX30102/A03_MAX30102_example.c
  10. 26 0
      app/A03_MAX30102/BUILD.gn
  11. 85 0
      app/A03_MAX30102/include/algorithm.h
  12. 42 0
      app/A03_MAX30102/include/max30102.h
  13. 379 0
      app/A03_MAX30102/src/algorithm.c
  14. 237 0
      app/A03_MAX30102/src/max30102.c
  15. 193 0
      app/A03_MAX30102_B/A03_MAX30102_example copy.c
  16. 89 0
      app/A03_MAX30102_B/A03_MAX30102_example.c
  17. 177 0
      app/A03_MAX30102_B/A03_MAX30102_example1.c
  18. 27 0
      app/A03_MAX30102_B/BUILD.gn
  19. 63 0
      app/A03_MAX30102_B/include/algorithm.h
  20. 99 0
      app/A03_MAX30102_B/include/algorithm1.h
  21. 25 0
      app/A03_MAX30102_B/include/blood.h
  22. 42 0
      app/A03_MAX30102_B/include/max30102 copy.h
  23. 46 0
      app/A03_MAX30102_B/include/max30102.h
  24. 248 0
      app/A03_MAX30102_B/src/algorithm.c
  25. 363 0
      app/A03_MAX30102_B/src/algorithm1.c
  26. 246 0
      app/A03_MAX30102_B/src/blood.c
  27. 237 0
      app/A03_MAX30102_B/src/max30102 copy 2.c
  28. 249 0
      app/A03_MAX30102_B/src/max30102.c
  29. 71 0
      app/A04_NOISE/A04_NOISE_example.c
  30. 26 0
      app/A04_NOISE/BUILD.gn
  31. 23 0
      app/A04_NOISE/include/noise.h
  32. 103 0
      app/A04_NOISE/src/noise.c
  33. 74 0
      app/A05_WATER/A02_WATER_example.c
  34. 26 0
      app/A05_WATER/BUILD.gn
  35. 23 0
      app/A05_WATER/include/WATER.h
  36. 100 0
      app/A05_WATER/src/WATER.c
  37. 66 0
      app/A06_VOICE_SWITCH/A11_PM2_5_example.c
  38. 26 0
      app/A06_VOICE_SWITCH/BUILD.gn
  39. 29 0
      app/A06_VOICE_SWITCH/include/PM2_5.h
  40. 89 0
      app/A06_VOICE_SWITCH/src/PM2_5.c
  41. 85 0
      app/A07_WATHER/A07_WATHER_example.c
  42. 28 0
      app/A07_WATHER/BUILD.gn
  43. 21 0
      app/A07_WATHER/include/WATHER.h
  44. 172 0
      app/A07_WATHER/include/bmp280.h
  45. 19 0
      app/A07_WATHER/include/dht21.h
  46. 53 0
      app/A07_WATHER/src/WATHER.c
  47. 307 0
      app/A07_WATHER/src/bmp280.c
  48. 245 0
      app/A07_WATHER/src/dht21.c
  49. 81 0
      app/A08_NFC/A08_NFC_example.c
  50. 26 0
      app/A08_NFC/BUILD.gn
  51. 81 0
      app/A08_NFC/include/MPU6050.h
  52. 277 0
      app/A08_NFC/include/pn532.h
  53. 48 0
      app/A08_NFC/include/pn532_hi3861.h
  54. 381 0
      app/A08_NFC/src/MPU6050.c
  55. 498 0
      app/A08_NFC/src/pn532.c
  56. 172 0
      app/A08_NFC/src/pn532_hi3861.c
  57. 74 0
      app/A09_Elevator/A09_Elevator_example.c
  58. 26 0
      app/A09_Elevator/BUILD.gn
  59. 32 0
      app/A09_Elevator/include/elevator.h
  60. 237 0
      app/A09_Elevator/src/elevator.c
  61. 63 0
      app/A11_PM2_5/A11_PM2_5_example.c
  62. 26 0
      app/A11_PM2_5/BUILD.gn
  63. 30 0
      app/A11_PM2_5/include/PM2_5.h
  64. 120 0
      app/A11_PM2_5/src/PM2_5.c
  65. 78 0
      app/A12_SOCKET/A12_SOCKET_example.c
  66. 25 0
      app/A12_SOCKET/BUILD.gn
  67. 32 0
      app/A12_SOCKET/include/SOCKET.h
  68. 126 0
      app/A12_SOCKET/src/SOCKET.c
  69. 73 0
      app/A13_FLAME/A13_FLAME_example..c
  70. 26 0
      app/A13_FLAME/BUILD.gn
  71. 23 0
      app/A13_FLAME/include/flame.h
  72. 103 0
      app/A13_FLAME/src/flame.c
  73. 112 0
      app/A14_CAR/A01_DOOR_example.c
  74. 26 0
      app/A14_CAR/BUILD.gn
  75. 23 0
      app/A14_CAR/include/DOOR.h
  76. 98 0
      app/A14_CAR/src/DOOR.c
  77. 69 0
      app/A16_PLAY/A24_GPS_example.c
  78. 25 0
      app/A16_PLAY/BUILD.gn
  79. 38 0
      app/A16_PLAY/include/L76K.h
  80. 81 0
      app/A16_PLAY/src/L76K.c
  81. 85 0
      app/A17_CH2O/A17_CH2O.c
  82. 25 0
      app/A17_CH2O/BUILD.gn
  83. 33 0
      app/A17_CH2O/include/CH2O.h
  84. 168 0
      app/A17_CH2O/src/CH2O.c
  85. 90 0
      app/A18_ST02D/A18_ST02D_example.c
  86. 26 0
      app/A18_ST02D/BUILD.gn
  87. 27 0
      app/A18_ST02D/include/st02d.h
  88. 119 0
      app/A18_ST02D/src/st02d.c
  89. 71 0
      app/A19_MXL90614/A19_MXL90614_example.c
  90. 27 0
      app/A19_MXL90614/BUILD.gn
  91. 32 0
      app/A19_MXL90614/include/mlx90614.h
  92. 26 0
      app/A19_MXL90614/include/smbus.h
  93. 246 0
      app/A19_MXL90614/src/mlx90614.c
  94. 158 0
      app/A19_MXL90614/src/smbus.c
  95. 71 0
      app/A20_VOICE/A20_VOICE_example.c
  96. 26 0
      app/A20_VOICE/BUILD.gn
  97. 24 0
      app/A20_VOICE/include/VOICE.h
  98. 128 0
      app/A20_VOICE/src/VOICE.c
  99. 102 0
      app/A21_Agriculture/A21_Agriculture_example.c
  100. 27 0
      app/A21_Agriculture/BUILD.gn

+ 92 - 0
app/A01_DOOR/A01_DOOR_example.c

@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "DOOR.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+// #define FLAGS_MSK1 0x00000001U
+
+// osEventFlagsId_t evt_id;
+
+// static void Beep_Alarm(char *arg)
+// {
+//     (void)arg;
+//     osEventFlagsSet(evt_id, FLAGS_MSK1);
+//     printf("Beep_Alarm\n");
+// }
+
+static void ExampleTask(void)
+{
+    // ST02D_Init();
+    // Button_Left_Read_Data(Beep_Alarm);
+    // Button_Right_Read_Data(Beep_Alarm);
+    // while (1)
+    // {
+    //     osEventFlagsWait(evt_id, FLAGS_MSK1, osFlagsWaitAny, osWaitForever);
+    //     BeepStatusSet(ON);
+    //     LedWarnStatusSet(ON);
+    //     osDelay(300);
+    //     BeepStatusSet(OFF);
+    //     LedWarnStatusSet(OFF);
+    // }
+    BoardInit();
+    // Button_Left_Read_Data(Beep_Alarm);
+    // Button_Right_Read_Data(Beep_Alarm);
+    while (1)
+    {
+		if(Door_Read_Data() == 0)
+        {
+            BeepStatusSet(ON);
+            LedWarnStatusSet(ON);
+            LedSafeStatusSet(OFF);
+            
+        }
+		else
+        {
+            BeepStatusSet(OFF);
+            LedWarnStatusSet(OFF);
+            LedSafeStatusSet(ON);
+        }
+        sleep(1);
+    }
+
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 26 - 0
app/A01_DOOR/BUILD.gn

@@ -0,0 +1,26 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A01_DOOR") {
+    sources = [
+        "src/DOOR.c",
+        "A01_DOOR_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "//device/bossay/hi3861_l0/sdk_liteos/include",
+        "include"
+    ]
+}

+ 23 - 0
app/A01_DOOR/include/DOOR.h

@@ -0,0 +1,23 @@
+#ifndef __DOOR_H__
+#define __DOOR_H__
+
+
+#include <stdint.h>
+
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+void BoardInit(void);
+
+uint8_t Button_Left_Read_Data(void);
+
+void BeepStatusSet(SwitchStatus status);
+void LedWarnStatusSet(SwitchStatus status);	
+void LedSafeStatusSet(SwitchStatus status);
+#endif
+
+

+ 99 - 0
app/A01_DOOR/src/DOOR.c

@@ -0,0 +1,99 @@
+#include "DOOR.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+
+
+#define OUT_GPIO 13
+#define LED_SAFE_GPIO 7
+#define LED_WARN_GPIO 14
+#define BEEP_GPIO 8
+
+uint8_t     RxBuffer[3];
+
+
+void BoardInit(void)
+{   
+    IoTGpioInit(OUT_GPIO);
+    IoTGpioSetFunc(OUT_GPIO, IOT_GPIO_FUNC_GPIO_13_GPIO);
+    IoTGpioSetDir(OUT_GPIO, IOT_GPIO_DIR_IN); // 设置GPIO_8为输出模式
+
+    IoTGpioInit(LED_SAFE_GPIO);
+    IoTGpioSetFunc(LED_SAFE_GPIO, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(LED_SAFE_GPIO, IOT_GPIO_DIR_OUT); // 设置为输出模式
+
+    IoTGpioInit(LED_WARN_GPIO);
+    IoTGpioSetFunc(LED_WARN_GPIO, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(LED_WARN_GPIO, IOT_GPIO_DIR_OUT); // 设置为输入模式
+
+    IoTGpioInit(BEEP_GPIO);
+    IoTGpioSetFunc(BEEP_GPIO, IOT_GPIO_FUNC_GPIO_8_GPIO);
+    IoTGpioSetDir(BEEP_GPIO, IOT_GPIO_DIR_OUT); // 设置为输入模式
+}
+
+/***************************************************************
+* 函数名称: Door_Read_Data
+* 说    明: 读取数据
+* 参    数: 无
+* 返 回 值: 无
+***************************************************************/
+uint8_t Door_Read_Data(void)
+{
+    IotGpioValue temp = {0};
+    IoTGpioGetInputVal(OUT_GPIO,&temp);
+    return temp;
+}
+
+/***************************************************************
+ * 函数名称: BeepStatusSet
+ * 说    明: Beep状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void BeepStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(BEEP_GPIO, 1); // 设置GPIO_7输出高电平点亮灯
+    }
+    if (status == OFF) {
+        IoTGpioSetOutputVal(BEEP_GPIO, 0); // 设置GPIO_7输出低电平关闭灯
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedWarnStatusSet
+ * 说    明: LED_Warn状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedWarnStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_WARN_GPIO, 1); // 设置输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_WARN_GPIO, 0); // 设置输出低电平关闭灯
+    }
+}
+/***************************************************************
+ * 函数名称: LedSafeStatusSet
+ * 说    明: LED_Safe状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedSafeStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_SAFE_GPIO, 1); // 设置输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_SAFE_GPIO, 0); // 设置输出低电平关闭灯
+    }
+}

+ 83 - 0
app/A02_MQ5/A02_MQ5.c

@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "ohos_init.h"
+#include "cmsis_os2.h"
+#include "MQ5.h"
+
+#define TASK_STACK_SIZE 1024*8
+#define TASK_PRIO 25
+
+
+static void ExampleTask(void)
+{
+    int ret;
+    float  ppm;
+    
+    BoardInit();
+    //Sensor calibration
+    usleep(1000000);        
+    MQ5PPMCalibration();  
+    
+    while (1) {
+        printf("=======================================\r\n");
+        printf("*************A02_MQ5_example***********\r\n");
+        printf("=======================================\r\n");
+        //get MQ5 ppm
+        ret = GetMQ5PPM(&ppm);
+        if (ret != 0) {
+            printf("ADC Read Fail\n");
+            return ;
+        }
+        printf("ppm:%.3f \n", ppm);
+        if (ppm > 30) {
+            BeepStatusSet(ON);
+            LedStatusSet(ON);
+        } else {
+            BeepStatusSet(OFF);
+            LedStatusSet(OFF);
+        }
+        usleep(1000000);                          
+    } 
+}
+
+/**
+ * @brief Main Entry of the A02_MQ5 Example
+ * 
+ */
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 25 - 0
app/A02_MQ5/BUILD.gn

@@ -0,0 +1,25 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A02_MQ5") {
+    sources = [
+        "src/MQ5.c",
+        "A02_MQ5.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "include"
+    ]
+}

+ 32 - 0
app/A02_MQ5/include/MQ5.h

@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __E53_SF1_H__
+#define __E53_SF1_H__
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+void BoardInit(void);
+void MQ2PPMCalibration(void);
+int GetMQ2PPM(float *ppm);
+void BeepStatusSet(SwitchStatus status);
+void LedStatusSet(SwitchStatus status);
+
+#endif /* __E53_SF1_H__ */
+

+ 144 - 0
app/A02_MQ5/src/MQ5.c

@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MQ5.h"
+#include "iot_adc.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+#include "iot_pwm.h"
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define CAL_PPM 20 //校准环境中PPM值
+#define RL 1       // RL阻值
+
+#define WIFI_IOT_IO_NAME_GPIO_8 8
+#define WIFI_IOT_PWM_PORT_PWM1 1
+#define WIFI_IOT_IO_FUNC_GPIO_8_PWM1_OUT 5
+
+#define LED_GPIO 14
+
+static float R0; //元件在洁净空气中的阻值
+
+/***************************************************************
+ * 函数名称: MQ5Init
+ * 说    明: 初始化MQ5Init
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void BoardInit(void)
+{
+    IoTGpioInit(LED_GPIO);
+    IoTGpioSetFunc(LED_GPIO, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(LED_GPIO, IOT_GPIO_DIR_OUT); //设置GPIO_7为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_8);                                      //初始化GPIO_8
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_PWM1_OUT); //设置GPIO_8引脚复用功能为PWM
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_DIR_OUT);                  //设置GPIO_8引脚为输出模式
+    IoTPwmInit(WIFI_IOT_PWM_PORT_PWM1);                                        //初始化PWM1端口
+}
+/***************************************************************
+* 函数名称: GetVoltage
+* 说    明: 获取电压值函数
+* 参    数: 无
+*								
+* 返 回 值: 无
+***************************************************************/
+static float GetVoltage(void)
+{
+    unsigned int ret;
+    unsigned short data;
+
+    ret = IoTAdcRead(6, &data, IOT_ADC_EQU_MODEL_8, IOT_ADC_CUR_BAIS_DEFAULT, 0xff);
+    if (ret != IOT_SUCCESS)
+    {
+        printf("ADC Read Fail\n");
+    }
+    return (float)data * 1.8 * 4 / 4096.0;
+}
+/***************************************************************
+ * 函数名称: GetMQ5PPM
+ * 说    明: 获取PPM函数
+ * 参    数: ppm 烟雾浓度
+ * 返 回 值: 0 成功; -1 失败
+ ***************************************************************/
+int GetMQ5PPM(float* ppm)
+{
+    unsigned int ret;
+    unsigned short data;
+    float voltage, RS;
+
+    ret = IoTAdcRead(5, &data, IOT_ADC_EQU_MODEL_8, IOT_ADC_CUR_BAIS_DEFAULT, 0xff);
+    if (ret != 0) {
+        printf("ADC Read Fail\n");
+        return -1;
+    }
+    voltage = (float)data * 1.8 * 4 / 4096.0;
+    RS = (5 - voltage) / voltage * RL;     //计算RS
+    *ppm = 613.9f * pow(RS / R0, -2.074f); //计算ppm
+    return 0;
+}
+
+/***************************************************************
+ * 函数名称: MQ5PPMCalibration
+ * 说    明: 传感器校准函数
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void MQ5PPMCalibration(void)
+{
+    float voltage = GetVoltage();
+    float RS = (5 - voltage) / voltage * RL;
+    R0 = RS / pow(CAL_PPM / 613.9f, 1 / -2.074f);
+}
+
+/***************************************************************
+ * 函数名称: BeepStatusSet
+ * 说    明: 蜂鸣器报警与否
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,蜂鸣器
+ *									ON,开蜂鸣器
+ * 返 回 值: 无
+ ***************************************************************/
+void BeepStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTPwmStart(WIFI_IOT_PWM_PORT_PWM1, 50, 4000); //输出PWM波
+    }
+    if (status == OFF) {
+        IoTPwmStop(WIFI_IOT_PWM_PORT_PWM1);
+    }
+}
+/***************************************************************
+ * 函数名称: LedStatusSet
+ * 说    明: 报警灯报警与否
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,光灯
+ *									ON,开灯
+ * 返 回 值: 无
+ ***************************************************************/
+void LedStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_GPIO, 1); //设置GPIO_7输出高电平点亮LED灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_GPIO, 0); //设置GPIO_7输出低电平点亮LED灯
+    }
+}

+ 193 - 0
app/A03_MAX30102/A03_MAX30102_example.c

@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "max30102.h"
+#include "algorithm.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+uint32_t aun_ir_buffer[500]; //IR LED sensor data
+int32_t n_ir_buffer_length;    //data length
+uint32_t aun_red_buffer[500];    //Red LED sensor data
+int32_t n_sp02; //SPO2 value
+int8_t ch_spo2_valid;   //indicator to show if the SP02 calculation is valid
+int32_t n_heart_rate;   //heart rate value
+int8_t  ch_hr_valid;    //indicator to show if the heart rate calculation is valid
+uint8_t uch_dummy;
+
+#define MAX_BRIGHTNESS 255
+
+static void ExampleTask(void)
+{
+	//variables to calculate the on-board LED brightness that reflects the heartbeats
+	uint32_t un_min, un_max, un_prev_data;  
+	int i;
+	int32_t n_brightness;
+	float f_temp;
+	uint8_t temp_num=0;
+	uint8_t temp[6]={0,0,0,0,0,0};
+	uint8_t str[100];
+	uint8_t dis_hr=0,dis_spo2=0;
+
+    BoardInit();
+
+	maxim_max30102_init();
+
+	printf("\r\n MAX30102  init  \r\n");
+
+	un_min=0x3FFFF;
+	un_max=0;
+	
+	n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps
+	//read the first 500 samples, and determine the signal range
+    for(i=0;i<n_ir_buffer_length;i++)
+    {
+        while(GetInit()==1);   //wait until the interrupt pin asserts
+        
+		max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
+		aun_red_buffer[i] =  (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2];    // Combine values to get the actual number
+		aun_ir_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5];   // Combine values to get the actual number
+            
+        if(un_min>aun_red_buffer[i])
+            un_min=aun_red_buffer[i];    //update signal min
+        if(un_max<aun_red_buffer[i])
+            un_max=aun_red_buffer[i];    //update signal max
+        // printf("red=");
+        // printf("%i", aun_red_buffer[i]);
+        // printf(", ir=");
+        // printf("%i\n\r", aun_ir_buffer[i]);
+    }
+	un_prev_data=aun_red_buffer[i];
+	//calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)
+    maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid); 
+	
+	while(1)
+	{
+		i=0;
+        un_min=0x3FFFF;
+        un_max=0;
+		
+		//dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top
+        for(i=100;i<500;i++)
+        {
+            aun_red_buffer[i-100]=aun_red_buffer[i];
+            aun_ir_buffer[i-100]=aun_ir_buffer[i];
+            
+            //update the signal min and max
+            if(un_min>aun_red_buffer[i])
+            un_min=aun_red_buffer[i];
+            if(un_max<aun_red_buffer[i])
+            un_max=aun_red_buffer[i];
+        }
+		//take 100 sets of samples before calculating the heart rate.
+        for(i=400;i<500;i++)
+        {
+            un_prev_data=aun_red_buffer[i-1];
+            while(GetInit()==1);
+			max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
+			aun_red_buffer[i] =  (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2];    // Combine values to get the actual number
+			aun_ir_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5];   // Combine values to get the actual number
+         
+            if(aun_red_buffer[i]>un_prev_data)
+            {
+                f_temp=aun_red_buffer[i]-un_prev_data;
+                f_temp/=(un_max-un_min);
+                f_temp*=MAX_BRIGHTNESS;
+                n_brightness-=(int)f_temp;
+                if(n_brightness<0)
+                    n_brightness=0;
+            }
+            else
+            {
+                f_temp=un_prev_data-aun_red_buffer[i];
+                f_temp/=(un_max-un_min);
+                f_temp*=MAX_BRIGHTNESS;
+                n_brightness+=(int)f_temp;
+                if(n_brightness>MAX_BRIGHTNESS)
+                    n_brightness=MAX_BRIGHTNESS;
+            }
+			//send samples and calculation result to terminal program through UART
+			if(ch_hr_valid == 1 && n_heart_rate<120)//**/ ch_hr_valid == 1 && ch_spo2_valid ==1 && n_heart_rate<120 && n_sp02<101
+			{
+				dis_hr = n_heart_rate;
+				dis_spo2 = n_sp02;
+			}
+			else
+			{
+				dis_hr = 0;
+				dis_spo2 = 0;
+			}
+
+		}
+        // for(i=0;i<500;i++){
+		// 	printf("0x%02x,",aun_ir_buffer[i]);  
+		// }
+		// printf("\r\n");  
+		// printf("--------0-0-----\r\n");
+        // for(i=0;i<500;i++){
+		// 	printf("0x%02x,",aun_red_buffer[i]);  
+		// }
+		// printf("\r\n");  
+		// printf("--------0-0-----\r\n");
+        maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
+        printf("HR=%i, ", n_heart_rate); 
+        printf("HRvalid=%i, ", ch_hr_valid);
+        // printf("SpO2=%i, ", n_sp02);
+        // printf("SPO2Valid=%i\r\n", ch_spo2_valid);
+
+        sleep(1);
+		// //显示刷新
+		// LED0=0;
+		// if(dis_hr == 0 && dis_spo2 == 0)  //**dis_hr == 0 && dis_spo2 == 0
+		// {
+		// 	sprintf((char *)str,"HR:--- SpO2:--- ");//**HR:--- SpO2:--- 
+		// }
+		// else{
+		// 	sprintf((char *)str,"HR:%3d SpO2:%3d ",dis_hr,dis_spo2);//**HR:%3d SpO2:%3d 
+		// }
+		// OLED_ShowString(0,0,str,16);
+		// OLED_Fill(0,23,127,63,0);
+		// //红光在上,红外在下
+		// dis_DrawCurve(aun_red_buffer,20);
+		// dis_DrawCurve(aun_ir_buffer,0);
+		// OLED_Refresh_Gram();//更新显示到OLED	 
+	}
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 26 - 0
app/A03_MAX30102/BUILD.gn

@@ -0,0 +1,26 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A03_MAX30102") {
+    sources = [
+        "src/max30102.c",
+        "src/algorithm.c",
+        "A03_MAX30102_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "include"
+    ]
+}

+ 85 - 0
app/A03_MAX30102/include/algorithm.h

@@ -0,0 +1,85 @@
+/** \file algorithm.h ******************************************************
+*
+* Project: MAXREFDES117#
+* Filename: algorithm.h
+* Description: This module is the heart rate/SpO2 calculation algorithm header file
+*
+* Revision History:
+*\n 1-18-2016 Rev 01.00 SK Initial release.
+*\n
+*
+* --------------------------------------------------------------------
+*
+* This code follows the following naming conventions:
+*
+*\n char              ch_pmod_value
+*\n char (array)      s_pmod_s_string[16]
+*\n float             f_pmod_value
+*\n int32_t           n_pmod_value
+*\n int32_t (array)   an_pmod_value[16]
+*\n int16_t           w_pmod_value
+*\n int16_t (array)   aw_pmod_value[16]
+*\n uint16_t          uw_pmod_value
+*\n uint16_t (array)  auw_pmod_value[16]
+*\n uint8_t           uch_pmod_value
+*\n uint8_t (array)   auch_pmod_buffer[16]
+*\n uint32_t          un_pmod_value
+*\n int32_t *         pn_pmod_value
+*
+* ------------------------------------------------------------------------- */
+/*******************************************************************************
+* Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+#ifndef ALGORITHM_H_
+#define ALGORITHM_H_
+#include <stdint.h>
+
+#define true 1
+#define false 0
+#define FS 100
+#define BUFFER_SIZE  (FS* 5) 
+#define HR_FIFO_SIZE 7
+#define MA4_SIZE  4 // DO NOT CHANGE
+#define HAMMING_SIZE  5// DO NOT CHANGE
+#define min(x,y) ((x) < (y) ? (x) : (y))
+
+
+
+
+void maxim_heart_rate_and_oxygen_saturation(uint32_t *pun_ir_buffer ,  int32_t n_ir_buffer_length, uint32_t *pun_red_buffer ,   int32_t *pn_spo2, int8_t *pch_spo2_valid ,  int32_t *pn_heart_rate , int8_t  *pch_hr_valid);
+void maxim_find_peaks( int32_t *pn_locs, int32_t *pn_npks,  int32_t *pn_x, int32_t n_size, int32_t n_min_height, int32_t n_min_distance, int32_t n_max_num );
+void maxim_peaks_above_min_height( int32_t *pn_locs, int32_t *pn_npks,  int32_t *pn_x, int32_t n_size, int32_t n_min_height );
+void maxim_remove_close_peaks( int32_t *pn_locs, int32_t *pn_npks,   int32_t  *pn_x, int32_t n_min_distance );
+void maxim_sort_ascend( int32_t *pn_x, int32_t n_size );
+void maxim_sort_indices_descend(  int32_t  *pn_x, int32_t *pn_indx, int32_t n_size);
+
+#endif /* ALGORITHM_H_ */

+ 42 - 0
app/A03_MAX30102/include/max30102.h

@@ -0,0 +1,42 @@
+
+#ifndef MAX30102_H_
+#define MAX30102_H_
+
+#include <stdint.h>
+
+#define MAX30102_SLAVE_ADDRESS 0x57
+
+//register addresses
+#define REG_INTR_STATUS_1 0x00
+#define REG_INTR_STATUS_2 0x01
+#define REG_INTR_ENABLE_1 0x02
+#define REG_INTR_ENABLE_2 0x03
+#define REG_FIFO_WR_PTR 0x04
+#define REG_OVF_COUNTER 0x05
+#define REG_FIFO_RD_PTR 0x06
+#define REG_FIFO_DATA 0x07
+#define REG_FIFO_CONFIG 0x08
+#define REG_MODE_CONFIG 0x09
+#define REG_SPO2_CONFIG 0x0A
+#define REG_LED1_PA 0x0C
+#define REG_LED2_PA 0x0D
+#define REG_PILOT_PA 0x10
+#define REG_MULTI_LED_CTRL1 0x11
+#define REG_MULTI_LED_CTRL2 0x12
+#define REG_TEMP_INTR 0x1F
+#define REG_TEMP_FRAC 0x20
+#define REG_TEMP_CONFIG 0x21
+#define REG_PROX_INT_THRESH 0x30
+#define REG_REV_ID 0xFE
+#define REG_PART_ID 0xFF
+
+void BoardInit(void);
+uint8_t GetInit(void);
+uint8_t maxim_max30102_reset();
+uint8_t maxim_max30102_init();
+uint8_t max30102_FIFO_ReadBytes(uint8_t Register_Address,uint8_t* Data);
+uint8_t maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led);
+
+
+
+#endif /* MAX30102_H_ */

+ 379 - 0
app/A03_MAX30102/src/algorithm.c

@@ -0,0 +1,379 @@
+/** \file algorithm.cpp ******************************************************
+*
+* Project: MAXREFDES117#
+* Filename: algorithm.cpp
+* Description: This module calculates the heart rate/SpO2 level
+*
+*
+* --------------------------------------------------------------------
+*
+* This code follows the following naming conventions:
+*
+* char              ch_pmod_value
+* char (array)      s_pmod_s_string[16]
+* float             f_pmod_value
+* int32_t           n_pmod_value
+* int32_t (array)   an_pmod_value[16]
+* int16_t           w_pmod_value
+* int16_t (array)   aw_pmod_value[16]
+* uint16_t          uw_pmod_value
+* uint16_t (array)  auw_pmod_value[16]
+* uint8_t           uch_pmod_value
+* uint8_t (array)   auch_pmod_buffer[16]
+* uint32_t          un_pmod_value
+* int32_t *         pn_pmod_value
+*
+* ------------------------------------------------------------------------- */
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+#include "algorithm.h"
+
+
+const uint16_t auw_hamm[31]={ 41,    276,    512,    276,     41 }; //Hamm=  long16(512* hamming(5)');
+//uch_spo2_table is computed as  -45.060*ratioAverage* ratioAverage + 30.354 *ratioAverage + 94.845 ;
+const uint8_t uch_spo2_table[184]={ 95, 95, 95, 96, 96, 96, 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 99, 99, 99, 99, 
+                            99, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 
+                            100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 97, 97, 
+                            97, 97, 96, 96, 96, 96, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 
+                            90, 90, 89, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 82, 82, 81, 81, 
+                            80, 80, 79, 78, 78, 77, 76, 76, 75, 74, 74, 73, 72, 72, 71, 70, 69, 69, 68, 67, 
+                            66, 66, 65, 64, 63, 62, 62, 61, 60, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 
+                            49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 31, 30, 29, 
+                            28, 27, 26, 25, 23, 22, 21, 20, 19, 17, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5, 
+                            3, 2, 1 } ;
+static  int32_t an_dx[ BUFFER_SIZE-MA4_SIZE]; // delta
+static  int32_t an_x[ BUFFER_SIZE]; //ir
+static  int32_t an_y[ BUFFER_SIZE]; //red
+
+void maxim_heart_rate_and_oxygen_saturation(uint32_t *pun_ir_buffer,  int32_t n_ir_buffer_length, uint32_t *pun_red_buffer, int32_t *pn_spo2, int8_t *pch_spo2_valid, 
+                              int32_t *pn_heart_rate, int8_t  *pch_hr_valid)
+/**
+* \brief        Calculate the heart rate and SpO2 level
+* \par          Details
+*               By detecting  peaks of PPG cycle and corresponding AC/DC of red/infra-red signal, the ratio for the SPO2 is computed.
+*               Since this algorithm is aiming for Arm M0/M3. formaula for SPO2 did not achieve the accuracy due to register overflow.
+*               Thus, accurate SPO2 is precalculated and save longo uch_spo2_table[] per each ratio.
+*
+* \param[in]    *pun_ir_buffer           - IR sensor data buffer
+* \param[in]    n_ir_buffer_length      - IR sensor data buffer length
+* \param[in]    *pun_red_buffer          - Red sensor data buffer
+* \param[out]    *pn_spo2                - Calculated SpO2 value
+* \param[out]    *pch_spo2_valid         - 1 if the calculated SpO2 value is valid
+* \param[out]    *pn_heart_rate          - Calculated heart rate value
+* \param[out]    *pch_hr_valid           - 1 if the calculated heart rate value is valid
+*
+* \retval       None
+*/
+{
+    uint32_t un_ir_mean ,un_only_once ;
+    int32_t k ,n_i_ratio_count;
+    int32_t i, s, m, n_exact_ir_valley_locs_count ,n_middle_idx;
+    int32_t n_th1, n_npks,n_c_min;      
+    int32_t an_ir_valley_locs[15] ;
+    int32_t an_exact_ir_valley_locs[15] ;
+    int32_t an_dx_peak_locs[15] ;
+    int32_t n_peak_interval_sum;
+    
+    int32_t n_y_ac, n_x_ac;
+    int32_t n_spo2_calc; 
+    int32_t n_y_dc_max, n_x_dc_max; 
+    int32_t n_y_dc_max_idx, n_x_dc_max_idx; 
+    int32_t an_ratio[5],n_ratio_average; 
+    int32_t n_nume,  n_denom ;
+    // remove DC of ir signal    
+    un_ir_mean =0; 
+    for (k=0 ; k<n_ir_buffer_length ; k++ ) un_ir_mean += pun_ir_buffer[k] ;
+    un_ir_mean =un_ir_mean/n_ir_buffer_length ;
+    for (k=0 ; k<n_ir_buffer_length ; k++ )  an_x[k] =  pun_ir_buffer[k] - un_ir_mean ; 
+    
+    // 4 pt Moving Average
+    for(k=0; k< BUFFER_SIZE-MA4_SIZE; k++){
+        n_denom= ( an_x[k]+an_x[k+1]+ an_x[k+2]+ an_x[k+3]);
+        an_x[k]=  n_denom/(int32_t)4; 
+    }
+
+    // get difference of smoothed IR signal
+    
+    for( k=0; k<BUFFER_SIZE-MA4_SIZE-1;  k++)
+        an_dx[k]= (an_x[k+1]- an_x[k]);
+
+    // 2-pt Moving Average to an_dx
+    for(k=0; k< BUFFER_SIZE-MA4_SIZE-2; k++){
+        an_dx[k] =  ( an_dx[k]+an_dx[k+1])/2 ;
+    }
+    
+    // hamming window
+    // flip wave form so that we can detect valley with peak detector
+    for ( i=0 ; i<BUFFER_SIZE-HAMMING_SIZE-MA4_SIZE-2 ;i++){
+        s= 0;
+        for( k=i; k<i+ HAMMING_SIZE ;k++){
+            s -= an_dx[k] *auw_hamm[k-i] ; 
+                     }
+        an_dx[i]= s/ (int32_t)1146; // divide by sum of auw_hamm 
+    }
+
+ 
+    n_th1=0; // threshold calculation
+    for ( k=0 ; k<BUFFER_SIZE-HAMMING_SIZE ;k++){
+        n_th1 += ((an_dx[k]>0)? an_dx[k] : ((int32_t)0-an_dx[k])) ;
+    }
+    n_th1= n_th1/ ( BUFFER_SIZE-HAMMING_SIZE);
+    // peak location is acutally index for sharpest location of raw signal since we flipped the signal         
+    maxim_find_peaks( an_dx_peak_locs, &n_npks, an_dx, BUFFER_SIZE-HAMMING_SIZE, n_th1, 8, 5 );//peak_height, peak_distance, max_num_peaks 
+
+    n_peak_interval_sum =0;
+    if (n_npks>=2){
+        for (k=1; k<n_npks; k++)
+            n_peak_interval_sum += (an_dx_peak_locs[k]-an_dx_peak_locs[k -1]);
+        n_peak_interval_sum=n_peak_interval_sum/(n_npks-1);
+        *pn_heart_rate=(int32_t)(6000/n_peak_interval_sum);// beats per minutes
+        *pch_hr_valid  = 1;
+    }
+    else  {
+        *pn_heart_rate = -999;
+        *pch_hr_valid  = 0;
+    }
+            
+    for ( k=0 ; k<n_npks ;k++)
+        an_ir_valley_locs[k]=an_dx_peak_locs[k]+HAMMING_SIZE/2; 
+
+
+    // raw value : RED(=y) and IR(=X)
+    // we need to assess DC and AC value of ir and red PPG. 
+    for (k=0 ; k<n_ir_buffer_length ; k++ )  {
+        an_x[k] =  pun_ir_buffer[k] ; 
+        an_y[k] =  pun_red_buffer[k] ; 
+    }
+
+    // find precise min near an_ir_valley_locs
+    n_exact_ir_valley_locs_count =0; 
+    for(k=0 ; k<n_npks ;k++){
+        un_only_once =1;
+        m=an_ir_valley_locs[k];
+        n_c_min= 16777216;//2^24;
+        if (m+5 <  BUFFER_SIZE-HAMMING_SIZE  && m-5 >0){
+            for(i= m-5;i<m+5; i++)
+                if (an_x[i]<n_c_min){
+                    if (un_only_once >0){
+                       un_only_once =0;
+                   } 
+                   n_c_min= an_x[i] ;
+                   an_exact_ir_valley_locs[k]=i;
+                }
+            if (un_only_once ==0)
+                n_exact_ir_valley_locs_count ++ ;
+        }
+    }
+    if (n_exact_ir_valley_locs_count <2 ){
+       *pn_spo2 =  -999 ; // do not use SPO2 since signal ratio is out of range
+       *pch_spo2_valid  = 0; 
+       return;
+    }
+    // 4 pt MA
+    for(k=0; k< BUFFER_SIZE-MA4_SIZE; k++){
+        an_x[k]=( an_x[k]+an_x[k+1]+ an_x[k+2]+ an_x[k+3])/(int32_t)4;
+        an_y[k]=( an_y[k]+an_y[k+1]+ an_y[k+2]+ an_y[k+3])/(int32_t)4;
+    }
+
+    //using an_exact_ir_valley_locs , find ir-red DC andir-red AC for SPO2 calibration ratio
+    //finding AC/DC maximum of raw ir * red between two valley locations
+    n_ratio_average =0; 
+    n_i_ratio_count =0; 
+    
+    for(k=0; k< 5; k++) an_ratio[k]=0;
+    for (k=0; k< n_exact_ir_valley_locs_count; k++){
+        if (an_exact_ir_valley_locs[k] > BUFFER_SIZE ){             
+            *pn_spo2 =  -999 ; // do not use SPO2 since valley loc is out of range
+            *pch_spo2_valid  = 0; 
+            return;
+        }
+    }
+    // find max between two valley locations 
+    // and use ratio betwen AC compoent of Ir & Red and DC compoent of Ir & Red for SPO2 
+
+    for (k=0; k< n_exact_ir_valley_locs_count-1; k++){
+        n_y_dc_max= -16777216 ; 
+        n_x_dc_max= - 16777216; 
+        if (an_exact_ir_valley_locs[k+1]-an_exact_ir_valley_locs[k] >10){
+            for (i=an_exact_ir_valley_locs[k]; i< an_exact_ir_valley_locs[k+1]; i++){
+                if (an_x[i]> n_x_dc_max) {n_x_dc_max =an_x[i];n_x_dc_max_idx =i; }
+                if (an_y[i]> n_y_dc_max) {n_y_dc_max =an_y[i];n_y_dc_max_idx=i;}
+            }
+            n_y_ac= (an_y[an_exact_ir_valley_locs[k+1]] - an_y[an_exact_ir_valley_locs[k] ] )*(n_y_dc_max_idx -an_exact_ir_valley_locs[k]); //red
+            n_y_ac=  an_y[an_exact_ir_valley_locs[k]] + n_y_ac/ (an_exact_ir_valley_locs[k+1] - an_exact_ir_valley_locs[k])  ; 
+        
+        
+            n_y_ac=  an_y[n_y_dc_max_idx] - n_y_ac;    // subracting linear DC compoenents from raw 
+            n_x_ac= (an_x[an_exact_ir_valley_locs[k+1]] - an_x[an_exact_ir_valley_locs[k] ] )*(n_x_dc_max_idx -an_exact_ir_valley_locs[k]); // ir
+            n_x_ac=  an_x[an_exact_ir_valley_locs[k]] + n_x_ac/ (an_exact_ir_valley_locs[k+1] - an_exact_ir_valley_locs[k]); 
+            n_x_ac=  an_x[n_y_dc_max_idx] - n_x_ac;      // subracting linear DC compoenents from raw 
+            n_nume=( n_y_ac *n_x_dc_max)>>7 ; //prepare X100 to preserve floating value
+            n_denom= ( n_x_ac *n_y_dc_max)>>7;
+            if (n_denom>0  && n_i_ratio_count <5 &&  n_nume != 0)
+            {   
+                an_ratio[n_i_ratio_count]= (n_nume*20)/n_denom ; //formular is ( n_y_ac *n_x_dc_max) / ( n_x_ac *n_y_dc_max) ;
+                n_i_ratio_count++;
+            }
+        }
+    }
+
+    maxim_sort_ascend(an_ratio, n_i_ratio_count);
+    n_middle_idx= n_i_ratio_count/2;
+
+    if (n_middle_idx >1)
+        n_ratio_average =( an_ratio[n_middle_idx-1] +an_ratio[n_middle_idx])/2; // use median
+    else
+        n_ratio_average = an_ratio[n_middle_idx ];
+
+    if( n_ratio_average>2 && n_ratio_average <184){
+        n_spo2_calc= uch_spo2_table[n_ratio_average] ;
+        *pn_spo2 = n_spo2_calc ;
+        *pch_spo2_valid  = 1;//  float_SPO2 =  -45.060*n_ratio_average* n_ratio_average/10000 + 30.354 *n_ratio_average/100 + 94.845 ;  // for comparison with table
+    }
+    else{
+        *pn_spo2 =  -999 ; // do not use SPO2 since signal ratio is out of range
+        *pch_spo2_valid  = 0; 
+    }
+}
+
+
+void maxim_find_peaks(int32_t *pn_locs, int32_t *pn_npks, int32_t *pn_x, int32_t n_size, int32_t n_min_height, int32_t n_min_distance, int32_t n_max_num)
+/**
+* \brief        Find peaks
+* \par          Details
+*               Find at most MAX_NUM peaks above MIN_HEIGHT separated by at least MIN_DISTANCE
+*
+* \retval       None
+*/
+{
+    maxim_peaks_above_min_height( pn_locs, pn_npks, pn_x, n_size, n_min_height );
+    maxim_remove_close_peaks( pn_locs, pn_npks, pn_x, n_min_distance );
+    *pn_npks = min( *pn_npks, n_max_num );
+}
+
+void maxim_peaks_above_min_height(int32_t *pn_locs, int32_t *pn_npks, int32_t  *pn_x, int32_t n_size, int32_t n_min_height)
+/**
+* \brief        Find peaks above n_min_height
+* \par          Details
+*               Find all peaks above MIN_HEIGHT
+*
+* \retval       None
+*/
+{
+    int32_t i = 1, n_width;
+    *pn_npks = 0;
+    
+    while (i < n_size-1){
+        if (pn_x[i] > n_min_height && pn_x[i] > pn_x[i-1]){            // find left edge of potential peaks
+            n_width = 1;
+            while (i+n_width < n_size && pn_x[i] == pn_x[i+n_width])    // find flat peaks
+                n_width++;
+            if (pn_x[i] > pn_x[i+n_width] && (*pn_npks) < 15 ){                            // find right edge of peaks
+                pn_locs[(*pn_npks)++] = i;        
+                // for flat peaks, peak location is left edge
+                i += n_width+1;
+            }
+            else
+                i += n_width;
+        }
+        else
+            i++;
+    }
+}
+
+
+void maxim_remove_close_peaks(int32_t *pn_locs, int32_t *pn_npks, int32_t *pn_x, int32_t n_min_distance)
+/**
+* \brief        Remove peaks
+* \par          Details
+*               Remove peaks separated by less than MIN_DISTANCE
+*
+* \retval       None
+*/
+{
+    
+    int32_t i, j, n_old_npks, n_dist;
+    
+    /* Order peaks from large to small */
+    maxim_sort_indices_descend( pn_x, pn_locs, *pn_npks );
+
+    for ( i = -1; i < *pn_npks; i++ ){
+        n_old_npks = *pn_npks;
+        *pn_npks = i+1;
+        for ( j = i+1; j < n_old_npks; j++ ){
+            n_dist =  pn_locs[j] - ( i == -1 ? -1 : pn_locs[i] ); // lag-zero peak of autocorr is at index -1
+            if ( n_dist > n_min_distance || n_dist < -n_min_distance )
+                pn_locs[(*pn_npks)++] = pn_locs[j];
+        }
+    }
+
+    // Resort indices longo ascending order
+    maxim_sort_ascend( pn_locs, *pn_npks );
+}
+
+void maxim_sort_ascend(int32_t *pn_x,int32_t n_size) 
+/**
+* \brief        Sort array
+* \par          Details
+*               Sort array in ascending order (insertion sort algorithm)
+*
+* \retval       None
+*/
+{
+    int32_t i, j, n_temp;
+    for (i = 1; i < n_size; i++) {
+        n_temp = pn_x[i];
+        for (j = i; j > 0 && n_temp < pn_x[j-1]; j--)
+            pn_x[j] = pn_x[j-1];
+        pn_x[j] = n_temp;
+    }
+}
+
+void maxim_sort_indices_descend(int32_t *pn_x, int32_t *pn_indx, int32_t n_size)
+/**
+* \brief        Sort indices
+* \par          Details
+*               Sort indices according to descending order (insertion sort algorithm)
+*
+* \retval       None
+*/ 
+{
+    int32_t i, j, n_temp;
+    for (i = 1; i < n_size; i++) {
+        n_temp = pn_indx[i];
+        for (j = i; j > 0 && pn_x[n_temp] > pn_x[pn_indx[j-1]]; j--)
+            pn_indx[j] = pn_indx[j-1];
+        pn_indx[j] = n_temp;
+    }
+}
+

+ 237 - 0
app/A03_MAX30102/src/max30102.c

@@ -0,0 +1,237 @@
+#include "max30102.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+#include "iot_i2c.h"
+#include "iot_i2c_ex.h"
+#include <stdio.h>
+
+#define WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA 6
+#define WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL 6
+#define WIFI_IOT_I2C_IDX_1 1
+#define WIFI_IOT_IO_NAME_GPIO_7 7
+#define WIFI_IOT_IO_NAME_GPIO_8 8
+#define WIFI_IOT_IO_NAME_GPIO_0 0
+#define WIFI_IOT_IO_NAME_GPIO_1 1
+#define MAX30102_INIT_GPIO 7
+/***************************************************************
+ * 函数名称: GpioInit
+ * 说    明:  GPIO初始化
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void BoardInit(void)
+{
+    // IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_8);
+    // IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_GPIO);
+    // IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_DIR_OUT); // 设置GPIO_8为输出模式
+
+    IoTGpioInit(MAX30102_INIT_GPIO);
+    IoTGpioSetFunc(MAX30102_INIT_GPIO, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(MAX30102_INIT_GPIO, IOT_GPIO_DIR_IN); // 设置GPIO_7为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_0);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA); // GPIO_0复用为I2C1_SDA
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_1);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL); // GPIO_1复用为I2C1_SCL
+    IoTI2cInit(WIFI_IOT_I2C_IDX_1, 400000);              /* baudrate: 400kbps */
+}
+
+
+uint8_t GetInit(void)
+{
+	IotGpioValue temp = {0};
+    IoTGpioGetInputVal(MAX30102_INIT_GPIO,&temp);
+    return temp;
+}
+
+
+/**
+* \brief        Write a value to a MAX30102 register
+* \par          Details
+*               This function writes a value to a MAX30102 register
+*
+* \param[in]    uch_addr    - register address
+* \param[in]    uch_data    - register data
+*
+* \retval       true on success
+*/
+static int maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data)
+{
+    uint32_t ret;
+    uint8_t send_data[2] = {uch_addr, uch_data};
+    ret = IoTI2cWrite(WIFI_IOT_I2C_IDX_1, (MAX30102_SLAVE_ADDRESS << 1) | 0x00, send_data, 2);
+    if (ret != 0) {
+        printf("===== Error: I2C write ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    return 0;
+}
+
+/**
+* \brief        Read a MAX30102 register
+* \par          Details
+*               This function reads a MAX30102 register
+*
+* \param[in]    uch_addr    - register address
+* \param[out]   puch_data    - pointer that stores the register data
+*
+* \retval       true on success
+*/
+uint8_t maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data)
+{
+    uint32_t ret = 0;
+    IotI2cData max30102_i2c_data = {0};
+    uint8_t buffer[1] = {uch_addr};
+    max30102_i2c_data.sendBuf = buffer;
+    max30102_i2c_data.sendLen = 1;
+    max30102_i2c_data.receiveBuf = puch_data;
+    max30102_i2c_data.receiveLen = 1;
+    ret = IoTI2cWriteread(WIFI_IOT_I2C_IDX_1, (MAX30102_SLAVE_ADDRESS << 1) | 0x00, &max30102_i2c_data);
+    if (ret != 0) {
+        printf("===== Error: I2C writeread ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    return 0;
+}
+
+uint8_t maxim_max30102_init()
+{
+	
+    if(maxim_max30102_write_reg(REG_INTR_ENABLE_1,0xc0)!=IOT_SUCCESS) // INTR setting
+        return 0;
+    if(maxim_max30102_write_reg(REG_INTR_ENABLE_2,0x00)!=IOT_SUCCESS)
+        return 0;
+    if(maxim_max30102_write_reg(REG_FIFO_WR_PTR,0x00)!=IOT_SUCCESS)  //FIFO_WR_PTR[4:0]
+        return 0;
+    if(maxim_max30102_write_reg(REG_OVF_COUNTER,0x00)!=IOT_SUCCESS)  //OVF_COUNTER[4:0]
+        return 0;
+    if(maxim_max30102_write_reg(REG_FIFO_RD_PTR,0x00)!=IOT_SUCCESS)  //FIFO_RD_PTR[4:0]
+        return 0;
+    if(maxim_max30102_write_reg(REG_FIFO_CONFIG,0x0f)!=IOT_SUCCESS)  //sample avg = 1, fifo rollover=false, fifo almost full = 17
+        return 0;
+    if(maxim_max30102_write_reg(REG_MODE_CONFIG,0x03)!=IOT_SUCCESS)   //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
+        return 0;
+    if(maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27)!=IOT_SUCCESS)  // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)
+        return 0;
+    
+    if(maxim_max30102_write_reg(REG_LED1_PA,0x32)!=IOT_SUCCESS)   //Choose value for ~ 7mA for LED1
+        return 0;
+    if(maxim_max30102_write_reg(REG_LED2_PA,0x32)!=IOT_SUCCESS)   // Choose value for ~ 7mA for LED2
+        return 0;
+    if(maxim_max30102_write_reg(REG_PILOT_PA,0x7f)!=IOT_SUCCESS)   // Choose value for ~ 25mA for Pilot LED
+        return 0;
+    return 1;  
+
+}
+
+
+/**
+* \brief        Reset the MAX30102
+* \par          Details
+*               This function resets the MAX30102
+*
+* \param        None
+*
+* \retval       true on success
+*/
+uint8_t maxim_max30102_reset()
+{
+    if(maxim_max30102_write_reg(REG_MODE_CONFIG,0x40)!=IOT_SUCCESS)
+        return 0;
+    else
+        return 1;    
+}
+/**
+* \brief        Read a set of samples from the MAX30102 FIFO register
+* \par          Details
+*               This function reads a set of samples from the MAX30102 FIFO register
+*
+* \param[out]   *pun_red_led   - pointer that stores the red LED reading data
+* \param[out]   *pun_ir_led    - pointer that stores the IR LED reading data
+*
+* \retval       true on success
+*/
+uint8_t max30102_FIFO_ReadBytes(uint8_t Register_Address,uint8_t* Data)
+{
+    uint32_t un_temp;
+    unsigned char uch_temp;
+  
+    //read and clear status register
+    maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);
+    maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);
+  
+//   ach_i2c_data[0]=REG_FIFO_DATA;
+	 
+    uint32_t ret = 0;
+    IotI2cData max30102_i2c_data = {0};
+    uint8_t buffer[1] = {REG_FIFO_DATA};
+    max30102_i2c_data.sendBuf = buffer;
+    max30102_i2c_data.sendLen = 1;
+    max30102_i2c_data.receiveBuf = Data;
+    max30102_i2c_data.receiveLen = 6;
+    ret = IoTI2cWriteread(WIFI_IOT_I2C_IDX_1, (MAX30102_SLAVE_ADDRESS << 1) | 0x00, &max30102_i2c_data);
+    if (ret != 0) {
+        printf("===== Error: I2C writeread ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    return 0;
+}
+
+/**
+* \brief        Read a set of samples from the MAX30102 FIFO register
+* \par          Details
+*               This function reads a set of samples from the MAX30102 FIFO register
+*
+* \param[out]   *pun_red_led   - pointer that stores the red LED reading data
+* \param[out]   *pun_ir_led    - pointer that stores the IR LED reading data
+*
+* \retval       true on success
+*/
+uint8_t maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)
+{
+    uint32_t un_temp;
+    unsigned char uch_temp;
+    *pun_red_led=0;
+    *pun_ir_led=0;
+    uint8_t ach_i2c_data[6];
+    
+    //read and clear status register
+    maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);
+    maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);
+  
+//   ach_i2c_data[0]=REG_FIFO_DATA;
+	 
+    uint32_t ret = 0;
+    IotI2cData max30102_i2c_data = {0};
+    uint8_t buffer[1] = {REG_FIFO_DATA};
+    max30102_i2c_data.sendBuf = buffer;
+    max30102_i2c_data.sendLen = 1;
+    max30102_i2c_data.receiveBuf = ach_i2c_data;
+    max30102_i2c_data.receiveLen = 6;
+    ret = IoTI2cWriteread(WIFI_IOT_I2C_IDX_1, (MAX30102_SLAVE_ADDRESS << 1) | 0x00, &max30102_i2c_data);
+    if (ret != 0) {
+        printf("===== Error: I2C writeread ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    un_temp=(unsigned char) ach_i2c_data[0];
+    un_temp<<=16;
+    *pun_red_led+=un_temp;
+    un_temp=(unsigned char) ach_i2c_data[1];
+    un_temp<<=8;
+    *pun_red_led+=un_temp;
+    un_temp=(unsigned char) ach_i2c_data[2];
+    *pun_red_led+=un_temp;
+    
+    un_temp=(unsigned char) ach_i2c_data[3];
+    un_temp<<=16;
+    *pun_ir_led+=un_temp;
+    un_temp=(unsigned char) ach_i2c_data[4];
+    un_temp<<=8;
+    *pun_ir_led+=un_temp;
+    un_temp=(unsigned char) ach_i2c_data[5];
+    *pun_ir_led+=un_temp;
+    *pun_red_led&=0x03FFFF;  //Mask MSB [23:18]
+    *pun_ir_led&=0x03FFFF;  //Mask MSB [23:18]
+    return 1;
+}

+ 193 - 0
app/A03_MAX30102_B/A03_MAX30102_example copy.c

@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "max30102.h"
+#include "algorithm.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+uint32_t aun_ir_buffer[500]; //IR LED sensor data
+int32_t n_ir_buffer_length;    //data length
+uint32_t aun_red_buffer[500];    //Red LED sensor data
+int32_t n_sp02; //SPO2 value
+int8_t ch_spo2_valid;   //indicator to show if the SP02 calculation is valid
+int32_t n_heart_rate;   //heart rate value
+int8_t  ch_hr_valid;    //indicator to show if the heart rate calculation is valid
+uint8_t uch_dummy;
+
+#define MAX_BRIGHTNESS 255
+
+static void ExampleTask(void)
+{
+	//variables to calculate the on-board LED brightness that reflects the heartbeats
+	uint32_t un_min, un_max, un_prev_data;  
+	int i;
+	int32_t n_brightness;
+	float f_temp;
+	uint8_t temp_num=0;
+	uint8_t temp[6]={0,0,0,0,0,0};
+	uint8_t str[100];
+	uint8_t dis_hr=0,dis_spo2=0;
+
+    BoardInit();
+
+	maxim_max30102_init();
+
+	printf("\r\n MAX30102  init  \r\n");
+
+	un_min=0x3FFFF;
+	un_max=0;
+	
+	n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps
+	//read the first 500 samples, and determine the signal range
+    for(i=0;i<n_ir_buffer_length;i++)
+    {
+        while(GetInit()==1);   //wait until the interrupt pin asserts
+        
+		max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
+		aun_red_buffer[i] =  (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2];    // Combine values to get the actual number
+		aun_ir_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5];   // Combine values to get the actual number
+            
+        if(un_min>aun_red_buffer[i])
+            un_min=aun_red_buffer[i];    //update signal min
+        if(un_max<aun_red_buffer[i])
+            un_max=aun_red_buffer[i];    //update signal max
+        // printf("red=");
+        // printf("%i", aun_red_buffer[i]);
+        // printf(", ir=");
+        // printf("%i\n\r", aun_ir_buffer[i]);
+    }
+	un_prev_data=aun_red_buffer[i];
+	//calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)
+    maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid); 
+	
+	while(1)
+	{
+		i=0;
+        un_min=0x3FFFF;
+        un_max=0;
+		
+		//dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top
+        for(i=100;i<500;i++)
+        {
+            aun_red_buffer[i-100]=aun_red_buffer[i];
+            aun_ir_buffer[i-100]=aun_ir_buffer[i];
+            
+            //update the signal min and max
+            if(un_min>aun_red_buffer[i])
+            un_min=aun_red_buffer[i];
+            if(un_max<aun_red_buffer[i])
+            un_max=aun_red_buffer[i];
+        }
+		//take 100 sets of samples before calculating the heart rate.
+        for(i=400;i<500;i++)
+        {
+            un_prev_data=aun_red_buffer[i-1];
+            while(GetInit()==1);
+			max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
+			aun_red_buffer[i] =  (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2];    // Combine values to get the actual number
+			aun_ir_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5];   // Combine values to get the actual number
+         
+            if(aun_red_buffer[i]>un_prev_data)
+            {
+                f_temp=aun_red_buffer[i]-un_prev_data;
+                f_temp/=(un_max-un_min);
+                f_temp*=MAX_BRIGHTNESS;
+                n_brightness-=(int)f_temp;
+                if(n_brightness<0)
+                    n_brightness=0;
+            }
+            else
+            {
+                f_temp=un_prev_data-aun_red_buffer[i];
+                f_temp/=(un_max-un_min);
+                f_temp*=MAX_BRIGHTNESS;
+                n_brightness+=(int)f_temp;
+                if(n_brightness>MAX_BRIGHTNESS)
+                    n_brightness=MAX_BRIGHTNESS;
+            }
+			//send samples and calculation result to terminal program through UART
+			if(ch_hr_valid == 1 && n_heart_rate<120)//**/ ch_hr_valid == 1 && ch_spo2_valid ==1 && n_heart_rate<120 && n_sp02<101
+			{
+				dis_hr = n_heart_rate;
+				dis_spo2 = n_sp02;
+			}
+			else
+			{
+				dis_hr = 0;
+				dis_spo2 = 0;
+			}
+
+		}
+        // for(i=0;i<500;i++){
+		// 	printf("0x%02x,",aun_ir_buffer[i]);  
+		// }
+		// printf("\r\n");  
+		// printf("--------0-0-----\r\n");
+        // for(i=0;i<500;i++){
+		// 	printf("0x%02x,",aun_red_buffer[i]);  
+		// }
+		// printf("\r\n");  
+		// printf("--------0-0-----\r\n");
+        maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
+        printf("HR=%i, ", n_heart_rate); 
+        printf("HRvalid=%i, ", ch_hr_valid);
+        printf("SpO2=%i, ", n_sp02);
+        printf("SPO2Valid=%i\r\n", ch_spo2_valid);
+
+        sleep(1);
+		// //显示刷新
+		// LED0=0;
+		// if(dis_hr == 0 && dis_spo2 == 0)  //**dis_hr == 0 && dis_spo2 == 0
+		// {
+		// 	sprintf((char *)str,"HR:--- SpO2:--- ");//**HR:--- SpO2:--- 
+		// }
+		// else{
+		// 	sprintf((char *)str,"HR:%3d SpO2:%3d ",dis_hr,dis_spo2);//**HR:%3d SpO2:%3d 
+		// }
+		// OLED_ShowString(0,0,str,16);
+		// OLED_Fill(0,23,127,63,0);
+		// //红光在上,红外在下
+		// dis_DrawCurve(aun_red_buffer,20);
+		// dis_DrawCurve(aun_ir_buffer,0);
+		// OLED_Refresh_Gram();//更新显示到OLED	 
+	}
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 89 - 0
app/A03_MAX30102_B/A03_MAX30102_example.c

@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+// #include "max30102.h"
+#include "algorithm.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+#include "blood.h"
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+uint32_t aun_ir_buffer[500]; //IR LED sensor data
+int32_t n_ir_buffer_length;    //data length
+uint32_t aun_red_buffer[500];    //Red LED sensor data
+int32_t n_sp02; //SPO2 value
+int8_t ch_spo2_valid;   //indicator to show if the SP02 calculation is valid
+int32_t n_heart_rate;   //heart rate value
+int8_t  ch_hr_valid;    //indicator to show if the heart rate calculation is valid
+uint8_t uch_dummy;
+
+#define MAX_BRIGHTNESS 255
+
+static void ExampleTask(void)
+{
+	//variables to calculate the on-board LED brightness that reflects the heartbeats
+	uint32_t un_min, un_max, un_prev_data;  
+	int i;
+	int32_t n_brightness;
+	float f_temp;
+	uint8_t temp_num=0;
+	uint8_t temp[6]={0,0,0,0,0,0};
+	uint8_t str[100];
+	uint8_t dis_hr=0,dis_spo2=0;
+
+    BoardInit();
+
+	maxim_max30102_init();
+
+	printf("\r\n MAX30102  init  \r\n");
+
+    for(i = 0;i < 128;i++) 
+	{
+		while(GetInit()==0)
+		{
+			max30102_read_fifo();
+		}
+	}
+	while(1)
+	{	
+		// deal_Temp();
+		blood_Loop();
+	}
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 177 - 0
app/A03_MAX30102_B/A03_MAX30102_example1.c

@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "max30102.h"
+#include "algorithm.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+uint32_t aun_ir_buffer[500]; //IR LED sensor data
+int32_t n_ir_buffer_length;    //data length
+uint32_t aun_red_buffer[500];    //Red LED sensor data
+int32_t n_sp02; //SPO2 value
+int8_t ch_spo2_valid;   //indicator to show if the SP02 calculation is valid
+int32_t n_heart_rate;   //heart rate value
+int8_t  ch_hr_valid;    //indicator to show if the heart rate calculation is valid
+uint8_t uch_dummy;
+
+#define MAX_BRIGHTNESS 255
+
+static void ExampleTask(void)
+{
+	//variables to calculate the on-board LED brightness that reflects the heartbeats
+	uint32_t un_min, un_max, un_prev_data;  
+	int i;
+	int32_t n_brightness;
+	float f_temp;
+	uint8_t temp_num=0;
+	uint8_t temp[6];
+	uint8_t str[100];
+	uint8_t dis_hr=0,dis_spo2=0;
+
+    BoardInit();
+
+	maxim_max30102_init();
+
+	printf("\r\n MAX30102  init  \r\n");
+
+	un_min=0x3FFFF;
+	un_max=0;
+	
+	n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps
+	//read the first 500 samples, and determine the signal range
+    for(i=0;i<n_ir_buffer_length;i++)
+    {
+        while(GetInit()==1);   //wait until the interrupt pin asserts
+        
+        maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));
+            
+        if(un_min>aun_red_buffer[i])
+            un_min=aun_red_buffer[i];    //update signal min
+        if(un_max<aun_red_buffer[i])
+            un_max=aun_red_buffer[i];    //update signal max
+        printf("red=");
+        printf("%i", aun_red_buffer[i]);
+        printf(", ir=");
+        printf("%i\n\r", aun_ir_buffer[i]);
+    }
+	un_prev_data=aun_red_buffer[i];
+	//calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)
+    maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid); 
+	
+	while(1)
+	{
+		i=0;
+        un_min=0x3FFFF;
+        un_max=0;
+		
+		//dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top
+        for(i=100;i<500;i++)
+        {
+            aun_red_buffer[i-100]=aun_red_buffer[i];
+            aun_ir_buffer[i-100]=aun_ir_buffer[i];
+            
+            //update the signal min and max
+            if(un_min>aun_red_buffer[i])
+            un_min=aun_red_buffer[i];
+            if(un_max<aun_red_buffer[i])
+            un_max=aun_red_buffer[i];
+        }
+		//take 100 sets of samples before calculating the heart rate.
+        for(i=400;i<500;i++)
+        {
+            un_prev_data=aun_red_buffer[i-1];
+            while(GetInit()==1);
+            maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));
+        
+            if(aun_red_buffer[i]>un_prev_data)
+            {
+                f_temp=aun_red_buffer[i]-un_prev_data;
+                f_temp/=(un_max-un_min);
+                f_temp*=MAX_BRIGHTNESS;
+                n_brightness-=(int)f_temp;
+                if(n_brightness<0)
+                    n_brightness=0;
+            }
+            else
+            {
+                f_temp=un_prev_data-aun_red_buffer[i];
+                f_temp/=(un_max-un_min);
+                f_temp*=MAX_BRIGHTNESS;
+                n_brightness+=(int)f_temp;
+                if(n_brightness>MAX_BRIGHTNESS)
+                    n_brightness=MAX_BRIGHTNESS;
+            }
+			//send samples and calculation result to terminal program through UART
+			// if(ch_hr_valid == 1 && n_heart_rate<120)//**/ ch_hr_valid == 1 && ch_spo2_valid ==1 && n_heart_rate<120 && n_sp02<101
+			// {
+			// 	dis_hr = n_heart_rate;
+			// 	dis_spo2 = n_sp02;
+			// }
+			// else
+			// {
+			// 	dis_hr = 0;
+			// 	dis_spo2 = 0;
+			// }
+				printf("HR=%i, ", n_heart_rate); 
+				printf("HRvalid=%i, ", ch_hr_valid);
+				printf("SpO2=%i, ", n_sp02);
+				printf("SPO2Valid=%i\r\n", ch_spo2_valid);
+		}
+        maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
+		
+		// //显示刷新
+		// LED0=0;
+		// if(dis_hr == 0 && dis_spo2 == 0)  //**dis_hr == 0 && dis_spo2 == 0
+		// {
+		// 	sprintf((char *)str,"HR:--- SpO2:--- ");//**HR:--- SpO2:--- 
+		// }
+		// else{
+		// 	sprintf((char *)str,"HR:%3d SpO2:%3d ",dis_hr,dis_spo2);//**HR:%3d SpO2:%3d 
+		// }
+		// OLED_ShowString(0,0,str,16);
+		// OLED_Fill(0,23,127,63,0);
+		// //红光在上,红外在下
+		// dis_DrawCurve(aun_red_buffer,20);
+		// dis_DrawCurve(aun_ir_buffer,0);
+		// OLED_Refresh_Gram();//更新显示到OLED	 
+	}
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 27 - 0
app/A03_MAX30102_B/BUILD.gn

@@ -0,0 +1,27 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A03_MAX30102") {
+    sources = [
+        "src/max30102.c",
+        "src/algorithm.c",
+        "src/blood.c",
+        "A03_MAX30102_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "include"
+    ]
+}

+ 63 - 0
app/A03_MAX30102_B/include/algorithm.h

@@ -0,0 +1,63 @@
+#ifndef __ALGORITHM_H
+#define __ALGORITHM_H
+#include <stdint.h>
+
+#define FFT_N 				512    //定义傅里叶变换的点数
+#define START_INDEX 	4  //低频过滤阈值
+
+struct compx     //定义一个复数结构
+{
+	float real;
+	float imag;
+};  
+
+//向下取整
+double my_floor(double x);
+//求余运算
+double my_fmod(double x, double y);
+//正弦函数
+double XSin( double x );
+//余弦函数 
+double XCos( double x );
+//开平方
+int qsqrt(int a);
+
+/*******************************************************************
+函数原型:struct compx EE(struct compx b1,struct compx b2)  
+函数功能:对两个复数进行乘法运算
+输入参数:两个以联合体定义的复数a,b
+输出参数:a和b的乘积,以联合体的形式输出
+*******************************************************************/
+struct compx EE(struct compx a,struct compx b);
+/*****************************************************************
+函数原型:void FFT(struct compx *xin,int N)
+函数功能:对输入的复数组进行快速傅里叶变换(FFT)
+输入参数:*xin复数结构体组的首地址指针,struct型
+*****************************************************************/
+void FFT(struct compx *xin);
+
+//读取峰值
+int find_max_num_index(struct compx *data,int count);
+
+typedef struct
+{
+	float w;
+	int init;
+	float a;
+
+}DC_FilterData;
+
+//直流滤波器
+int dc_filter(int input,DC_FilterData * df);
+
+typedef struct
+{
+	float v0;
+	float v1;
+}BW_FilterData;
+
+int bw_filter(int input,BW_FilterData * bw);
+
+
+#endif  /*__ALGORITHM_H*/
+

+ 99 - 0
app/A03_MAX30102_B/include/algorithm1.h

@@ -0,0 +1,99 @@
+/** \file algorithm.h ******************************************************
+*
+* Project: MAXREFDES117#
+* Filename: algorithm.h
+* Description: This module is the heart rate/SpO2 calculation algorithm header file
+*
+* Revision History:
+*\n 1-18-2016 Rev 01.00 SK Initial release.
+*\n
+*
+* --------------------------------------------------------------------
+*
+* This code follows the following naming conventions:
+*
+*\n char              ch_pmod_value
+*\n char (array)      s_pmod_s_string[16]
+*\n float             f_pmod_value
+*\n int32_t           n_pmod_value
+*\n int32_t (array)   an_pmod_value[16]
+*\n int16_t           w_pmod_value
+*\n int16_t (array)   aw_pmod_value[16]
+*\n uint16_t          uw_pmod_value
+*\n uint16_t (array)  auw_pmod_value[16]
+*\n uint8_t           uch_pmod_value
+*\n uint8_t (array)   auch_pmod_buffer[16]
+*\n uint32_t          un_pmod_value
+*\n int32_t *         pn_pmod_value
+*
+* ------------------------------------------------------------------------- */
+/*******************************************************************************
+* Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+#ifndef ALGORITHM_H_
+#define ALGORITHM_H_
+#include <stdint.h>
+
+#define true 1
+#define false 0
+#define FS 100
+#define BUFFER_SIZE  (FS* 5) 
+#define HR_FIFO_SIZE 7
+#define MA4_SIZE  4 // DO NOT CHANGE
+#define HAMMING_SIZE  5// DO NOT CHANGE
+#define min(x,y) ((x) < (y) ? (x) : (y))
+
+ const uint16_t auw_hamm[31]={ 41,    276,    512,    276,     41 }; //Hamm=  long16(512* hamming(5)');
+//uch_spo2_table is computed as  -45.060*ratioAverage* ratioAverage + 30.354 *ratioAverage + 94.845 ;
+ const uint8_t uch_spo2_table[184]={ 95, 95, 95, 96, 96, 96, 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 99, 99, 99, 99, 
+                            99, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 
+                            100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 97, 97, 
+                            97, 97, 96, 96, 96, 96, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 
+                            90, 90, 89, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 82, 82, 81, 81, 
+                            80, 80, 79, 78, 78, 77, 76, 76, 75, 74, 74, 73, 72, 72, 71, 70, 69, 69, 68, 67, 
+                            66, 66, 65, 64, 63, 62, 62, 61, 60, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 
+                            49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 31, 30, 29, 
+                            28, 27, 26, 25, 23, 22, 21, 20, 19, 17, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5, 
+                            3, 2, 1 } ;
+static  int32_t an_dx[ BUFFER_SIZE-MA4_SIZE]; // delta
+static  int32_t an_x[ BUFFER_SIZE]; //ir
+static  int32_t an_y[ BUFFER_SIZE]; //red
+
+
+void maxim_heart_rate_and_oxygen_saturation(uint32_t *pun_ir_buffer ,  int32_t n_ir_buffer_length, uint32_t *pun_red_buffer ,   int32_t *pn_spo2, int8_t *pch_spo2_valid ,  int32_t *pn_heart_rate , int8_t  *pch_hr_valid);
+void maxim_find_peaks( int32_t *pn_locs, int32_t *pn_npks,  int32_t *pn_x, int32_t n_size, int32_t n_min_height, int32_t n_min_distance, int32_t n_max_num );
+void maxim_peaks_above_min_height( int32_t *pn_locs, int32_t *pn_npks,  int32_t *pn_x, int32_t n_size, int32_t n_min_height );
+void maxim_remove_close_peaks( int32_t *pn_locs, int32_t *pn_npks,   int32_t  *pn_x, int32_t n_min_distance );
+void maxim_sort_ascend( int32_t *pn_x, int32_t n_size );
+void maxim_sort_indices_descend(  int32_t  *pn_x, int32_t *pn_indx, int32_t n_size);
+
+#endif /* ALGORITHM_H_ */

+ 25 - 0
app/A03_MAX30102_B/include/blood.h

@@ -0,0 +1,25 @@
+#ifndef _BLOOD_H
+#define _BLOOD_H
+#include "max30102.h"
+#include "algorithm.h"
+#include "math.h"
+typedef enum
+{
+	BLD_NORMAL,		//正常
+	BLD_ERROR,		//侦测错误
+	
+}BloodState;//血液状态
+typedef struct
+{
+	int 		heart;		//心率数据
+	float 		SpO2;	//血氧数据
+}BloodData;
+
+
+void blood_data_translate(void);
+void blood_data_update(void);
+void blood_Loop(void);
+
+#endif
+
+

+ 42 - 0
app/A03_MAX30102_B/include/max30102 copy.h

@@ -0,0 +1,42 @@
+
+#ifndef MAX30102_H_
+#define MAX30102_H_
+
+#include <stdint.h>
+
+#define MAX30102_SLAVE_ADDRESS 0x57
+
+//register addresses
+#define REG_INTR_STATUS_1 0x00
+#define REG_INTR_STATUS_2 0x01
+#define REG_INTR_ENABLE_1 0x02
+#define REG_INTR_ENABLE_2 0x03
+#define REG_FIFO_WR_PTR 0x04
+#define REG_OVF_COUNTER 0x05
+#define REG_FIFO_RD_PTR 0x06
+#define REG_FIFO_DATA 0x07
+#define REG_FIFO_CONFIG 0x08
+#define REG_MODE_CONFIG 0x09
+#define REG_SPO2_CONFIG 0x0A
+#define REG_LED1_PA 0x0C
+#define REG_LED2_PA 0x0D
+#define REG_PILOT_PA 0x10
+#define REG_MULTI_LED_CTRL1 0x11
+#define REG_MULTI_LED_CTRL2 0x12
+#define REG_TEMP_INTR 0x1F
+#define REG_TEMP_FRAC 0x20
+#define REG_TEMP_CONFIG 0x21
+#define REG_PROX_INT_THRESH 0x30
+#define REG_REV_ID 0xFE
+#define REG_PART_ID 0xFF
+
+void BoardInit(void);
+uint8_t GetInit(void);
+uint8_t maxim_max30102_reset();
+uint8_t maxim_max30102_init();
+uint8_t max30102_FIFO_ReadBytes(uint8_t Register_Address,uint8_t* Data);
+uint8_t maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led);
+
+
+
+#endif /* MAX30102_H_ */

+ 46 - 0
app/A03_MAX30102_B/include/max30102.h

@@ -0,0 +1,46 @@
+
+#ifndef MAX30102_H_
+#define MAX30102_H_
+
+#include <stdint.h>
+
+#define MAX30102_SLAVE_ADDRESS 0x57
+
+//register addresses
+#define REG_INTR_STATUS_1 0x00
+#define REG_INTR_STATUS_2 0x01
+#define REG_INTR_ENABLE_1 0x02
+#define REG_INTR_ENABLE_2 0x03
+#define REG_FIFO_WR_PTR 0x04
+#define REG_OVF_COUNTER 0x05
+#define REG_FIFO_RD_PTR 0x06
+#define REG_FIFO_DATA 0x07
+#define REG_FIFO_CONFIG 0x08
+#define REG_MODE_CONFIG 0x09
+#define REG_SPO2_CONFIG 0x0A
+#define REG_LED1_PA 0x0C
+#define REG_LED2_PA 0x0D
+#define REG_PILOT_PA 0x10
+#define REG_MULTI_LED_CTRL1 0x11
+#define REG_MULTI_LED_CTRL2 0x12
+#define REG_TEMP_INTR 0x1F
+#define REG_TEMP_FRAC 0x20
+#define REG_TEMP_CONFIG 0x21
+#define REG_PROX_INT_THRESH 0x30
+#define REG_REV_ID 0xFE
+#define REG_PART_ID 0xFF
+
+
+extern uint16_t fifo_red;
+extern uint16_t fifo_ir;
+
+void BoardInit(void);
+uint8_t GetInit(void);
+uint8_t maxim_max30102_reset();
+uint8_t maxim_max30102_init();
+uint8_t max30102_FIFO_ReadBytes(uint8_t Register_Address,uint8_t* Data);
+void max30102_read_fifo(void);
+
+
+
+#endif /* MAX30102_H_ */

+ 248 - 0
app/A03_MAX30102_B/src/algorithm.c

@@ -0,0 +1,248 @@
+/**
+  ******************************************************************************
+  * @file    algorithm.c
+  * @author  张东
+  * @version V1.0.0
+  * @date    2019-12-28
+  * @brief   基础计算算法
+  ******************************************************************************
+  */
+/*--Include-start-------------------------------------------------------------*/
+#include "algorithm.h"
+
+/*base value define-----------------------------------------------------------*/
+#define XPI            	(3.1415926535897932384626433832795)
+#define XENTRY        	(100)
+#define XINCL        		(XPI/2/XENTRY)
+#define PI 							3.1415926535897932384626433832795028841971               //定义圆周率值
+
+/*Global data space ----------------------------------------------------------*/
+//正弦值对应表
+static const double XSinTbl[] = {
+			0.00000000000000000  , 0.015707317311820675 , 0.031410759078128292 , 0.047106450709642665 , 0.062790519529313374 ,
+			0.078459095727844944 , 0.094108313318514325 , 0.10973431109104528  , 0.12533323356430426  , 0.14090123193758267  ,
+			0.15643446504023087  , 0.17192910027940955  , 0.18738131458572463  , 0.20278729535651249  , 0.21814324139654256  ,
+			0.23344536385590542  , 0.24868988716485479  , 0.26387304996537292  , 0.27899110603922928  , 0.29404032523230400  ,
+			0.30901699437494740  , 0.32391741819814940  , 0.33873792024529142  , 0.35347484377925714  , 0.36812455268467797  ,
+			0.38268343236508978  , 0.39714789063478062  , 0.41151435860510882  , 0.42577929156507272  , 0.43993916985591514  ,
+			0.45399049973954680  , 0.46792981426057340  , 0.48175367410171532  , 0.49545866843240760  , 0.50904141575037132  ,
+			0.52249856471594880  , 0.53582679497899666  , 0.54902281799813180  , 0.56208337785213058  , 0.57500525204327857  ,
+			0.58778525229247314  , 0.60042022532588402  , 0.61290705365297649  , 0.62524265633570519  , 0.63742398974868975  ,
+			0.64944804833018377  , 0.66131186532365183  , 0.67301251350977331  , 0.68454710592868873  , 0.69591279659231442  ,
+			0.70710678118654757  , 0.71812629776318881  , 0.72896862742141155  , 0.73963109497860968  , 0.75011106963045959  ,
+			0.76040596560003104  , 0.77051324277578925  , 0.78043040733832969  , 0.79015501237569041  , 0.79968465848709058  ,
+			0.80901699437494745  , 0.81814971742502351  , 0.82708057427456183  , 0.83580736136827027  , 0.84432792550201508  ,
+			0.85264016435409218  , 0.86074202700394364  , 0.86863151443819120  , 0.87630668004386369  , 0.88376563008869347  ,
+			0.89100652418836779  , 0.89802757576061565  , 0.90482705246601958  , 0.91140327663544529  , 0.91775462568398114  ,
+			0.92387953251128674  , 0.92977648588825146  , 0.93544403082986738  , 0.94088076895422557  , 0.94608535882754530  ,
+			0.95105651629515353  , 0.95579301479833012  , 0.96029368567694307  , 0.96455741845779808  , 0.96858316112863108  ,
+			0.97236992039767667  , 0.97591676193874743  , 0.97922281062176575  , 0.98228725072868872  , 0.98510932615477398  ,
+			0.98768834059513777  , 0.99002365771655754  , 0.99211470131447788  , 0.99396095545517971  , 0.99556196460308000  ,
+			0.99691733373312796  , 0.99802672842827156  , 0.99888987496197001  , 0.99950656036573160  , 0.99987663248166059  ,
+			1.00000000000000000  };
+			
+//向下取整
+double my_floor(double x)
+{
+   double y=x;
+    if( (*( ( (int *) &y)+1) & 0x80000000)  != 0) //或者if(x<0)
+        return (float)((int)x)-1;
+    else
+        return (float)((int)x);
+}
+
+//求余运算
+double my_fmod(double x, double y)
+{
+   double temp, ret;
+  
+   if (y == 0.0)
+      return 0.0;
+   temp = my_floor(x/y);
+   ret = x - temp * y;
+   if ((x < 0.0) != (y < 0.0))
+      ret = ret - y;
+   return ret;
+}
+
+//正弦函数
+double XSin( double x )
+{
+    int s = 0 , n;
+    double dx , sx , cx;
+    if( x < 0 )
+        s = 1 , x = -x;
+    x = my_fmod( x , 2 * XPI );
+    if( x > XPI )
+        s = !s , x -= XPI;
+    if( x > XPI / 2 )
+        x = XPI - x;
+    n = (int)( x / XINCL );
+    dx = x - n * XINCL;
+    if( dx > XINCL / 2 )
+        ++n , dx -= XINCL;
+    sx = XSinTbl[n];
+    cx = XSinTbl[XENTRY-n];
+    x = sx + dx*cx - (dx*dx)*sx/2
+        - (dx*dx*dx)*cx/6 
+        + (dx*dx*dx*dx)*sx/24;
+     
+    return s ? -x : x;
+}
+
+//余弦函数 
+double XCos( double x )
+{
+    return XSin( x + XPI/2 );
+}
+
+//开平方
+int qsqrt(int a)
+{
+  uint32_t rem = 0, root = 0, divisor = 0;
+  uint16_t i;
+  for(i=0; i<16; i++)
+  {
+    root <<= 1;
+    rem = ((rem << 2) + (a>>30));
+    a <<= 2;
+    divisor = (root << 1) + 1;
+    if(divisor <= rem)
+    {
+      rem -= divisor;
+      root++;
+    }
+  }
+  return root;
+}
+
+/*********************************FFT*********************************
+                         快速傅里叶变换C函数
+函数简介:此函数是通用的快速傅里叶变换C语言函数,移植性强,以下部分不依
+          赖硬件。此函数采用联合体的形式表示一个复数,输入为自然顺序的复
+          数(输入实数是可令复数虚部为0),输出为经过FFT变换的自然顺序的
+          复数
+使用说明:使用此函数只需更改宏定义FFT_N的值即可实现点数的改变,FFT_N的
+          应该为2的N次方,不满足此条件时应在后面补0
+函数调用:FFT(s);
+时    间:2010-2-20
+版    本:Ver1.0
+参考文献:     
+**********************************************************************/
+
+/*******************************************************************
+函数原型:struct compx EE(struct compx b1,struct compx b2)  
+函数功能:对两个复数进行乘法运算
+输入参数:两个以联合体定义的复数a,b
+输出参数:a和b的乘积,以联合体的形式输出
+*******************************************************************/
+struct compx EE(struct compx a,struct compx b)      
+{
+	 struct compx c;
+	 c.real=a.real*b.real-a.imag*b.imag;
+	 c.imag=a.real*b.imag+a.imag*b.real;
+	 return(c);
+}
+
+/*****************************************************************
+函数原型:void FFT(struct compx *xin,int N)
+函数功能:对输入的复数组进行快速傅里叶变换(FFT)
+输入参数:*xin复数结构体组的首地址指针,struct型
+*****************************************************************/
+void FFT(struct compx *xin)
+{
+	int f,m,nv2,nm1,i,k,l,j=0;
+	struct compx u,w,t;
+
+	nv2=FFT_N/2;                  //变址运算,即把自然顺序变成倒位序,采用雷德算法
+	nm1=FFT_N-1;  
+	for(i=0;i<nm1;i++)        
+	{
+		if(i<j)                    //如果i<j,即进行变址
+		{
+			t=xin[j];           
+			xin[j]=xin[i];
+			xin[i]=t;
+		}
+		k=nv2;                    //求j的下一个倒位序
+		
+		while(k<=j)               //如果k<=j,表示j的最高位为1   
+		{           
+			j=j-k;                 //把最高位变成0
+			k=k/2;                 //k/2,比较次高位,依次类推,逐个比较,直到某个位为0
+		}
+		
+		j=j+k;                   //把0改为1
+	}
+	 
+	{  //FFT运算核,使用蝶形运算完成FFT运算
+		int le,lei,ip;                           
+		f=FFT_N;
+		for(l=1;(f=f/2)!=1;l++)                  //计算l的值,即计算蝶形级数
+			;
+		for(m=1;m<=l;m++)                           // 控制蝶形结级数
+		{                                           //m表示第m级蝶形,l为蝶形级总数l=log(2)N
+			le=2<<(m-1);                            //le蝶形结距离,即第m级蝶形的蝶形结相距le点
+			lei=le/2;                               //同一蝶形结中参加运算的两点的距离
+			u.real=1.0;                             //u为蝶形结运算系数,初始值为1
+			u.imag=0.0;
+			w.real=XCos(PI/lei);                     //w为系数商,即当前系数与前一个系数的商
+			w.imag=-XSin(PI/lei);
+			for(j=0;j<=lei-1;j++)                   //控制计算不同种蝶形结,即计算系数不同的蝶形结
+			{
+				for(i=j;i<=FFT_N-1;i=i+le)            //控制同一蝶形结运算,即计算系数相同蝶形结
+				{
+					ip=i+lei;                           //i,ip分别表示参加蝶形运算的两个节点
+					t=EE(xin[ip],u);                    //蝶形运算,详见公式
+					xin[ip].real=xin[i].real-t.real;
+					xin[ip].imag=xin[i].imag-t.imag;
+					xin[i].real=xin[i].real+t.real;
+					xin[i].imag=xin[i].imag+t.imag;
+				}
+				u=EE(u,w);                           //改变系数,进行下一个蝶形运算
+			}
+		}
+	}
+}
+
+//读取峰值
+int find_max_num_index(struct compx *data,int count)
+{
+	int i=START_INDEX;
+	int max_num_index = i;
+	//struct compx temp=data[i];
+	float temp = data[i].real;
+	for(i=START_INDEX;i<count;i++)
+	{
+		if(temp < data[i].real)
+		{
+			temp = data[i].real;
+			max_num_index = i;
+		}
+	}
+	//printf("max_num_index=%d\r\n",max_num_index);
+	return max_num_index; 
+}
+
+
+//直流滤波器
+int dc_filter(int input,DC_FilterData * df) 
+{
+
+	float new_w  = input + df->w * df->a;
+	int16_t result = 5*(new_w - df->w);
+	df->w = new_w;
+	
+	return result;
+}
+
+
+int bw_filter(int input,BW_FilterData * bw) {
+    bw->v0 = bw->v1;
+    
+   // v1 = (3.04687470e-2 * input) + (0.9390625058 * v0);
+    bw->v1 = (1.241106190967544882e-2*input)+(0.97517787618064910582 * bw->v0);
+    return bw->v0 + bw->v1;
+}
+
+

+ 363 - 0
app/A03_MAX30102_B/src/algorithm1.c

@@ -0,0 +1,363 @@
+/** \file algorithm.cpp ******************************************************
+*
+* Project: MAXREFDES117#
+* Filename: algorithm.cpp
+* Description: This module calculates the heart rate/SpO2 level
+*
+*
+* --------------------------------------------------------------------
+*
+* This code follows the following naming conventions:
+*
+* char              ch_pmod_value
+* char (array)      s_pmod_s_string[16]
+* float             f_pmod_value
+* int32_t           n_pmod_value
+* int32_t (array)   an_pmod_value[16]
+* int16_t           w_pmod_value
+* int16_t (array)   aw_pmod_value[16]
+* uint16_t          uw_pmod_value
+* uint16_t (array)  auw_pmod_value[16]
+* uint8_t           uch_pmod_value
+* uint8_t (array)   auch_pmod_buffer[16]
+* uint32_t          un_pmod_value
+* int32_t *         pn_pmod_value
+*
+* ------------------------------------------------------------------------- */
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+#include "algorithm.h"
+
+
+void maxim_heart_rate_and_oxygen_saturation(uint32_t *pun_ir_buffer,  int32_t n_ir_buffer_length, uint32_t *pun_red_buffer, int32_t *pn_spo2, int8_t *pch_spo2_valid, 
+                              int32_t *pn_heart_rate, int8_t  *pch_hr_valid)
+/**
+* \brief        Calculate the heart rate and SpO2 level
+* \par          Details
+*               By detecting  peaks of PPG cycle and corresponding AC/DC of red/infra-red signal, the ratio for the SPO2 is computed.
+*               Since this algorithm is aiming for Arm M0/M3. formaula for SPO2 did not achieve the accuracy due to register overflow.
+*               Thus, accurate SPO2 is precalculated and save longo uch_spo2_table[] per each ratio.
+*
+* \param[in]    *pun_ir_buffer           - IR sensor data buffer
+* \param[in]    n_ir_buffer_length      - IR sensor data buffer length
+* \param[in]    *pun_red_buffer          - Red sensor data buffer
+* \param[out]    *pn_spo2                - Calculated SpO2 value
+* \param[out]    *pch_spo2_valid         - 1 if the calculated SpO2 value is valid
+* \param[out]    *pn_heart_rate          - Calculated heart rate value
+* \param[out]    *pch_hr_valid           - 1 if the calculated heart rate value is valid
+*
+* \retval       None
+*/
+{
+    uint32_t un_ir_mean ,un_only_once ;
+    int32_t k ,n_i_ratio_count;
+    int32_t i, s, m, n_exact_ir_valley_locs_count ,n_middle_idx;
+    int32_t n_th1, n_npks,n_c_min;      
+    int32_t an_ir_valley_locs[15] ;
+    int32_t an_exact_ir_valley_locs[15] ;
+    int32_t an_dx_peak_locs[15] ;
+    int32_t n_peak_interval_sum;
+    
+    int32_t n_y_ac, n_x_ac;
+    int32_t n_spo2_calc; 
+    int32_t n_y_dc_max, n_x_dc_max; 
+    int32_t n_y_dc_max_idx, n_x_dc_max_idx; 
+    int32_t an_ratio[5],n_ratio_average; 
+    int32_t n_nume,  n_denom ;
+    // remove DC of ir signal    
+    un_ir_mean =0; 
+    for (k=0 ; k<n_ir_buffer_length ; k++ ) un_ir_mean += pun_ir_buffer[k] ;
+    un_ir_mean =un_ir_mean/n_ir_buffer_length ;
+    for (k=0 ; k<n_ir_buffer_length ; k++ )  an_x[k] =  pun_ir_buffer[k] - un_ir_mean ; 
+    
+    // 4 pt Moving Average
+    for(k=0; k< BUFFER_SIZE-MA4_SIZE; k++){
+        n_denom= ( an_x[k]+an_x[k+1]+ an_x[k+2]+ an_x[k+3]);
+        an_x[k]=  n_denom/(int32_t)4; 
+    }
+
+    // get difference of smoothed IR signal
+    
+    for( k=0; k<BUFFER_SIZE-MA4_SIZE-1;  k++)
+        an_dx[k]= (an_x[k+1]- an_x[k]);
+
+    // 2-pt Moving Average to an_dx
+    for(k=0; k< BUFFER_SIZE-MA4_SIZE-2; k++){
+        an_dx[k] =  ( an_dx[k]+an_dx[k+1])/2 ;
+    }
+    
+    // hamming window
+    // flip wave form so that we can detect valley with peak detector
+    for ( i=0 ; i<BUFFER_SIZE-HAMMING_SIZE-MA4_SIZE-2 ;i++){
+        s= 0;
+        for( k=i; k<i+ HAMMING_SIZE ;k++){
+            s -= an_dx[k] *auw_hamm[k-i] ; 
+                     }
+        an_dx[i]= s/ (int32_t)1146; // divide by sum of auw_hamm 
+    }
+
+ 
+    n_th1=0; // threshold calculation
+    for ( k=0 ; k<BUFFER_SIZE-HAMMING_SIZE ;k++){
+        n_th1 += ((an_dx[k]>0)? an_dx[k] : ((int32_t)0-an_dx[k])) ;
+    }
+    n_th1= n_th1/ ( BUFFER_SIZE-HAMMING_SIZE);
+    // peak location is acutally index for sharpest location of raw signal since we flipped the signal         
+    maxim_find_peaks( an_dx_peak_locs, &n_npks, an_dx, BUFFER_SIZE-HAMMING_SIZE, n_th1, 8, 5 );//peak_height, peak_distance, max_num_peaks 
+
+    n_peak_interval_sum =0;
+    if (n_npks>=2){
+        for (k=1; k<n_npks; k++)
+            n_peak_interval_sum += (an_dx_peak_locs[k]-an_dx_peak_locs[k -1]);
+        n_peak_interval_sum=n_peak_interval_sum/(n_npks-1);
+        *pn_heart_rate=(int32_t)(6000/n_peak_interval_sum);// beats per minutes
+        *pch_hr_valid  = 1;
+    }
+    else  {
+        *pn_heart_rate = -999;
+        *pch_hr_valid  = 0;
+    }
+            
+    for ( k=0 ; k<n_npks ;k++)
+        an_ir_valley_locs[k]=an_dx_peak_locs[k]+HAMMING_SIZE/2; 
+
+
+    // raw value : RED(=y) and IR(=X)
+    // we need to assess DC and AC value of ir and red PPG. 
+    for (k=0 ; k<n_ir_buffer_length ; k++ )  {
+        an_x[k] =  pun_ir_buffer[k] ; 
+        an_y[k] =  pun_red_buffer[k] ; 
+    }
+
+    // find precise min near an_ir_valley_locs
+    n_exact_ir_valley_locs_count =0; 
+    for(k=0 ; k<n_npks ;k++){
+        un_only_once =1;
+        m=an_ir_valley_locs[k];
+        n_c_min= 16777216;//2^24;
+        if (m+5 <  BUFFER_SIZE-HAMMING_SIZE  && m-5 >0){
+            for(i= m-5;i<m+5; i++)
+                if (an_x[i]<n_c_min){
+                    if (un_only_once >0){
+                       un_only_once =0;
+                   } 
+                   n_c_min= an_x[i] ;
+                   an_exact_ir_valley_locs[k]=i;
+                }
+            if (un_only_once ==0)
+                n_exact_ir_valley_locs_count ++ ;
+        }
+    }
+    if (n_exact_ir_valley_locs_count <2 ){
+       *pn_spo2 =  -999 ; // do not use SPO2 since signal ratio is out of range
+       *pch_spo2_valid  = 0; 
+       return;
+    }
+    // 4 pt MA
+    for(k=0; k< BUFFER_SIZE-MA4_SIZE; k++){
+        an_x[k]=( an_x[k]+an_x[k+1]+ an_x[k+2]+ an_x[k+3])/(int32_t)4;
+        an_y[k]=( an_y[k]+an_y[k+1]+ an_y[k+2]+ an_y[k+3])/(int32_t)4;
+    }
+
+    //using an_exact_ir_valley_locs , find ir-red DC andir-red AC for SPO2 calibration ratio
+    //finding AC/DC maximum of raw ir * red between two valley locations
+    n_ratio_average =0; 
+    n_i_ratio_count =0; 
+    
+    for(k=0; k< 5; k++) an_ratio[k]=0;
+    for (k=0; k< n_exact_ir_valley_locs_count; k++){
+        if (an_exact_ir_valley_locs[k] > BUFFER_SIZE ){             
+            *pn_spo2 =  -999 ; // do not use SPO2 since valley loc is out of range
+            *pch_spo2_valid  = 0; 
+            return;
+        }
+    }
+    // find max between two valley locations 
+    // and use ratio betwen AC compoent of Ir & Red and DC compoent of Ir & Red for SPO2 
+
+    for (k=0; k< n_exact_ir_valley_locs_count-1; k++){
+        n_y_dc_max= -16777216 ; 
+        n_x_dc_max= - 16777216; 
+        if (an_exact_ir_valley_locs[k+1]-an_exact_ir_valley_locs[k] >10){
+            for (i=an_exact_ir_valley_locs[k]; i< an_exact_ir_valley_locs[k+1]; i++){
+                if (an_x[i]> n_x_dc_max) {n_x_dc_max =an_x[i];n_x_dc_max_idx =i; }
+                if (an_y[i]> n_y_dc_max) {n_y_dc_max =an_y[i];n_y_dc_max_idx=i;}
+            }
+            n_y_ac= (an_y[an_exact_ir_valley_locs[k+1]] - an_y[an_exact_ir_valley_locs[k] ] )*(n_y_dc_max_idx -an_exact_ir_valley_locs[k]); //red
+            n_y_ac=  an_y[an_exact_ir_valley_locs[k]] + n_y_ac/ (an_exact_ir_valley_locs[k+1] - an_exact_ir_valley_locs[k])  ; 
+        
+        
+            n_y_ac=  an_y[n_y_dc_max_idx] - n_y_ac;    // subracting linear DC compoenents from raw 
+            n_x_ac= (an_x[an_exact_ir_valley_locs[k+1]] - an_x[an_exact_ir_valley_locs[k] ] )*(n_x_dc_max_idx -an_exact_ir_valley_locs[k]); // ir
+            n_x_ac=  an_x[an_exact_ir_valley_locs[k]] + n_x_ac/ (an_exact_ir_valley_locs[k+1] - an_exact_ir_valley_locs[k]); 
+            n_x_ac=  an_x[n_y_dc_max_idx] - n_x_ac;      // subracting linear DC compoenents from raw 
+            n_nume=( n_y_ac *n_x_dc_max)>>7 ; //prepare X100 to preserve floating value
+            n_denom= ( n_x_ac *n_y_dc_max)>>7;
+            if (n_denom>0  && n_i_ratio_count <5 &&  n_nume != 0)
+            {   
+                an_ratio[n_i_ratio_count]= (n_nume*20)/n_denom ; //formular is ( n_y_ac *n_x_dc_max) / ( n_x_ac *n_y_dc_max) ;
+                n_i_ratio_count++;
+            }
+        }
+    }
+
+    maxim_sort_ascend(an_ratio, n_i_ratio_count);
+    n_middle_idx= n_i_ratio_count/2;
+
+    if (n_middle_idx >1)
+        n_ratio_average =( an_ratio[n_middle_idx-1] +an_ratio[n_middle_idx])/2; // use median
+    else
+        n_ratio_average = an_ratio[n_middle_idx ];
+
+    if( n_ratio_average>2 && n_ratio_average <184){
+        n_spo2_calc= uch_spo2_table[n_ratio_average] ;
+        *pn_spo2 = n_spo2_calc ;
+        *pch_spo2_valid  = 1;//  float_SPO2 =  -45.060*n_ratio_average* n_ratio_average/10000 + 30.354 *n_ratio_average/100 + 94.845 ;  // for comparison with table
+    }
+    else{
+        *pn_spo2 =  -999 ; // do not use SPO2 since signal ratio is out of range
+        *pch_spo2_valid  = 0; 
+    }
+}
+
+
+void maxim_find_peaks(int32_t *pn_locs, int32_t *pn_npks, int32_t *pn_x, int32_t n_size, int32_t n_min_height, int32_t n_min_distance, int32_t n_max_num)
+/**
+* \brief        Find peaks
+* \par          Details
+*               Find at most MAX_NUM peaks above MIN_HEIGHT separated by at least MIN_DISTANCE
+*
+* \retval       None
+*/
+{
+    maxim_peaks_above_min_height( pn_locs, pn_npks, pn_x, n_size, n_min_height );
+    maxim_remove_close_peaks( pn_locs, pn_npks, pn_x, n_min_distance );
+    *pn_npks = min( *pn_npks, n_max_num );
+}
+
+void maxim_peaks_above_min_height(int32_t *pn_locs, int32_t *pn_npks, int32_t  *pn_x, int32_t n_size, int32_t n_min_height)
+/**
+* \brief        Find peaks above n_min_height
+* \par          Details
+*               Find all peaks above MIN_HEIGHT
+*
+* \retval       None
+*/
+{
+    int32_t i = 1, n_width;
+    *pn_npks = 0;
+    
+    while (i < n_size-1){
+        if (pn_x[i] > n_min_height && pn_x[i] > pn_x[i-1]){            // find left edge of potential peaks
+            n_width = 1;
+            while (i+n_width < n_size && pn_x[i] == pn_x[i+n_width])    // find flat peaks
+                n_width++;
+            if (pn_x[i] > pn_x[i+n_width] && (*pn_npks) < 15 ){                            // find right edge of peaks
+                pn_locs[(*pn_npks)++] = i;        
+                // for flat peaks, peak location is left edge
+                i += n_width+1;
+            }
+            else
+                i += n_width;
+        }
+        else
+            i++;
+    }
+}
+
+
+void maxim_remove_close_peaks(int32_t *pn_locs, int32_t *pn_npks, int32_t *pn_x, int32_t n_min_distance)
+/**
+* \brief        Remove peaks
+* \par          Details
+*               Remove peaks separated by less than MIN_DISTANCE
+*
+* \retval       None
+*/
+{
+    
+    int32_t i, j, n_old_npks, n_dist;
+    
+    /* Order peaks from large to small */
+    maxim_sort_indices_descend( pn_x, pn_locs, *pn_npks );
+
+    for ( i = -1; i < *pn_npks; i++ ){
+        n_old_npks = *pn_npks;
+        *pn_npks = i+1;
+        for ( j = i+1; j < n_old_npks; j++ ){
+            n_dist =  pn_locs[j] - ( i == -1 ? -1 : pn_locs[i] ); // lag-zero peak of autocorr is at index -1
+            if ( n_dist > n_min_distance || n_dist < -n_min_distance )
+                pn_locs[(*pn_npks)++] = pn_locs[j];
+        }
+    }
+
+    // Resort indices longo ascending order
+    maxim_sort_ascend( pn_locs, *pn_npks );
+}
+
+void maxim_sort_ascend(int32_t *pn_x,int32_t n_size) 
+/**
+* \brief        Sort array
+* \par          Details
+*               Sort array in ascending order (insertion sort algorithm)
+*
+* \retval       None
+*/
+{
+    int32_t i, j, n_temp;
+    for (i = 1; i < n_size; i++) {
+        n_temp = pn_x[i];
+        for (j = i; j > 0 && n_temp < pn_x[j-1]; j--)
+            pn_x[j] = pn_x[j-1];
+        pn_x[j] = n_temp;
+    }
+}
+
+void maxim_sort_indices_descend(int32_t *pn_x, int32_t *pn_indx, int32_t n_size)
+/**
+* \brief        Sort indices
+* \par          Details
+*               Sort indices according to descending order (insertion sort algorithm)
+*
+* \retval       None
+*/ 
+{
+    int32_t i, j, n_temp;
+    for (i = 1; i < n_size; i++) {
+        n_temp = pn_indx[i];
+        for (j = i; j > 0 && pn_x[n_temp] > pn_x[pn_indx[j-1]]; j--)
+            pn_indx[j] = pn_indx[j-1];
+        pn_indx[j] = n_temp;
+    }
+}
+

+ 246 - 0
app/A03_MAX30102_B/src/blood.c

@@ -0,0 +1,246 @@
+#include "blood.h"
+uint16_t g_fft_index = 0;         	 	//fft输入输出下标
+
+struct compx s1[FFT_N+16];           	//FFT输入和输出:从S[1]开始存放,根据大小自己定义
+struct compx s2[FFT_N+16];           	//FFT输入和输出:从S[1]开始存放,根据大小自己定义
+
+struct
+{
+	float 	Hp	;			//血红蛋白	
+	float 	HpO2;			//氧合血红蛋白
+	
+}g_BloodWave;//血液波形数据
+
+BloodData g_blooddata = {0};					//血液数据存储
+
+#define CORRECTED_VALUE			47   			//标定血液氧气含量
+
+
+#define asuint(f) ((union{float _f; uint32_t _i;}){f})._i
+#define asfloat(i) ((union{uint32_t _i; float _f;}){i})._f
+
+#define GET_FLOAT_WORD(w,d)                       \
+do {                                              \
+  (w) = asuint(d);                                \
+} while (0)
+
+#define SET_FLOAT_WORD(d,w)                       \
+do {                                              \
+  (d) = asfloat(w);                               \
+} while (0)
+
+static const float tiny = 1.0e-30;
+
+float sqrtf(float x)
+{
+	float z;
+	int32_t sign = (int)0x80000000;
+	int32_t ix,s,q,m,t,i;
+	uint32_t r;
+
+	GET_FLOAT_WORD(ix, x);
+
+	/* take care of Inf and NaN */
+	if ((ix&0x7f800000) == 0x7f800000)
+		return x*x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */
+
+	/* take care of zero */
+	if (ix <= 0) {
+		if ((ix&~sign) == 0)
+			return x;  /* sqrt(+-0) = +-0 */
+		if (ix < 0)
+			return (x-x)/(x-x);  /* sqrt(-ve) = sNaN */
+	}
+	/* normalize x */
+	m = ix>>23;
+	if (m == 0) {  /* subnormal x */
+		for (i = 0; (ix&0x00800000) == 0; i++)
+			ix<<=1;
+		m -= i - 1;
+	}
+	m -= 127;  /* unbias exponent */
+	ix = (ix&0x007fffff)|0x00800000;
+	if (m&1)  /* odd m, double x to make it even */
+		ix += ix;
+	m >>= 1;  /* m = [m/2] */
+
+	/* generate sqrt(x) bit by bit */
+	ix += ix;
+	q = s = 0;       /* q = sqrt(x) */
+	r = 0x01000000;  /* r = moving bit from right to left */
+
+	while (r != 0) {
+		t = s + r;
+		if (t <= ix) {
+			s = t+r;
+			ix -= t;
+			q += r;
+		}
+		ix += ix;
+		r >>= 1;
+	}
+
+	/* use floating add to find out rounding direction */
+	if (ix != 0) {
+		z = 1.0f - tiny; /* raise inexact flag */
+		if (z >= 1.0f) {
+			z = 1.0f + tiny;
+			if (z > 1.0f)
+				q += 2;
+			else
+				q += q & 1;
+		}
+	}
+	ix = (q>>1) + 0x3f000000;
+	SET_FLOAT_WORD(z, ix + ((uint32_t)m << 23));
+	return z;
+}
+
+/*funcation start ------------------------------------------------------------*/
+//血液检测信息更新
+void blood_data_update(void)
+{
+	//标志位被使能时 读取FIFO
+	g_fft_index=0;
+	while(g_fft_index < FFT_N)
+	{
+		while(GetInit()==0)
+		{
+			//读取FIFO
+			max30102_read_fifo();  //read from MAX30102 FIFO2
+			//将数据写入fft输入并清除输出
+			if(g_fft_index < FFT_N)
+			{
+				//将数据写入fft输入并清除输出
+				s1[g_fft_index].real = fifo_red;
+				s1[g_fft_index].imag= 0;
+				s2[g_fft_index].real = fifo_ir;
+				s2[g_fft_index].imag= 0;
+				g_fft_index++;
+			}
+		}
+	}
+}
+
+//血液信息转换
+void blood_data_translate(void)
+{	
+	float n_denom;
+	uint16_t i;
+	//直流滤波
+	float dc_red =0; 
+	float dc_ir =0;
+	float ac_red =0; 
+	float ac_ir =0;
+	
+	for (i=0 ; i<FFT_N ; i++ ) 
+	{
+		dc_red += s1[i].real ;
+		dc_ir +=  s2[i].real ;
+	}
+		dc_red =dc_red/FFT_N ;
+		dc_ir =dc_ir/FFT_N ;
+	for (i=0 ; i<FFT_N ; i++ )  
+	{
+		s1[i].real =  s1[i].real - dc_red ; 
+		s2[i].real =  s2[i].real - dc_ir ; 
+	}
+	
+	//移动平均滤波
+	printf("***********8 pt Moving Average red******************************************************\r\n");
+	for(i = 1;i < FFT_N-1;i++) 
+	{
+			n_denom= ( s1[i-1].real + 2*s1[i].real + s1[i+1].real);
+			s1[i].real=  n_denom/4.00; 
+			
+			n_denom= ( s2[i-1].real + 2*s2[i].real + s2[i+1].real);
+			s2[i].real=  n_denom/4.00; 			
+	}
+	//八点平均滤波
+	for(i = 0;i < FFT_N-8;i++) 
+	{
+			n_denom= ( s1[i].real+s1[i+1].real+ s1[i+2].real+ s1[i+3].real+ s1[i+4].real+ s1[i+5].real+ s1[i+6].real+ s1[i+7].real);
+			s1[i].real=  n_denom/8.00; 
+			
+			n_denom= ( s2[i].real+s2[i+1].real+ s2[i+2].real+ s2[i+3].real+ s2[i+4].real+ s2[i+5].real+ s2[i+6].real+ s2[i+7].real);
+			s2[i].real=  n_denom/8.00; 
+		
+			printf("%f\r\n",s1[i].real);		
+	}
+	printf("************8 pt Moving Average ir*************************************************************\r\n");
+	for(i = 0;i < FFT_N;i++) 
+	{
+		printf("%f\r\n",s2[i].real);	
+	}
+	printf("**************************************************************************************************\r\n");
+	//开始变换显示	
+	g_fft_index = 0;	
+	//快速傅里叶变换
+	FFT(s1);
+	FFT(s2);
+	
+	//解平方
+	printf("开始FFT算法****************************************************************************************************\r\n");
+	for(i = 0;i < FFT_N;i++) 
+	{
+		s1[i].real=sqrtf(s1[i].real*s1[i].real+s1[i].imag*s1[i].imag);
+		s1[i].real=sqrtf(s2[i].real*s2[i].real+s2[i].imag*s2[i].imag);
+	}
+	//计算交流分量
+	for (i=1 ; i<FFT_N ; i++ ) 
+	{
+		ac_red += s1[i].real ;
+		ac_ir +=  s2[i].real ;
+	}
+	
+	for(i = 0;i < FFT_N/2;i++) 
+	{
+		printf("%f\r\n",s1[i].real);
+	}
+	printf("****************************************************************************************\r\n");
+	for(i = 0;i < FFT_N/2;i++) 
+	{
+		printf("%f\r\n",s2[i].real);
+	}
+	
+	printf("结束FFT算法***************************************************************************************************************\r\n");
+
+
+	//读取峰值点的横坐标  结果的物理意义为 
+	int s1_max_index = find_max_num_index(s1, 30);
+	int s2_max_index = find_max_num_index(s2, 30);
+	printf("%d\r\n",s1_max_index);
+	printf("%d\r\n",s2_max_index);
+	//检查HbO2和Hb的变化频率是否一致
+
+		
+    float Heart_Rate = 60.00 * ((100.0 * s1_max_index )/ 512.00);
+    
+    g_blooddata.heart = Heart_Rate;
+			
+    float R = (ac_ir*dc_red)/(ac_red*dc_ir);
+    float sp02_num =-45.060*R*R+ 30.354 *R + 94.845;
+    g_blooddata.SpO2 = sp02_num;
+			
+}
+
+
+void blood_Loop(void)
+{
+
+	//血液信息获取
+	blood_data_update();
+	//血液信息转换
+	blood_data_translate();
+
+	//显示血液状态信息
+	// OLED_Printf_EN(2,0,"heart:%3d/min  ",g_blooddata.heart);
+	g_blooddata.SpO2 = (g_blooddata.SpO2 > 99.99) ? 99.99:g_blooddata.SpO2;
+	// OLED_Printf_EN(4,0,"SpO2:%2.2f%%  ",g_blooddata.SpO2);
+	printf("指令心率%3d",g_blooddata.heart);
+	osDelay(10);
+	printf("指令血氧%0.2f",g_blooddata.SpO2);
+	//tft显示刷新
+	//LED 蜂鸣器信息更新
+}
+

+ 237 - 0
app/A03_MAX30102_B/src/max30102 copy 2.c

@@ -0,0 +1,237 @@
+#include "max30102.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+#include "iot_i2c.h"
+#include "iot_i2c_ex.h"
+#include <stdio.h>
+
+#define WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA 6
+#define WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL 6
+#define WIFI_IOT_I2C_IDX_1 1
+#define WIFI_IOT_IO_NAME_GPIO_7 7
+#define WIFI_IOT_IO_NAME_GPIO_8 8
+#define WIFI_IOT_IO_NAME_GPIO_0 0
+#define WIFI_IOT_IO_NAME_GPIO_1 1
+#define MAX30102_INIT_GPIO 7
+/***************************************************************
+ * 函数名称: GpioInit
+ * 说    明:  GPIO初始化
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void BoardInit(void)
+{
+    // IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_8);
+    // IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_GPIO);
+    // IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_DIR_OUT); // 设置GPIO_8为输出模式
+
+    IoTGpioInit(MAX30102_INIT_GPIO);
+    IoTGpioSetFunc(MAX30102_INIT_GPIO, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(MAX30102_INIT_GPIO, IOT_GPIO_DIR_IN); // 设置GPIO_7为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_0);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA); // GPIO_0复用为I2C1_SDA
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_1);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL); // GPIO_1复用为I2C1_SCL
+    IoTI2cInit(WIFI_IOT_I2C_IDX_1, 400000);              /* baudrate: 400kbps */
+}
+
+
+uint8_t GetInit(void)
+{
+	IotGpioValue temp = {0};
+    IoTGpioGetInputVal(MAX30102_INIT_GPIO,&temp);
+    return temp;
+}
+
+
+/**
+* \brief        Write a value to a MAX30102 register
+* \par          Details
+*               This function writes a value to a MAX30102 register
+*
+* \param[in]    uch_addr    - register address
+* \param[in]    uch_data    - register data
+*
+* \retval       true on success
+*/
+static int maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data)
+{
+    uint32_t ret;
+    uint8_t send_data[2] = {uch_addr, uch_data};
+    ret = IoTI2cWrite(WIFI_IOT_I2C_IDX_1, (MAX30102_SLAVE_ADDRESS << 1) | 0x00, send_data, 2);
+    if (ret != 0) {
+        printf("===== Error: I2C write ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    return 0;
+}
+
+/**
+* \brief        Read a MAX30102 register
+* \par          Details
+*               This function reads a MAX30102 register
+*
+* \param[in]    uch_addr    - register address
+* \param[out]   puch_data    - pointer that stores the register data
+*
+* \retval       true on success
+*/
+uint8_t maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data)
+{
+    uint32_t ret = 0;
+    IotI2cData max30102_i2c_data = {0};
+    uint8_t buffer[1] = {uch_addr};
+    max30102_i2c_data.sendBuf = buffer;
+    max30102_i2c_data.sendLen = 1;
+    max30102_i2c_data.receiveBuf = puch_data;
+    max30102_i2c_data.receiveLen = 1;
+    ret = IoTI2cWriteread(WIFI_IOT_I2C_IDX_1, (MAX30102_SLAVE_ADDRESS << 1) | 0x00, &max30102_i2c_data);
+    if (ret != 0) {
+        printf("===== Error: I2C writeread ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    return 0;
+}
+
+uint8_t maxim_max30102_init()
+{
+	
+    if(maxim_max30102_write_reg(REG_INTR_ENABLE_1,0xc0)!=IOT_SUCCESS) // INTR setting
+        return 0;
+    if(maxim_max30102_write_reg(REG_INTR_ENABLE_2,0x00)!=IOT_SUCCESS)
+        return 0;
+    if(maxim_max30102_write_reg(REG_FIFO_WR_PTR,0x00)!=IOT_SUCCESS)  //FIFO_WR_PTR[4:0]
+        return 0;
+    if(maxim_max30102_write_reg(REG_OVF_COUNTER,0x00)!=IOT_SUCCESS)  //OVF_COUNTER[4:0]
+        return 0;
+    if(maxim_max30102_write_reg(REG_FIFO_RD_PTR,0x00)!=IOT_SUCCESS)  //FIFO_RD_PTR[4:0]
+        return 0;
+    if(maxim_max30102_write_reg(REG_FIFO_CONFIG,0x0f)!=IOT_SUCCESS)  //sample avg = 1, fifo rollover=false, fifo almost full = 17
+        return 0;
+    if(maxim_max30102_write_reg(REG_MODE_CONFIG,0x03)!=IOT_SUCCESS)   //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
+        return 0;
+    if(maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27)!=IOT_SUCCESS)  // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)
+        return 0;
+    
+    if(maxim_max30102_write_reg(REG_LED1_PA,0x32)!=IOT_SUCCESS)   //Choose value for ~ 7mA for LED1
+        return 0;
+    if(maxim_max30102_write_reg(REG_LED2_PA,0x32)!=IOT_SUCCESS)   // Choose value for ~ 7mA for LED2
+        return 0;
+    if(maxim_max30102_write_reg(REG_PILOT_PA,0x7f)!=IOT_SUCCESS)   // Choose value for ~ 25mA for Pilot LED
+        return 0;
+    return 1;  
+
+}
+
+
+/**
+* \brief        Reset the MAX30102
+* \par          Details
+*               This function resets the MAX30102
+*
+* \param        None
+*
+* \retval       true on success
+*/
+uint8_t maxim_max30102_reset()
+{
+    if(maxim_max30102_write_reg(REG_MODE_CONFIG,0x40)!=IOT_SUCCESS)
+        return 0;
+    else
+        return 1;    
+}
+/**
+* \brief        Read a set of samples from the MAX30102 FIFO register
+* \par          Details
+*               This function reads a set of samples from the MAX30102 FIFO register
+*
+* \param[out]   *pun_red_led   - pointer that stores the red LED reading data
+* \param[out]   *pun_ir_led    - pointer that stores the IR LED reading data
+*
+* \retval       true on success
+*/
+uint8_t max30102_FIFO_ReadBytes(uint8_t Register_Address,uint8_t* Data)
+{
+    uint32_t un_temp;
+    unsigned char uch_temp;
+  
+    //read and clear status register
+    maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);
+    maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);
+  
+//   ach_i2c_data[0]=REG_FIFO_DATA;
+	 
+    uint32_t ret = 0;
+    IotI2cData max30102_i2c_data = {0};
+    uint8_t buffer[1] = {REG_FIFO_DATA};
+    max30102_i2c_data.sendBuf = buffer;
+    max30102_i2c_data.sendLen = 1;
+    max30102_i2c_data.receiveBuf = Data;
+    max30102_i2c_data.receiveLen = 6;
+    ret = IoTI2cWriteread(WIFI_IOT_I2C_IDX_1, (MAX30102_SLAVE_ADDRESS << 1) | 0x00, &max30102_i2c_data);
+    if (ret != 0) {
+        printf("===== Error: I2C writeread ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    return 0;
+}
+
+/**
+* \brief        Read a set of samples from the MAX30102 FIFO register
+* \par          Details
+*               This function reads a set of samples from the MAX30102 FIFO register
+*
+* \param[out]   *pun_red_led   - pointer that stores the red LED reading data
+* \param[out]   *pun_ir_led    - pointer that stores the IR LED reading data
+*
+* \retval       true on success
+*/
+uint8_t maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)
+{
+    uint32_t un_temp;
+    unsigned char uch_temp;
+    *pun_red_led=0;
+    *pun_ir_led=0;
+    uint8_t ach_i2c_data[6];
+    
+    //read and clear status register
+    maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);
+    maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);
+  
+//   ach_i2c_data[0]=REG_FIFO_DATA;
+	 
+    uint32_t ret = 0;
+    IotI2cData max30102_i2c_data = {0};
+    uint8_t buffer[1] = {REG_FIFO_DATA};
+    max30102_i2c_data.sendBuf = buffer;
+    max30102_i2c_data.sendLen = 1;
+    max30102_i2c_data.receiveBuf = ach_i2c_data;
+    max30102_i2c_data.receiveLen = 6;
+    ret = IoTI2cWriteread(WIFI_IOT_I2C_IDX_1, (MAX30102_SLAVE_ADDRESS << 1) | 0x00, &max30102_i2c_data);
+    if (ret != 0) {
+        printf("===== Error: I2C writeread ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    un_temp=(unsigned char) ach_i2c_data[0];
+    un_temp<<=16;
+    *pun_red_led+=un_temp;
+    un_temp=(unsigned char) ach_i2c_data[1];
+    un_temp<<=8;
+    *pun_red_led+=un_temp;
+    un_temp=(unsigned char) ach_i2c_data[2];
+    *pun_red_led+=un_temp;
+    
+    un_temp=(unsigned char) ach_i2c_data[3];
+    un_temp<<=16;
+    *pun_ir_led+=un_temp;
+    un_temp=(unsigned char) ach_i2c_data[4];
+    un_temp<<=8;
+    *pun_ir_led+=un_temp;
+    un_temp=(unsigned char) ach_i2c_data[5];
+    *pun_ir_led+=un_temp;
+    *pun_red_led&=0x03FFFF;  //Mask MSB [23:18]
+    *pun_ir_led&=0x03FFFF;  //Mask MSB [23:18]
+    return 1;
+}

+ 249 - 0
app/A03_MAX30102_B/src/max30102.c

@@ -0,0 +1,249 @@
+#include "max30102.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+#include "iot_i2c.h"
+#include "iot_i2c_ex.h"
+#include <stdio.h>
+
+#define WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA 6
+#define WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL 6
+#define WIFI_IOT_I2C_IDX_1 1
+#define WIFI_IOT_IO_NAME_GPIO_7 7
+#define WIFI_IOT_IO_NAME_GPIO_8 8
+#define WIFI_IOT_IO_NAME_GPIO_0 0
+#define WIFI_IOT_IO_NAME_GPIO_1 1
+#define MAX30102_INIT_GPIO 7
+/***************************************************************
+ * 函数名称: GpioInit
+ * 说    明:  GPIO初始化
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void BoardInit(void)
+{
+    // IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_8);
+    // IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_GPIO);
+    // IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_DIR_OUT); // 设置GPIO_8为输出模式
+
+    IoTGpioInit(MAX30102_INIT_GPIO);
+    IoTGpioSetFunc(MAX30102_INIT_GPIO, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(MAX30102_INIT_GPIO, IOT_GPIO_DIR_IN); // 设置GPIO_7为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_0);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA); // GPIO_0复用为I2C1_SDA
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_1);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL); // GPIO_1复用为I2C1_SCL
+    IoTI2cInit(WIFI_IOT_I2C_IDX_1, 400000);              /* baudrate: 400kbps */
+}
+
+
+uint8_t GetInit(void)
+{
+	IotGpioValue temp = {0};
+    IoTGpioGetInputVal(MAX30102_INIT_GPIO,&temp);
+    return temp;
+}
+
+
+/**
+* \brief        Write a value to a MAX30102 register
+* \par          Details
+*               This function writes a value to a MAX30102 register
+*
+* \param[in]    uch_addr    - register address
+* \param[in]    uch_data    - register data
+*
+* \retval       true on success
+*/
+static int maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data)
+{
+    uint32_t ret;
+    uint8_t send_data[2] = {uch_addr, uch_data};
+    ret = IoTI2cWrite(WIFI_IOT_I2C_IDX_1, (MAX30102_SLAVE_ADDRESS << 1) | 0x00, send_data, 2);
+    if (ret != 0) {
+        printf("===== Error: I2C write ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    return 0;
+}
+
+/**
+* \brief        Read a MAX30102 register
+* \par          Details
+*               This function reads a MAX30102 register
+*
+* \param[in]    uch_addr    - register address
+* \param[out]   puch_data    - pointer that stores the register data
+*
+* \retval       true on success
+*/
+uint8_t maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data)
+{
+    uint32_t ret = 0;
+    IotI2cData max30102_i2c_data = {0};
+    uint8_t buffer[1] = {uch_addr};
+    max30102_i2c_data.sendBuf = buffer;
+    max30102_i2c_data.sendLen = 1;
+    max30102_i2c_data.receiveBuf = puch_data;
+    max30102_i2c_data.receiveLen = 1;
+    ret = IoTI2cWriteread(WIFI_IOT_I2C_IDX_1, (MAX30102_SLAVE_ADDRESS << 1) | 0x00, &max30102_i2c_data);
+    if (ret != 0) {
+        printf("===== Error: I2C writeread ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    return 0;
+}
+
+uint8_t maxim_max30102_init()
+{
+	
+    if(maxim_max30102_write_reg(REG_INTR_ENABLE_1,0xc0)!=IOT_SUCCESS) // INTR setting
+        return 0;
+    if(maxim_max30102_write_reg(REG_INTR_ENABLE_2,0x00)!=IOT_SUCCESS)
+        return 0;
+    if(maxim_max30102_write_reg(REG_FIFO_WR_PTR,0x00)!=IOT_SUCCESS)  //FIFO_WR_PTR[4:0]
+        return 0;
+    if(maxim_max30102_write_reg(REG_OVF_COUNTER,0x00)!=IOT_SUCCESS)  //OVF_COUNTER[4:0]
+        return 0;
+    if(maxim_max30102_write_reg(REG_FIFO_RD_PTR,0x00)!=IOT_SUCCESS)  //FIFO_RD_PTR[4:0]
+        return 0;
+    if(maxim_max30102_write_reg(REG_FIFO_CONFIG,0x0f)!=IOT_SUCCESS)  //sample avg = 1, fifo rollover=false, fifo almost full = 17
+        return 0;
+    if(maxim_max30102_write_reg(REG_MODE_CONFIG,0x03)!=IOT_SUCCESS)   //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
+        return 0;
+    if(maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27)!=IOT_SUCCESS)  // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)
+        return 0;
+    
+    if(maxim_max30102_write_reg(REG_LED1_PA,0x32)!=IOT_SUCCESS)   //Choose value for ~ 7mA for LED1
+        return 0;
+    if(maxim_max30102_write_reg(REG_LED2_PA,0x32)!=IOT_SUCCESS)   // Choose value for ~ 7mA for LED2
+        return 0;
+    if(maxim_max30102_write_reg(REG_PILOT_PA,0x7f)!=IOT_SUCCESS)   // Choose value for ~ 25mA for Pilot LED
+        return 0;
+    return 1;  
+
+}
+
+
+/**
+* \brief        Reset the MAX30102
+* \par          Details
+*               This function resets the MAX30102
+*
+* \param        None
+*
+* \retval       true on success
+*/
+uint8_t maxim_max30102_reset()
+{
+    if(maxim_max30102_write_reg(REG_MODE_CONFIG,0x40)!=IOT_SUCCESS)
+        return 0;
+    else
+        return 1;    
+}
+/**
+* \brief        Read a set of samples from the MAX30102 FIFO register
+* \par          Details
+*               This function reads a set of samples from the MAX30102 FIFO register
+*
+* \param[out]   *pun_red_led   - pointer that stores the red LED reading data
+* \param[out]   *pun_ir_led    - pointer that stores the IR LED reading data
+*
+* \retval       true on success
+*/
+uint8_t max30102_FIFO_ReadBytes(uint8_t Register_Address,uint8_t* Data)
+{
+    uint32_t un_temp;
+    unsigned char uch_temp;
+  
+    //read and clear status register
+    maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);
+    maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);
+  
+//   ach_i2c_data[0]=REG_FIFO_DATA;
+	 
+    uint32_t ret = 0;
+    IotI2cData max30102_i2c_data = {0};
+    uint8_t buffer[1] = {REG_FIFO_DATA};
+    max30102_i2c_data.sendBuf = buffer;
+    max30102_i2c_data.sendLen = 1;
+    max30102_i2c_data.receiveBuf = Data;
+    max30102_i2c_data.receiveLen = 6;
+    ret = IoTI2cWriteread(WIFI_IOT_I2C_IDX_1, (MAX30102_SLAVE_ADDRESS << 1) | 0x00, &max30102_i2c_data);
+    if (ret != 0) {
+        printf("===== Error: I2C writeread ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    return 0;
+}
+
+uint16_t fifo_red;
+uint16_t fifo_ir;
+
+/**
+* \brief        Read a set of samples from the MAX30102 FIFO register
+* \par          Details
+*               This function reads a set of samples from the MAX30102 FIFO register
+*
+* \param[out]   *pun_red_led   - pointer that stores the red LED reading data
+* \param[out]   *pun_ir_led    - pointer that stores the IR LED reading data
+*
+* \retval       true on success
+*/
+void max30102_read_fifo(void)
+{
+    uint32_t un_temp;
+    unsigned char uch_temp;
+    fifo_red=0;
+    fifo_ir=0;
+    uint8_t ach_i2c_data[6];
+    
+    //read and clear status register
+    maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);
+    maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);
+  
+//   ach_i2c_data[0]=REG_FIFO_DATA;
+	 
+    uint32_t ret = 0;
+    IotI2cData max30102_i2c_data = {0};
+    uint8_t buffer[1] = {REG_FIFO_DATA};
+    max30102_i2c_data.sendBuf = buffer;
+    max30102_i2c_data.sendLen = 1;
+    max30102_i2c_data.receiveBuf = ach_i2c_data;
+    max30102_i2c_data.receiveLen = 6;
+    ret = IoTI2cWriteread(WIFI_IOT_I2C_IDX_1, (MAX30102_SLAVE_ADDRESS << 1) | 0x00, &max30102_i2c_data);
+    if (ret != 0) {
+        printf("===== Error: I2C writeread ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    un_temp=(unsigned char) ach_i2c_data[0];
+    un_temp<<=14;
+    fifo_red+=un_temp;
+    un_temp=(unsigned char) ach_i2c_data[1];
+    un_temp<<=8;
+    fifo_red+=un_temp;
+    un_temp=(unsigned char) ach_i2c_data[2];
+    un_temp>>=2;
+    fifo_red+=un_temp;
+
+    
+    un_temp=(unsigned char) ach_i2c_data[3];
+    un_temp<<=16;
+    fifo_ir+=un_temp;
+    un_temp=(unsigned char) ach_i2c_data[4];
+    un_temp<<=8;
+    fifo_ir+=un_temp;
+    un_temp=(unsigned char) ach_i2c_data[5];
+    un_temp>>=2;
+    fifo_ir+=un_temp;
+	if(fifo_ir<=10000)
+	{
+		fifo_ir=0;
+	}
+	if(fifo_red<=10000)
+	{
+		fifo_red=0;
+	}
+    return 1;
+}

+ 71 - 0
app/A04_NOISE/A04_NOISE_example.c

@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "noise.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+
+static void ExampleTask(void)
+{
+    float ad_value;
+    BoardInit();
+    usleep(1000000);      
+    while (1)
+    {
+		ad_value = GetVoltage();
+		if(NoiseReadData() == 0)
+			{
+				printf("Near the noise!\n");
+				printf("ad_value:%2.2fV\n",ad_value);
+                LedWarnStatusSet(ON);
+				
+			}
+		else{
+			printf("Far the noise!\n");
+            printf("ad_value:%2.2fV\n",ad_value);
+            LedWarnStatusSet(OFF);
+        }
+
+        sleep(1);
+    }
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 26 - 0
app/A04_NOISE/BUILD.gn

@@ -0,0 +1,26 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A04_NOISE") {
+    sources = [
+        "src/noise.c",
+        "A04_NOISE_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "//device/bossay/hi3861_l0/sdk_liteos/include",
+        "include"
+    ]
+}

+ 23 - 0
app/A04_NOISE/include/noise.h

@@ -0,0 +1,23 @@
+#ifndef __FLAME_H__
+#define __FLAME_H__
+
+
+#include <stdint.h>
+
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+
+void BoardInit(void);
+float GetVoltage(void);
+uint8_t NoiseReadData(void);
+// void BeepStatusSet(SwitchStatus status);
+void LedWarnStatusSet(SwitchStatus status);	
+
+#endif
+
+

+ 103 - 0
app/A04_NOISE/src/noise.c

@@ -0,0 +1,103 @@
+#include "noise.h"
+#include "iot_adc.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+
+#define WIFI_IOT_IO_NAME_GPIO_8 8
+#define WIFI_IOT_IO_NAME_GPIO_14 14
+
+#define OUT_GPIO 12
+
+
+
+void BoardInit(void)
+{   
+    IoTGpioInit(OUT_GPIO);
+    IoTGpioSetFunc(OUT_GPIO, IOT_GPIO_FUNC_GPIO_12_GPIO);
+    IoTGpioSetDir(OUT_GPIO, IOT_GPIO_DIR_IN); // 设置GPIO_8为输出模式
+
+    // IoTGpioInit(13);
+    // IoTGpioSetFunc(13, IOT_GPIO_FUNC_GPIO_13_GPIO);
+    // IoTGpioSetDir(13, IOT_GPIO_DIR_IN); // 设置GPIO_8为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_14);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_14, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_14, IOT_GPIO_DIR_OUT);
+
+    // IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_8);
+    // IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_FUNC_GPIO_8_GPIO);
+    // IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_DIR_OUT);
+}
+
+/***************************************************************
+* 函数名称: GetVoltage
+* 说    明: 获取电压值函数
+* 参    数: 无
+*								
+* 返 回 值: 无
+***************************************************************/
+float GetVoltage(void)
+{
+    unsigned int ret;
+    unsigned short data;
+
+    ret = IoTAdcRead(6, &data, IOT_ADC_EQU_MODEL_8, IOT_ADC_CUR_BAIS_DEFAULT, 0xff);
+    if (ret != IOT_SUCCESS)
+    {
+        printf("ADC Read Fail\n");
+    }
+    return (float)data * 1.8 * 4 / 4096.0;
+}
+
+/***************************************************************
+* 函数名称: NoiseReadData
+* 说    明: 读取数据
+* 参    数: 无
+* 返 回 值: 无
+***************************************************************/
+uint8_t NoiseReadData(void)
+{
+    IotGpioValue temp = {0};
+    IoTGpioGetInputVal(OUT_GPIO,&temp);
+    return temp;
+}
+
+
+/***************************************************************
+ * 函数名称: BeepStatusSet
+ * 说    明: Beep状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+// void BeepStatusSet(SwitchStatus status)
+// {
+//     if (status == ON) {
+//         IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_8, 1); // 设置GPIO_7输出高电平点亮灯
+//     }
+//     if (status == OFF) {
+//         IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_8, 0); // 设置GPIO_7输出低电平关闭灯
+//     }
+// }
+
+/***************************************************************
+ * 函数名称: LedWarnStatusSet
+ * 说    明: LED_Warn状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedWarnStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 1); // 设置GPIO_14输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 0); // 设置GPIO_14输出低电平关闭灯
+    }
+}
+

+ 74 - 0
app/A05_WATER/A02_WATER_example.c

@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "WATER.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+
+static void ExampleTask(void)
+{
+    float ad_value;
+    BoardInit();
+ 
+    while (1)
+    {
+		ad_value = GetVoltage();
+		if(WaterReadData() == 0)
+        {
+            printf("Near the water!\n");
+            printf("ad_value:%2.2fV\n",ad_value);
+            BeepStatusSet(ON);
+            LedWarnStatusSet(ON);
+            
+        }
+		else
+        {
+			printf("Far the water!\n");
+            printf("ad_value:%2.2fV\n",ad_value);
+            BeepStatusSet(OFF);
+            LedWarnStatusSet(OFF);
+        }
+
+        sleep(1);
+    }
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 26 - 0
app/A05_WATER/BUILD.gn

@@ -0,0 +1,26 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A05_WATER") {
+    sources = [
+        "src/WATER.c",
+        "A02_WATER_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "//device/bossay/hi3861_l0/sdk_liteos/include",
+        "include"
+    ]
+}

+ 23 - 0
app/A05_WATER/include/WATER.h

@@ -0,0 +1,23 @@
+#ifndef __WATER_H__
+#define __WATER_H__
+
+
+#include <stdint.h>
+
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+
+void BoardInit(void);
+float GetVoltage(void);
+uint8_t WaterReadData(void);
+void BeepStatusSet(SwitchStatus status);
+void LedWarnStatusSet(SwitchStatus status);	
+
+#endif
+
+

+ 100 - 0
app/A05_WATER/src/WATER.c

@@ -0,0 +1,100 @@
+#include "WATER.h"
+#include "iot_adc.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+
+#define WIFI_IOT_IO_NAME_GPIO_8 8
+#define WIFI_IOT_IO_NAME_GPIO_14 14
+
+#define OUT_GPIO 7
+
+
+
+void BoardInit(void)
+{   
+    IoTGpioInit(OUT_GPIO);
+    IoTGpioSetFunc(OUT_GPIO, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(OUT_GPIO, IOT_GPIO_DIR_IN); // 设置为输入模式
+
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_14);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_14, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_14, IOT_GPIO_DIR_OUT); // 设置为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_8);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_FUNC_GPIO_8_GPIO);
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_DIR_OUT); // 设置为输出模式
+}
+
+/***************************************************************
+* 函数名称: GetVoltage
+* 说    明: 获取电压值函数
+* 参    数: 无
+*								
+* 返 回 值: 无
+***************************************************************/
+float GetVoltage(void)
+{
+    unsigned int ret;
+    unsigned short data;
+
+    ret = IoTAdcRead(6, &data, IOT_ADC_EQU_MODEL_8, IOT_ADC_CUR_BAIS_DEFAULT, 0xff);
+    if (ret != IOT_SUCCESS)
+    {
+        printf("ADC Read Fail\n");
+    }
+    return (float)data * 1.8 * 4 / 4096.0;
+}
+
+/***************************************************************
+* 函数名称: WaterReadData
+* 说    明: 读取数据
+* 参    数: 无
+* 返 回 值: 无
+***************************************************************/
+uint8_t WaterReadData(void)
+{
+    IotGpioValue temp = {0};
+    IoTGpioGetInputVal(OUT_GPIO,&temp);
+    return temp;
+}
+
+
+/***************************************************************
+ * 函数名称: BeepStatusSet
+ * 说    明: Beep状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void BeepStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_8, 1); // 设置输出高电平打开蜂鸣器
+    }
+    if (status == OFF) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_8, 0); // 设置输出低电平关闭蜂鸣器
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedWarnStatusSet
+ * 说    明: LED_Warn状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedWarnStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 1); // 设置GPIO_14输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 0); // 设置GPIO_14输出低电平关闭灯
+    }
+}
+

+ 66 - 0
app/A06_VOICE_SWITCH/A11_PM2_5_example.c

@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "PM2_5.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+
+static void ExampleTask(void)
+{
+    PM2D5Data data;
+
+    BoardInit();
+
+    while (1) {
+        PM2DReadData(&data);
+        // printf("\r\n******************************PM1.0 is  %d\r\n", data.pm1_0);
+        // printf("\r\n******************************PM2.5 is  %d\r\n", data.pm2_5);
+        // printf("\r\n******************************PM10 is  %d\r\n", data.pm10);
+        // sleep(1);
+        RelayStatusSet(ON);
+        osDelay(200);
+        RelayStatusSet(OFF);
+        osDelay(200);
+    }
+
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 26 - 0
app/A06_VOICE_SWITCH/BUILD.gn

@@ -0,0 +1,26 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A6_VOICE_SWITCH") {
+    sources = [
+        "src/PM2_5.c",
+        "A11_PM2_5_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "//device/bossay/hi3861_l0/sdk_liteos/include",
+        "include"
+    ]
+}

+ 29 - 0
app/A06_VOICE_SWITCH/include/PM2_5.h

@@ -0,0 +1,29 @@
+#ifndef __PM_2_5_H__
+#define __PM_2_5_H__
+
+
+#include <stdint.h>
+
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+typedef struct
+{
+    uint32_t    pm1_0;	
+    uint32_t    pm2_5;
+    uint32_t    pm10;		
+} PM2D5Data;
+
+void BoardInit(void);
+
+uint8_t Button_Left_Read_Data(void);
+
+void PM2DReadData(PM2D5Data* ReadData);
+void RelayStatusSet(SwitchStatus status);
+#endif
+
+

+ 89 - 0
app/A06_VOICE_SWITCH/src/PM2_5.c

@@ -0,0 +1,89 @@
+#include "PM2_5.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+#include "iot_uart.h"
+#include "stdio.h"
+
+#define RESET_GPIO 7
+#define LED_SAFE_GPIO 8
+#define LED_WARN_GPIO 14
+#define SET_GPIO 13
+#define WIFI_IOT_UART_IDX_1 1
+
+uint8_t     RxBuffer[3];
+
+#define RELAY_GPIO 14
+
+void BoardInit(void)
+{   
+    IoTGpioInit(RELAY_GPIO);
+    IoTGpioSetFunc(RELAY_GPIO, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(RELAY_GPIO, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    uint32_t ret;
+
+    IotUartAttribute uart_attr = {
+
+        // baud_rate: 9600
+        .baudRate = 9600,
+
+        // data_bits: 8bits
+        .dataBits = 8,
+        .stopBits = 1,
+        .parity = 0,
+    };
+
+    // Initialize uart driver
+    ret = IoTUartInit(WIFI_IOT_UART_IDX_1, &uart_attr);
+    if (ret != IOT_SUCCESS) {
+        printf("Failed to init uart! Err code = %d\n", ret);
+        return;
+    }
+}
+
+static unsigned char read_date[32];
+
+/***************************************************************
+ * 函数名称: PM2DReadData
+ * 说    明: 获取GPS经纬度信息
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void PM2DReadData(PM2D5Data* ReadData)
+{
+    //通过串口1接收数据
+    IoTUartRead(WIFI_IOT_UART_IDX_1, read_date, 200);
+
+    for(int i = 0; i<200; i++)
+    {
+        printf("%d------%x\r\n",i,read_date[i]);
+    }
+    // if(read_date[0]== 0x42 && read_date[1]== 0x4d)
+    // {
+    //     ReadData->pm1_0=read_date[2]<<8|read_date[3];
+    //     ReadData->pm2_5=read_date[4]<<8|read_date[5];
+    //     ReadData->pm10=read_date[6]<<8|read_date[7];
+    // }
+
+}
+
+
+/***************************************************************
+ * 函数名称: RelayStatusSet
+ * 说    明: 开关继电器
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,光灯
+ *									ON,开灯
+ * 返 回 值: 无
+ ***************************************************************/
+void RelayStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(RELAY_GPIO, 1); //设置输出高电平点亮LED灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(RELAY_GPIO, 0); //设置输出低电平点亮LED灯
+    }
+}

+ 85 - 0
app/A07_WATHER/A07_WATHER_example.c

@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+#include "WATHER.h"
+
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+BMP280_HandleTypedef bmp280;
+float pressure, temperature, asl,humidity;
+
+static void ExampleTask(void)
+{
+    uint16_t dht_temperature;
+	uint16_t dht_humidity;
+    BoardInit();
+
+    bmp280_init_default_params(&bmp280.params);
+    	while (!bmp280_init(&bmp280, &bmp280.params)) {
+		printf("BMP280 initialization failed\n");
+	}
+    DHT21_Init();
+    while (1)
+    {
+        printf("=======================================\r\n");
+        printf("*************A07_WATHER_example***********\r\n");
+        printf("=======================================\r\n");
+        DHT21_onewire(&dht_temperature,&dht_humidity);
+		humidity = (float)dht_humidity/10;
+        if(humidity>80){
+            BeepStatusSet(ON);
+        }
+        else{
+            BeepStatusSet(OFF);
+        }
+		// printf("temperature=%d \r\n",dht_temperature);
+		// printf("humidity=%d %%\r\n",dht_humidity);
+
+        //读取温度、气压、海拔数据,学员自行补充
+        while (!bmp280_read_float(&bmp280, &temperature, &pressure, &asl)) {
+            printf("Temperature/pressure reading failed\n");
+        }
+        printf("Temperature: %.2f C\r\nHumidity: %.2f %%\r\nPressure: %.2f hPa\r\nAltiude: %.2f m\r\n",temperature,humidity, pressure,asl);
+
+        sleep(3);
+    }
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 28 - 0
app/A07_WATHER/BUILD.gn

@@ -0,0 +1,28 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A07_WATHER") {
+    sources = [
+        "src/dht21.c",
+        "src/bmp280.c",
+        "src/WATHER.c",
+        "A07_WATHER_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "//device/bossay/hi3861_l0/sdk_liteos/include",
+        "include"
+    ]
+}

+ 21 - 0
app/A07_WATHER/include/WATHER.h

@@ -0,0 +1,21 @@
+#ifndef __WATER_H__
+#define __WATER_H__
+
+
+#include <stdint.h>
+#include "bmp280.h"
+#include "dht21.h"
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+
+void BoardInit(void);
+void BeepStatusSet(SwitchStatus status);
+
+#endif
+
+

+ 172 - 0
app/A07_WATHER/include/bmp280.h

@@ -0,0 +1,172 @@
+/**
+ * Ciastkolog.pl (https://github.com/ciastkolog)
+ * 
+*/
+/**
+ * The MIT License (MIT)
+ * Copyright (c) 2016 sheinz (https://github.com/sheinz)
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ */
+#ifndef __BMP280_H__
+#define __BMP280_H__
+
+// #include "stm32f0xx_hal.h"
+#include <stdint.h>
+#include <stdbool.h>
+
+/**
+ * BMP280 or BME280 address is 0x77 if SDO pin is high, and is 0x76 if
+ * SDO pin is low.
+ */
+
+#define BMP280_I2C_ADDRESS_0  0x76
+#define BMP280_I2C_ADDRESS_1  0x77
+
+#define BMP280_CHIP_ID  0x58 /* BMP280 has chip-id 0x58 */
+#define BME280_CHIP_ID  0x60 /* BME280 has chip-id 0x60 */
+
+/**
+ * Mode of BMP280 module operation.
+ * Forced - Measurement is initiated by user.
+ * Normal - Continues measurement.
+ */
+typedef enum {
+    BMP280_MODE_SLEEP = 0,
+    BMP280_MODE_FORCED = 1,
+    BMP280_MODE_NORMAL = 3
+} BMP280_Mode;
+
+typedef enum {
+    BMP280_FILTER_OFF = 0,
+    BMP280_FILTER_2 = 1,
+    BMP280_FILTER_4 = 2,
+    BMP280_FILTER_8 = 3,
+    BMP280_FILTER_16 = 4
+} BMP280_Filter;
+
+/**
+ * Pressure oversampling settings
+ */
+typedef enum {
+    BMP280_SKIPPED = 0,          /* no measurement  */
+    BMP280_ULTRA_LOW_POWER = 1,  /* oversampling x1 */
+    BMP280_LOW_POWER = 2,        /* oversampling x2 */
+    BMP280_STANDARD = 3,         /* oversampling x4 */
+    BMP280_HIGH_RES = 4,         /* oversampling x8 */
+    BMP280_ULTRA_HIGH_RES = 5    /* oversampling x16 */
+} BMP280_Oversampling;
+
+/**
+ * Stand by time between measurements in normal mode
+ */
+typedef enum {
+    BMP280_STANDBY_05 = 0,      /* stand by time 0.5ms */
+    BMP280_STANDBY_62 = 1,      /* stand by time 62.5ms */
+    BMP280_STANDBY_125 = 2,     /* stand by time 125ms */
+    BMP280_STANDBY_250 = 3,     /* stand by time 250ms */
+    BMP280_STANDBY_500 = 4,     /* stand by time 500ms */
+    BMP280_STANDBY_1000 = 5,    /* stand by time 1s */
+    BMP280_STANDBY_2000 = 6,    /* stand by time 2s BMP280, 10ms BME280 */
+    BMP280_STANDBY_4000 = 7,    /* stand by time 4s BMP280, 20ms BME280 */
+} BMP280_StandbyTime;
+
+/**
+ * Configuration parameters for BMP280 module.
+ * Use function bmp280_init_default_params to use default configuration.
+ */
+typedef struct {
+    BMP280_Mode mode;
+    BMP280_Filter filter;
+    BMP280_Oversampling oversampling_pressure;
+    BMP280_Oversampling oversampling_temperature;
+    BMP280_StandbyTime standby;
+} bmp280_params_t;
+
+
+typedef struct {
+    uint16_t dig_T1;
+    int16_t  dig_T2;
+    int16_t  dig_T3;
+    uint16_t dig_P1;
+    int16_t  dig_P2;
+    int16_t  dig_P3;
+    int16_t  dig_P4;
+    int16_t  dig_P5;
+    int16_t  dig_P6;
+    int16_t  dig_P7;
+    int16_t  dig_P8;
+    int16_t  dig_P9;
+
+    /* Humidity compensation for BME280 */
+    uint8_t  dig_H1;
+    int16_t  dig_H2;
+    uint8_t  dig_H3;
+    int16_t  dig_H4;
+    int16_t  dig_H5;
+    int8_t   dig_H6;
+
+    bmp280_params_t params;
+    uint8_t  id;        /* Chip ID */
+
+} BMP280_HandleTypedef;
+
+/**
+ * Initialize default parameters.
+ * Default configuration:
+ *      mode: NORAML
+ *      filter: OFF
+ *      oversampling: x4
+ *      standby time: 250ms
+ */
+void bmp280_init_default_params(bmp280_params_t *params);
+
+/**
+ * Initialize BMP280 module, probes for the device, soft resets the device,
+ * reads the calibration constants, and configures the device using the supplied
+ * parameters. Returns true on success otherwise false.
+ *
+ * The I2C address is assumed to have been initialized in the dev, and
+ * may be either BMP280_I2C_ADDRESS_0 or BMP280_I2C_ADDRESS_1. If the I2C
+ * address is unknown then try initializing each in turn.
+ *
+ * This may be called again to soft reset the device and initialize it again.
+ */
+bool bmp280_init(BMP280_HandleTypedef *dev, bmp280_params_t *params);
+
+/**
+ * Start measurement in forced mode.
+ * The module remains in forced mode after this call.
+ * Do not call this method in normal mode.
+ */
+bool bmp280_force_measurement(void);
+
+/**
+ * Check if BMP280 is busy with measuring temperature/pressure.
+ * Return true if BMP280 is busy.
+ */
+bool bmp280_is_measuring(void);
+
+/**
+ * Read compensated temperature and pressure data:
+ *
+ *  Temperature in degrees Celsius times 100.
+ *
+ *  Pressure in Pascals in fixed point 24 bit integer 8 bit fraction format.
+ *
+ *  Humidity is optional and only read for the BME280, in percent relative
+ *  humidity as a fixed point 22 bit interger and 10 bit fraction format.
+ */
+bool bmp280_read_fixed(BMP280_HandleTypedef *dev, int32_t *temperature,
+                       uint32_t *pressure);
+
+/**
+ * Read compensated temperature and pressure data:
+ *  Temperature in degrees Celsius.
+ *  Pressure in Pascals.
+ *  Humidity is optional and only read for the BME280, in percent relative
+ *  humidity.
+ */
+bool bmp280_read_float(BMP280_HandleTypedef *dev, float *temperature,
+                       float *pressure, float* asl);
+
+#endif  // __BMP280_H__

+ 19 - 0
app/A07_WATHER/include/dht21.h

@@ -0,0 +1,19 @@
+#ifndef __DHT21_H_
+#define __DHT21_H_
+
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+#include <stdint.h>
+
+#define DHT11_DQ_GPIO 13
+											   
+#define	DHT11_DQ_OUT_OFF   	IoTGpioSetOutputVal(DHT11_DQ_GPIO, 0);
+#define	DHT11_DQ_OUT_ON   	IoTGpioSetOutputVal(DHT11_DQ_GPIO, 1);
+
+
+void DHT21_Init(void);
+uint8_t DHT21_onewire(uint16_t *tem,uint16_t *hum);
+
+
+
+#endif

+ 53 - 0
app/A07_WATHER/src/WATHER.c

@@ -0,0 +1,53 @@
+#include "WATHER.h"
+#include "iot_adc.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+#include "iot_i2c.h"
+
+#define I2C1_SDA_GPIO 0
+#define I2C1_SCL_GPIO 1
+#define IOT_GPIO_FUNC_GPIO_0_I2C1_SDA  6
+#define IOT_GPIO_FUNC_GPIO_1_I2C1_SCL 6
+#define WIFI_IOT_I2C_IDX_1 1
+
+#define BEEP_GPIO 8
+
+
+
+void BoardInit(void)
+{   
+    IoTGpioInit(BEEP_GPIO);
+    IoTGpioSetFunc(BEEP_GPIO, IOT_GPIO_FUNC_GPIO_8_GPIO);
+    IoTGpioSetDir(BEEP_GPIO, IOT_GPIO_DIR_OUT); // 设置GPIO_14为输出模式
+    
+    //GPIO_0复用为I2C1_SDA
+    IoTGpioInit(I2C1_SDA_GPIO);
+    IoTGpioSetFunc(I2C1_SDA_GPIO, IOT_GPIO_FUNC_GPIO_0_I2C1_SDA);
+
+    //GPIO_1复用为I2C1_SCL
+    IoTGpioInit(I2C1_SCL_GPIO);
+    IoTGpioSetFunc(I2C1_SCL_GPIO, IOT_GPIO_FUNC_GPIO_1_I2C1_SCL);
+
+    //baudrate: 400kbps
+    IoTI2cInit(WIFI_IOT_I2C_IDX_1, 400000);
+
+}
+
+/***************************************************************
+ * 函数名称: BeepStatusSet
+ * 说    明: Beep状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void BeepStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(BEEP_GPIO, 1); // 设置输出高电平打开蜂鸣器
+    }
+    if (status == OFF) {
+        IoTGpioSetOutputVal(BEEP_GPIO, 0); // 设置输出低电平关闭蜂鸣器
+    }
+}

+ 307 - 0
app/A07_WATHER/src/bmp280.c

@@ -0,0 +1,307 @@
+/**
+ * Ciastkolog.pl (https://github.com/ciastkolog)
+ * 
+*/
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 sheinz (https://github.com/sheinz)
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "bmp280.h"
+#include <stdio.h>
+#include <math.h>
+#include "iot_i2c.h"
+#include "iot_i2c_ex.h"
+
+/**
+ * BMP280 registers
+ */
+#define BMP280_REG_TEMP_XLSB   0xFC /* bits: 7-4 */
+#define BMP280_REG_TEMP_LSB    0xFB
+#define BMP280_REG_TEMP_MSB    0xFA
+#define BMP280_REG_TEMP        (BMP280_REG_TEMP_MSB)
+#define BMP280_REG_PRESS_XLSB  0xF9 /* bits: 7-4 */
+#define BMP280_REG_PRESS_LSB   0xF8
+#define BMP280_REG_PRESS_MSB   0xF7
+#define BMP280_REG_PRESSURE    (BMP280_REG_PRESS_MSB)
+#define BMP280_REG_CONFIG      0xF5 /* bits: 7-5 t_sb; 4-2 filter; 0 spi3w_en */
+#define BMP280_REG_CTRL        0xF4 /* bits: 7-5 osrs_t; 4-2 osrs_p; 1-0 mode */
+#define BMP280_REG_STATUS      0xF3 /* bits: 3 measuring; 0 im_update */
+#define BMP280_REG_RESET       0xE0
+#define BMP280_REG_ID          0xD0
+#define BMP280_REG_CALIB       0x88
+
+#define BMP280_RESET_VALUE     0xB6
+
+#define WIFI_IOT_I2C_IDX_1 1
+
+void bmp280_init_default_params(bmp280_params_t *params) {
+	params->mode = BMP280_MODE_NORMAL;
+	params->filter = BMP280_FILTER_OFF;
+	params->oversampling_pressure = BMP280_STANDARD;
+	params->oversampling_temperature = BMP280_STANDARD;
+	params->standby = BMP280_STANDBY_250;
+}
+
+static uint8_t read_register16(uint8_t reg, uint16_t *value) {
+    uint8_t rx_buff[2];
+	uint32_t status = 0;
+    IotI2cData bmp280_i2c_data = {0};
+    uint8_t  buffer[1] = {reg};
+    bmp280_i2c_data.sendBuf = buffer;
+    bmp280_i2c_data.sendLen = 1;
+    bmp280_i2c_data.receiveBuf = rx_buff;
+    bmp280_i2c_data.receiveLen = 2;
+    status = IoTI2cWriteread(WIFI_IOT_I2C_IDX_1, (BMP280_I2C_ADDRESS_0<<1)|0x00, &bmp280_i2c_data);
+    if (status != 0)
+    {
+        printf("===== Error: I2C write status = 0x%x! =====\r\n", status);
+        return false;
+    }
+	*value = (uint16_t) ((rx_buff[1] << 8) | rx_buff[0]);
+	return true;
+}
+
+static uint8_t read_data( uint8_t reg, uint8_t *value,uint8_t len) {
+    uint32_t status = 0;
+    IotI2cData bmp280_i2c_data = {0};
+    uint8_t  buffer[1] = {reg};
+    bmp280_i2c_data.sendBuf = buffer;
+    bmp280_i2c_data.sendLen = 1;
+    bmp280_i2c_data.receiveBuf = value;
+    bmp280_i2c_data.receiveLen = len;
+    status = IoTI2cWriteread(WIFI_IOT_I2C_IDX_1, (BMP280_I2C_ADDRESS_0<<1)|0x00, &bmp280_i2c_data);
+    if (status != 0)
+    {
+        printf("===== Error: I2C write status = 0x%x! =====\r\n", status);
+        return 1;
+    }
+	return 0;
+}
+
+static bool read_calibration_data(BMP280_HandleTypedef *dev) {
+
+	if (read_register16(0x88, &dev->dig_T1)
+			&& read_register16(0x8a, (uint16_t *) &dev->dig_T2)
+			&& read_register16(0x8c, (uint16_t *) &dev->dig_T3)
+			&& read_register16(0x8e, &dev->dig_P1)
+			&& read_register16(0x90, (uint16_t *) &dev->dig_P2)
+			&& read_register16(0x92, (uint16_t *) &dev->dig_P3)
+			&& read_register16(0x94, (uint16_t *) &dev->dig_P4)
+			&& read_register16(0x96, (uint16_t *) &dev->dig_P5)
+			&& read_register16(0x98, (uint16_t *) &dev->dig_P6)
+			&& read_register16(0x9a, (uint16_t *) &dev->dig_P7)
+			&& read_register16(0x9c, (uint16_t *) &dev->dig_P8)
+			&& read_register16(0x9e,(uint16_t *) &dev->dig_P9)) {
+
+		return true;
+	}
+
+	return false;
+}
+
+
+static int write_register8(uint8_t reg, uint8_t value) {
+ 	
+	uint32_t status = 0;
+    uint8_t send_data[2] = { reg,value };
+    status = IoTI2cWrite(WIFI_IOT_I2C_IDX_1,(BMP280_I2C_ADDRESS_0<<1)|0x00,send_data,2); 
+	if (status != 0)
+    {
+        printf("===== Error: I2C write status = 0x%x! =====\r\n", status);
+        return status;
+    }
+    return 0;  
+}
+
+bool bmp280_init(BMP280_HandleTypedef *dev, bmp280_params_t *params) {
+
+	if (read_data(BMP280_REG_ID, &dev->id, 1)) {
+		return false;
+	}
+
+	if (dev->id != BMP280_CHIP_ID && dev->id != BME280_CHIP_ID) {
+		return false;
+	}
+
+	// Soft reset.
+	if (write_register8(BMP280_REG_RESET, BMP280_RESET_VALUE)) {
+		return false;
+	}
+	// Wait until finished copying over the NVP data.
+	while (1) {
+		uint8_t status;
+		if (!read_data(BMP280_REG_STATUS, &status, 1)
+				&& (status & 1) == 0)
+			break;
+	}
+	if (!read_calibration_data(dev)) {
+		return false;
+	}
+
+
+	uint8_t config = (params->standby << 5) | (params->filter << 2);
+	if (write_register8(BMP280_REG_CONFIG, config)) {
+		return false;
+	}
+
+	if (params->mode == BMP280_MODE_FORCED) {
+		params->mode = BMP280_MODE_SLEEP;  // initial mode for forced is sleep
+	}
+
+	uint8_t ctrl = (params->oversampling_temperature << 5)
+			| (params->oversampling_pressure << 2) | (params->mode);
+
+
+	if (write_register8(BMP280_REG_CTRL, ctrl)) {
+		return false;
+	}
+
+	return true;
+}
+
+bool bmp280_force_measurement(void) {
+	uint8_t ctrl;
+	if (read_data(BMP280_REG_CTRL, &ctrl, 1))
+		return false;
+	ctrl &= ~0b11;  // clear two lower bits
+	ctrl |= BMP280_MODE_FORCED;
+	if (write_register8(BMP280_REG_CTRL, ctrl)) {
+		return false;
+	}
+	return true;
+}
+
+bool bmp280_is_measuring(void) {
+	uint8_t status;
+	if (read_data(BMP280_REG_STATUS, &status, 1))
+		return false;
+	if (status & (1 << 3)) {
+		return true;
+	}
+	return false;
+}
+
+/**
+ * Compensation algorithm is taken from BMP280 datasheet.
+ *
+ * Return value is in degrees Celsius.
+ */
+static inline int32_t compensate_temperature(BMP280_HandleTypedef *dev, int32_t adc_temp,
+		int32_t *fine_temp) {
+	int32_t var1, var2;
+
+	var1 = ((((adc_temp >> 3) - ((int32_t) dev->dig_T1 << 1)))
+			* (int32_t) dev->dig_T2) >> 11;
+	var2 = (((((adc_temp >> 4) - (int32_t) dev->dig_T1)
+			* ((adc_temp >> 4) - (int32_t) dev->dig_T1)) >> 12)
+			* (int32_t) dev->dig_T3) >> 14;
+
+	*fine_temp = var1 + var2;
+	return (*fine_temp * 5 + 128) >> 8;
+}
+
+/**
+ * Compensation algorithm is taken from BMP280 datasheet.
+ *
+ * Return value is in Pa, 24 integer bits and 8 fractional bits.
+ */
+static inline uint32_t compensate_pressure(BMP280_HandleTypedef *dev, int32_t adc_press,
+		int32_t fine_temp) {
+	int64_t var1, var2, p;
+
+	var1 = (int64_t) fine_temp - 128000;
+	var2 = var1 * var1 * (int64_t) dev->dig_P6;
+	var2 = var2 + ((var1 * (int64_t) dev->dig_P5) << 17);
+	var2 = var2 + (((int64_t) dev->dig_P4) << 35);
+	var1 = ((var1 * var1 * (int64_t) dev->dig_P3) >> 8)
+			+ ((var1 * (int64_t) dev->dig_P2) << 12);
+	var1 = (((int64_t) 1 << 47) + var1) * ((int64_t) dev->dig_P1) >> 33;
+
+	if (var1 == 0) {
+		return 0;  // avoid exception caused by division by zero
+	}
+
+	p = 1048576 - adc_press;
+	p = (((p << 31) - var2) * 3125) / var1;
+	var1 = ((int64_t) dev->dig_P9 * (p >> 13) * (p >> 13)) >> 25;
+	var2 = ((int64_t) dev->dig_P8 * p) >> 19;
+
+	p = ((p + var1 + var2) >> 8) + ((int64_t) dev->dig_P7 << 4);
+	return p;
+}
+
+
+#define CONST_PF 	0.1902630958	                                           //(1/5.25588f) Pressure factor
+#define FIX_TEMP 	25				                                               // Fixed Temperature. ASL is a function of pressure and temperature, but as the temperature changes so much (blow a little towards the flie and watch it drop 5 degrees) it corrupts the ASL estimates.
+								                                               // TLDR: Adjusting for temp changes does more harm than good.
+/*
+ * Converts pressure to altitude above sea level (ASL) in meters
+*/
+static float bme280PressureToAltitude(float* pressure/*, float* groundPressure, float* groundTemp*/)
+{
+    if (*pressure>0)
+    {
+        return((1.0f-pow((*pressure/1010),CONST_PF))*(25+273.15f))/0.0065f;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+
+bool bmp280_read_fixed(BMP280_HandleTypedef *dev, int32_t *temperature, uint32_t *pressure) {
+	int32_t adc_pressure;
+	int32_t adc_temp;
+	uint8_t data[8];
+
+
+	// Need to read in one sequence to ensure they match.
+	size_t size =  6;
+	if (read_data(0xf7, data, size)) {
+		return false;
+	}
+
+	adc_pressure = data[0] << 12 | data[1] << 4 | data[2] >> 4;
+	adc_temp = data[3] << 12 | data[4] << 4 | data[5] >> 4;
+
+	int32_t fine_temp;
+	*temperature = compensate_temperature(dev, adc_temp, &fine_temp);
+	*pressure = compensate_pressure(dev, adc_pressure, fine_temp);
+
+	return true;
+}
+
+bool bmp280_read_float(BMP280_HandleTypedef *dev, float *temperature, float *pressure, float* asl) {
+	int32_t fixed_temperature;
+	uint32_t fixed_pressure;
+	if (bmp280_read_fixed(dev, &fixed_temperature, &fixed_pressure)) {
+		*temperature = (float) fixed_temperature / 100;
+		*pressure = (float) fixed_pressure / 25600;
+		*asl = (float)bme280PressureToAltitude(pressure);
+		return true;
+	}
+
+	return false;
+}

+ 245 - 0
app/A07_WATHER/src/dht21.c

@@ -0,0 +1,245 @@
+#include "dht21.h"
+#include "hi_time.h"
+
+
+static void SDA_Output(void)
+{
+    IoTGpioInit(DHT11_DQ_GPIO);
+    IoTGpioSetFunc(DHT11_DQ_GPIO, IOT_GPIO_FUNC_GPIO_13_GPIO);
+    IoTGpioSetDir(DHT11_DQ_GPIO, IOT_GPIO_DIR_OUT); // 设置为输出模式
+}
+
+static void SDA_Input(void)
+{
+    IoTGpioInit(DHT11_DQ_GPIO);
+    IoTGpioSetFunc(DHT11_DQ_GPIO, IOT_GPIO_FUNC_GPIO_13_GPIO);
+    IoTGpioSetDir(DHT11_DQ_GPIO, IOT_GPIO_DIR_IN); // 设置为输入模式
+
+}
+
+static uint8_t Get_SDA(void)
+{
+	IotGpioValue temp = {0};
+    IoTGpioGetInputVal(DHT11_DQ_GPIO,&temp);
+    return temp;
+}
+
+static void DQ_Rst(void)
+{
+	SDA_Output();
+	hi_udelay(5); 
+	DHT11_DQ_OUT_OFF;
+	hi_udelay(480);; 
+	DHT11_DQ_OUT_ON; 
+	hi_udelay(8); 
+}
+
+static uint8_t DQ_Presence(void)
+{
+	uint8_t pulse_time = 0;
+	SDA_Input();
+	hi_udelay(5); 
+	while(Get_SDA() && pulse_time<100 ) 
+	{
+		pulse_time++;
+		hi_udelay(10);//>6us
+	}
+	if( pulse_time >=20 )
+		return 0x01;
+	else
+		pulse_time = 0;
+	while((Get_SDA()==0) && (pulse_time<240 )) 
+	{
+		pulse_time++;
+		hi_udelay(5);//1~5us
+	}
+	if( pulse_time >=10 )
+	{
+		return 0x01;
+	}
+		else
+	return 0x0;
+}
+
+
+//拉低最少1us 后延时一小段时间如6us,后再15us内读取完。 后延时45us以上 即一个周期是60us 
+//tINIT+tRC+tSample < 15us
+//tINIT+tRC+tSample+tDelay>60us
+
+static uint8_t DQ_Read_Bit(void)
+{
+	uint8_t dat;
+	SDA_Output();
+	DHT11_DQ_OUT_OFF
+	hi_udelay(5); //tINIT>1us 典型5us <15us 
+	DHT11_DQ_OUT_ON
+	SDA_Input();
+	hi_udelay(5);//tRC  典型5us 
+	if(Get_SDA())//tSample
+		dat = 1;
+	else
+		dat = 0;
+	hi_udelay(70);//tDelay >60us 确保一帧数据传输完毕
+	return dat;
+}
+
+static uint8_t DQ_Read_Byte(void)
+{
+	uint8_t i, j, dat = 0;
+	for(i=0; i<8; i++)
+	{
+		j = DQ_Read_Bit();
+		dat = (dat) | (j<<i);
+	}
+	return dat;
+}	
+	
+static void DQ_Write_Byte(uint8_t dat)
+{
+	uint8_t i, testb;
+	SDA_Output();
+	for( i=0; i<8; i++ )
+	{
+		testb = dat&0x01;
+		dat = dat>>1;
+		if(testb)//写1
+		{
+			DHT11_DQ_OUT_OFF
+			hi_udelay(5);//>1us <15us
+			DHT11_DQ_OUT_ON
+			hi_udelay(70);//>=60us
+		}
+		else//写0
+		{
+			DHT11_DQ_OUT_OFF
+			hi_udelay(70);//MY_hi_udelay(70);>60us
+			DHT11_DQ_OUT_ON
+			hi_udelay(5);//???? 5us	
+		}
+	}
+}	
+
+
+static uint8_t CRC8MHT_Cal(uint8_t *serial, uint8_t length)
+{
+	uint8_t result = 0x00;
+	uint8_t pDataBuf;
+	uint8_t i;
+	while(length--) 
+	{	
+		pDataBuf = *serial++;
+		for(i=0; i<8; i++) 
+		{
+			if((result^(pDataBuf))&0x01)
+			{
+				result ^= 0x18;
+				result >>= 1;
+				result |= 0x80;
+			}
+			else 
+			{
+				result >>= 1;
+			}
+			pDataBuf >>= 1;
+		}
+	}
+return result;
+}
+
+static uint16_t OwHumA,OwHumB;
+
+//初始化,获取校准数据A B值
+void DHT21_Init()
+{
+	uint8_t i,crc;
+	uint8_t ResDat[13];
+	
+	//Timer4Stop(); 	
+	DQ_Rst();
+	DQ_Presence();
+	DQ_Write_Byte(0xcc);
+	DQ_Write_Byte(0xdd);
+	
+/*	OwHumA = DQ_Read_Byte();
+	OwHumA = (OwHumA<<8)|DQ_Read_Byte();
+	OwHumB = DQ_Read_Byte();
+	OwHumB = (OwHumB<<8)|DQ_Read_Byte();
+	*/		
+	//Timer4Start();
+//当读取满一组数据即 13 个字节后,才有 CRC 值
+//无需要时可以按上面读取前面 4 个即可
+	
+    for(i=0;i<13;i++)
+    {
+        ResDat[i] = DQ_Read_Byte();
+    }
+    crc = CRC8MHT_Cal(ResDat,13);
+    if(crc == 0)
+    {
+        OwHumA = ResDat[0];
+        OwHumA = (OwHumA<<8)|ResDat[1];
+        OwHumB = ResDat[2];
+        OwHumB = (OwHumB<<8)|ResDat[3];
+    }
+
+}
+
+
+
+
+//读取温湿度函数
+uint8_t DHT21_onewire(uint16_t *tem,uint16_t *hum)
+	{
+		uint8_t ResDat[5],crc=0;
+		uint16_t TemBuf;
+		uint16_t CapBuf;
+
+ 
+        DQ_Rst();   
+        DQ_Presence();
+        DQ_Write_Byte(0xcc);
+        DQ_Write_Byte(0x10);
+        osDelay(3);	
+
+        DQ_Rst();
+        DQ_Presence();
+        DQ_Write_Byte(0xcc);
+        DQ_Write_Byte(0xbd);
+        ResDat[0] = DQ_Read_Byte();
+        ResDat[1] = DQ_Read_Byte();
+        ResDat[2] = DQ_Read_Byte();
+        ResDat[3] = DQ_Read_Byte();
+        ResDat[4] = DQ_Read_Byte();
+
+
+		crc = CRC8MHT_Cal(ResDat,5);
+		if(crc == 0)
+		{
+			TemBuf = (uint16_t)ResDat[1]<<8|(ResDat[0]);
+			TemBuf = 40+TemBuf/256;  //*10  结果*10倍 286即28.6℃;
+			*tem = TemBuf;
+			
+			CapBuf = (uint16_t)ResDat[3]<<8|(ResDat[2]);
+			CapBuf = (CapBuf-OwHumB)*600/(OwHumA-OwHumB)+300;//同样结果*10
+			//20℃为5个湿度点  即1℃为0.25个湿度点  0.1℃为0.025
+			CapBuf = CapBuf+ 2.5*(TemBuf-250)/10;
+			if(CapBuf>999)CapBuf = 999;
+			else if(CapBuf<0)CapBuf=0;
+			*hum = (uint16_t)CapBuf;
+		}
+	return crc;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 81 - 0
app/A08_NFC/A08_NFC_example.c

@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pn532_hi3861.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+static void ExampleTask(void)
+{
+    uint8_t buff[255];
+    uint8_t uid[MIFARE_UID_MAX_LENGTH];
+    int32_t uid_len = 0;
+    /* USER CODE BEGIN 2 */
+    printf("Hello!\r\n");
+    PN532 pn532;
+    // PN532_SPI_Init(&pn532);
+    PN532_I2C_Init(&pn532);
+    PN532_GetFirmwareVersion(&pn532, buff);
+    if (PN532_GetFirmwareVersion(&pn532, buff) == PN532_STATUS_OK) {
+        printf("Found PN532 with firmware version: %d.%d\r\n", buff[1], buff[2]);
+    } else {
+        return -1;
+    }
+    PN532_SamConfiguration(&pn532);
+    printf("Waiting for RFID/NFC card...\r\n");
+    while (1)
+    {
+        /* USER CODE END WHILE */
+
+        /* USER CODE BEGIN 3 */
+        // Check if a card is available to read
+        uid_len = PN532_ReadPassiveTarget(&pn532, uid, PN532_MIFARE_ISO14443A, 1000);
+        if (uid_len == PN532_STATUS_ERROR) {
+        printf(".");
+        } else {
+        printf("Found card with UID: ");
+        for (uint8_t i = 0; i < uid_len; i++) {
+            printf("%02x ", uid[i]);
+        }
+        printf("\r\n");
+        }
+    }
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 26 - 0
app/A08_NFC/BUILD.gn

@@ -0,0 +1,26 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A08_NFC") {
+    sources = [
+        "src/pn532_hi3861.c",
+        "src/pn532.c",
+        "A08_NFC_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "include"
+    ]
+}

+ 81 - 0
app/A08_NFC/include/MPU6050.h

@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MPU6050_H__
+#define __MPU6050_H__
+
+
+/* 宏定义 --------------------------------------------------------------------*/
+#define MPU6050_GYRO_OUT            0x43  //MPU6050陀螺仪数据寄存器地址
+#define MPU6050_ACC_OUT             0x3B  //MPU6050加速度数据寄存器地址
+#define MPU6050_SLAVE_ADDRESS       0x68  //MPU6050器件读地址
+#define MPU6050_ADDRESS_AD0_LOW     0x68 // address pin low (GND), default for InvenSense evaluation board
+#define MPU6050_RA_CONFIG           0x1A
+#define MPU6050_RA_ACCEL_CONFIG     0x1C
+#define MPU6050_RA_FF_THR           0x1D
+#define MPU6050_RA_FF_DUR           0x1E
+#define MPU6050_RA_MOT_THR          0x1F  //运动检测阀值设置寄存器
+#define MPU6050_RA_MOT_DUR          0x20  //运动检测时间阀值
+#define MPU6050_RA_ZRMOT_THR        0x21
+#define MPU6050_RA_ZRMOT_DUR        0x22
+#define MPU6050_RA_FIFO_EN          0x23
+#define MPU6050_RA_INT_PIN_CFG      0x37   //中断/旁路设置寄存器
+#define MPU6050_RA_INT_ENABLE       0x38   //中断使能寄存器
+#define MPU6050_RA_TEMP_OUT_H       0x41
+#define MPU6050_RA_USER_CTRL        0x6A
+#define MPU6050_RA_PWR_MGMT_1       0x6B
+#define MPU6050_RA_WHO_AM_I         0x75
+#define SENSOR_DATA_WIDTH_8_BIT     8 // 8 bit
+#define ACCEL_DATA_LEN              6
+#define TEMP_DATA_LEN               2
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+enum AccelAxisNum {
+    ACCEL_X_AXIS = 0,
+    ACCEL_Y_AXIS = 1,
+    ACCEL_Z_AXIS = 2,
+    ACCEL_AXIS_NUM = 3,
+};
+enum AccelAxisPart {
+    ACCEL_X_AXIS_LSB = 0,
+    ACCEL_X_AXIS_MSB = 1,
+    ACCEL_Y_AXIS_LSB = 2,
+    ACCEL_Y_AXIS_MSB = 3,
+    ACCEL_Z_AXIS_LSB = 4,
+    ACCEL_Z_AXIS_MSB = 5,
+    ACCEL_AXIS_BUTT,
+};
+enum TempPart {
+    TEMP_LSB = 0,
+    TEMP_MSB = 1,
+};
+/* MPU6050传感器数据类型定义 ------------------------------------------------------------*/
+typedef struct
+{
+    short   Temperature;     
+    short   Accel[3];
+} MPU6050Data;
+
+int BoardInit(void);
+int MPU6050ReadData(MPU6050Data *ReadData);
+void LedD1StatusSet(SwitchStatus status);
+void LedD2StatusSet(SwitchStatus status);
+
+#endif 

+ 277 - 0
app/A08_NFC/include/pn532.h

@@ -0,0 +1,277 @@
+/**************************************************************************
+ *  @file     pn532.h
+ *  @author   Yehui from Waveshare
+ *  @license  BSD
+ *  
+ *  Header file for pn532.c
+ *  
+ *  Check out the links above for our tutorials and wiring diagrams 
+ *  These chips use SPI communicate.
+ *  
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documnetation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to  whom the Software is
+ * furished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ **************************************************************************/
+
+#ifndef PN532_H
+#define PN532_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PN532_PREAMBLE                      (0x00)
+#define PN532_STARTCODE1                    (0x00)
+#define PN532_STARTCODE2                    (0xFF)
+#define PN532_POSTAMBLE                     (0x00)
+
+#define PN532_HOSTTOPN532                   (0xD4)
+#define PN532_PN532TOHOST                   (0xD5)
+
+// PN532 Commands
+#define PN532_COMMAND_DIAGNOSE              (0x00)
+#define PN532_COMMAND_GETFIRMWAREVERSION    (0x02)
+#define PN532_COMMAND_GETGENERALSTATUS      (0x04)
+#define PN532_COMMAND_READREGISTER          (0x06)
+#define PN532_COMMAND_WRITEREGISTER         (0x08)
+#define PN532_COMMAND_READGPIO              (0x0C)
+#define PN532_COMMAND_WRITEGPIO             (0x0E)
+#define PN532_COMMAND_SETSERIALBAUDRATE     (0x10)
+#define PN532_COMMAND_SETPARAMETERS         (0x12)
+#define PN532_COMMAND_SAMCONFIGURATION      (0x14)
+#define PN532_COMMAND_POWERDOWN             (0x16)
+#define PN532_COMMAND_RFCONFIGURATION       (0x32)
+#define PN532_COMMAND_RFREGULATIONTEST      (0x58)
+#define PN532_COMMAND_INJUMPFORDEP          (0x56)
+#define PN532_COMMAND_INJUMPFORPSL          (0x46)
+#define PN532_COMMAND_INLISTPASSIVETARGET   (0x4A)
+#define PN532_COMMAND_INATR                 (0x50)
+#define PN532_COMMAND_INPSL                 (0x4E)
+#define PN532_COMMAND_INDATAEXCHANGE        (0x40)
+#define PN532_COMMAND_INCOMMUNICATETHRU     (0x42)
+#define PN532_COMMAND_INDESELECT            (0x44)
+#define PN532_COMMAND_INRELEASE             (0x52)
+#define PN532_COMMAND_INSELECT              (0x54)
+#define PN532_COMMAND_INAUTOPOLL            (0x60)
+#define PN532_COMMAND_TGINITASTARGET        (0x8C)
+#define PN532_COMMAND_TGSETGENERALBYTES     (0x92)
+#define PN532_COMMAND_TGGETDATA             (0x86)
+#define PN532_COMMAND_TGSETDATA             (0x8E)
+#define PN532_COMMAND_TGSETMETADATA         (0x94)
+#define PN532_COMMAND_TGGETINITIATORCOMMAND (0x88)
+#define PN532_COMMAND_TGRESPONSETOINITIATOR (0x90)
+#define PN532_COMMAND_TGGETTARGETSTATUS     (0x8A)
+
+#define PN532_RESPONSE_INDATAEXCHANGE       (0x41)
+#define PN532_RESPONSE_INLISTPASSIVETARGET  (0x4B)
+
+#define PN532_WAKEUP                        (0x55)
+
+#define PN532_SPI_STATREAD                  (0x02)
+#define PN532_SPI_DATAWRITE                 (0x01)
+#define PN532_SPI_DATAREAD                  (0x03)
+#define PN532_SPI_READY                     (0x01)
+
+#define PN532_I2C_ADDRESS                   (0x48 >> 1)
+#define PN532_I2C_READBIT                   (0x01)
+#define PN532_I2C_BUSY                      (0x00)
+#define PN532_I2C_READY                     (0x01)
+#define PN532_I2C_READYTIMEOUT              (20)
+
+#define PN532_MIFARE_ISO14443A              (0x00)
+
+// Mifare Commands
+#define MIFARE_CMD_AUTH_A                   (0x60)
+#define MIFARE_CMD_AUTH_B                   (0x61)
+#define MIFARE_CMD_READ                     (0x30)
+#define MIFARE_CMD_WRITE                    (0xA0)
+#define MIFARE_CMD_TRANSFER                 (0xB0)
+#define MIFARE_CMD_DECREMENT                (0xC0)
+#define MIFARE_CMD_INCREMENT                (0xC1)
+#define MIFARE_CMD_STORE                    (0xC2)
+#define MIFARE_ULTRALIGHT_CMD_WRITE         (0xA2)
+
+#define MIFARE_UID_MAX_LENGTH               MIFARE_UID_TRIPLE_LENGTH
+#define MIFARE_UID_SINGLE_LENGTH            (4)
+#define MIFARE_UID_DOUBLE_LENGTH            (7)
+#define MIFARE_UID_TRIPLE_LENGTH            (10)
+#define MIFARE_KEY_LENGTH                   (6)
+#define MIFARE_BLOCK_LENGTH                 (16)
+
+// NTAG2xx Commands
+#define NTAG2XX_BLOCK_LENGTH                (4)
+
+// Prefixes for NDEF Records (to identify record type)
+#define NDEF_URIPREFIX_NONE                 (0x00)
+#define NDEF_URIPREFIX_HTTP_WWWDOT          (0x01)
+#define NDEF_URIPREFIX_HTTPS_WWWDOT         (0x02)
+#define NDEF_URIPREFIX_HTTP                 (0x03)
+#define NDEF_URIPREFIX_HTTPS                (0x04)
+#define NDEF_URIPREFIX_TEL                  (0x05)
+#define NDEF_URIPREFIX_MAILTO               (0x06)
+#define NDEF_URIPREFIX_FTP_ANONAT           (0x07)
+#define NDEF_URIPREFIX_FTP_FTPDOT           (0x08)
+#define NDEF_URIPREFIX_FTPS                 (0x09)
+#define NDEF_URIPREFIX_SFTP                 (0x0A)
+#define NDEF_URIPREFIX_SMB                  (0x0B)
+#define NDEF_URIPREFIX_NFS                  (0x0C)
+#define NDEF_URIPREFIX_FTP                  (0x0D)
+#define NDEF_URIPREFIX_DAV                  (0x0E)
+#define NDEF_URIPREFIX_NEWS                 (0x0F)
+#define NDEF_URIPREFIX_TELNET               (0x10)
+#define NDEF_URIPREFIX_IMAP                 (0x11)
+#define NDEF_URIPREFIX_RTSP                 (0x12)
+#define NDEF_URIPREFIX_URN                  (0x13)
+#define NDEF_URIPREFIX_POP                  (0x14)
+#define NDEF_URIPREFIX_SIP                  (0x15)
+#define NDEF_URIPREFIX_SIPS                 (0x16)
+#define NDEF_URIPREFIX_TFTP                 (0x17)
+#define NDEF_URIPREFIX_BTSPP                (0x18)
+#define NDEF_URIPREFIX_BTL2CAP              (0x19)
+#define NDEF_URIPREFIX_BTGOEP               (0x1A)
+#define NDEF_URIPREFIX_TCPOBEX              (0x1B)
+#define NDEF_URIPREFIX_IRDAOBEX             (0x1C)
+#define NDEF_URIPREFIX_FILE                 (0x1D)
+#define NDEF_URIPREFIX_URN_EPC_ID           (0x1E)
+#define NDEF_URIPREFIX_URN_EPC_TAG          (0x1F)
+#define NDEF_URIPREFIX_URN_EPC_PAT          (0x20)
+#define NDEF_URIPREFIX_URN_EPC_RAW          (0x21)
+#define NDEF_URIPREFIX_URN_EPC              (0x22)
+#define NDEF_URIPREFIX_URN_NFC              (0x23)
+
+#define PN532_GPIO_VALIDATIONBIT            (0x80)
+
+/* Official PN532 Errors Definitions */
+#define PN532_ERROR_NONE                                                (0x00)
+// Time Out, the target has not answered
+#define PN532_ERROR_TIMEOUT                                             (0x01)
+// A CRC error has been detected by the CIU
+#define PN532_ERROR_CRC                                                 (0x02)
+// A Parity error has been detected by the CIU
+#define PN532_ERROR_PARITY                                              (0x03)
+// During an anti-collision/select operation (ISO/IEC14443-3 Type A and
+// ISO/IEC18092 106 kbps passive mode), an erroneous Bit Count has been
+// detected
+#define PN532_ERROR_COLLISION_BITCOUNT                                  (0x04)
+// Framing error during MIFARE operation
+#define PN532_ERROR_MIFARE_FRAMING                                      (0x05)
+// An abnormal bit-collision has been detected during bit wise
+// anti-collision at 106 kbps
+#define PN532_ERROR_COLLISION_BITCOLLISION                              (0x06)
+// Communication buffer size insufficien
+#define PN532_ERROR_NOBUFS                                              (0x07)
+// RF Buffer overflow has been detected by the CI
+#define PN532_ERROR_RFNOBUFS                                            (0x09)
+// In active communication mode, the RF field has not been switched on
+// in time by the counterpart (as defined in NFCIP-1 standard
+#define PN532_ERROR_ACTIVE_TOOSLOW                                      (0x0a)
+// RF Protocol error
+#define PN532_ERROR_RFPROTO                                             (0x0b)
+// Temperature error: the internal temperature sensor has detected
+// overheating, and therefore has automatically switched off the
+// antenna drivers
+#define PN532_ERROR_TOOHOT                                              (0x0d)
+// Internal buffer overflow
+#define PN532_ERROR_INTERNAL_NOBUFS                                     (0x0e)
+// Invalid parameter (range, format...)
+#define PN532_ERROR_INVAL                                               (0x10)
+// DEP Protocol: The PN533 configured in target mode does not support
+// the command received from the initiator (the command received is not
+// one of the following: ATR_REQ, WUP_REQ, PSL_REQ, DEP_REQ, DSL_REQ,
+// RLS_REQ)
+#define PN532_ERROR_DEP_INVALID_COMMAND                                 (0x12)
+// DEP Protocol, MIFARE or ISO/IEC14443-4: The data format does not
+// match to the specification.  Depending on the RF protocol used, it
+// can be: Bad length of RF received frame, Incorrect value of PCB or
+// PFB, Invalid or unexpected RF received frame, NAD or DID incoherence.
+#define PN532_ERROR_DEP_BADDATA                                         (0x13)
+// MIFARE: Authentication error
+#define PN532_ERROR_MIFARE_AUTH                                         (0x14)
+// Target or Initiator does not support NFC Secur
+#define PN532_ERROR_NOSECURE                                            (0x18)
+// I2C bus line is Busy. A TDA transaction is on going
+#define PN532_ERROR_I2CBUSY                                             (0x19)
+// ISO/IEC14443-3: UID Check byte is wrong
+#define PN532_ERROR_UIDCHECKSUM                                         (0x23)
+// DEP Protocol: Invalid device state, the system is in a state which
+// does not allow the operation
+#define PN532_ERROR_DEPSTATE                                            (0x25)
+// Operation not allowed in this configuration (host controller
+// interface)
+#define PN532_ERROR_HCIINVAL                                            (0x26)
+// This command is not acceptable due to the current context of the
+// PN533 (Initiator vs. Target, unknown target number, Target not in the
+// good state, ...)
+#define PN532_ERROR_CONTEXT                                             (0x27)
+// The PN533 configured as target has been released by its initiator
+#define PN532_ERROR_RELEASED                                            (0x29)
+// PN533 and ISO/IEC14443-3B only: the ID of the card does not match,
+// meaning that the expected card has been exchanged with another one.
+#define PN532_ERROR_CARDSWAPPED                                         (0x2a)
+// PN533 and ISO/IEC14443-3B only: the card previously activated has
+// disappeared.
+#define PN532_ERROR_NOCARD                                              (0x2b)
+// Mismatch between the NFCID3 initiator and the NFCID3 target in DEP
+// 212/424 kbps passive.
+#define PN532_ERROR_MISMATCH                                            (0x2c)
+// An over-current event has been detected
+#define PN532_ERROR_OVERCURRENT                                         (0x2d)
+// NAD missing in DEP frame
+#define PN532_ERROR_NONAD                                               (0x2e)
+/* End: Official PN532 Errors Definitions */
+
+// Other Error Definitions
+#define PN532_STATUS_ERROR                                              (-1)
+#define PN532_STATUS_OK                                                 (0)
+
+typedef struct _PN532 {
+    int (*reset)(void);
+    int (*read_data)(uint8_t* data, uint16_t count);
+    int (*write_data)(uint8_t *data, uint16_t count);
+    bool (*wait_ready)(uint32_t timeout);
+    int (*wakeup)(void);
+    void (*log)(const char* log);
+} PN532;
+
+
+int PN532_WriteFrame(PN532* pn532, uint8_t* data, uint16_t length);
+int PN532_ReadFrame(PN532* pn532, uint8_t* buff, uint16_t length);
+int PN532_CallFunction(PN532* pn532, uint8_t command, uint8_t* response, uint16_t response_length, uint8_t* params, uint16_t params_length, uint32_t timeout);
+int PN532_GetFirmwareVersion(PN532* pn532, uint8_t* version);
+int PN532_SamConfiguration(PN532* pn532);
+int PN532_ReadPassiveTarget(PN532* pn532, uint8_t* response, uint8_t card_baud, uint32_t timeout);
+int PN532_MifareClassicAuthenticateBlock(PN532* pn532, uint8_t* uid, uint8_t uid_length, uint16_t block_number, uint16_t key_number, uint8_t* key);
+int PN532_MifareClassicReadBlock(PN532* pn532, uint8_t* response, uint16_t block_number);
+int PN532_MifareClassicWriteBlock(PN532* pn532, uint8_t* data, uint16_t block_number);
+int PN532_Ntag2xxReadBlock(PN532* pn532, uint8_t* response, uint16_t block_number);
+int PN532_Ntag2xxWriteBlock(PN532* pn532, uint8_t* data, uint16_t block_number);
+int PN532_ReadGpio(PN532* pn532, uint8_t* pins_state);
+bool PN532_ReadGpioP(PN532* pn532, uint8_t pin_number);
+bool PN532_ReadGpioI(PN532* pn532, uint8_t pin_number);
+int PN532_WriteGpio(PN532* pn532, uint8_t* pins_state);
+int PN532_WriteGpioP(PN532* pn532, uint8_t pin_number, bool pin_state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* PN532_H */
+
+/* End of file */

+ 48 - 0
app/A08_NFC/include/pn532_hi3861.h

@@ -0,0 +1,48 @@
+/**************************************************************************
+ *  @file     pn532_stm32f1.h
+ *  @author   Yehui from Waveshare
+ *  @license  BSD
+ *  
+ *  Header file for pn532_stm32f1.c
+ *  
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documnetation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to  whom the Software is
+ * furished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ **************************************************************************/
+
+#ifndef PN532_STM32F1
+#define PN532_STM32F1
+
+#include "pn532.h"
+
+void PN532_Init(PN532* dev);
+int PN532_Reset(void);
+void PN532_Log(const char* log);
+
+int PN532_SPI_ReadData(uint8_t* data, uint16_t count);
+int PN532_SPI_WriteData(uint8_t *data, uint16_t count);
+bool PN532_SPI_WaitReady(uint32_t timeout);
+int PN532_SPI_Wakeup(void);
+void PN532_SPI_Init(PN532* dev);
+
+int PN532_I2C_ReadData(uint8_t* data, uint16_t count);
+int PN532_I2C_WriteData(uint8_t *data, uint16_t count);
+bool PN532_I2C_WaitReady(uint32_t timeout);
+int PN532_I2C_Wakeup(void);
+void PN532_I2C_Init(PN532* dev);
+
+#endif  /* PN532_STM32F1 */

+ 381 - 0
app/A08_NFC/src/MPU6050.c

@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MPU6050.h"
+#include "cmsis_os2.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+#include "iot_i2c.h"
+#include "iot_i2c_ex.h"
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA 6
+#define WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL 6
+#define WIFI_IOT_IO_FUNC_GPIO_8_GPIO 0
+#define WIFI_IOT_IO_FUNC_GPIO_7_GPIO 0
+#define WIFI_IOT_I2C_IDX_1 1
+#define WIFI_IOT_IO_NAME_GPIO_7 7
+#define WIFI_IOT_IO_NAME_GPIO_8 8
+#define WIFI_IOT_IO_NAME_GPIO_0 0
+#define WIFI_IOT_IO_NAME_GPIO_1 1
+#define RESET_DELAY_US 20000
+#define READ_DATA_DELAY_US 50000
+
+/***************************************************************
+ * 函数名称: GpioInit
+ * 说    明:  GPIO初始化
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+static void GpioInit(void)
+{
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_8);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_GPIO);
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_DIR_OUT); // 设置GPIO_8为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_7);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_7, WIFI_IOT_IO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_7, IOT_GPIO_DIR_OUT); // 设置GPIO_7为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_0);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA); // GPIO_0复用为I2C1_SDA
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_1);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL); // GPIO_1复用为I2C1_SCL
+    IoTI2cInit(WIFI_IOT_I2C_IDX_1, 400000);              /* baudrate: 400kbps */
+}
+/***************************************************************
+ * 函数功能: 通过I2C写入一个值到指定寄存器内
+ * 输入参数: Addr:I2C设备地址
+ *           Reg:目标寄存器
+ *           Value:值
+ * 返 回 值: 无
+ * 说    明: 无
+ **************************************************************/
+static int MPU6050WriteData(uint8_t Reg, uint8_t Value)
+{
+    uint32_t ret;
+    uint8_t send_data[2] = {Reg, Value};
+    ret = IoTI2cWrite(WIFI_IOT_I2C_IDX_1, (MPU6050_SLAVE_ADDRESS << 1) | 0x00, send_data, 2);
+    if (ret != 0) {
+        printf("===== Error: I2C write ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    return 0;
+}
+/***************************************************************
+ * 函数功能: 通过I2C写入一段数据到指定寄存器内
+ * 输入参数: Addr:I2C设备地址
+ *           Reg:目标寄存器
+ *           RegSize:寄存器尺寸(8位或者16位)
+ *           pBuffer:缓冲区指针
+ *           Length:缓冲区长度
+ * 返 回 值: HAL_StatusTypeDef:操作结果
+ * 说    明: 在循环调用是需加一定延时时间
+ **************************************************************/
+static int MPU6050WriteBuffer(uint8_t Reg, uint8_t* pBuffer, uint16_t Length)
+{
+    uint32_t ret = 0;
+    uint8_t send_data[256] = {0};
+
+    send_data[0] = Reg;
+    for (int j = 0; j < Length; j++) {
+        send_data[j + 1] = pBuffer[j];
+    }
+
+    ret = IoTI2cWrite(WIFI_IOT_I2C_IDX_1, (MPU6050_SLAVE_ADDRESS << 1) | 0x00, send_data, Length + 1);
+    if (ret != 0) {
+        printf("===== Error: I2C write ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    return 0;
+}
+
+/***************************************************************
+ * 函数功能: 通过I2C读取一段寄存器内容存放到指定的缓冲区内
+ * 输入参数: Addr:I2C设备地址
+ *           Reg:目标寄存器
+ *           RegSize:寄存器尺寸(8位或者16位)
+ *           pBuffer:缓冲区指针
+ *           Length:缓冲区长度
+ * 返 回 值: HAL_StatusTypeDef:操作结果
+ * 说    明: 无
+ **************************************************************/
+static int MPU6050ReadBuffer(uint8_t Reg, uint8_t* pBuffer, uint16_t Length)
+{
+    uint32_t ret = 0;
+    IotI2cData mpu6050_i2c_data = {0};
+    uint8_t buffer[1] = {Reg};
+    mpu6050_i2c_data.sendBuf = buffer;
+    mpu6050_i2c_data.sendLen = 1;
+    mpu6050_i2c_data.receiveBuf = pBuffer;
+    mpu6050_i2c_data.receiveLen = Length;
+    ret = IoTI2cWriteread(WIFI_IOT_I2C_IDX_1, (MPU6050_SLAVE_ADDRESS << 1) | 0x00, &mpu6050_i2c_data);
+    if (ret != 0) {
+        printf("===== Error: I2C writeread ret = 0x%x! =====\r\n", ret);
+        return -1;
+    }
+    return 0;
+}
+/***************************************************************
+ * 函数功能: 写数据到MPU6050寄存器
+ * 输入参数: 无
+ * 返 回 值: 无
+ * 说    明: 无
+ ***************************************************************/
+static void MPU6050WriteReg(uint8_t reg_add, uint8_t reg_dat)
+{
+    MPU6050WriteData(reg_add, reg_dat);
+}
+
+/***************************************************************
+ * 函数功能: 从MPU6050寄存器读取数据
+ * 输入参数: 无
+ * 返 回 值: 无
+ * 说    明: 无
+ ***************************************************************/
+static int MPU6050Read(uint8_t reg_add, unsigned char* read, uint8_t num)
+{
+    return MPU6050ReadBuffer(reg_add, read, num);
+}
+
+/***************************************************************
+ * 函数功能: 读取MPU6050的加速度数据
+ * 输入参数: 无
+ * 返 回 值: 无
+ * 说    明: 无
+ ***************************************************************/
+static int MPU6050ReadAcc(short* accData)
+{
+    int ret;
+    uint8_t buf[ACCEL_DATA_LEN];
+    ret = MPU6050Read(MPU6050_ACC_OUT, buf, ACCEL_DATA_LEN);
+    if (ret != 0) {
+        return -1;
+    }
+    accData[ACCEL_X_AXIS] = (buf[ACCEL_X_AXIS_LSB] << SENSOR_DATA_WIDTH_8_BIT) | buf[ACCEL_X_AXIS_MSB];
+    accData[ACCEL_Y_AXIS] = (buf[ACCEL_Y_AXIS_LSB] << SENSOR_DATA_WIDTH_8_BIT) | buf[ACCEL_Y_AXIS_MSB];
+    accData[ACCEL_Z_AXIS] = (buf[ACCEL_Z_AXIS_LSB] << SENSOR_DATA_WIDTH_8_BIT) | buf[ACCEL_Z_AXIS_MSB];
+    return 0;
+}
+
+/***************************************************************
+ * 函数功能: 读取MPU6050的角速度数据
+ * 输入参数: 无
+ * 返 回 值: 无
+ * 说    明: 无
+ ***************************************************************/
+static int MPU6050ReadGyro(short* gyroData)
+{
+    int ret;
+    uint8_t buf[ACCEL_DATA_LEN];
+    ret = MPU6050Read(MPU6050_GYRO_OUT, buf, ACCEL_DATA_LEN);
+    if (ret != 0) {
+        return -1;
+    }
+    gyroData[ACCEL_X_AXIS] = (buf[ACCEL_X_AXIS_LSB] << SENSOR_DATA_WIDTH_8_BIT) | buf[ACCEL_X_AXIS_MSB];
+    gyroData[ACCEL_Y_AXIS] = (buf[ACCEL_Y_AXIS_LSB] << SENSOR_DATA_WIDTH_8_BIT) | buf[ACCEL_Y_AXIS_MSB];
+    gyroData[ACCEL_Z_AXIS] = (buf[ACCEL_Z_AXIS_LSB] << SENSOR_DATA_WIDTH_8_BIT) | buf[ACCEL_Z_AXIS_MSB];
+    return 0;
+}
+
+/***************************************************************
+ * 函数功能: 读取MPU6050的原始温度数据
+ * 输入参数: 无
+ * 返 回 值: 无
+ * 说    明: 无
+ ***************************************************************/
+static int MPU6050ReadTemp(short* tempData)
+{
+    int ret;
+    uint8_t buf[TEMP_DATA_LEN];
+    ret = MPU6050Read(MPU6050_RA_TEMP_OUT_H, buf, TEMP_DATA_LEN); // 读取温度值
+    if (ret != 0) {
+        return -1;
+    }
+    *tempData = (buf[TEMP_LSB] << SENSOR_DATA_WIDTH_8_BIT) | buf[TEMP_MSB];
+    return 0;
+}
+
+/***************************************************************
+ * 函数功能: 读取MPU6050的温度数据,转化成摄氏度
+ * 输入参数: 无
+ * 返 回 值: 无
+ * 说    明: 无
+ **************************************************************/
+static int MPU6050ReturnTemp(short* Temperature)
+{
+    int ret;
+    short temp3;
+    uint8_t buf[TEMP_DATA_LEN];
+
+    ret = MPU6050Read(MPU6050_RA_TEMP_OUT_H, buf, TEMP_DATA_LEN); // 读取温度值
+    if (ret != 0) {
+        return -1;
+    }
+    temp3 = (buf[TEMP_LSB] << SENSOR_DATA_WIDTH_8_BIT) | buf[TEMP_MSB];
+    *Temperature = (((double)(temp3 + 13200)) / 280) - 13;
+    return 0;
+}
+
+/***************************************************************
+ * 函数功能: 自由落体中断
+ * 输入参数: 无
+ * 返 回 值: 无
+ * 说    明: 无
+ **************************************************************/
+void FreeFallInterrupt(void) // 自由落体中断
+{
+    MPU6050WriteReg(MPU6050_RA_FF_THR, 0x01); // 自由落体阈值
+    MPU6050WriteReg(MPU6050_RA_FF_DUR, 0x01); // 自由落体检测时间20ms 单位1ms 寄存器0X20
+}
+void MotionInterrupt(void) // 运动中断
+{
+    MPU6050WriteReg(MPU6050_RA_MOT_THR, 0x03); // 运动阈值
+    MPU6050WriteReg(MPU6050_RA_MOT_DUR, 0x14); // 检测时间20ms 单位1ms 寄存器0X20
+}
+void ZeroMotionInterrupt(void) // 静止中断
+{
+    MPU6050WriteReg(MPU6050_RA_ZRMOT_THR, 0x20); // 静止阈值
+    MPU6050WriteReg(MPU6050_RA_ZRMOT_DUR, 0x20); // 静止检测时间20ms 单位1ms 寄存器0X20
+}
+
+/***************************************************************
+ * 函数功能: 初始化MPU6050芯片
+ * 输入参数: 无
+ * 返 回 值: 无
+ * 说    明: 无
+ ***************************************************************/
+void MPU6050Init(void)
+{
+    MPU6050WriteReg(MPU6050_RA_PWR_MGMT_1, 0X80); // 复位MPU6050
+    usleep(RESET_DELAY_US);
+    MPU6050WriteReg(MPU6050_RA_PWR_MGMT_1, 0X00); // 唤醒MPU6050
+    MPU6050WriteReg(MPU6050_RA_INT_ENABLE, 0X00); // 关闭所有中断
+    MPU6050WriteReg(MPU6050_RA_USER_CTRL, 0X00);  // I2C主模式关闭
+    MPU6050WriteReg(MPU6050_RA_FIFO_EN, 0X00);    // 关闭FIFO
+    MPU6050WriteReg(MPU6050_RA_INT_PIN_CFG,
+                    0X80); // 中断的逻辑电平模式,设置为0,中断信号为高电;设置为1,中断信号为低电平时。
+    MotionInterrupt();                              // 运动中断
+    MPU6050WriteReg(MPU6050_RA_CONFIG, 0x04);       // 配置外部引脚采样和DLPF数字低通滤波器
+    MPU6050WriteReg(MPU6050_RA_ACCEL_CONFIG, 0x1C); // 加速度传感器量程和高通滤波器配置
+    MPU6050WriteReg(MPU6050_RA_INT_PIN_CFG, 0X1C);  // INT引脚低电平平时
+    MPU6050WriteReg(MPU6050_RA_INT_ENABLE, 0x40);   // 中断使能寄存器
+}
+
+/***************************************************************
+ * 函数功能: 读取MPU6050的ID
+ * 输入参数: 无
+ * 返 回 值: 无
+ * 说    明: 无
+ ***************************************************************/
+int MPU6050ReadID(void)
+{
+    unsigned char Re = 0;
+    MPU6050Read(MPU6050_RA_WHO_AM_I, &Re, 1); // 读器件地址
+    if (Re != 0x68) {
+        printf("MPU6050 dectected error!\r\n");
+        return -1;
+    } else {
+        return 0;
+    }
+}
+/***************************************************************
+ * 函数名称: BoardInit
+ * 说    明: 初始化扩展板
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+int BoardInit(void)
+{
+    uint32_t ret = 0;
+    GpioInit();
+    MPU6050Init();
+    ret = MPU6050ReadID();
+    if (ret != 0) {
+        return -1;
+    }
+    osDelay(100);
+    return 0;
+}
+/***************************************************************
+ * 函数名称: MPU6050ReadData
+ * 说    明: 读取数据
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+int MPU6050ReadData(MPU6050Data* ReadData)
+{
+    int ret;
+    short Accel[3];
+    short Temp;
+    if (MPU6050ReadID() != 0) {
+        return -1;
+    }
+    ret = MPU6050ReadAcc(Accel);
+    if (ret != 0) {
+        return -1;
+    }
+
+    ret = MPU6050ReturnTemp(&Temp);
+    if (ret != 0) {
+        return -1;
+    }
+    ReadData->Temperature = Temp;
+    ReadData->Accel[ACCEL_X_AXIS] = Accel[ACCEL_X_AXIS];
+    ReadData->Accel[ACCEL_Y_AXIS] = Accel[ACCEL_Y_AXIS];
+    ReadData->Accel[ACCEL_Z_AXIS] = Accel[ACCEL_Z_AXIS];
+    usleep(READ_DATA_DELAY_US);
+    return 0;
+}
+/***************************************************************
+ * 函数名称: LedD1StatusSet
+ * 说    明: LED_D1状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedD1StatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(7, 1); // 设置GPIO_7输出高电平点亮灯
+    }
+    if (status == OFF) {
+        IoTGpioSetOutputVal(7, 0); // 设置GPIO_7输出低电平关闭灯
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedD2StatusSet
+ * 说    明: LED_D2状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedD2StatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(8, 1); // 设置GPIO_8输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(8, 0); // 设置GPIO_8输出低电平关闭灯
+    }
+}

+ 498 - 0
app/A08_NFC/src/pn532.c

@@ -0,0 +1,498 @@
+/**************************************************************************
+ *  @file     pn532.c
+ *  @author   Yehui from Waveshare
+ *  @license  BSD
+ *  
+ *  This is a library for the Waveshare PN532 NFC modules
+ *  
+ *  Check out the links above for our tutorials and wiring diagrams 
+ *  These chips use SPI communicate.
+ *  
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documnetation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to  whom the Software is
+ * furished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ **************************************************************************/
+
+#include <stdio.h>
+#include "pn532.h"
+
+const uint8_t PN532_ACK[] = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00};
+const uint8_t PN532_FRAME_START[] = {0x00, 0x00, 0xFF};
+
+#define PN532_FRAME_MAX_LENGTH              255
+#define PN532_DEFAULT_TIMEOUT               1000
+
+/**
+  * @brief: Write a frame to the PN532 of at most length bytes in size.
+  *     Note that less than length bytes might be returned!
+  * @retval: Returns -1 if there is an error parsing the frame.  
+  */
+int PN532_WriteFrame(PN532* pn532, uint8_t* data, uint16_t length) {
+    if (length > PN532_FRAME_MAX_LENGTH || length < 1) {
+        return PN532_STATUS_ERROR; // Data must be array of 1 to 255 bytes.
+    }
+    // Build frame to send as:
+    // - Preamble (0x00)
+    // - Start code  (0x00, 0xFF)
+    // - Command length (1 byte)
+    // - Command length checksum
+    // - Command bytes
+    // - Checksum
+    // - Postamble (0x00)
+
+    uint8_t frame[PN532_FRAME_MAX_LENGTH + 7];
+    uint8_t checksum = 0;
+    frame[0] = PN532_PREAMBLE;
+    frame[1] = PN532_STARTCODE1;
+    frame[2] = PN532_STARTCODE2;
+    for (uint8_t i = 0; i < 3; i++) {
+        checksum += frame[i];
+    }
+    frame[3] = length & 0xFF;
+    frame[4] = (~length + 1) & 0xFF;
+    for (uint8_t i = 0; i < length; i++) {
+        frame[5 + i] = data[i];
+        checksum += data[i];
+    }
+    frame[length + 5] = ~checksum & 0xFF;
+    frame[length + 6] = PN532_POSTAMBLE;
+    if (pn532->write_data(frame, length + 7) != PN532_STATUS_OK) {
+        return PN532_STATUS_ERROR;
+    }
+    return PN532_STATUS_OK;
+}
+
+/**
+  * @brief: Read a response frame from the PN532 of at most length bytes in size.
+  *     Note that less than length bytes might be returned!
+  * @retval: Returns frame length or -1 if there is an error parsing the frame.  
+  */
+int PN532_ReadFrame(PN532* pn532, uint8_t* response, uint16_t length) {
+    uint8_t buff[PN532_FRAME_MAX_LENGTH + 7];
+    uint8_t checksum = 0;
+    // Read frame with expected length of data.
+    pn532->read_data(buff, length + 7);
+    // Swallow all the 0x00 values that preceed 0xFF.
+    uint8_t offset = 0;
+    while (buff[offset] == 0x00) {
+        offset += 1;
+        if (offset >= length + 8){
+            pn532->log("Response frame preamble does not contain 0x00FF!");
+            return PN532_STATUS_ERROR;
+        }
+    }
+    if (buff[offset] != 0xFF) {
+        pn532->log("Response frame preamble does not contain 0x00FF!");
+        return PN532_STATUS_ERROR;
+    }
+    offset += 1;
+    if (offset >= length + 8) {
+        pn532->log("Response contains no data!");
+        return PN532_STATUS_ERROR;
+    }
+    // Check length & length checksum match.
+    uint8_t frame_len = buff[offset];
+    if (((frame_len + buff[offset+1]) & 0xFF) != 0) {
+        pn532->log("Response length checksum did not match length!");
+        return PN532_STATUS_ERROR;
+    }
+    // Check frame checksum value matches bytes.
+    for (uint8_t i = 0; i < frame_len + 1; i++) {
+        checksum += buff[offset + 2 + i];
+    }
+    checksum &= 0xFF;
+    if (checksum != 0) {
+        pn532->log("Response checksum did not match expected checksum");
+        return PN532_STATUS_ERROR;
+    }
+    // Return frame data.
+    for (uint8_t i = 0; i < frame_len; i++) {
+        response[i] = buff[offset + 2 + i];
+    }
+    return frame_len;
+}
+
+/**
+  * @brief: Send specified command to the PN532 and expect up to response_length.
+  *     Will wait up to timeout seconds for a response and read a bytearray into
+  *     response buffer.
+  * @param pn532: PN532 handler
+  * @param command: command to send
+  * @param response: buffer returned
+  * @param response_length: expected response length
+  * @param params: can optionally specify an array of bytes to send as parameters
+  *     to the function call, or NULL if there is no need to send parameters.
+  * @param params_length: length of the argument params
+  * @param timeout: timout of systick
+  * @retval: Returns the length of response or -1 if error.
+  */
+int PN532_CallFunction(
+    PN532* pn532,
+    uint8_t command,
+    uint8_t* response,
+    uint16_t response_length,
+    uint8_t* params,
+    uint16_t params_length,
+    uint32_t timeout
+) {
+    // Build frame data with command and parameters.
+    uint8_t buff[PN532_FRAME_MAX_LENGTH];
+    buff[0] = PN532_HOSTTOPN532;
+    buff[1] = command & 0xFF;
+    for (uint8_t i = 0; i < params_length; i++) {
+        buff[2 + i] = params[i];
+    }
+    // Send frame and wait for response.
+    if (PN532_WriteFrame(pn532, buff, params_length + 2) != PN532_STATUS_OK) {
+        pn532->wakeup();
+        pn532->log("Trying to wakeup");
+        return PN532_STATUS_ERROR;
+    }
+    if (!pn532->wait_ready(timeout)) {
+        return PN532_STATUS_ERROR;
+    }
+    // Verify ACK response and wait to be ready for function response.
+    pn532->read_data(buff, sizeof(PN532_ACK));
+    for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) {
+        if (PN532_ACK[i] != buff[i]) {
+            pn532->log("Did not receive expected ACK from PN532!");
+            return PN532_STATUS_ERROR;
+        }
+    }
+    if (!pn532->wait_ready(timeout)) {
+        return PN532_STATUS_ERROR;
+    }
+    // Read response bytes.
+    int frame_len = PN532_ReadFrame(pn532, buff, response_length + 2);
+
+    // Check that response is for the called function.
+    if (! ((buff[0] == PN532_PN532TOHOST) && (buff[1] == (command+1)))) {
+        pn532->log("Received unexpected command response!");
+        return PN532_STATUS_ERROR;
+    }
+    // Return response data.
+    for (uint8_t i = 0; i < response_length; i++) {
+        response[i] = buff[i + 2];
+    }
+    // The the number of bytes read
+    return frame_len - 2;
+}
+
+/**
+  * @brief: Call PN532 GetFirmwareVersion function and return a buff with the IC,
+  *  Ver, Rev, and Support values.
+  */
+int PN532_GetFirmwareVersion(PN532* pn532, uint8_t* version) {
+    // length of version: 4
+    if (PN532_CallFunction(pn532, PN532_COMMAND_GETFIRMWAREVERSION,
+                           version, 4, NULL, 0, 500) == PN532_STATUS_ERROR) {
+        pn532->log("Failed to detect the PN532");
+        return PN532_STATUS_ERROR;
+    }
+    return PN532_STATUS_OK;
+}
+
+/**
+  * @brief: Configure the PN532 to read MiFare cards.
+  */
+int PN532_SamConfiguration(PN532* pn532) {
+    // Send SAM configuration command with configuration for:
+    // - 0x01, normal mode
+    // - 0x14, timeout 50ms * 20 = 1 second
+    // - 0x01, use IRQ pin
+    // Note that no other verification is necessary as call_function will
+    // check the command was executed as expected.
+    uint8_t params[] = {0x01, 0x14, 0x01};
+    PN532_CallFunction(pn532, PN532_COMMAND_SAMCONFIGURATION,
+                       NULL, 0, params, sizeof(params), PN532_DEFAULT_TIMEOUT);
+    return PN532_STATUS_OK;
+}
+
+/**
+  * @brief: Wait for a MiFare card to be available and return its UID when found.
+  *     Will wait up to timeout seconds and return None if no card is found,
+  *     otherwise a bytearray with the UID of the found card is returned.
+  * @retval: Length of UID, or -1 if error.
+  */
+int PN532_ReadPassiveTarget(
+    PN532* pn532,
+    uint8_t* response,
+    uint8_t card_baud,
+    uint32_t timeout
+) {
+    // Send passive read command for 1 card.  Expect at most a 7 byte UUID.
+    uint8_t params[] = {0x01, card_baud};
+    uint8_t buff[19];
+    int length = PN532_CallFunction(pn532, PN532_COMMAND_INLISTPASSIVETARGET,
+                        buff, sizeof(buff), params, sizeof(params), timeout);
+    if (length < 0) {
+        return PN532_STATUS_ERROR; // No card found
+    }
+    // Check only 1 card with up to a 7 byte UID is present.
+    if (buff[0] != 0x01) {
+        pn532->log("More than one card detected!");
+        return PN532_STATUS_ERROR;
+    }
+    if (buff[5] > 7) {
+        pn532->log("Found card with unexpectedly long UID!");
+        return PN532_STATUS_ERROR;
+    }
+    for (uint8_t i = 0; i < buff[5]; i++) {
+        response[i] = buff[6 + i];
+    }
+    return buff[5];
+}
+
+/**
+  * @brief: Authenticate specified block number for a MiFare classic card.
+  * @param uid: A byte array with the UID of the card.
+  * @param uid_length: Length of the UID of the card.
+  * @param block_number: The block to authenticate.
+  * @param key_number: The key type (like MIFARE_CMD_AUTH_A or MIFARE_CMD_AUTH_B).
+  * @param key: A byte array with the key data.
+  * @retval: true if the block was authenticated, or false if not authenticated.
+  * @retval: PN532 error code.
+  */
+int PN532_MifareClassicAuthenticateBlock(
+    PN532* pn532,
+    uint8_t* uid,
+    uint8_t uid_length,
+    uint16_t block_number,
+    uint16_t key_number,
+    uint8_t* key
+) {
+    // Build parameters for InDataExchange command to authenticate MiFare card.
+    uint8_t response[1] = {0xFF};
+    uint8_t params[3 + MIFARE_UID_MAX_LENGTH + MIFARE_KEY_LENGTH];
+    params[0] = 0x01;
+    params[1] = key_number & 0xFF;
+    params[2] = block_number & 0xFF;
+    // params[3:3+keylen] = key
+    for (uint8_t i = 0; i < MIFARE_KEY_LENGTH; i++) {
+        params[3 + i] = key[i];
+    }
+    // params[3+keylen:] = uid
+    for (uint8_t i = 0; i < uid_length; i++) {
+        params[3 + MIFARE_KEY_LENGTH + i] = uid[i];
+    }
+    // Send InDataExchange request
+    PN532_CallFunction(pn532, PN532_COMMAND_INDATAEXCHANGE, response, sizeof(response),
+                       params, 3 + MIFARE_KEY_LENGTH + uid_length, PN532_DEFAULT_TIMEOUT);
+    return response[0];
+}
+
+/**
+  * @brief: Read a block of data from the card. Block number should be the block
+  *     to read.
+  * @param response: buffer of length 16 returned if the block is successfully read.
+  * @param block_number: specify a block to read.
+  * @retval: PN532 error code.
+  */
+int PN532_MifareClassicReadBlock(PN532* pn532, uint8_t* response, uint16_t block_number) {
+    uint8_t params[] = {0x01, MIFARE_CMD_READ, block_number & 0xFF};
+    uint8_t buff[MIFARE_BLOCK_LENGTH + 1];
+    // Send InDataExchange request to read block of MiFare data.
+    PN532_CallFunction(pn532, PN532_COMMAND_INDATAEXCHANGE, buff, sizeof(buff),
+                       params, sizeof(params), PN532_DEFAULT_TIMEOUT);
+    // Check first response is 0x00 to show success.
+    if (buff[0] != PN532_ERROR_NONE) {
+        return buff[0];
+    }
+    for (uint8_t i = 0; i < MIFARE_BLOCK_LENGTH; i++) {
+        response[i] = buff[i + 1];
+    }
+    return buff[0];
+}
+
+/**
+  * @brief: Write a block of data to the card.  Block number should be the block
+  *     to write and data should be a byte array of length 16 with the data to
+  *     write.
+  * @param data: data to write.
+  * @param block_number: specify a block to write.
+  * @retval: PN532 error code.
+  */
+int PN532_MifareClassicWriteBlock(PN532* pn532, uint8_t* data, uint16_t block_number) {
+    uint8_t params[MIFARE_BLOCK_LENGTH + 3];
+    uint8_t response[1];
+    params[0] = 0x01;  // Max card numbers
+    params[1] = MIFARE_CMD_WRITE;
+    params[2] = block_number & 0xFF;
+    for (uint8_t i = 0; i < MIFARE_BLOCK_LENGTH; i++) {
+        params[3 + i] = data[i];
+    }
+    PN532_CallFunction(pn532, PN532_COMMAND_INDATAEXCHANGE, response,
+                       sizeof(response), params, sizeof(params), PN532_DEFAULT_TIMEOUT);
+    return response[0];
+}
+
+/**
+  * @brief: Read a block of data from the card. Block number should be the block
+  *     to read.
+  * @param response: buffer of length 4 returned if the block is successfully read.
+  * @param block_number: specify a block to read.
+  * @retval: PN532 error code.
+  */
+int PN532_Ntag2xxReadBlock(PN532* pn532, uint8_t* response, uint16_t block_number) {
+    uint8_t params[] = {0x01, MIFARE_CMD_READ, block_number & 0xFF};
+    // The response length of NTAG2xx is same as Mifare's
+    uint8_t buff[MIFARE_BLOCK_LENGTH + 1];
+    // Send InDataExchange request to read block of MiFare data.
+    PN532_CallFunction(pn532, PN532_COMMAND_INDATAEXCHANGE, buff, sizeof(buff),
+                       params, sizeof(params), PN532_DEFAULT_TIMEOUT);
+    // Check first response is 0x00 to show success.
+    if (buff[0] != PN532_ERROR_NONE) {
+        return buff[0];
+    }
+    // Although the response length of NTAG2xx is same as Mifare's,
+    // only the first 4 bytes are available
+    for (uint8_t i = 0; i < NTAG2XX_BLOCK_LENGTH; i++) {
+        response[i] = buff[i + 1];
+    }
+    return buff[0];
+}
+
+/**
+  * @brief: Write a block of data to the card.  Block number should be the block
+  *     to write and data should be a byte array of length 4 with the data to
+  *     write.
+  * @param data: data to write.
+  * @param block_number: specify a block to write.
+  * @retval: PN532 error code.
+  */
+int PN532_Ntag2xxWriteBlock(PN532* pn532, uint8_t* data, uint16_t block_number) {
+    uint8_t params[NTAG2XX_BLOCK_LENGTH + 3];
+    uint8_t response[1];
+    params[0] = 0x01;  // Max card numbers
+    params[1] = MIFARE_ULTRALIGHT_CMD_WRITE;
+    params[2] = block_number & 0xFF;
+    for (uint8_t i = 0; i < NTAG2XX_BLOCK_LENGTH; i++) {
+        params[3 + i] = data[i];
+    }
+    PN532_CallFunction(pn532, PN532_COMMAND_INDATAEXCHANGE, response,
+                       sizeof(response), params, sizeof(params), PN532_DEFAULT_TIMEOUT);
+    return response[0];
+}
+
+/**
+  * @brief: Read the GPIO states.
+  * @param pin_state: pin state buffer (3 bytes) returned.
+  * returns 3 bytes containing the pin state where:
+  *     P3[0] = P30,   P7[0] = 0,   I[0] = I0,
+  *     P3[1] = P31,   P7[1] = P71, I[1] = I1,
+  *     P3[2] = P32,   P7[2] = P72, I[2] = 0,
+  *     P3[3] = P33,   P7[3] = 0,   I[3] = 0,
+  *     P3[4] = P34,   P7[4] = 0,   I[4] = 0,
+  *     P3[5] = P35,   P7[5] = 0,   I[5] = 0,
+  *     P3[6] = 0,     P7[6] = 0,   I[6] = 0,
+  *     P3[7] = 0,     P7[7] = 0,   I[7] = 0,
+  * @retval: -1 if error
+  */
+int PN532_ReadGpio(PN532* pn532, uint8_t* pins_state) {
+    return PN532_CallFunction(pn532, PN532_COMMAND_READGPIO, pins_state, 3,
+                              NULL, 0, PN532_DEFAULT_TIMEOUT);
+}
+/**
+  * @brief: Read the GPIO state of specified pins in (P30 ... P35).
+  * @param pin_number: specify the pin to read.
+  * @retval: true if HIGH, false if LOW
+  */
+bool PN532_ReadGpioP(PN532* pn532, uint8_t pin_number) {
+    uint8_t pins_state[3];
+    PN532_CallFunction(pn532, PN532_COMMAND_READGPIO, pins_state,
+                       sizeof(pins_state), NULL, 0, PN532_DEFAULT_TIMEOUT);
+    if ((pin_number >= 30) && (pin_number <= 37)) {
+        return (pins_state[0] >> (pin_number - 30)) & 1 ? true : false;
+    }
+    if ((pin_number >= 70) && (pin_number <= 77)) {
+        return (pins_state[1] >> (pin_number - 70)) & 1 ? true : false;
+    }
+    return false;
+}
+/**
+  * @brief: Read the GPIO state of I0 or I1 pin.
+  * @param pin_number: specify the pin to read.
+  * @retval: true if HIGH, false if LOW
+  */
+bool PN532_ReadGpioI(PN532* pn532, uint8_t pin_number) {
+    uint8_t pins_state[3];
+    PN532_CallFunction(pn532, PN532_COMMAND_READGPIO, pins_state,
+                       sizeof(pins_state), NULL, 0, PN532_DEFAULT_TIMEOUT);
+    if (pin_number <= 7) {
+        return (pins_state[2] >> pin_number) & 1 ? true : false;
+    }
+    return false;
+}
+/**
+  * @brief: Write the GPIO states.
+  * @param pins_state: pin state buffer (2 bytes) to write.
+  *     no need to read pin states before write with the param pin_state
+  *         P3 = pin_state[0], P7 = pin_state[1]
+  *     bits:
+  *         P3[0] = P30,   P7[0] = 0,
+  *         P3[1] = P31,   P7[1] = P71,
+  *         P3[2] = P32,   P7[2] = P72,
+  *         P3[3] = P33,   P7[3] = nu,
+  *         P3[4] = P34,   P7[4] = nu,
+  *         P3[5] = P35,   P7[5] = nu,
+  *         P3[6] = nu,    P7[6] = nu,
+  *         P3[7] = Val,   P7[7] = Val,
+  *     For each port that is validated (bit Val = 1), all the bits are applied
+  *     simultaneously. It is not possible for example to modify the state of
+  *     the port P32 without applying a value to the ports P30, P31, P33, P34
+  *     and P35.
+  * @retval: -1 if error
+  */
+int PN532_WriteGpio(PN532* pn532, uint8_t* pins_state) {
+    uint8_t params[2];
+    // 0x80, the validation bit.
+    params[0] = 0x80 | pins_state[0];
+    params[1] = 0x80 | pins_state[1];
+    return PN532_CallFunction(pn532, PN532_COMMAND_WRITEGPIO, NULL, 0,
+                              params, sizeof(params), PN532_DEFAULT_TIMEOUT);
+}
+/**
+  * @brief: Write the specified pin with given states.
+  * @param pin_number: specify the pin to write.
+  * @param pin_state: specify the pin state. true for HIGH, false for LOW.
+  * @retval: -1 if error
+  */
+int PN532_WriteGpioP(PN532* pn532, uint8_t pin_number, bool pin_state) {
+    uint8_t pins_state[2];
+    uint8_t params[2];
+    if (PN532_ReadGpio(pn532, pins_state) == PN532_STATUS_ERROR) {
+        return PN532_STATUS_ERROR;
+    }
+    if ((pin_number >= 30) && (pin_number <= 37)) {
+        if (pin_state) {
+            params[0] = 0x80 | pins_state[0] | 1 << (pin_number - 30);
+        } else {
+            params[0] = (0x80 | pins_state[0]) & ~(1 << (pin_number - 30));
+        }
+        params[1] = 0x00;   // leave p7 unchanged
+    }
+    if ((pin_number >= 70) && (pin_number <= 77)) {
+        if (pin_state) {
+            params[1] = 0x80 | pins_state[1] | 1 << (pin_number - 70);
+        } else {
+            params[1] = (0x80 | pins_state[1]) & ~(1 << (pin_number - 70));
+        }
+        params[0] = 0x00;   // leave p3 unchanged
+    }
+    return PN532_CallFunction(pn532, PN532_COMMAND_WRITEGPIO, NULL, 0,
+                              params, sizeof(params), PN532_DEFAULT_TIMEOUT);
+}

+ 172 - 0
app/A08_NFC/src/pn532_hi3861.c

@@ -0,0 +1,172 @@
+/**************************************************************************
+ *  @file     pn532_stm32f1.c
+ *  @author   Yehui from Waveshare
+ *  @license  BSD
+ *  
+ *  This implements the peripheral interfaces.
+ *  
+ *  Check out the links above for our tutorials and wiring diagrams 
+ *  These chips use SPI communicate.
+ *  
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documnetation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to  whom the Software is
+ * furished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ **************************************************************************/
+
+// #include "stm32f1xx_hal.h"
+// #include "main.h"
+#include "pn532_hi3861.h"
+#include "cmsis_os2.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+#include "iot_i2c.h"
+#include "iot_i2c_ex.h"
+
+#define RESET_GPIO 14
+#define WIFI_IOT_I2C_IDX_1 1
+
+#define _I2C_ADDRESS                    0x24
+#define _I2C_TIMEOUT                    10
+
+#define WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA 6
+#define WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL 6
+#define WIFI_IOT_I2C_IDX_1 1
+#define WIFI_IOT_IO_NAME_GPIO_7 7
+#define WIFI_IOT_IO_NAME_GPIO_8 8
+#define WIFI_IOT_IO_NAME_GPIO_0 0
+#define WIFI_IOT_IO_NAME_GPIO_1 1
+#define MAX30102_INIT_GPIO 7
+/***************************************************************
+ * 函数名称: GpioInit
+ * 说    明:  GPIO初始化
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void BoardInit(void)
+{
+    IoTGpioInit(RESET_GPIO);
+    IoTGpioSetFunc(RESET_GPIO, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(RESET_GPIO, IOT_GPIO_DIR_OUT); // 设置GPIO_8为输出模式
+
+    // IoTGpioInit(MAX30102_INIT_GPIO);
+    // IoTGpioSetFunc(MAX30102_INIT_GPIO, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    // IoTGpioSetDir(MAX30102_INIT_GPIO, IOT_GPIO_DIR_IN); // 设置GPIO_7为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_0);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA); // GPIO_0复用为I2C1_SDA
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_1);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL); // GPIO_1复用为I2C1_SCL
+    IoTI2cInit(WIFI_IOT_I2C_IDX_1, 400000);              /* baudrate: 400kbps */
+}
+
+/**************************************************************************
+ * Reset and Log implements
+ **************************************************************************/
+int PN532_Reset(void) {
+    IoTGpioSetOutputVal(RESET_GPIO, 1); 
+    osDelay(100);
+    IoTGpioSetOutputVal(RESET_GPIO, 0); 
+    osDelay(500);
+    IoTGpioSetOutputVal(RESET_GPIO, 1); 
+    osDelay(100);
+    return PN532_STATUS_OK;
+}
+
+void PN532_Log(const char* log) {
+    printf("%s\r\n", log);
+}
+
+/**************************************************************************
+ * End: Reset and Log implements
+ **************************************************************************/
+
+/**************************************************************************
+ * I2C
+ **************************************************************************/
+void I2cRead(uint8_t* data, uint16_t count) {
+    // HAL_I2C_Master_Receive(&hi2c1, _I2C_ADDRESS, data, count, _I2C_TIMEOUT);
+    IoTI2cRead(WIFI_IOT_I2C_IDX_1, (_I2C_ADDRESS << 1) | 0x01, data, count);
+
+}
+
+void I2cWrite(uint8_t* data, uint16_t count) {
+    // HAL_I2C_Master_Transmit(&hi2c1, _I2C_ADDRESS, data, count, _I2C_TIMEOUT);
+    IoTI2cWrite(WIFI_IOT_I2C_IDX_1, (_I2C_ADDRESS << 1) | 0x00, data, count);
+
+}
+
+int PN532_I2C_ReadData(uint8_t* data, uint16_t count) {
+    uint8_t status[] = {0x00};
+    uint8_t frame[count + 1];
+    I2cRead(status, sizeof(status));
+    if (status[0] != PN532_I2C_READY) {
+        return PN532_STATUS_ERROR;
+    }
+    I2cRead(frame, count + 1);
+    for (uint8_t i = 0; i < count; i++) {
+        data[i] = frame[i + 1];
+    }
+    return PN532_STATUS_OK;
+}
+
+int PN532_I2C_WriteData(uint8_t *data, uint16_t count) {
+    I2cWrite(data, count);
+    return PN532_STATUS_OK;
+}
+
+bool PN532_I2C_WaitReady(uint32_t timeout) {
+    uint8_t status[] = {0x00};
+    uint32_t tickstart = osKernelGetTickCount();
+    while (osKernelGetTickCount() - tickstart < timeout) {
+        I2cRead(status, sizeof(status));
+        if (status[0] == PN532_I2C_READY) {
+            return true;
+        } else {
+            osDelay(5);
+        }
+    }
+    return false;
+}
+
+int PN532_I2C_Wakeup(void) {
+    // TODO
+    // HAL_GPIO_WritePin(PN532_REQ_GPIO_Port, PN532_REQ_Pin, GPIO_PIN_SET);
+    osDelay(100);
+    // HAL_GPIO_WritePin(PN532_REQ_GPIO_Port, PN532_REQ_Pin, GPIO_PIN_RESET);
+    osDelay(100);
+    // HAL_GPIO_WritePin(PN532_REQ_GPIO_Port, PN532_REQ_Pin, GPIO_PIN_SET);
+    osDelay(500);
+    return PN532_STATUS_OK;
+}
+
+void PN532_I2C_Init(PN532* pn532) {
+    BoardInit();
+    // init the pn532 functions
+    pn532->reset =  PN532_Reset;
+    pn532->read_data = PN532_I2C_ReadData;
+    pn532->write_data = PN532_I2C_WriteData;
+    pn532->wait_ready = PN532_I2C_WaitReady;
+    pn532->wakeup = PN532_I2C_Wakeup;
+    pn532->log = PN532_Log;
+
+    // hardware wakeup
+    pn532->wakeup();
+}
+/**************************************************************************
+ * End: I2C
+ **************************************************************************/

+ 74 - 0
app/A09_Elevator/A09_Elevator_example.c

@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "elevator.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+
+static void ExampleTask(void)
+{
+    int ret;
+    // uint8_t dht_temperature;
+	// uint8_t dht_humidity;
+    // float Lux;
+    // BoardInit();
+     //GPIO_0复用为I2C1_SDA
+    BoardInit();
+
+    while (1)
+    {
+        
+        if(ElevatorReadData() == 0)
+        {
+            printf("Near the flame!\n");
+            FanStatusSet(ON);
+            
+        }
+		else
+        {
+			printf("Far the flame!\n");
+            FanStatusSet(OFF);
+        }
+         sleep(1);
+    }
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 26 - 0
app/A09_Elevator/BUILD.gn

@@ -0,0 +1,26 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A09_Elevator") {
+    sources = [
+        "src/elevator.c",
+        "A09_Elevator_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "//device/bossay/hi3861_l0/sdk_liteos/include",
+        "include"
+    ]
+}

+ 32 - 0
app/A09_Elevator/include/elevator.h

@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __Elevator_H__
+#define __Elevator_H__
+#include <stdint.h>
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+void BoardInit(void);
+uint8_t ElevatorReadData(void);
+void FanStatusSet(SwitchStatus status);
+
+
+#endif /* __Elevator_H__ */
+

+ 237 - 0
app/A09_Elevator/src/elevator.c

@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "elevator.h"
+#include "cmsis_os2.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+#include "iot_i2c.h"
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA 6
+#define WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL 6
+#define WIFI_IOT_IO_FUNC_GPIO_7_GPIO 0
+#define WIFI_IOT_I2C_IDX_1 1
+
+#define LED1 12
+#define LED2 7
+#define LED3 14
+#define LED4 10
+#define LED5 13
+
+// #define LED6 14
+// #define LED7 7
+// #define LED8 8
+// #define LED9 1
+// #define LED10 0
+
+#define OUT_GPIO 2
+
+/***************************************************************
+ * 函数名称: BoardInit
+ * 说    明: GPIO初始化
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void BoardInit(void)
+{
+    IoTGpioInit(LED1);
+    IoTGpioSetFunc(LED1, IOT_GPIO_FUNC_GPIO_12_GPIO);
+    IoTGpioSetDir(LED1, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    IoTGpioInit(LED2);
+    IoTGpioSetFunc(LED2, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(LED2, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    IoTGpioInit(LED3);
+    IoTGpioSetFunc(LED3, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(LED3, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    IoTGpioInit(LED4);
+    IoTGpioSetFunc(LED4, IOT_GPIO_FUNC_GPIO_10_GPIO);
+    IoTGpioSetDir(LED4, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    IoTGpioInit(LED5);
+    IoTGpioSetFunc(LED5, IOT_GPIO_FUNC_GPIO_13_GPIO);
+    IoTGpioSetDir(LED5, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    // IoTGpioInit(LED6);
+    // IoTGpioSetFunc(LED6, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    // IoTGpioSetDir(LED6, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    // IoTGpioInit(LED7);
+    // IoTGpioSetFunc(LED7, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    // IoTGpioSetDir(LED7, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    // IoTGpioInit(LED8);
+    // IoTGpioSetFunc(LED8, IOT_GPIO_FUNC_GPIO_8_GPIO);
+    // IoTGpioSetDir(LED8, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    // IoTGpioInit(LED9);
+    // IoTGpioSetFunc(LED9, IOT_GPIO_FUNC_GPIO_1_GPIO);
+    // IoTGpioSetDir(LED9, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    // IoTGpioInit(LED10);
+    // IoTGpioSetFunc(LED10, IOT_GPIO_FUNC_GPIO_0_GPIO);
+    // IoTGpioSetDir(LED10, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    IoTGpioInit(OUT_GPIO);
+    IoTGpioSetFunc(OUT_GPIO, IOT_GPIO_FUNC_GPIO_2_GPIO);
+    IoTGpioSetDir(OUT_GPIO, IOT_GPIO_DIR_IN); // 设置为输入模式
+
+}
+
+/***************************************************************
+* 函数名称: ElevatorReadData
+* 说    明: 读取数据
+* 参    数: 无
+* 返 回 值: 无
+***************************************************************/
+uint8_t ElevatorReadData(void)
+{
+    IotGpioValue temp = {0};
+    IoTGpioGetInputVal(OUT_GPIO,&temp);
+    return temp;
+}
+
+
+/***************************************************************
+ * 函数名称: FanStatusSet
+ * 说    明: 风扇状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关风扇
+ *									ON,开风扇
+ * 返 回 值: 无
+ ***************************************************************/
+void FanStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED1, 0);
+        IoTGpioSetOutputVal(LED2, 1); 
+        IoTGpioSetOutputVal(LED3, 1); 
+        IoTGpioSetOutputVal(LED4, 1); 
+        IoTGpioSetOutputVal(LED5, 1);  
+        // IoTGpioSetOutputVal(LED6, 1); 
+        // IoTGpioSetOutputVal(LED7, 1); 
+        // IoTGpioSetOutputVal(LED8, 1); 
+        // IoTGpioSetOutputVal(LED9, 1); 
+        // IoTGpioSetOutputVal(LED10, 0);
+        osDelay(20);
+        IoTGpioSetOutputVal(LED1, 0);
+        IoTGpioSetOutputVal(LED2, 0); 
+        IoTGpioSetOutputVal(LED3, 1); 
+        IoTGpioSetOutputVal(LED4, 1); 
+        IoTGpioSetOutputVal(LED5, 1);  
+        // IoTGpioSetOutputVal(LED6, 1); 
+        // IoTGpioSetOutputVal(LED7, 1); 
+        // IoTGpioSetOutputVal(LED8, 1); 
+        // IoTGpioSetOutputVal(LED9, 0); 
+        // IoTGpioSetOutputVal(LED10, 0);
+        osDelay(20);
+        IoTGpioSetOutputVal(LED1, 0);
+        IoTGpioSetOutputVal(LED2, 0); 
+        IoTGpioSetOutputVal(LED3, 0); 
+        IoTGpioSetOutputVal(LED4, 1); 
+        IoTGpioSetOutputVal(LED5, 1);  
+        // IoTGpioSetOutputVal(LED6, 1); 
+        // IoTGpioSetOutputVal(LED7, 1); 
+        // IoTGpioSetOutputVal(LED8, 0); 
+        // IoTGpioSetOutputVal(LED9, 0); 
+        // IoTGpioSetOutputVal(LED10, 0);
+        osDelay(20);
+        IoTGpioSetOutputVal(LED1, 0);
+        IoTGpioSetOutputVal(LED2, 0); 
+        IoTGpioSetOutputVal(LED3, 0); 
+        IoTGpioSetOutputVal(LED4, 0); 
+        IoTGpioSetOutputVal(LED5, 1);  
+        // IoTGpioSetOutputVal(LED6, 1); 
+        // IoTGpioSetOutputVal(LED7, 0); 
+        // IoTGpioSetOutputVal(LED8, 0); 
+        // IoTGpioSetOutputVal(LED9, 0); 
+        // IoTGpioSetOutputVal(LED10, 0);
+        osDelay(20); 
+        IoTGpioSetOutputVal(LED1, 0);
+        IoTGpioSetOutputVal(LED2, 0); 
+        IoTGpioSetOutputVal(LED3, 0); 
+        IoTGpioSetOutputVal(LED4, 0); 
+        IoTGpioSetOutputVal(LED5, 0);  
+        // IoTGpioSetOutputVal(LED6, 0); 
+        // IoTGpioSetOutputVal(LED7, 0); 
+        // IoTGpioSetOutputVal(LED8, 0); 
+        // IoTGpioSetOutputVal(LED9, 0); 
+        // IoTGpioSetOutputVal(LED10, 0);
+    }
+
+    if (status == OFF) {      
+        IoTGpioSetOutputVal(LED1, 0);
+        IoTGpioSetOutputVal(LED2, 0); 
+        IoTGpioSetOutputVal(LED3, 0); 
+        IoTGpioSetOutputVal(LED4, 0); 
+        IoTGpioSetOutputVal(LED5, 1);  
+        // IoTGpioSetOutputVal(LED6, 1); 
+        // IoTGpioSetOutputVal(LED7, 0); 
+        // IoTGpioSetOutputVal(LED8, 0); 
+        // IoTGpioSetOutputVal(LED9, 0); 
+        // IoTGpioSetOutputVal(LED10, 0);
+        osDelay(20);
+        IoTGpioSetOutputVal(LED1, 0);
+        IoTGpioSetOutputVal(LED2, 0); 
+        IoTGpioSetOutputVal(LED3, 0); 
+        IoTGpioSetOutputVal(LED4, 1); 
+        IoTGpioSetOutputVal(LED5, 1);  
+        // IoTGpioSetOutputVal(LED6, 1); 
+        // IoTGpioSetOutputVal(LED7, 1); 
+        // IoTGpioSetOutputVal(LED8, 0); 
+        // IoTGpioSetOutputVal(LED9, 0); 
+        // IoTGpioSetOutputVal(LED10, 0);
+        osDelay(20);
+        IoTGpioSetOutputVal(LED1, 0);
+        IoTGpioSetOutputVal(LED2, 0); 
+        IoTGpioSetOutputVal(LED3, 1); 
+        IoTGpioSetOutputVal(LED4, 1); 
+        IoTGpioSetOutputVal(LED5, 1);  
+        // IoTGpioSetOutputVal(LED6, 1); 
+        // IoTGpioSetOutputVal(LED7, 1); 
+        // IoTGpioSetOutputVal(LED8, 1); 
+        // IoTGpioSetOutputVal(LED9, 0); 
+        // IoTGpioSetOutputVal(LED10, 0);
+        osDelay(20);
+        IoTGpioSetOutputVal(LED1, 0);
+        IoTGpioSetOutputVal(LED2, 1); 
+        IoTGpioSetOutputVal(LED3, 1); 
+        IoTGpioSetOutputVal(LED4, 1); 
+        IoTGpioSetOutputVal(LED5, 1);  
+        // IoTGpioSetOutputVal(LED6, 1); 
+        // IoTGpioSetOutputVal(LED7, 1); 
+        // IoTGpioSetOutputVal(LED8, 1); 
+        // IoTGpioSetOutputVal(LED9, 1); 
+        // IoTGpioSetOutputVal(LED10, 0);
+        osDelay(20); 
+        IoTGpioSetOutputVal(LED1, 1);
+        IoTGpioSetOutputVal(LED2, 1); 
+        IoTGpioSetOutputVal(LED3, 1); 
+        IoTGpioSetOutputVal(LED4, 1); 
+        IoTGpioSetOutputVal(LED5, 1);  
+        // IoTGpioSetOutputVal(LED6, 1); 
+        // IoTGpioSetOutputVal(LED7, 1); 
+        // IoTGpioSetOutputVal(LED8, 1); 
+        // IoTGpioSetOutputVal(LED9, 1); 
+        // IoTGpioSetOutputVal(LED10, 1);  
+    }
+}

+ 63 - 0
app/A11_PM2_5/A11_PM2_5_example.c

@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "PM2_5.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+
+static void ExampleTask(void)
+{
+    PM2D5Data data;
+
+    BoardInit();
+    // LedWarnStatusSet(ON);
+    LedSafeStatusSet(ON);
+    while (1) {
+        PM2DReadData(&data);
+        printf("\r\n******************************PM1.0 is  %d\r\n", data.pm1_0);
+        printf("\r\n******************************PM2.5 is  %d\r\n", data.pm2_5);
+        printf("\r\n******************************PM10 is  %d\r\n", data.pm10);
+        sleep(1);
+    }
+
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 26 - 0
app/A11_PM2_5/BUILD.gn

@@ -0,0 +1,26 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A11_PM2_5") {
+    sources = [
+        "src/PM2_5.c",
+        "A11_PM2_5_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "//device/bossay/hi3861_l0/sdk_liteos/include",
+        "include"
+    ]
+}

+ 30 - 0
app/A11_PM2_5/include/PM2_5.h

@@ -0,0 +1,30 @@
+#ifndef __PM_2_5_H__
+#define __PM_2_5_H__
+
+
+#include <stdint.h>
+
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+typedef struct
+{
+    uint32_t    pm1_0;	
+    uint32_t    pm2_5;
+    uint32_t    pm10;		
+} PM2D5Data;
+
+void BoardInit(void);
+
+uint8_t Button_Left_Read_Data(void);
+
+void PM2DReadData(PM2D5Data* ReadData);
+void LedWarnStatusSet(SwitchStatus status);	
+void LedSafeStatusSet(SwitchStatus status);
+#endif
+
+

+ 120 - 0
app/A11_PM2_5/src/PM2_5.c

@@ -0,0 +1,120 @@
+#include "PM2_5.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+#include "iot_uart.h"
+#include "stdio.h"
+
+#define RESET_GPIO 7
+#define LED_SAFE_GPIO 8
+#define LED_WARN_GPIO 14
+#define SET_GPIO 13
+#define WIFI_IOT_UART_IDX_1 1
+
+uint8_t     RxBuffer[3];
+
+
+void BoardInit(void)
+{   
+    IoTGpioInit(RESET_GPIO);
+    IoTGpioSetFunc(RESET_GPIO, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(RESET_GPIO, IOT_GPIO_DIR_OUT); // 设置为输出模式
+    IoTGpioSetOutputVal(RESET_GPIO, 1);
+
+    IoTGpioInit(LED_SAFE_GPIO);
+    IoTGpioSetFunc(LED_SAFE_GPIO, IOT_GPIO_FUNC_GPIO_8_GPIO);
+    IoTGpioSetDir(LED_SAFE_GPIO, IOT_GPIO_DIR_OUT); // 设置为输出模式
+
+    IoTGpioInit(LED_WARN_GPIO);
+    IoTGpioSetFunc(LED_WARN_GPIO, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(LED_WARN_GPIO, IOT_GPIO_DIR_OUT); // 设置为输出模式
+
+    IoTGpioInit(SET_GPIO);
+    IoTGpioSetFunc(SET_GPIO, IOT_GPIO_FUNC_GPIO_13_GPIO);
+    IoTGpioSetDir(SET_GPIO, IOT_GPIO_DIR_OUT); // 设置为输入模式
+    IoTGpioSetOutputVal(SET_GPIO, 1);
+
+    uint32_t ret;
+
+    IotUartAttribute uart_attr = {
+
+        // baud_rate: 9600
+        .baudRate = 9600,
+
+        // data_bits: 8bits
+        .dataBits = 8,
+        .stopBits = 1,
+        .parity = 0,
+    };
+
+    // Initialize uart driver
+    ret = IoTUartInit(WIFI_IOT_UART_IDX_1, &uart_attr);
+    if (ret != IOT_SUCCESS) {
+        printf("Failed to init uart! Err code = %d\n", ret);
+        return;
+    }
+}
+
+static unsigned char read_date[32];
+
+/***************************************************************
+ * 函数名称: PM2DReadData
+ * 说    明: 获取GPS经纬度信息
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void PM2DReadData(PM2D5Data* ReadData)
+{
+    //通过串口1接收数据
+    IoTUartRead(WIFI_IOT_UART_IDX_1, read_date, 32);
+
+    // for(int i = 0; i<32; i++)
+    // {
+    //     printf("%d------%x\r\n",i,read_date[i]);
+    // }
+    if(read_date[0]== 0x42 && read_date[1]== 0x4d)
+    {
+        ReadData->pm1_0=read_date[2]<<8|read_date[3];
+        ReadData->pm2_5=read_date[4]<<8|read_date[5];
+        ReadData->pm10=read_date[6]<<8|read_date[7];
+    }
+
+}
+
+
+/***************************************************************
+ * 函数名称: LedWarnStatusSet
+ * 说    明: LED_Warn状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedWarnStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_WARN_GPIO, 1); // 设置输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_WARN_GPIO, 0); // 设置输出低电平关闭灯
+    }
+}
+/***************************************************************
+ * 函数名称: LedSafeStatusSet
+ * 说    明: LED_Safe状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedSafeStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_SAFE_GPIO, 1); // 设置输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_SAFE_GPIO, 0); // 设置输出低电平关闭灯
+    }
+}

+ 78 - 0
app/A12_SOCKET/A12_SOCKET_example.c

@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "ohos_init.h"
+#include "cmsis_os2.h"
+#include "SOCKET.h"
+
+#define TASK_STACK_SIZE 1024*8
+#define TASK_PRIO 25
+
+
+static void ExampleTask(void)
+{
+   
+    BoardInit();
+    
+    while (1) {
+        printf("=======================================\r\n");
+        printf("*************A12_SOCKET_example***********\r\n");
+        printf("=======================================\r\n");
+        RelayStatusSet(ON);
+
+        LedRedStatusSet(OFF);
+        LedGreenStatusSet(OFF); 
+        LedBlueStatusSet(ON);
+        osDelay(200);
+        LedRedStatusSet(ON);
+        LedGreenStatusSet(OFF); 
+        LedBlueStatusSet(OFF); 
+        osDelay(200);
+        LedRedStatusSet(OFF);
+        LedGreenStatusSet(ON); 
+        LedBlueStatusSet(OFF);
+        osDelay(200); 
+        // LedBlueStatusSet(ON);                         
+    } 
+}
+
+/**
+ * @brief Main Entry of the A22_MQ2 Example
+ * 
+ */
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 25 - 0
app/A12_SOCKET/BUILD.gn

@@ -0,0 +1,25 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A12_SOCKET") {
+    sources = [
+        "src/SOCKET.c",
+        "A12_SOCKET_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "include"
+    ]
+}

+ 32 - 0
app/A12_SOCKET/include/SOCKET.h

@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __SOCKET_H__
+#define __SOCKET_H__
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+void BoardInit(void);
+void RelayStatusSet(SwitchStatus status);
+void LedRedStatusSet(SwitchStatus status);
+void LedGreenStatusSet(SwitchStatus status);
+void LedBlueStatusSet(SwitchStatus status);
+
+#endif /* __SOCKET_H__ */
+

+ 126 - 0
app/A12_SOCKET/src/SOCKET.c

@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SOCKET.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+
+#define RELAY_GPIO 14
+#define LED_RED_GPIO 7
+#define LED_GREEN_GPIO 8
+#define LED_BLUE_GPIO 13
+
+/***************************************************************
+ * 函数名称: BoardInit
+ * 说    明: 初始化
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void BoardInit(void)
+{
+    IoTGpioInit(RELAY_GPIO);
+    IoTGpioSetFunc(RELAY_GPIO, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(RELAY_GPIO, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    IoTGpioInit(LED_RED_GPIO);
+    IoTGpioSetFunc(LED_RED_GPIO, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(LED_RED_GPIO, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    IoTGpioInit(LED_GREEN_GPIO);
+    IoTGpioSetFunc(LED_GREEN_GPIO, IOT_GPIO_FUNC_GPIO_8_GPIO);
+    IoTGpioSetDir(LED_GREEN_GPIO, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    IoTGpioInit(LED_BLUE_GPIO);
+    IoTGpioSetFunc(LED_BLUE_GPIO, IOT_GPIO_FUNC_GPIO_13_GPIO);
+    IoTGpioSetDir(LED_BLUE_GPIO, IOT_GPIO_DIR_OUT); //设置为输出模式
+}
+
+
+/***************************************************************
+ * 函数名称: RelayStatusSet
+ * 说    明: 开关继电器
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,光灯
+ *									ON,开灯
+ * 返 回 值: 无
+ ***************************************************************/
+void RelayStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(RELAY_GPIO, 1); //设置输出高电平点亮LED灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(RELAY_GPIO, 0); //设置输出低电平点亮LED灯
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedRedStatusSet
+ * 说    明: 开关灯
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,光灯
+ *									ON,开灯
+ * 返 回 值: 无
+ ***************************************************************/
+void LedRedStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_RED_GPIO, 0); //设置输出高电平点亮LED灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_RED_GPIO, 1); //设置输出低电平点亮LED灯
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedGreenStatusSet
+ * 说    明: 开关灯
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,光灯
+ *									ON,开灯
+ * 返 回 值: 无
+ ***************************************************************/
+void LedGreenStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_GREEN_GPIO, 0); //设置输出高电平点亮LED灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_GREEN_GPIO, 1); //设置输出低电平点亮LED灯
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedBlueStatusSet
+ * 说    明: 开关灯
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,光灯
+ *									ON,开灯
+ * 返 回 值: 无
+ ***************************************************************/
+void LedBlueStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_BLUE_GPIO, 0); //设置输出高电平点亮LED灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_BLUE_GPIO, 1); //设置输出低电平点亮LED灯
+    }
+}

+ 73 - 0
app/A13_FLAME/A13_FLAME_example..c

@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "flame.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+
+static void ExampleTask(void)
+{
+    float ad_value;
+    FlameInit();
+    usleep(1000000);      
+    while (1)
+    {
+		ad_value = GetVoltage();
+		if(FlameReadData() == 0)
+			{
+				printf("Near the flame!\n");
+				printf("ad_value:%2.2fV\n",ad_value);
+                BeepStatusSet(ON);
+                LedWarnStatusSet(ON);
+				
+			}
+		else{
+			printf("Far the flame!\n");
+            printf("ad_value:%2.2fV\n",ad_value);
+            BeepStatusSet(OFF);
+            LedWarnStatusSet(OFF);
+        }
+
+        sleep(1);
+    }
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 26 - 0
app/A13_FLAME/BUILD.gn

@@ -0,0 +1,26 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A13_FLAME") {
+    sources = [
+        "src/flame.c",
+        "A13_FLAME_example..c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "//device/bossay/hi3861_l0/sdk_liteos/include",
+        "include"
+    ]
+}

+ 23 - 0
app/A13_FLAME/include/flame.h

@@ -0,0 +1,23 @@
+#ifndef __FLAME_H__
+#define __FLAME_H__
+
+
+#include <stdint.h>
+
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+
+void FlameInit(void);
+float GetVoltage(void);
+uint8_t FlameReadData(void);
+void BeepStatusSet(SwitchStatus status);
+void LedWarnStatusSet(SwitchStatus status);	
+
+#endif
+
+

+ 103 - 0
app/A13_FLAME/src/flame.c

@@ -0,0 +1,103 @@
+#include "flame.h"
+#include "iot_adc.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+
+#define WIFI_IOT_IO_NAME_GPIO_8 8
+#define WIFI_IOT_IO_NAME_GPIO_14 14
+
+#define OUT_GPIO 7
+
+
+
+void FlameInit(void)
+{   
+    IoTGpioInit(OUT_GPIO);
+    IoTGpioSetFunc(OUT_GPIO, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(OUT_GPIO, IOT_GPIO_DIR_IN); // 设置GPIO_8为输出模式
+
+    // IoTGpioInit(13);
+    // IoTGpioSetFunc(13, IOT_GPIO_FUNC_GPIO_13_GPIO);
+    // IoTGpioSetDir(13, IOT_GPIO_DIR_IN); // 设置GPIO_8为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_14);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_14, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_14, IOT_GPIO_DIR_OUT);
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_8);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_FUNC_GPIO_8_GPIO);
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_DIR_OUT);
+}
+
+/***************************************************************
+* 函数名称: GetVoltage
+* 说    明: 获取电压值函数
+* 参    数: 无
+*								
+* 返 回 值: 无
+***************************************************************/
+float GetVoltage(void)
+{
+    unsigned int ret;
+    unsigned short data;
+
+    ret = IoTAdcRead(6, &data, IOT_ADC_EQU_MODEL_8, IOT_ADC_CUR_BAIS_DEFAULT, 0xff);
+    if (ret != IOT_SUCCESS)
+    {
+        printf("ADC Read Fail\n");
+    }
+    return (float)data * 1.8 * 4 / 4096.0;
+}
+
+/***************************************************************
+* 函数名称: FlameReadData
+* 说    明: 读取数据
+* 参    数: 无
+* 返 回 值: 无
+***************************************************************/
+uint8_t FlameReadData(void)
+{
+    IotGpioValue temp = {0};
+    IoTGpioGetInputVal(OUT_GPIO,&temp);
+    return temp;
+}
+
+
+/***************************************************************
+ * 函数名称: BeepStatusSet
+ * 说    明: Beep状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void BeepStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_8, 1); // 设置GPIO_7输出高电平点亮灯
+    }
+    if (status == OFF) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_8, 0); // 设置GPIO_7输出低电平关闭灯
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedWarnStatusSet
+ * 说    明: LED_Warn状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedWarnStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 1); // 设置GPIO_14输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 0); // 设置GPIO_14输出低电平关闭灯
+    }
+}
+

+ 112 - 0
app/A14_CAR/A01_DOOR_example.c

@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "DOOR.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+
+#include "hi_time.h"
+
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+
+#define GPIO_0 10
+#define GPIO_1 12
+
+float GetDistance  (void) {
+    static unsigned long start_time = 0, time = 0;
+    float distance = 0.0;
+    IotGpioValue value = IOT_GPIO_VALUE0;
+    unsigned int flag = 0;
+    IoTWatchDogDisable();
+
+    // hi_io_set_func(GPIO_8, GPIO_FUNC);
+    IoTGpioInit(GPIO_0);
+    IoTGpioSetFunc(GPIO_0, IOT_GPIO_FUNC_GPIO_10_GPIO);
+    IoTGpioSetDir(GPIO_0, IOT_GPIO_DIR_IN);
+
+    IoTGpioInit(GPIO_1);
+    IoTGpioSetFunc(GPIO_1, IOT_GPIO_FUNC_GPIO_12_GPIO);
+    IoTGpioSetDir(GPIO_1, IOT_GPIO_DIR_OUT);
+    IoTGpioSetOutputVal(GPIO_1, IOT_GPIO_VALUE1);
+    hi_udelay(20);
+    IoTGpioSetOutputVal(GPIO_1, IOT_GPIO_VALUE0);
+
+    while (1) {
+        IoTGpioGetInputVal(GPIO_0, &value);
+        if ( value == IOT_GPIO_VALUE1 && flag == 0) {
+            start_time = hi_get_us();
+            flag = 1;
+        }
+        if (value == IOT_GPIO_VALUE0 && flag == 1) {
+            time = hi_get_us() - start_time;
+            start_time = 0;
+            break;
+        }
+    }
+    distance = time * 0.034 / 2;
+    return distance;
+}
+
+ 
+ 
+static void ExampleTask(void)
+{
+    IotGpioValue value = IOT_GPIO_VALUE0;
+    // IoTGpioInit(11);
+    // IoTGpioSetFunc(11, IOT_GPIO_FUNC_GPIO_11_GPIO);
+    // IoTGpioSetPull(11,IOT_GPIO_PULL_UP);
+    // IoTGpioSetDir(11, IOT_GPIO_DIR_IN);
+    
+    printf("start test hcsr04\r\n");
+    while (1) {
+        // IoTGpioGetInputVal(11, &value);
+        // if (value == IOT_GPIO_VALUE0) {
+            float distance = GetDistance();
+            printf("distance is %f\r\n", distance);
+            // 
+        // }
+        osDelay(100);
+    }
+
+}
+
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 26 - 0
app/A14_CAR/BUILD.gn

@@ -0,0 +1,26 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A14_CAR") {
+    sources = [
+        "src/DOOR.c",
+        "A01_DOOR_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "//device/bossay/hi3861_l0/sdk_liteos/include",
+        "include"
+    ]
+}

+ 23 - 0
app/A14_CAR/include/DOOR.h

@@ -0,0 +1,23 @@
+#ifndef __DOOR_H__
+#define __DOOR_H__
+
+
+#include <stdint.h>
+
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+void BoardInit(void);
+
+uint8_t Button_Left_Read_Data(void);
+
+void BeepStatusSet(SwitchStatus status);
+void LedWarnStatusSet(SwitchStatus status);	
+void LedSafeStatusSet(SwitchStatus status);
+#endif
+
+

+ 98 - 0
app/A14_CAR/src/DOOR.c

@@ -0,0 +1,98 @@
+#include "DOOR.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+
+
+#define OUT_GPIO 13
+#define LED_SAFE_GPIO 7
+#define LED_WARN_GPIO 14
+#define BEEP_GPIO 8
+
+
+
+void BoardInit(void)
+{   
+    IoTGpioInit(OUT_GPIO);
+    IoTGpioSetFunc(OUT_GPIO, IOT_GPIO_FUNC_GPIO_13_GPIO);
+    IoTGpioSetDir(OUT_GPIO, IOT_GPIO_DIR_IN); // 设置GPIO_8为输出模式
+
+    IoTGpioInit(LED_SAFE_GPIO);
+    IoTGpioSetFunc(LED_SAFE_GPIO, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(LED_SAFE_GPIO, IOT_GPIO_DIR_OUT); // 设置为输出模式
+
+    IoTGpioInit(LED_WARN_GPIO);
+    IoTGpioSetFunc(LED_WARN_GPIO, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(LED_WARN_GPIO, IOT_GPIO_DIR_OUT); // 设置为输入模式
+
+    IoTGpioInit(BEEP_GPIO);
+    IoTGpioSetFunc(BEEP_GPIO, IOT_GPIO_FUNC_GPIO_8_GPIO);
+    IoTGpioSetDir(BEEP_GPIO, IOT_GPIO_DIR_OUT); // 设置为输入模式
+}
+
+/***************************************************************
+* 函数名称: Door_Read_Data
+* 说    明: 读取数据
+* 参    数: 无
+* 返 回 值: 无
+***************************************************************/
+uint8_t Door_Read_Data(void)
+{
+    IotGpioValue temp = {0};
+    IoTGpioGetInputVal(OUT_GPIO,&temp);
+    return temp;
+}
+
+/***************************************************************
+ * 函数名称: BeepStatusSet
+ * 说    明: Beep状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void BeepStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(BEEP_GPIO, 1); // 设置GPIO_7输出高电平点亮灯
+    }
+    if (status == OFF) {
+        IoTGpioSetOutputVal(BEEP_GPIO, 0); // 设置GPIO_7输出低电平关闭灯
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedWarnStatusSet
+ * 说    明: LED_Warn状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedWarnStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_WARN_GPIO, 1); // 设置输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_WARN_GPIO, 0); // 设置输出低电平关闭灯
+    }
+}
+/***************************************************************
+ * 函数名称: LedSafeStatusSet
+ * 说    明: LED_Safe状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedSafeStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_SAFE_GPIO, 1); // 设置输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_SAFE_GPIO, 0); // 设置输出低电平关闭灯
+    }
+}

+ 69 - 0
app/A16_PLAY/A24_GPS_example.c

@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "L76K.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+// #define FLAGS_MSK1 0x00000001U
+
+// osEventFlagsId_t evt_id;
+
+// static void Beep_Alarm(char *arg)
+// {
+//     (void)arg;
+//     osEventFlagsSet(evt_id, FLAGS_MSK1);
+//     printf("Beep_Alarm\n");
+// }
+
+static void ExampleTask(void)
+{
+    // L76Data data;
+
+    BoardInit();
+    // LedWarnStatusSet(ON);
+    // BeepStatusSet(ON);
+    while (1) {
+        PLAY();
+        sleep(2);
+    }
+
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 25 - 0
app/A16_PLAY/BUILD.gn

@@ -0,0 +1,25 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A16_PLAY") {
+    sources = [
+        "src/L76K.c",
+        "A24_GPS_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "include"
+    ]
+}

+ 38 - 0
app/A16_PLAY/include/L76K.h

@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __L76_H__
+#define __L76_H__
+
+#include <stdint.h>
+
+/***************************************************************
+* 名		称: GasStatus_ENUM
+* 说    明:枚举状态结构体
+***************************************************************/
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+
+
+void BoardInit(void);
+void PLAY(void);
+
+
+#endif /* __L76_H__ */
+

+ 81 - 0
app/A16_PLAY/src/L76K.c

@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "L76K.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+#include "iot_pwm.h"
+#include "iot_uart.h"
+
+#define WIFI_IOT_PWM_PORT_PWM1 1
+#define WIFI_IOT_IO_FUNC_GPIO_8_PWM1_OUT 5
+#define WIFI_IOT_IO_FUNC_GPIO_7_GPIO 0
+
+#define BEEP_GPIO 8
+#define LED_GPIO 14
+#define RESET_GPIO 7
+#define STANDBY_GPIO 13
+#define WIFI_IOT_UART_IDX_1 1
+
+
+/***************************************************************
+ * 函数名称: BoardInit
+ * 说    明: 初始化扩展板
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void BoardInit(void)
+{
+    uint32_t ret;
+    
+    IotUartAttribute uart_attr = {
+
+        // baud_rate: 9600
+        .baudRate = 9600,
+
+        // data_bits: 8bits
+        .dataBits = 8,
+        .stopBits = 1,
+        .parity = 0,
+    };
+
+    // Initialize uart driver
+    ret = IoTUartInit(WIFI_IOT_UART_IDX_1, &uart_attr);
+    if (ret != IOT_SUCCESS) {
+        printf("Failed to init uart! Err code = %d\n", ret);
+        return;
+    }
+}
+
+
+static const char* data = "A2\r\n";
+/***************************************************************
+ * 函数名称: L76ReadData
+ * 说    明: 获取经纬度信息
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void PLAY(void)
+{
+    //通过串口1接收数据
+    IoTUartWrite(WIFI_IOT_UART_IDX_1, (unsigned char*)data, strlen(data));
+
+}
+
+

+ 85 - 0
app/A17_CH2O/A17_CH2O.c

@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "ohos_init.h"
+#include "cmsis_os2.h"
+#include "CH2O.h"
+
+#define TASK_STACK_SIZE 1024*8
+#define TASK_PRIO 25
+
+
+static void ExampleTask(void)
+{
+    int ret;
+    float  ppm;
+    
+    BoardInit();
+    //Sensor calibration
+    usleep(1000000);        
+    MQ2PPMCalibration();  
+    
+    while (1) {
+        printf("=======================================\r\n");
+        printf("*************A22_MQ2_example***********\r\n");
+        printf("=======================================\r\n");
+        //get mq2 ppm
+        ret = GetMQ2PPM(&ppm);
+        if (ret != 0) {
+            printf("ADC Read Fail\n");
+            return ;
+        }
+        printf("ppm:%.3f \n", ppm);
+        if (ppm > 20) {
+            BeepStatusSet(ON);
+            LedSafeStatusSet(OFF);
+            LedWarnStatusSet(ON);
+        } else {
+            BeepStatusSet(OFF);
+            LedSafeStatusSet(ON);
+            LedWarnStatusSet(OFF);
+        }
+        usleep(1000000);                          
+    } 
+}
+
+/**
+ * @brief Main Entry of the A22_MQ2 Example
+ * 
+ */
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 25 - 0
app/A17_CH2O/BUILD.gn

@@ -0,0 +1,25 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A17_CH2O") {
+    sources = [
+        "src/CH2O.c",
+        "A17_CH2O.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "include"
+    ]
+}

+ 33 - 0
app/A17_CH2O/include/CH2O.h

@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __E53_SF1_H__
+#define __E53_SF1_H__
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+void BoardInit(void);
+void MQ2PPMCalibration(void);
+int GetMQ2PPM(float *ppm);
+void BeepStatusSet(SwitchStatus status);
+void LedSafeStatusSet(SwitchStatus status);
+void LedWarnStatusSet(SwitchStatus status);	
+
+#endif /* __E53_SF1_H__ */
+

+ 168 - 0
app/A17_CH2O/src/CH2O.c

@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CH2O.h"
+#include "iot_adc.h"
+#include "iot_errno.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+#include "iot_pwm.h"
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define CAL_PPM 20 //校准环境中PPM值
+#define RL 1       // RL阻值
+
+#define WIFI_IOT_IO_NAME_GPIO_8 8
+#define WIFI_IOT_PWM_PORT_PWM1 1
+#define WIFI_IOT_IO_FUNC_GPIO_8_PWM1_OUT 5
+
+#define SAFE_LED_GPIO 14
+#define WARN_LED_GPIO 7
+
+static float R0; //元件在洁净空气中的阻值
+
+/***************************************************************
+ * 函数名称: MQ2Init
+ * 说    明: 初始化MQ2Init
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void BoardInit(void)
+{
+    IoTGpioInit(SAFE_LED_GPIO);
+    IoTGpioSetFunc(SAFE_LED_GPIO, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(SAFE_LED_GPIO, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    IoTGpioInit(WARN_LED_GPIO);
+    IoTGpioSetFunc(WARN_LED_GPIO, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(WARN_LED_GPIO, IOT_GPIO_DIR_OUT); //设置为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_8);                                      //初始化GPIO_8
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_PWM1_OUT); //设置GPIO_8引脚复用功能为PWM
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_DIR_OUT);                  //设置GPIO_8引脚为输出模式
+    IoTPwmInit(WIFI_IOT_PWM_PORT_PWM1);                                        //初始化PWM1端口
+}
+/***************************************************************
+* 函数名称: GetVoltage
+* 说    明: 获取电压值函数
+* 参    数: 无
+*								
+* 返 回 值: 无
+***************************************************************/
+static float GetVoltage(void)
+{
+    unsigned int ret;
+    unsigned short data;
+
+    ret = IoTAdcRead(5, &data, IOT_ADC_EQU_MODEL_8, IOT_ADC_CUR_BAIS_DEFAULT, 0xff);
+    if (ret != IOT_SUCCESS)
+    {
+        printf("ADC Read Fail\n");
+    }
+    return (float)data * 1.8 * 4 / 4096.0;
+}
+/***************************************************************
+ * 函数名称: GetMQ2PPM
+ * 说    明: 获取PPM函数
+ * 参    数: ppm 烟雾浓度
+ * 返 回 值: 0 成功; -1 失败
+ ***************************************************************/
+int GetMQ2PPM(float* ppm)
+{
+    unsigned int ret;
+    unsigned short data;
+    float voltage, RS;
+
+    ret = IoTAdcRead(6, &data, IOT_ADC_EQU_MODEL_8, IOT_ADC_CUR_BAIS_DEFAULT, 0xff);
+    if (ret != 0) {
+        printf("ADC Read Fail\n");
+        return -1;
+    }
+    voltage = (float)data * 1.8 * 4 / 4096.0;
+    printf("voltage:%2.2fV\n",voltage);
+    RS = (5 - voltage) / voltage * RL;     //计算RS
+    *ppm = 613.9f * pow(RS / R0, -2.074f); //计算ppm
+    return 0;
+}
+
+/***************************************************************
+ * 函数名称: MQ2PPMCalibration
+ * 说    明: 传感器校准函数
+ * 参    数: 无
+ * 返 回 值: 无
+ ***************************************************************/
+void MQ2PPMCalibration(void)
+{
+    float voltage = GetVoltage();
+    float RS = (5 - voltage) / voltage * RL;
+    R0 = RS / pow(CAL_PPM / 613.9f, 1 / -2.074f);
+}
+
+/***************************************************************
+ * 函数名称: BeepStatusSet
+ * 说    明: 蜂鸣器报警与否
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,蜂鸣器
+ *									ON,开蜂鸣器
+ * 返 回 值: 无
+ ***************************************************************/
+void BeepStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTPwmStart(WIFI_IOT_PWM_PORT_PWM1, 50, 4000); //输出PWM波
+    }
+    if (status == OFF) {
+        IoTPwmStop(WIFI_IOT_PWM_PORT_PWM1);
+    }
+}
+/***************************************************************
+ * 函数名称: LedSafeStatusSet
+ * 说    明: LED_Safe状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedSafeStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(SAFE_LED_GPIO, 1); // 设置GPIO_7输出高电平点亮灯
+    }
+    if (status == OFF) {
+        IoTGpioSetOutputVal(SAFE_LED_GPIO, 0); // 设置GPIO_7输出低电平关闭灯
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedWarnStatusSet
+ * 说    明: LED_Warn状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedWarnStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(WARN_LED_GPIO, 1); // 设置GPIO_14输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(WARN_LED_GPIO, 0); // 设置GPIO_14输出低电平关闭灯
+    }
+}

+ 90 - 0
app/A18_ST02D/A18_ST02D_example.c

@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "st02d.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+// #define FLAGS_MSK1 0x00000001U
+
+// osEventFlagsId_t evt_id;
+
+// static void Beep_Alarm(char *arg)
+// {
+//     (void)arg;
+//     osEventFlagsSet(evt_id, FLAGS_MSK1);
+//     printf("Beep_Alarm\n");
+// }
+
+static void ExampleTask(void)
+{
+    // ST02D_Init();
+    // Button_Left_Read_Data(Beep_Alarm);
+    // Button_Right_Read_Data(Beep_Alarm);
+    // while (1)
+    // {
+    //     osEventFlagsWait(evt_id, FLAGS_MSK1, osFlagsWaitAny, osWaitForever);
+    //     BeepStatusSet(ON);
+    //     LedWarnStatusSet(ON);
+    //     osDelay(300);
+    //     BeepStatusSet(OFF);
+    //     LedWarnStatusSet(OFF);
+    // }
+    ST02D_Init();
+    // Button_Left_Read_Data(Beep_Alarm);
+    // Button_Right_Read_Data(Beep_Alarm);
+    while (1)
+    {
+		if(Button_Left_Read_Data() == 0|Button_Right_Read_Data() == 0)
+        {
+            BeepStatusSet(ON);
+            LedWarnStatusSet(ON);
+            
+        }
+		else
+        {
+            BeepStatusSet(OFF);
+            LedWarnStatusSet(OFF);
+        }
+        sleep(1);
+    }
+
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 26 - 0
app/A18_ST02D/BUILD.gn

@@ -0,0 +1,26 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A18_ST02D") {
+    sources = [
+        "src/st02d.c",
+        "A18_ST02D_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "//device/bossay/hi3861_l0/sdk_liteos/include",
+        "include"
+    ]
+}

+ 27 - 0
app/A18_ST02D/include/st02d.h

@@ -0,0 +1,27 @@
+#ifndef __ST02D_H__
+#define __ST02D_H__
+
+
+#include <stdint.h>
+
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+
+typedef void (*ST02D_CallbackFunc) (char *arg);
+
+void ST02D_Init(void);
+// void Button_Left_Read_Data(ST02D_CallbackFunc func);
+// void Button_Right_Read_Data(ST02D_CallbackFunc func);
+uint8_t Button_Left_Read_Data(void);
+uint8_t Button_Right_Read_Data(void);
+void BeepStatusSet(SwitchStatus status);
+void LedWarnStatusSet(SwitchStatus status);	
+
+#endif
+
+

+ 119 - 0
app/A18_ST02D/src/st02d.c

@@ -0,0 +1,119 @@
+#include "st02d.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+
+#define WIFI_IOT_IO_NAME_GPIO_8 8
+#define WIFI_IOT_IO_NAME_GPIO_14 14
+#define WIFI_IOT_IO_NAME_GPIO_0 0
+#define WIFI_IOT_IO_NAME_GPIO_1 1
+#define WIFI_IOT_I2C_IDX_1 1
+
+#define OUT1_GPIO 13
+#define OUT2_GPIO 7
+
+uint8_t     RxBuffer[3];
+
+
+void ST02D_Init(void)
+{   
+    IoTGpioInit(OUT1_GPIO);
+    IoTGpioSetFunc(OUT1_GPIO, IOT_GPIO_FUNC_GPIO_13_GPIO);
+    IoTGpioSetDir(OUT1_GPIO, IOT_GPIO_DIR_IN); // 设置GPIO_8为输出模式
+
+    IoTGpioInit(OUT2_GPIO);
+    IoTGpioSetFunc(OUT2_GPIO, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(OUT2_GPIO, IOT_GPIO_DIR_IN); // 设置GPIO_8为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_14);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_14, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_14, IOT_GPIO_DIR_OUT); // 设置为输入模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_8);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_FUNC_GPIO_8_GPIO);
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, IOT_GPIO_DIR_OUT); // 设置为输入模式
+}
+
+// /***************************************************************
+// * 函数名称: Button_Left_Read_Data
+// * 说    明: 读取数据
+// * 参    数: 无
+// * 返 回 值: 无
+// ***************************************************************/
+// void Button_Left_Read_Data(void)
+// {
+// 	IoTGpioRegisterIsrFunc(WIFI_IOT_IO_NAME_GPIO_14, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_FALL_LEVEL_LOW,func, 0);
+// }
+
+// /***************************************************************
+// * 函数名称: Button_Right_Read_Data
+// * 说    明: 读取数据
+// * 参    数: 无
+// * 返 回 值: 无
+// ***************************************************************/
+// void Button_Right_Read_Data(void)
+// {
+// 	IoTGpioRegisterIsrFunc(WIFI_IOT_IO_NAME_GPIO_8, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_FALL_LEVEL_LOW,func, 0);
+// }
+
+/***************************************************************
+* 函数名称: Button_Left_Read_Data
+* 说    明: 读取数据
+* 参    数: 无
+* 返 回 值: 无
+***************************************************************/
+uint8_t Button_Left_Read_Data(void)
+{
+    IotGpioValue temp = {0};
+    IoTGpioGetInputVal(OUT1_GPIO,&temp);
+    return temp;
+}
+
+/***************************************************************
+* 函数名称: Button_Right_Read_Data
+* 说    明: 读取数据
+* 参    数: 无
+* 返 回 值: 无
+***************************************************************/
+uint8_t Button_Right_Read_Data(void)
+{
+    IotGpioValue temp = {0};
+    IoTGpioGetInputVal(OUT2_GPIO,&temp);
+    return temp;
+}
+/***************************************************************
+ * 函数名称: BeepStatusSet
+ * 说    明: Beep状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void BeepStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_8, 1); // 设置GPIO_7输出高电平点亮灯
+    }
+    if (status == OFF) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_8, 0); // 设置GPIO_7输出低电平关闭灯
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedWarnStatusSet
+ * 说    明: LED_Warn状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedWarnStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 1); // 设置GPIO_14输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 0); // 设置GPIO_14输出低电平关闭灯
+    }
+}
+

+ 71 - 0
app/A19_MXL90614/A19_MXL90614_example.c

@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mlx90614.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+
+
+static void ExampleTask(void)
+{
+
+    MLX90614_Init();
+
+    while (1) {
+        printf("\r\n Ambient Temp: %0.2f \r\n", MLX90614_Read_TempData(MLX90614_RAM | AMBIENT_TEMP));    // ambient 
+        printf("\r\n Object Temp: %0.2f \r\n", MLX90614_Read_TempData(MLX90614_RAM | OBJECT_TEMP));     // object
+        
+        if(MLX90614_Read_TempData(MLX90614_RAM | OBJECT_TEMP)>32)
+        {
+            LedSafeStatusSet(OFF);
+            LedWarnStatusSet(ON);
+            BeepStatusSet(ON);
+        }
+        else
+        {
+            LedSafeStatusSet(ON);
+            LedWarnStatusSet(OFF);
+            BeepStatusSet(OFF);
+        }
+        sleep(2);
+    }
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 27 - 0
app/A19_MXL90614/BUILD.gn

@@ -0,0 +1,27 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A19_MXL90614") {
+    sources = [
+        "src/smbus.c",
+        "src/mlx90614.c",
+        "A19_MXL90614_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "//device/bossay/hi3861_l0/sdk_liteos/include",
+        "include"
+    ]
+}

+ 32 - 0
app/A19_MXL90614/include/mlx90614.h

@@ -0,0 +1,32 @@
+#ifndef __MLX90614_H
+#define __MLX90614_H
+
+
+#include <stdint.h>
+
+
+#define   MLX90614_ADDR_WRITE   0x00	
+#define   MLX90614_ADDR_READ    0x01
+
+#define   MLX90614_RAM    0x00
+
+#define   AMBIENT_TEMP    0x06
+#define   OBJECT_TEMP     0x07
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+
+extern uint8_t  RxBuffer[3];
+void MLX90614_Init(void);
+float MLX90614_Read_TempData(uint8_t  ambient_or_object);
+void LedSafeStatusSet(SwitchStatus status);
+void LedWarnStatusSet(SwitchStatus status);	
+void BeepStatusSet(SwitchStatus status);
+
+#endif
+
+

+ 26 - 0
app/A19_MXL90614/include/smbus.h

@@ -0,0 +1,26 @@
+#ifndef __SMBUS_H
+#define __SMBUS_H
+
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+
+#define ACK 0
+#define NACK 1
+#define WIFI_IOT_IO_NAME_GPIO_10 10
+#define WIFI_IOT_IO_NAME_GPIO_12 12
+
+
+#define    SMBUS_SCL_H()       IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_10, 1);
+#define    SMBUS_SCL_L()       IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_10, 0);
+#define    SMBUS_SDA_H()       IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_12, 1);
+#define    SMBUS_SDA_L()       IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_12, 0);
+
+void SMBus_Start(void);
+void SMBus_Stop(void);
+void SMBus_SendBit(uint8_t bit_out);
+uint8_t SMBus_ReceiveBit(void);
+uint8_t SMBus_SendByte(uint8_t Tx_buffer);
+uint8_t SMBus_ReceiveByte(uint8_t ack_nack);
+
+#endif
+

+ 246 - 0
app/A19_MXL90614/src/mlx90614.c

@@ -0,0 +1,246 @@
+#include "mlx90614.h"
+#include "smbus.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+
+#define WIFI_IOT_IO_NAME_GPIO_7 7
+#define WIFI_IOT_IO_NAME_GPIO_14 14
+#define WIFI_IOT_IO_NAME_GPIO_10 10
+#define WIFI_IOT_IO_NAME_GPIO_12 12
+#define WIFI_IOT_I2C_IDX_1 1
+
+
+uint8_t     RxBuffer[3];
+#define BEEP_GPIO 8
+
+void MLX90614_Init(void)
+{   
+    IoTGpioInit(BEEP_GPIO);
+    IoTGpioSetFunc(BEEP_GPIO, IOT_GPIO_FUNC_GPIO_8_GPIO);
+    IoTGpioSetDir(BEEP_GPIO, IOT_GPIO_DIR_OUT); //设置为输出模式
+    
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_10);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_10, IOT_GPIO_FUNC_GPIO_10_GPIO);
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_10, IOT_GPIO_DIR_OUT); // 设置GPIO_8为输出模式
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_12);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_12, IOT_GPIO_FUNC_GPIO_12_GPIO);
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_12, IOT_GPIO_DIR_OUT); // 设置GPIO_8为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_14);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_14, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_14, IOT_GPIO_DIR_OUT); // 设置GPIO_14为输出模式
+
+    IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_7);
+    IoTGpioSetFunc(WIFI_IOT_IO_NAME_GPIO_7, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(WIFI_IOT_IO_NAME_GPIO_7, IOT_GPIO_DIR_OUT); // 设置GPIO_7为输出模式
+}
+
+/*******************************************************************************
+* 函数名: PEC_calculation
+* 功能 : 数据校验
+* Input          : pec[]
+* Output         : None
+* Return         : pec[0]-this byte contains calculated crc value
+*******************************************************************************/
+uint8_t PEC_Calculation(uint8_t pec[])
+{
+    uint8_t         crc[6];
+    uint8_t        BitPosition=47;
+    uint8_t        shift;
+    uint8_t        i;
+    uint8_t        j;
+    uint8_t        temp;
+
+    do
+    {
+        /*Load pattern value 0x000000000107*/
+        crc[5]=0;
+        crc[4]=0;
+        crc[3]=0;
+        crc[2]=0;
+        crc[1]=0x01;
+        crc[0]=0x07;
+
+        /*Set maximum bit position at 47 ( six bytes byte5...byte0,MSbit=47)*/
+        BitPosition=47;
+
+        /*Set shift position at 0*/
+        shift=0;
+
+        /*Find first "1" in the transmited message beginning from the MSByte byte5*/
+        i=5;
+        j=0;
+        while((pec[i]&(0x80>>j))==0 && i>0)
+        {
+            BitPosition--;
+            if(j<7)
+            {
+                j++;
+            }
+            else
+            {
+                j=0x00;
+                i--;
+            }
+        }/*End of while */
+
+        /*Get shift value for pattern value*/
+        shift=BitPosition-8;
+
+        /*Shift pattern value */
+        while(shift)
+        {
+            for(i=5; i<0xFF; i--)
+            {
+                if((crc[i-1]&0x80) && (i>0))
+                {
+                    temp=1;
+                }
+                else
+                {
+                    temp=0;
+                }
+                crc[i]<<=1;
+                crc[i]+=temp;
+            }/*End of for*/
+            shift--;
+        }/*End of while*/
+
+        /*Exclusive OR between pec and crc*/
+        for(i=0; i<=5; i++)
+        {
+            pec[i] ^=crc[i];
+        }/*End of for*/
+    }
+    while(BitPosition>8); /*End of do-while*/
+
+    return pec[0];
+}
+/*******************************************************************************
+* 函数名: SMBus_ReadMemory
+* 功能: READ DATA FROM RAM/EEPROM
+* Input          : slaveAddress, command
+* Return         : Data
+*******************************************************************************/
+uint16_t SMBus_ReadMemory(uint8_t slaveAddress, uint8_t command)
+{
+    uint16_t data;                        // Data storage (DataH:DataL)
+    uint8_t Pec;                                // PEC byte storage
+    uint8_t DataL=0;                        // Low data byte storage
+    uint8_t DataH=0;                        // High data byte storage
+    uint8_t arr[6];                        // Buffer for the sent bytes
+    uint8_t PecReg;                        // Calculated PEC byte storage
+    uint8_t ErrorCounter;        // Defines the number of the attempts for communication with MLX90614
+
+    ErrorCounter=0x00;                                // Initialising of ErrorCounter
+        slaveAddress <<= 1;        //2-7位表示从机地址
+        
+    do
+    {
+repeat:
+        SMBus_Stop();                            //If slave send NACK stop comunication
+        --ErrorCounter;                                    //Pre-decrement ErrorCounter
+        if(!ErrorCounter)                             //ErrorCounter=0?
+        {
+            break;                                            //Yes,go out from do-while{}
+        }
+
+        SMBus_Start();                                //Start condition
+        if(SMBus_SendByte(slaveAddress))//Send SlaveAddress 最低位Wr=0表示接下来写命令
+        {
+            goto        repeat;                            //Repeat comunication again
+        }
+        if(SMBus_SendByte(command))            //Send command
+        {
+            goto        repeat;                            //Repeat comunication again
+        }
+
+        SMBus_Start();                                        //Repeated Start condition
+        if(SMBus_SendByte(slaveAddress+1))        //Send SlaveAddress 最低位Rd=1表示接下来读数据
+        {
+            goto        repeat;                     //Repeat comunication again
+        }
+
+        DataL = SMBus_ReceiveByte(ACK);        //Read low data,master must send ACK
+        DataH = SMBus_ReceiveByte(ACK); //Read high data,master must send ACK
+        Pec = SMBus_ReceiveByte(NACK);        //Read PEC byte, master must send NACK
+        SMBus_Stop();                                //Stop condition
+
+        arr[5] = slaveAddress;                //
+        arr[4] = command;                        //
+        arr[3] = slaveAddress+1;        //Load array arr
+        arr[2] = DataL;                                //
+        arr[1] = DataH;                                //
+        arr[0] = 0;                                        //
+        PecReg=PEC_Calculation(arr);//Calculate CRC
+    }
+    while(PecReg != Pec);                //If received and calculated CRC are equal go out from do-while{}
+
+        data = (DataH<<8) | DataL;        //data=DataH:DataL
+    return data;
+}
+
+/***************************************************************************
+* @brief      Read object temperature(Tobj) from  RAM registers of MLX90614
+* @param      ambient_or_object : Which temperature you want to get
+* @retval     Object temperature
+****************************************************************************/
+float   MLX90614_Read_TempData(uint8_t  ambient_or_object)
+{
+	return SMBus_ReadMemory(MLX90614_ADDR_WRITE, ambient_or_object)*0.02-273.15;
+}
+
+/***************************************************************
+ * 函数名称: LedSafeStatusSet
+ * 说    明: LED_Safe状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedSafeStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(7, 1); // 设置GPIO_7输出高电平点亮灯
+    }
+    if (status == OFF) {
+        IoTGpioSetOutputVal(7, 0); // 设置GPIO_7输出低电平关闭灯
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedWarnStatusSet
+ * 说    明: LED_Warn状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedWarnStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 1); // 设置GPIO_14输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 0); // 设置GPIO_14输出低电平关闭灯
+    }
+}
+/***************************************************************
+ * 函数名称: BeepStatusSet
+ * 说    明: Beep状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void BeepStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(BEEP_GPIO, 1); // 设置GPIO_7输出高电平点亮灯
+    }
+    if (status == OFF) {
+        IoTGpioSetOutputVal(BEEP_GPIO, 0); // 设置GPIO_7输出低电平关闭灯
+    }
+}
+

+ 158 - 0
app/A19_MXL90614/src/smbus.c

@@ -0,0 +1,158 @@
+#include "mlx90614.h"
+#include "smbus.h"
+#include "hi_time.h"
+
+
+/***************************************************************************
+* @brief      SMBus start bit
+* @param      None
+* @retval     None
+****************************************************************************/
+void SMBus_Start(void)
+{
+	SMBUS_SDA_H();
+    hi_udelay(5);
+	SMBUS_SCL_H();
+	hi_udelay(5);
+	SMBUS_SDA_L();
+	hi_udelay(5);
+	SMBUS_SCL_L();
+	hi_udelay(5);
+}
+
+/***************************************************************************
+* @brief      SMBus stop bit
+* @param      None
+* @retval     None
+****************************************************************************/
+void SMBus_Stop(void)
+{
+    SMBUS_SCL_L();
+    hi_udelay(5);
+	SMBUS_SDA_L();
+	hi_udelay(5);
+	SMBUS_SCL_H();
+	hi_udelay(5);
+	SMBUS_SDA_H();
+}
+/*******************************************************************************
+* 函数名: SMBus_SendBit
+* 功能: Send a bit on SMBus 82.5kHz
+* Input          : bit_out
+* Output         : None
+* Return         : None
+*******************************************************************************/
+void SMBus_SendBit(uint8_t bit_out)
+{
+    if(bit_out==0)
+    {
+        SMBUS_SDA_L();
+    }
+    else
+    {
+        SMBUS_SDA_H();
+    }
+    hi_udelay(2);                                        // Tsu:dat = 250ns minimum
+    SMBUS_SCL_H();                                        // Set SCL line
+    hi_udelay(6);                                        // High Level of Clock Pulse
+    SMBUS_SCL_L();                                        // Clear SCL line
+    hi_udelay(3);                                        // Low Level of Clock Pulse
+    return;
+}
+static uint8_t SMBUS_SDA_READ(void)
+{
+	IotGpioValue temp = {0};
+    IoTGpioGetInputVal(WIFI_IOT_IO_NAME_GPIO_12,&temp);
+    return temp;
+}
+
+/*******************************************************************************
+* Function Name  : SMBus_ReceiveBit
+* Description    : Receive a bit on SMBus
+* Input          : None
+* Output         : None
+* Return         : Ack_bit
+*******************************************************************************/
+uint8_t SMBus_ReceiveBit(void)
+{
+    uint8_t Ack_bit;
+
+    SMBUS_SDA_H();          //引脚靠外部电阻上拉,当作输入
+    hi_udelay(2);                        // High Level of Clock Pulse
+    SMBUS_SCL_H();                        // Set SCL line
+    hi_udelay(5);                        // High Level of Clock Pulse
+    if (SMBUS_SDA_READ())
+    {
+        Ack_bit=1;
+    }
+    else
+    {
+        Ack_bit=0;
+    }
+    SMBUS_SCL_L();                        // Clear SCL line
+    hi_udelay(3);                        // Low Level of Clock Pulse
+
+    return        Ack_bit;
+}
+
+/*******************************************************************************
+* 函数名: SMBus_SendByte
+* 功能: Send a byte on SMBus
+* Input          : Tx_buffer
+* Output         : None
+* Return         : None
+*******************************************************************************/
+uint8_t SMBus_SendByte(uint8_t Tx_buffer)
+{
+    uint8_t        Bit_counter;
+    uint8_t        Ack_bit;
+    uint8_t        bit_out;
+
+    for(Bit_counter=8; Bit_counter; Bit_counter--)
+    {
+        if (Tx_buffer&0x80)
+        {
+            bit_out=1;   // If the current bit of Tx_buffer is 1 set bit_out
+        }
+        else
+        {
+            bit_out=0;  // else clear bit_out
+        }
+        SMBus_SendBit(bit_out);                // Send the current bit on SDA
+        Tx_buffer<<=1;                                // Get next bit for checking
+    }
+
+    Ack_bit=SMBus_ReceiveBit();                // Get acknowledgment bit
+    return        Ack_bit;
+}
+
+/*******************************************************************************
+* 函数名: SMBus_ReceiveByte
+* 功能: Receive a byte on SMBus
+* Input          : ack_nack
+* Output         : None
+* Return         : RX_buffer
+*******************************************************************************/
+uint8_t SMBus_ReceiveByte(uint8_t ack_nack)
+{
+    uint8_t         RX_buffer;
+    uint8_t        Bit_Counter;
+
+    for(Bit_Counter=8; Bit_Counter; Bit_Counter--)
+    {
+        if(SMBus_ReceiveBit())                        // Get a bit from the SDA line
+        {
+            RX_buffer <<= 1;                        // If the bit is HIGH save 1  in RX_buffer
+            RX_buffer |=0x01;
+        }
+        else
+        {
+            RX_buffer <<= 1;                        // If the bit is LOW save 0 in RX_buffer
+            RX_buffer &=0xfe;
+        }
+    }
+    SMBus_SendBit(ack_nack);                        // Sends acknowledgment bit
+    return RX_buffer;
+}
+
+

+ 71 - 0
app/A20_VOICE/A20_VOICE_example.c

@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "VOICE.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+
+static void ExampleTask(void)
+{
+
+    BoardInit();
+
+    while (1)
+    {
+		
+        BeepStatusSet(ON);
+        LedRed1StatusSet(ON);
+        LedRed2StatusSet(ON);
+        LedBlue1StatusSet(OFF);
+        LedBlue2StatusSet(OFF);
+        osDelay(50);
+
+        BeepStatusSet(OFF);
+        LedRed1StatusSet(OFF);
+        LedRed2StatusSet(OFF);
+        LedBlue1StatusSet(ON);
+        LedBlue2StatusSet(ON);
+
+        osDelay(150);
+    }
+
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 26 - 0
app/A20_VOICE/BUILD.gn

@@ -0,0 +1,26 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A20_VOICE") {
+    sources = [
+        "src/VOICE.c",
+        "A20_VOICE_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "//device/bossay/hi3861_l0/sdk_liteos/include",
+        "include"
+    ]
+}

+ 24 - 0
app/A20_VOICE/include/VOICE.h

@@ -0,0 +1,24 @@
+#ifndef __VOICE_H__
+#define __VOICE_H__
+
+
+#include <stdint.h>
+
+
+typedef enum
+{
+	OFF = 0,
+	ON
+} SwitchStatus;
+
+void BoardInit(void);
+
+void BeepStatusSet(SwitchStatus status);
+void LedBlue1StatusSet(SwitchStatus status);
+void LedBlue2StatusSet(SwitchStatus status);
+void LedRed1StatusSet(SwitchStatus status);
+void LedRed2StatusSet(SwitchStatus status);
+
+#endif
+
+

+ 128 - 0
app/A20_VOICE/src/VOICE.c

@@ -0,0 +1,128 @@
+#include "VOICE.h"
+#include "iot_gpio.h"
+#include "iot_gpio_ex.h"
+
+
+#define LED_BLUE1_GPIO 5
+#define LED_BLUE2_GPIO 6
+#define LED_RED1_GPIO 14
+#define LED_RED2_GPIO 7
+#define BEEP_GPIO 8
+
+void BoardInit(void)
+{   
+    IoTGpioInit(LED_BLUE1_GPIO);
+    IoTGpioSetFunc(LED_BLUE1_GPIO, IOT_GPIO_FUNC_GPIO_5_GPIO);
+    IoTGpioSetDir(LED_BLUE1_GPIO, IOT_GPIO_DIR_OUT); // 设置GPIO_8为输出模式
+
+    IoTGpioInit(LED_BLUE2_GPIO);
+    IoTGpioSetFunc(LED_BLUE2_GPIO, IOT_GPIO_FUNC_GPIO_6_GPIO);
+    IoTGpioSetDir(LED_BLUE2_GPIO, IOT_GPIO_DIR_OUT); // 设置GPIO_8为输出模式
+
+    IoTGpioInit(LED_RED1_GPIO);
+    IoTGpioSetFunc(LED_RED1_GPIO, IOT_GPIO_FUNC_GPIO_14_GPIO);
+    IoTGpioSetDir(LED_RED1_GPIO, IOT_GPIO_DIR_OUT); // 设置为输入模式
+
+    IoTGpioInit(LED_RED2_GPIO);
+    IoTGpioSetFunc(LED_RED2_GPIO, IOT_GPIO_FUNC_GPIO_7_GPIO);
+    IoTGpioSetDir(LED_RED2_GPIO, IOT_GPIO_DIR_OUT); // 设置为输出模式
+
+    IoTGpioInit(BEEP_GPIO);
+    IoTGpioSetFunc(BEEP_GPIO, IOT_GPIO_FUNC_GPIO_8_GPIO);
+    IoTGpioSetDir(BEEP_GPIO, IOT_GPIO_DIR_OUT); // 设置为输入模式
+}
+
+
+/***************************************************************
+ * 函数名称: BeepStatusSet
+ * 说    明: Beep状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void BeepStatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(BEEP_GPIO, 1); // 设置GPIO_7输出高电平点亮灯
+    }
+    if (status == OFF) {
+        IoTGpioSetOutputVal(BEEP_GPIO, 0); // 设置GPIO_7输出低电平关闭灯
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedBlue1StatusSet
+ * 说    明: LED_Blue1状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedBlue1StatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_BLUE1_GPIO, 1); // 设置输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_BLUE1_GPIO, 0); // 设置输出低电平关闭灯
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedBlue2StatusSet
+ * 说    明: LED_Blue1状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedBlue2StatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_BLUE2_GPIO, 1); // 设置输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_BLUE2_GPIO, 0); // 设置输出低电平关闭灯
+    }
+}
+/***************************************************************
+ * 函数名称: LedBlue1StatusSet
+ * 说    明: LED_Red2状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedRed1StatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_RED1_GPIO, 1); // 设置输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_RED1_GPIO, 0); // 设置输出低电平关闭灯
+    }
+}
+
+/***************************************************************
+ * 函数名称: LedRed2StatusSet
+ * 说    明: LED_Red2状态设置
+ * 参    数: status,ENUM枚举的数据
+ *									OFF,关
+ *									ON,开
+ * 返 回 值: 无
+ ***************************************************************/
+void LedRed2StatusSet(SwitchStatus status)
+{
+    if (status == ON) {
+        IoTGpioSetOutputVal(LED_RED2_GPIO, 1); // 设置输出高电平点亮灯
+    }
+
+    if (status == OFF) {
+        IoTGpioSetOutputVal(LED_RED2_GPIO, 0); // 设置输出低电平关闭灯
+    }
+}
+

+ 102 - 0
app/A21_Agriculture/A21_Agriculture_example.c

@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "DHT11.h"
+#include "BH1750.h"
+#include "cmsis_os2.h"
+#include "ohos_init.h"
+
+
+#define TASK_STACK_SIZE 1024 * 8
+#define TASK_PRIO 25
+uint8_t fan_status;
+
+static void FanTask(void)
+{
+    while (1)
+    {
+        if(fan_status == 1)
+            FanStatusSet(ON,1);
+        else
+        {
+            FanStatusSet(OFF,0);
+            sleep(1);
+        }
+    }
+}
+
+static void ExampleTask(void)
+{
+    int ret;
+    uint8_t dht_temperature;
+	uint8_t dht_humidity;
+    float Lux;
+    // BoardInit();
+     //GPIO_0复用为I2C1_SDA
+    ret = BoardInit();
+    if (ret != 0) {
+        printf("E53_SC1 Init failed!\r\n");
+        return;
+    }
+    while (1)
+    {
+		DHT11_Read_Data(&dht_temperature,&dht_humidity);
+		printf("temperature=%d \r\n",dht_temperature);
+		printf("humidity=%d %%\r\n",dht_humidity);
+        ret = BH1750ReadData(&Lux);
+        if (ret != 0) {
+            printf("E53_SC1 Read Data failed!\r\n");
+            return;
+        }
+        printf("Lux data:%.2f\r\n", Lux);
+        if (Lux < 20) {
+            fan_status = 1;
+            LightStatusSet(ON);
+        } else {
+            LightStatusSet(OFF);
+            fan_status = 0;
+            FanStatusSet(OFF,1);
+        }
+        sleep(3);
+    }
+}
+
+static void ExampleEntry(void)
+{
+    osThreadAttr_t attr;
+
+    attr.name = "ExampleTask";
+    attr.attr_bits = 0U;
+    attr.cb_mem = NULL;
+    attr.cb_size = 0U;
+    attr.stack_mem = NULL;
+    attr.stack_size = TASK_STACK_SIZE;
+    attr.priority = TASK_PRIO;
+
+
+    if (osThreadNew((osThreadFunc_t)ExampleTask, NULL, &attr) == NULL) {
+        printf("Failed to create ExampleTask!\n");
+    }
+    attr.name = "FanTask";
+    if (osThreadNew((osThreadFunc_t)FanTask, NULL, &attr) == NULL) {
+        printf("Failed to create FanTask!\n");
+    }
+}
+
+APP_FEATURE_INIT(ExampleEntry);

+ 27 - 0
app/A21_Agriculture/BUILD.gn

@@ -0,0 +1,27 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("A21_Agriculture") {
+    sources = [
+        "src/DHT11.c",
+        "src/BH1750.c",
+        "A21_Agriculture_example.c"
+    ]
+
+    include_dirs = [
+        "//base/iot_hardware/peripheral/interfaces/kits",
+        "//device/bossay/hi3861_l0/iot_hardware_hals/include",
+        "//device/bossay/hi3861_l0/sdk_liteos/include",
+        "include"
+    ]
+}

Някои файлове не бяха показани, защото твърде много файлове са промени