代码上传
This commit is contained in:
commit
6728aa47ca
21
README.md
Normal file
21
README.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
## 1、下载3.0LTS代码
|
||||
|
||||
```
|
||||
repo init -u git@gitee.com:openharmony/manifest.git -b OpenHarmony-3.0-LTS --no-repo-verify
|
||||
repo sync -c
|
||||
repo forall -c 'git lfs pull'
|
||||
```
|
||||
|
||||
## 2、将bossay_release_out中的代码放置与对应目录
|
||||
|
||||
其中:
|
||||
app文件夹放到applications/sample
|
||||
iot_link放到third_party目录下
|
||||
vendor和device中的文件夹放置对应目录
|
||||
|
||||
## 3、编译
|
||||
hb set
|
||||
|
||||
选择bossay的产品
|
||||
|
||||
hb build -f 编译代码
|
||||
92
app/A01_DOOR/A01_DOOR_example.c
Normal file
92
app/A01_DOOR/A01_DOOR_example.c
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A01_DOOR/BUILD.gn
Normal file
26
app/A01_DOOR/BUILD.gn
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2020 Jinan Bosai Network 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
app/A01_DOOR/include/DOOR.h
Normal file
23
app/A01_DOOR/include/DOOR.h
Normal file
|
|
@ -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
app/A01_DOOR/src/DOOR.c
Normal file
99
app/A01_DOOR/src/DOOR.c
Normal file
|
|
@ -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
app/A02_MQ5/A02_MQ5.c
Normal file
83
app/A02_MQ5/A02_MQ5.c
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A02_MQ5/BUILD.gn
Normal file
25
app/A02_MQ5/BUILD.gn
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Copyright (c) 2020 Jinan Bosai Network 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
app/A02_MQ5/include/MQ5.h
Normal file
32
app/A02_MQ5/include/MQ5.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A02_MQ5/src/MQ5.c
Normal file
144
app/A02_MQ5/src/MQ5.c
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A03_MAX30102/A03_MAX30102_example.c
Normal file
193
app/A03_MAX30102/A03_MAX30102_example.c
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A03_MAX30102/BUILD.gn
Normal file
26
app/A03_MAX30102/BUILD.gn
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A03_MAX30102/include/algorithm.h
Normal file
85
app/A03_MAX30102/include/algorithm.h
Normal file
|
|
@ -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
app/A03_MAX30102/include/max30102.h
Normal file
42
app/A03_MAX30102/include/max30102.h
Normal file
|
|
@ -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
app/A03_MAX30102/src/algorithm.c
Normal file
379
app/A03_MAX30102/src/algorithm.c
Normal file
|
|
@ -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
app/A03_MAX30102/src/max30102.c
Normal file
237
app/A03_MAX30102/src/max30102.c
Normal file
|
|
@ -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
app/A03_MAX30102_B/A03_MAX30102_example copy.c
Normal file
193
app/A03_MAX30102_B/A03_MAX30102_example copy.c
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A03_MAX30102_B/A03_MAX30102_example.c
Normal file
89
app/A03_MAX30102_B/A03_MAX30102_example.c
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A03_MAX30102_B/A03_MAX30102_example1.c
Normal file
177
app/A03_MAX30102_B/A03_MAX30102_example1.c
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A03_MAX30102_B/BUILD.gn
Normal file
27
app/A03_MAX30102_B/BUILD.gn
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Copyright (c) 2020 Jinan Bosai Network 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
app/A03_MAX30102_B/include/algorithm.h
Normal file
63
app/A03_MAX30102_B/include/algorithm.h
Normal file
|
|
@ -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
app/A03_MAX30102_B/include/algorithm1.h
Normal file
99
app/A03_MAX30102_B/include/algorithm1.h
Normal file
|
|
@ -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
app/A03_MAX30102_B/include/blood.h
Normal file
25
app/A03_MAX30102_B/include/blood.h
Normal file
|
|
@ -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
app/A03_MAX30102_B/include/max30102 copy.h
Normal file
42
app/A03_MAX30102_B/include/max30102 copy.h
Normal file
|
|
@ -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
app/A03_MAX30102_B/include/max30102.h
Normal file
46
app/A03_MAX30102_B/include/max30102.h
Normal file
|
|
@ -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
app/A03_MAX30102_B/src/algorithm.c
Normal file
248
app/A03_MAX30102_B/src/algorithm.c
Normal file
|
|
@ -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
app/A03_MAX30102_B/src/algorithm1.c
Normal file
363
app/A03_MAX30102_B/src/algorithm1.c
Normal file
|
|
@ -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
app/A03_MAX30102_B/src/blood.c
Normal file
246
app/A03_MAX30102_B/src/blood.c
Normal file
|
|
@ -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
app/A03_MAX30102_B/src/max30102 copy 2.c
Normal file
237
app/A03_MAX30102_B/src/max30102 copy 2.c
Normal file
|
|
@ -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
app/A03_MAX30102_B/src/max30102.c
Normal file
249
app/A03_MAX30102_B/src/max30102.c
Normal file
|
|
@ -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
app/A04_NOISE/A04_NOISE_example.c
Normal file
71
app/A04_NOISE/A04_NOISE_example.c
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A04_NOISE/BUILD.gn
Normal file
26
app/A04_NOISE/BUILD.gn
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2020 Jinan Bosai Network 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
app/A04_NOISE/include/noise.h
Normal file
23
app/A04_NOISE/include/noise.h
Normal file
|
|
@ -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
app/A04_NOISE/src/noise.c
Normal file
103
app/A04_NOISE/src/noise.c
Normal file
|
|
@ -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
app/A05_WATER/A02_WATER_example.c
Normal file
74
app/A05_WATER/A02_WATER_example.c
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A05_WATER/BUILD.gn
Normal file
26
app/A05_WATER/BUILD.gn
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2020 Jinan Bosai Network 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
app/A05_WATER/include/WATER.h
Normal file
23
app/A05_WATER/include/WATER.h
Normal file
|
|
@ -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
app/A05_WATER/src/WATER.c
Normal file
100
app/A05_WATER/src/WATER.c
Normal file
|
|
@ -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
app/A06_VOICE_SWITCH/A11_PM2_5_example.c
Normal file
66
app/A06_VOICE_SWITCH/A11_PM2_5_example.c
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A06_VOICE_SWITCH/BUILD.gn
Normal file
26
app/A06_VOICE_SWITCH/BUILD.gn
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2020 Jinan Bosai Network 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
app/A06_VOICE_SWITCH/include/PM2_5.h
Normal file
29
app/A06_VOICE_SWITCH/include/PM2_5.h
Normal file
|
|
@ -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
app/A06_VOICE_SWITCH/src/PM2_5.c
Normal file
89
app/A06_VOICE_SWITCH/src/PM2_5.c
Normal file
|
|
@ -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
app/A07_WATHER/A07_WATHER_example.c
Normal file
85
app/A07_WATHER/A07_WATHER_example.c
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A07_WATHER/BUILD.gn
Normal file
28
app/A07_WATHER/BUILD.gn
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A07_WATHER/include/WATHER.h
Normal file
21
app/A07_WATHER/include/WATHER.h
Normal file
|
|
@ -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
app/A07_WATHER/include/bmp280.h
Normal file
172
app/A07_WATHER/include/bmp280.h
Normal file
|
|
@ -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 Jinan Bosai Network 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
app/A07_WATHER/include/dht21.h
Normal file
19
app/A07_WATHER/include/dht21.h
Normal file
|
|
@ -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
app/A07_WATHER/src/WATHER.c
Normal file
53
app/A07_WATHER/src/WATHER.c
Normal file
|
|
@ -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
app/A07_WATHER/src/bmp280.c
Normal file
307
app/A07_WATHER/src/bmp280.c
Normal file
|
|
@ -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 Jinan Bosai Network 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
app/A07_WATHER/src/dht21.c
Normal file
245
app/A07_WATHER/src/dht21.c
Normal file
|
|
@ -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
app/A08_NFC/A08_NFC_example.c
Normal file
81
app/A08_NFC/A08_NFC_example.c
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A08_NFC/BUILD.gn
Normal file
26
app/A08_NFC/BUILD.gn
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2020 Jinan Bosai Network 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
app/A08_NFC/include/MPU6050.h
Normal file
81
app/A08_NFC/include/MPU6050.h
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A08_NFC/include/pn532.h
Normal file
277
app/A08_NFC/include/pn532.h
Normal file
|
|
@ -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
app/A08_NFC/include/pn532_hi3861.h
Normal file
48
app/A08_NFC/include/pn532_hi3861.h
Normal file
|
|
@ -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
app/A08_NFC/src/MPU6050.c
Normal file
381
app/A08_NFC/src/MPU6050.c
Normal file
|
|
@ -0,0 +1,381 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A08_NFC/src/pn532.c
Normal file
498
app/A08_NFC/src/pn532.c
Normal file
|
|
@ -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
app/A08_NFC/src/pn532_hi3861.c
Normal file
172
app/A08_NFC/src/pn532_hi3861.c
Normal file
|
|
@ -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
app/A09_Elevator/A09_Elevator_example.c
Normal file
74
app/A09_Elevator/A09_Elevator_example.c
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A09_Elevator/BUILD.gn
Normal file
26
app/A09_Elevator/BUILD.gn
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2020 Jinan Bosai Network 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
app/A09_Elevator/include/elevator.h
Normal file
32
app/A09_Elevator/include/elevator.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A09_Elevator/src/elevator.c
Normal file
237
app/A09_Elevator/src/elevator.c
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A11_PM2_5/A11_PM2_5_example.c
Normal file
63
app/A11_PM2_5/A11_PM2_5_example.c
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A11_PM2_5/BUILD.gn
Normal file
26
app/A11_PM2_5/BUILD.gn
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A11_PM2_5/include/PM2_5.h
Normal file
30
app/A11_PM2_5/include/PM2_5.h
Normal file
|
|
@ -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
app/A11_PM2_5/src/PM2_5.c
Normal file
120
app/A11_PM2_5/src/PM2_5.c
Normal file
|
|
@ -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
app/A12_SOCKET/A12_SOCKET_example.c
Normal file
78
app/A12_SOCKET/A12_SOCKET_example.c
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A12_SOCKET/BUILD.gn
Normal file
25
app/A12_SOCKET/BUILD.gn
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A12_SOCKET/include/SOCKET.h
Normal file
32
app/A12_SOCKET/include/SOCKET.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A12_SOCKET/src/SOCKET.c
Normal file
126
app/A12_SOCKET/src/SOCKET.c
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A13_FLAME/A13_FLAME_example..c
Normal file
73
app/A13_FLAME/A13_FLAME_example..c
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A13_FLAME/BUILD.gn
Normal file
26
app/A13_FLAME/BUILD.gn
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2020 Jinan Bosai Network 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
app/A13_FLAME/include/flame.h
Normal file
23
app/A13_FLAME/include/flame.h
Normal file
|
|
@ -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
app/A13_FLAME/src/flame.c
Normal file
103
app/A13_FLAME/src/flame.c
Normal file
|
|
@ -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
app/A14_CAR/A01_DOOR_example.c
Normal file
112
app/A14_CAR/A01_DOOR_example.c
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A14_CAR/BUILD.gn
Normal file
26
app/A14_CAR/BUILD.gn
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A14_CAR/include/DOOR.h
Normal file
23
app/A14_CAR/include/DOOR.h
Normal file
|
|
@ -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
app/A14_CAR/src/DOOR.c
Normal file
98
app/A14_CAR/src/DOOR.c
Normal file
|
|
@ -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
app/A16_PLAY/A24_GPS_example.c
Normal file
69
app/A16_PLAY/A24_GPS_example.c
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A16_PLAY/BUILD.gn
Normal file
25
app/A16_PLAY/BUILD.gn
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Copyright (c) 2020 Jinan Bosai Network 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
app/A16_PLAY/include/L76K.h
Normal file
38
app/A16_PLAY/include/L76K.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A16_PLAY/src/L76K.c
Normal file
81
app/A16_PLAY/src/L76K.c
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A17_CH2O/A17_CH2O.c
Normal file
85
app/A17_CH2O/A17_CH2O.c
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A17_CH2O/BUILD.gn
Normal file
25
app/A17_CH2O/BUILD.gn
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A17_CH2O/include/CH2O.h
Normal file
33
app/A17_CH2O/include/CH2O.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A17_CH2O/src/CH2O.c
Normal file
168
app/A17_CH2O/src/CH2O.c
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A18_ST02D/A18_ST02D_example.c
Normal file
90
app/A18_ST02D/A18_ST02D_example.c
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A18_ST02D/BUILD.gn
Normal file
26
app/A18_ST02D/BUILD.gn
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2022 Jinan Bosai Network Technology Co., LTD 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
app/A18_ST02D/include/st02d.h
Normal file
27
app/A18_ST02D/include/st02d.h
Normal file
|
|
@ -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
app/A18_ST02D/src/st02d.c
Normal file
119
app/A18_ST02D/src/st02d.c
Normal file
|
|
@ -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
app/A19_MXL90614/A19_MXL90614_example.c
Normal file
71
app/A19_MXL90614/A19_MXL90614_example.c
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A19_MXL90614/BUILD.gn
Normal file
27
app/A19_MXL90614/BUILD.gn
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Copyright (c) 2020 Jinan Bosai Network 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
app/A19_MXL90614/include/mlx90614.h
Normal file
32
app/A19_MXL90614/include/mlx90614.h
Normal file
|
|
@ -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
app/A19_MXL90614/include/smbus.h
Normal file
26
app/A19_MXL90614/include/smbus.h
Normal file
|
|
@ -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
app/A19_MXL90614/src/mlx90614.c
Normal file
246
app/A19_MXL90614/src/mlx90614.c
Normal file
|
|
@ -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
app/A19_MXL90614/src/smbus.c
Normal file
158
app/A19_MXL90614/src/smbus.c
Normal file
|
|
@ -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
app/A20_VOICE/A20_VOICE_example.c
Normal file
71
app/A20_VOICE/A20_VOICE_example.c
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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
app/A20_VOICE/BUILD.gn
Normal file
26
app/A20_VOICE/BUILD.gn
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2020 Jinan Bosai Network 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
app/A20_VOICE/include/VOICE.h
Normal file
24
app/A20_VOICE/include/VOICE.h
Normal file
|
|
@ -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
app/A20_VOICE/src/VOICE.c
Normal file
128
app/A20_VOICE/src/VOICE.c
Normal file
|
|
@ -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
app/A21_Agriculture/A21_Agriculture_example.c
Normal file
102
app/A21_Agriculture/A21_Agriculture_example.c
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Jinan Bosai Network 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);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user