Job_SignsPads/STM32/Code/STM32F405/USER/main.c

1403 lines
44 KiB
C
Raw Normal View History

2025-04-22 02:29:37 +00:00
#include "main.h"
#include <math.h>
#include <stdio.h>
#include "key.h"
#include "cJSON.h"
// #include "nnom.h" //神经网络的函数调用,不需要改动
#include "cal_sleep_stage.h" //计算睡眠周期
#include "myMalloc.h"
// #include "image.h"
// #include "ppg_data.h" //测试用到的数据集这个文件是用py文件生成的不需要改已更新
// 保存了网络结构的参数这个文件是用py文件生成的不需要改
// #include "breath_heart.h" //预测呼吸心跳的模型
// #include "pre_stage.h" //预测睡眠阶段的模型
#include "stmflash.h"
#include <stdlib.h>
#include "wificom.h"
#include <stdio.h>
#include <time.h>
#include "find_peaks.h"
#include "queue_mem.h" //分配内存的函数
#include "sleepReport.h"
#include "drv_SGM58031.h"
// DSP 相关
#include "MyTool.h"
#include "arm_math.h"
#include "MyAlgorithm.h"
#include "MyBandFitter.h"
#if THE_VERSION
unsigned char version[8] = {0xA5, 0x5A, 0x08, 0x00, 0xBB, 0x01, 0x00, 0x1a}; // 版本号E.1.0.26 -> 养老版本
#else
unsigned char version[8] = {0xA5, 0x5A, 0x08, 0x00, 0xBB, 0x01, 0x01, 0x05}; // 版本号M.1.1.5 -> BCS版本
#endif
/**********************
* IROM
* IROM1:0x8010000--0x40000(old版本)
* IROM2:0x8080000--0x40000(bin文件给服务器)
***********************/
// 设置一个模型运行的内存空间40Kb
// 后续会在main函数中对它初始化。
// 如果定义了NNOM_USING_STATIC_MEMORY就是使用静态内存
// 如果没有定义,修改NNOM_USING_STATIC_MEMORY的方法在nnom_port.h中
// 这部分不需要改动,使用静态内存比较稳定,而且空间也小。
/**********************
report_get_buf
* 0~99
* 0~9+
* 10~29:+++
* 200~200+1024*9
* 200+1024*9~200+1024*(9*2)
***********************/
/**********************
* report_abnormal_buf
* 0~7
* 8~9
* 10~11:
* 12~13:
***********************/
struct Sleep_report
{
// uint8_t report_save_buf[1200]; //存储buf
// uint8_t report_send_buf[1200]; //读取buf
uint8_t report_get_buf[200]; // 前期介绍
// uint8_t report_abnormal_buf[2000]; //异常存储
uint8_t time_num[8]; // 时间buf
int report_save_len; // 存储长度
int report_send_len; // 读取长度
char breathe_abnormal_flg; // 呼吸异常标志
uint16_t breathe_abnormal_length; // 呼吸异常长度
uint16_t breathe_abnormal_time; // 呼吸异常长度
char all_num; // 总天数1~7
char report_num; // 当前天数1~7
char circle_num; // 当前循环条数
char report_time_flg; // 更新时间标志位
uint32_t storage_location_num; // 当前存储数量--地址等于
uint8_t storage_location_buf[4]; // 存储数量转换buf
int equipment_status_time; // 判断离床时间
char sleep_stage_flg; // 出睡眠报告的标志位
} Sleep;
uint32_t FlashPtr = 0X08004000; // 呼吸心率上下限存储地址
int currentSize_num = 0; // 进行睡眠计算时间
char OffBed_Flag = 0;
uint16_t number0 = 0;
int BH_time = 0;
int stage_time = 0;
char start_calculate_flg = 0;
char start_stage_flg = 0;
char led_flg = 0;
char uart_flg = 0;
int uart_time = 0;
int led_num = 0;
char stage_len = 0;
float ppg_data2_buf[2] = {0};
float Local_ON_BED_Threshold = 0.0f;
float Local_OFF_BED_Threshold = 0.0f;
char ppg_stage_index = 0;
int led_time = 200;
char OffBed_Time = 0;
char queue_flg = 0;
char FFT_Count_State_Flag = 0;
char FFT_Calculate_State_Flag = 0;
char start_ConnectNet_flg = 0;
char Breathe_H = 0x19;
char Breathe_L = 0x08;
char HeartRate_H = 0x64;
char HeartRate_L = 0x37;
float Diff = 0.0f;
float Diff_Detail = 0.0f;
extern uint8_t BreathRate;
extern uint8_t HeartBeatRate;
extern uint8_t BreathRate_Record;
extern uint8_t HeartBeatRate_Record;
extern int FitterCount_Heart;
extern int FitterCount_Breath;
extern int FitterCount_CheckBed;
extern char FitterCollectDoneFlag_Heart;
extern char FitterCollectDoneFlag_Breath;
extern char FitterCollectDoneFlag_CheckBed;
extern char WarnConfigDoneFlag;
extern warning_config_t warning_config;
WarningMsg_t WarningMsg; // 告警消息
uint8_t g_mon, g_day, g_hour, g_min, g_sec = 0;
uint16_t Roll_Over_Count = 0; // 翻身计数
uint16_t Sleep_Report_Start_Flag = 0; // 睡眠报告开始
uint16_t TimeClock_Recalibrate_Count = 0; // 重新校准时间避免时间戳错误
// 睡眠报告的存储--15天
typedef struct SleepRecord_T
{
char SleepReport_Directory[REPORT_SAVE_SIZE]; // 存储字典
char SleepReport_CurrentSaveNum; // 当前值
char SleepReport_CurrentIndex; // 当前角标
uint8_t SleepReport_TimeStamp[8]; // 时间戳
uint8_t SleepReport_Score; // 得分
uint8_t SleepReport_Efficiency; // 效率
} SleepRecord_t;
SleepRecord_t SleepRecord;
uint32_t Calibration_Template = 0;
uint32_t Calibration_Template_2 = 0;
float Optical_Calibration_Value = 0.0f;
float Optical_Calibration_Value_OffBed = 0.0f;
float Optical_Calibration_Value_OnBed = 0.0f;
char Calibration_Off_Bed_Done_Flag = 0;
char Calibration_In_Bed_Done_Flag = 0;
char PowerOn_NetStatusFlg = 0; // 上电状态标志位
char PowerOn_OneMinuteCount = 0; // 上电一分钟计次
char PowerOn_OneMinuteCount_Start = 0; // 上电一分钟启动标志
char PowerOn_StartConfigFlg = 0; // 上电配网启动标志位
struct struct_stage get_sleep_stage;
int score_eff_buff[2] = {0};
float ppg_data_500_buf[500] = {0}; // 500发送数据集
unsigned short int ppg_stage_buf[10] = {0}; // stage 的数据是一秒钟10个
unsigned short int BH_data_500[500] = {0};
// unsigned short int sdst[3000] = {0}; // 接收呼吸心跳中间值
signed long int max_min2[2] = {-500, 50000}; // 数据集中的最大值和最小值
unsigned short int c_BH_max = 0;
unsigned short int c_BH_index = 0;
unsigned short int c_BH_num = 0;
// unsigned char que_static_buf[1024 * 18] = {0}; // 18*300=
#ifdef NNOM_USING_STATIC_MEMORY
// uint8_t BH_static_buf[1024 * 41] = {0}; // 呼吸心跳 模型 内存
#ifndef NOT_PRE_STAGE
uint8_t Stage_static_buf[1024 * 28] = {0}; // 失眠分期 模型内存
#endif
#endif
char wifi_json_flg = 0;
// char info[512] = {0};
// uint8_t s[256] = {0};
char MovementBuffer[REPORT_BUFFER_MAX]; // 12小时的体动数据 __attribute__((at(0x080E0000)))
char HeartRateBuffer[REPORT_BUFFER_MAX]; // 12小时的心率数据__attribute__((at(0x080E0000 + (0x400))))
char BreathRateBuffer[REPORT_BUFFER_MAX]; // 12小时的呼吸数据__attribute__((at(0x080E0000 + (0x400))))
char sleepStatusBuffer[REPORT_BUFFER_MAX]; // 12小时的睡眠阶段数据__attribute__((at(0x080E0000 + (0x800))))
char sleepTempBuffer[REPORT_BUFFER_MAX + 20] = {0}; // 12小时的缓存数据(包括上报)
extern warning_config_t warning_config;
#define FLASH_SAVE_ADDR 0X080C0000 // 代码用了126K地址需要大于它
// void c_BH_stage(nnom_model_t *BH_model, nnom_model_t *stage_model);
// void pre_bh(nnom_model_t *BH_model);
int MyDSP_Init(void);
void MyFitter(void);
/**
* @function: IWDG_Init
* @brief: None
* @return {*}
* @author: lzc
*/
void IWDG_Init(void)
{
// 1、 取消寄存器写保护:
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
// 2、设置独立看门狗的预分频系数确定时钟:125HZ
IWDG_SetPrescaler(IWDG_Prescaler_256);
// 3、设置看门狗重装载值确定溢出时间:32s
IWDG_SetReload(4000);
// 4、重新载入计数器
IWDG_ReloadCounter();
// 5、使能
IWDG_Enable(); // 使能看门狗 打开看门狗好像会导致光功率值跳动?
}
/**
* @function: IWDG_Feed
* @brief:
* @return {*}
* @author: lzc
*/
void IWDG_Feed(void)
{
// 把重装载寄存器的值放到计数器中喂狗防止IWDG复位
// 当计数器的值减到0的时候会产生系统复位
IWDG_ReloadCounter();
}
/**
* @function: SleepReportSend
* @brief: None
* @param {unsigned char} *buf
* @param {int} size
* @return {*}
* @author: lzc
*/
char LastSleepReportPacket_Flag = 0;
char SleepReportSend(unsigned char *buf, int size, int circle_num)
{
int PacketLength = 17;
char Header[2] = {0xA5, 0x5A};
char FrameLength[2] = {0};
char FrameType[1] = {0x02};
char TimeStamp[8] = {0};
char TestScoreBuffer[2] = {0x27, 0x40};
char TestPackets[2] = {0x01, 0x01};
char TestPacketBuffer[17] = {0};
char TestDataSend[321] = {0}; // 最大 1H 的数据
uint16_t Length = size + 17;
FrameLength[1] = Length >> 8;
FrameLength[0] = Length & 0xff;
memcpy(TimeStamp, Sleep.time_num, sizeof(TimeStamp));
// 将帧头赋值
strcat(TestPacketBuffer, Header);
// 长度
TestPacketBuffer[2] = FrameLength[0];
TestPacketBuffer[3] = FrameLength[1];
// 将帧类型赋值
TestPacketBuffer[4] = FrameType[0];
// 将时间赋值
TestPacketBuffer[5] = TimeStamp[0];
TestPacketBuffer[6] = TimeStamp[1];
TestPacketBuffer[7] = TimeStamp[2];
TestPacketBuffer[8] = TimeStamp[3];
TestPacketBuffer[9] = TimeStamp[4];
TestPacketBuffer[10] = TimeStamp[5];
TestPacketBuffer[11] = TimeStamp[6];
TestPacketBuffer[12] = TimeStamp[7];
// 得分 + 效率
TestPacketBuffer[13] = get_sleep_stage.score; // 将得分和效率传递给数组;
TestPacketBuffer[14] = get_sleep_stage.eff;
// 数据包数
TestPacketBuffer[16] = circle_num + 1;
if (LastSleepReportPacket_Flag == 1)
TestPacketBuffer[15] = circle_num + 1;
else
TestPacketBuffer[15] = 24;
// 数据拷贝
memcpy(TestDataSend, TestPacketBuffer, sizeof(TestPacketBuffer));
// memcpy(TestDataSend + 17, buf, size);
memcpy(TestDataSend + 17, buf + (REPORT_SEND_COUNTS * circle_num), size);
// WIFI 发送的Buffer
wifi_crc_send((uint8_t *)TestDataSend, PacketLength + size);
// 清空buffer
memset(TestDataSend, 0, sizeof(TestDataSend));
return 0;
}
/**
* @function: BaseParmReport
* @brief
* @return {*}
* @author: lzc
*/
// TODO: 增加夜间翻身次数的统计以及上报
void BaseParmReport(void)
{
int PacketLength = 32 - 4;
char Header[2] = {0xA5, 0x5A};
char FrameLength[2] = {0};
char FrameType[1] = {0x04};
char TimeStamp[8] = {0};
char ParmSendBuffer[32] = {0};
FrameLength[1] = PacketLength >> 8;
FrameLength[0] = PacketLength & 0xff;
memcpy(TimeStamp, &timeClockCount, sizeof(timeClockCount));
// 将帧头赋值
strcat(ParmSendBuffer, Header);
// 长度
ParmSendBuffer[2] = FrameLength[0];
ParmSendBuffer[3] = FrameLength[1];
// 将帧类型赋值
ParmSendBuffer[4] = FrameType[0];
// 将时间赋值
ParmSendBuffer[5] = TimeStamp[0];
ParmSendBuffer[6] = TimeStamp[1];
ParmSendBuffer[7] = TimeStamp[2];
ParmSendBuffer[8] = TimeStamp[3];
ParmSendBuffer[9] = TimeStamp[4];
ParmSendBuffer[10] = TimeStamp[5];
ParmSendBuffer[11] = TimeStamp[6];
ParmSendBuffer[12] = TimeStamp[7];
// 将参数正常赋值
ParmSendBuffer[13] = Roll_Over_Count; // 翻身次数计数
// WIFI 发送的Buffer
if (OffBed_Flag == 4) // 在床才会发送数据
#if SLEEP_DEBUG_MODE
;
#else
// 每天早上830 报一次夜间的翻身次数
// if ((g_hour == 8 && g_min == 30 && g_sec == 0) && Roll_Over_Count != 0)
// {
// wifi_crc_send((uint8_t *)ParmSendBuffer, 28);
// Roll_Over_Count = 0; // 翻身次数清除
// }
#endif
// 清空buffer
memset(ParmSendBuffer, 0, sizeof(ParmSendBuffer));
}
#define NumberToWrite 1200
/**
* @function:SleepReportSave
* @brief
* @param {unsigned char} *buf
* @param {char} SaveIndex
* @param {unsigned char} *TimeStamp_buf
* @param {char} Score
* @param {char} Efficiency
* @return {*}
* @author: lzc
*/
char SleepReportSave(unsigned char *buf, char SaveIndex, unsigned char *TimeStamp_buf, char Score, char Efficiency)
{
uint8_t Result = 0;
uint8_t Error_cnt = 0;
uint32_t Report_Offset = 0;
Report_Offset += (0x4000 * SaveIndex);
// 由于buffer大小为7200同时扇区最大为4KB需要存储两次存满两个扇区
// 第一个扇区存储时间戳以及一些其他东西
unsigned char TimeStamp[8] = {0}; // 时间戳
unsigned char Sleep_Score_Eff[2] = {0}; // 睡眠得分和效率
// 用于比较
unsigned char cmp_Buffer[8] = {0}; // 时间戳
unsigned char cmp_Score_Eff_Buffer[2] = {0}; // 睡眠得分和效率
// 第二个扇区存储第一块的数据,第三个存储后面的
unsigned char temp_Buffer[NumberToWrite] = {0}; // 原始数据的缓存
// unsigned char SleepReport_Length[4] = {0}; // 睡眠报告数据长度
// 复制时间戳以及得分和效率
Sleep_Score_Eff[0] = (unsigned char)Score;
Sleep_Score_Eff[1] = (unsigned char)Efficiency;
memcpy(TimeStamp, TimeStamp_buf, sizeof(TimeStamp));
// 先擦除INFO位置的扇区
EN25QXX_Erase_Sector(FLASH_SLEEP_REPORT_INFO_ADDRESS + Report_Offset);
// // NOTE: 存储时间戳
do
{
EN25QXX_Write(TimeStamp, (FLASH_SLEEP_REPORT_TIMESTAMP_ADDRESS + Report_Offset), sizeof(TimeStamp));
memset(cmp_Buffer, 0, sizeof(cmp_Buffer));
EN25QXX_Read(cmp_Buffer, (FLASH_SLEEP_REPORT_TIMESTAMP_ADDRESS + Report_Offset), sizeof(cmp_Buffer));
Result = memcmp(TimeStamp, cmp_Buffer, sizeof(TimeStamp));
} while (Result != 0);
memset(TimeStamp, 0, sizeof(TimeStamp));
memset(cmp_Buffer, 0, sizeof(cmp_Buffer));
// NOTE: 存储得分&&效率
do
{
EN25QXX_Write(Sleep_Score_Eff, (FLASH_SLEEP_REPORT_SCORE_EFFICIENCY_ADDRESS + Report_Offset), sizeof(Sleep_Score_Eff));
memset(cmp_Score_Eff_Buffer, 0, sizeof(cmp_Score_Eff_Buffer));
EN25QXX_Read(cmp_Score_Eff_Buffer, (FLASH_SLEEP_REPORT_SCORE_EFFICIENCY_ADDRESS + Report_Offset), sizeof(cmp_Score_Eff_Buffer));
Result = memcmp(Sleep_Score_Eff, cmp_Score_Eff_Buffer, sizeof(Sleep_Score_Eff));
} while (Result != 0);
memset(Sleep_Score_Eff, 0, sizeof(Sleep_Score_Eff));
memset(cmp_Score_Eff_Buffer, 0, sizeof(cmp_Score_Eff_Buffer));
// 再擦除数据块1 的扇区
EN25QXX_Erase_Sector(FLASH_SLEEP_REPORT_DATA_1_ADDRESS + Report_Offset);
// 每一块扇区存3600字节
for (int i = 0; i < 3; i++)
{
// 拷贝数据
memcpy(temp_Buffer, buf + (NumberToWrite * i), NumberToWrite);
// 写块1的数据
EN25QXX_Write(temp_Buffer, (FLASH_SLEEP_REPORT_DATA_1_ADDRESS + Report_Offset + (NumberToWrite * i)), NumberToWrite);
// 清除数据
memset(temp_Buffer, 0, NumberToWrite);
// 读取做校验
EN25QXX_Read(temp_Buffer, (FLASH_SLEEP_REPORT_DATA_1_ADDRESS + Report_Offset + (NumberToWrite * i)), NumberToWrite);
// 比较
Result = memcmp(temp_Buffer, buf + (NumberToWrite * i), NumberToWrite);
if (Result != 0)
{
i--;
Error_cnt++;
}
if (Error_cnt >= 10)
{
Error_cnt = 0;
break;
}
}
// 清除数据
memset(temp_Buffer, 0, NumberToWrite);
// 再擦除数据块2 的扇区
EN25QXX_Erase_Sector(FLASH_SLEEP_REPORT_DATA_2_ADDRESS + Report_Offset);
// 每一块扇区存3600字节
for (int i = 0; i < 3; i++)
{
// 拷贝数据
memcpy(temp_Buffer, buf + (3 * NumberToWrite) + (NumberToWrite * i), NumberToWrite);
// 写块2的数据
EN25QXX_Write(temp_Buffer, (FLASH_SLEEP_REPORT_DATA_2_ADDRESS + Report_Offset + (NumberToWrite * i)), NumberToWrite);
// 清除数据
memset(temp_Buffer, 0, NumberToWrite);
// 读取做校验
EN25QXX_Read(temp_Buffer, (FLASH_SLEEP_REPORT_DATA_2_ADDRESS + Report_Offset + (NumberToWrite * i)), NumberToWrite);
// 比较
Result = memcmp(temp_Buffer, buf + (3 * NumberToWrite) + (NumberToWrite * i), NumberToWrite);
if (Result != 0)
{
i--;
Error_cnt++;
}
if (Error_cnt >= 10)
break;
}
// 清除数据
memset(temp_Buffer, 0, sizeof(temp_Buffer));
// 再擦除保留数据块的扇区
EN25QXX_Erase_Sector(FLASH_SLEEP_REPORT_RETAIN_ADDRESS + Report_Offset);
return 0;
}
/**
* @function: SleepReportGet
* @brief
* @param {unsigned char} *buf
* @param {char} Index
* @return {*}
* @author: lzc
*/
char SleepReportGet(unsigned char *buf, char Index)
{
uint8_t Result = 0;
uint8_t Error_cnt = 0;
char FlashDataBuffer[7200] = {0};
unsigned char temp_Buffer[NumberToWrite] = {0}; // 原始数据的缓存
uint32_t Report_Offset = 0;
Report_Offset += (0x4000 * Index);
// 每一块扇区存3600字节
for (int i = 0; i < 3; i++)
{
// 清除数据
memset(temp_Buffer, 0, NumberToWrite);
// 读取块1的数据
EN25QXX_Read(temp_Buffer, (FLASH_SLEEP_REPORT_DATA_1_ADDRESS + Report_Offset + (NumberToWrite * i)), NumberToWrite);
// 复制数据
memcpy(FlashDataBuffer + (NumberToWrite * i), temp_Buffer, NumberToWrite);
}
// 每一块扇区存3600字节
for (int i = 0; i < 3; i++)
{
// 清除数据
memset(temp_Buffer, 0, NumberToWrite);
// 读取块2的数据
EN25QXX_Read(temp_Buffer, (FLASH_SLEEP_REPORT_DATA_2_ADDRESS + Report_Offset + (NumberToWrite * i)), NumberToWrite);
// 复制数据
memcpy(FlashDataBuffer + (NumberToWrite * i) + (3 * NumberToWrite), temp_Buffer, NumberToWrite);
}
memcpy(buf, FlashDataBuffer, sizeof(FlashDataBuffer));
return 0;
}
/**
* @function: get_flash_init
* @brief: Flash
* @return {*}
* @author: wt
*/
void get_flash_init(void)
{
Sleep.breathe_abnormal_flg = 0;
EN25QXX_Read((u8 *)Sleep.report_get_buf, 0, 200); // 前200个数据等于整体介绍
Sleep.all_num = Sleep.report_get_buf[0]; // 总天数
Sleep.report_num = Sleep.report_get_buf[1]; // 当前天数
// Sleep.report_get_buf[0] = 0; //总天数
// Sleep.report_get_buf[1] = 0; //当前天数
// EN25QXX_Write((u8 *)Sleep.report_get_buf, 0, 200); //存储
if (Sleep.all_num == 0) // 还没有数据
{
Sleep.report_num = 1;
Sleep.all_num = 1;
}
else if ((Sleep.all_num >= 7) && (Sleep.report_num >= 7)) // 已经满了
{
Sleep.report_num = 1;
}
else if (Sleep.all_num >= 7) // 已经一轮了
{
Sleep.report_num++;
}
else // 不到一轮
{
Sleep.all_num++;
Sleep.report_num++;
}
Sleep.storage_location_num = 200 + 1024 * (9 * (Sleep.report_num - 1)); // 当前存储数量--地址等于
Sleep.report_time_flg = 1; // 更新时间戳
OffBed_Flag = 0; // 离床
Sleep.equipment_status_time = 0; // 初始离床时间0
Sleep.sleep_stage_flg = 0; // 不出睡眠报告
Sleep.circle_num = 0; // 当前循环为0
}
/**
* @function: SleepRecord_SaveDirectory
* @brief:
* @return {*}
* @author: lzc
*/
void SleepRecord_SaveDirectory(char *buffer)
{
// 判断是否是空的
int Counter = 0;
char index = 0;
char Value = 0;
for (Counter = 0; Counter < REPORT_SAVE_SIZE; Counter++)
{
if (buffer[Counter] != DEFAULT_FF)
break;
}
// 第一次做记录
if (Counter == REPORT_SAVE_SIZE)
{
buffer[0] = 0;
index++;
Value++;
SleepRecord.SleepReport_CurrentIndex = 0;
}
else
{
// 先遍历一次
for (Counter = 0; Counter < REPORT_SAVE_SIZE; Counter++)
{
// 找到了空余区域
if (buffer[Counter] == DEFAULT_FF)
{
SleepRecord.SleepReport_CurrentIndex = Counter;
buffer[Counter] = Counter;
index = Counter + 1;
Value++;
break;
}
}
if (Counter == REPORT_SAVE_SIZE)
{
// 已经存储完成,需要顶替
for (Counter = 0; Counter < REPORT_SAVE_SIZE; Counter++)
{
if (buffer[Counter] != 0)
{
buffer[Counter] -= 1;
}
else
{
SleepRecord.SleepReport_CurrentIndex = Counter;
buffer[Counter] = REPORT_SAVE_SIZE - 1;
index = Counter;
Value = buffer[Counter];
}
}
}
}
SleepRecord.SleepReport_CurrentSaveNum = Value;
}
/**
* @function:cjson_ReInitHook
* @brief
* @return {*}
* @author: lzc
*/
void cjson_ReInitHook(void)
{
static cJSON_Hooks m_iot_hooks;
m_iot_hooks.malloc_fn = mymalloc;
m_iot_hooks.free_fn = myfree;
cJSON_InitHooks(&m_iot_hooks);
}
/**
* @function: MattressFunctionInit
* @brief:
* @return {*}
* @author: lzc
*/
char bootResult = 0;
RCC_ClocksTypeDef get_RCC_Clock;
void MattressParameterInit(void)
{
System_Init();
// NOTE: 将静态数组的指针传入,以其作为队列的存储
// node_set_static_buf(que_static_buf, sizeof(que_static_buf));
// NOTE: 初始化队列,设置个数
// InitQueue(&Stage_q, 301, 1); // 300秒5分钟
// NOTE: 此处用于清空睡眠阶段的结构体
// init_struct_stage(&get_sleep_stage);
wait(5); // 等待一段时间避免ESP32的串口数据有影响
get_flash_init(); // flash初始化
cjson_ReInitHook();
if ((*(__IO uint16_t *)0X08004000) != 0x1111) // 没有存储 写入默认值
{
FLASH_Unlock();
FLASH_EraseSector(FLASH_Sector_1, VoltageRange_3);
flashWrite(get_breathe_buf, 6); // 写入flash,固定一包写6个字节
FLASH_Lock();
}
else
{
Breathe_H = (*(__IO uint8_t *)0X08004002);
Breathe_L = (*(__IO uint8_t *)0X08004003);
HeartRate_H = (*(__IO uint8_t *)0X08004004);
HeartRate_L = (*(__IO uint8_t *)0X08004005);
}
if (EN25QXX_ReadID() != EN25Q64) // 检测不到EN25Q64
{
printf("EN25Q64 Check Failed!\r\n");
}
else
{
printf("EN25Q64 Check right!\r\n");
}
// 读取复位原因
if ((RCC->CSR & 0X80000000) != 0) // 1 低功耗复位
{
bootResult = Low_Power_Reset;
printf("[Reset]: Low Power Reset\r\n");
}
else if ((RCC->CSR & 0X40000000) != 0) // 2 窗口看门狗复位
{
bootResult = WWDG_Reset;
printf("[Reset]: WWDG Reset\r\n");
}
else if ((RCC->CSR & 0X20000000) != 0) // 3 独立看门狗复位
{
bootResult = IWDG_Reset;
printf("[Reset]: IWDG Reset\r\n");
}
else if ((RCC->CSR & 0X10000000) != 0) // 4 软件复位
{
bootResult = SoftWare_Reset;
printf("[Reset]: SoftWare Reset\r\n");
}
else if ((RCC->CSR & 0X08000000) != 0) // 5 上电复位
{
bootResult = PowerOn_Reset;
printf("[Reset]: PowerOn Reset\r\n");
}
else if ((RCC->CSR & 0X04000000) != 0) // 6 PIN复位
{
bootResult = Pin_Reset;
printf("[Reset]: Pin Reset\r\n");
}
RCC->CSR = 0X01000000;
// 读取时钟
RCC_GetClocksFreq(&get_RCC_Clock); /**/
printf("-----------------------------------------------\r\n");
printf("[System Clock]: HCLK_Frequency %d\r\n", get_RCC_Clock.HCLK_Frequency);
printf("[System Clock]: PCLK1_Frequency %d\r\n", get_RCC_Clock.PCLK1_Frequency);
printf("[System Clock]: PCLK2_Frequency %d\r\n", get_RCC_Clock.PCLK2_Frequency);
printf("[System Clock]: SYSCLK_Frequency %d\r\n", get_RCC_Clock.SYSCLK_Frequency);
printf("-----------------------------------------------\r\n");
}
/**
* @function: Storage_Initialization
* @brief:
* @return {*}
* @author: lzc
*/
extern float OPM_Original;
void Storage_Initialization(void)
{
// DONE::获取光功阈值存储数据,如果没有使用默认值
EN25QXX_Read((uint8_t *)&OPM_Original, FLASH_IN_OFF_BED_OPM_RECORD_ADDRESS, sizeof(float32_t));
EN25QXX_Read((u8 *)&Calibration_Template, FLASH_IN_BED_THRESHOLD_ADDRESS, sizeof(Calibration_Template));
EN25QXX_Read((u8 *)&Calibration_Template_2, FLASH_OFF_BED_THRESHOLD_ADDRESS, sizeof(Calibration_Template_2));
// 如果读取数据错误则写入默认值
if (OPM_Original >= WEAK_OPM && OPM_Original <= -10.0f)
{
printf("\r\n OPM_Original : %f\r\n", OPM_Original);
}
else
{
OPM_Original = -10.0f;
EN25QXX_Write((uint8_t *)&OPM_Original,
FLASH_IN_OFF_BED_OPM_RECORD_ADDRESS,
sizeof(float32_t));
printf("\r\n OPM_Original Empty\r\n");
}
// 如果获取的数据不是空数据
if (Calibration_Template != 0xffffffff &&
Calibration_Template_2 != 0xffffffff)
{
// 增加LED灯的指示会闪一下浅色LED
LED_G = 0;
LED_B = 0;
delay_ms(500);
LED_R = 1;
LED_G = 1;
LED_B = 1;
EN25QXX_Read((u8 *)&ON_BED_Threshold, FLASH_IN_BED_THRESHOLD_ADDRESS, sizeof(ON_BED_Threshold));
EN25QXX_Read((u8 *)&OFF_BED_Threshold, FLASH_OFF_BED_THRESHOLD_ADDRESS, sizeof(OFF_BED_Threshold));
}
// TODO: 增加读取睡眠报告的目录参数
// 睡眠报告的配置结构--清空配置
SleepRecord.SleepReport_CurrentIndex = 0;
SleepRecord.SleepReport_CurrentSaveNum = 0;
// 读取
EN25QXX_Read((u8 *)&SleepRecord.SleepReport_Directory,
FLASH_SLEEP_REPORT_DIRECTORY_ADDRESS,
sizeof(SleepRecord.SleepReport_Directory));
Key_Cal_Flag = 0; // 此处不能删除,删除会导致上电黑掉的情况
// 设置随机种子
MySetRandom(AIN_1310);
}
/**
* @function: OPM_MattressCalibration
* @brief:
* @return {*}
* @author: lzc
*/
void OPM_MattressCalibration(void)
{
if (opm_cal_flag == 1) // 需要进行校准
{
IWDG_Feed(); // // NOTE:喂狗 超时 32s 就复位(防止硬件设备错误以及卡死)
// 青色LED = G + B
// 紫色LED = R + B
float Optical_Sum = 0.0f;
// 修正值为空,且没有进行空床校准
if (Optical_Calibration_Value == 0.0f &&
((Calibration_Off_Bed_Done_Flag == 0) ||
(Calibration_In_Bed_Done_Flag == 1)))
{
for (char i = 0; i < 10; i++)
{
LED_G = 0;
LED_B = 0;
delay_ms(8000);
LED_G = 1;
LED_B = 1;
delay_ms(8000);
get_optical_power(); // 获取光功
Optical_Sum += dbm_value_1310;
}
Optical_Calibration_Value = Optical_Sum / 10.0f; // 作均值
// 记录以及计算阈值
Optical_Calibration_Value_OffBed = Optical_Calibration_Value;
// 更新阈值
OFF_BED_Threshold = Optical_Calibration_Value_OffBed - (float)2.0;
// 更新阈值
ON_BED_Threshold = OFF_BED_Threshold - 10;
// 喂狗 超时 32s 就复位(防止硬件设备错误以及卡死)
IWDG_Feed(); // NOTE:喂狗
// 空床也进行保存
EN25QXX_Write((u8 *)&ON_BED_Threshold, FLASH_IN_BED_THRESHOLD_ADDRESS, sizeof(ON_BED_Threshold));
EN25QXX_Write((u8 *)&OFF_BED_Threshold, FLASH_OFF_BED_THRESHOLD_ADDRESS, sizeof(OFF_BED_Threshold));
Key_Cal_Flag = 0;
opm_cal_flag = 0;
Local_ON_BED_Threshold = ON_BED_Threshold;
Local_OFF_BED_Threshold = OFF_BED_Threshold;
TIM_Cmd(TIM3, ENABLE); // 使能定时器3
Calibration_In_Bed_Done_Flag = 0;
Calibration_Off_Bed_Done_Flag = 1;
}
else if (Optical_Calibration_Value == 0.0f &&
Calibration_Off_Bed_Done_Flag == 1)
{
for (char i = 0; i < 10; i++)
{
LED_R = 0;
LED_B = 0;
delay_ms(8000);
LED_R = 1;
LED_B = 1;
delay_ms(8000);
get_optical_power(); // 获取光功
Optical_Sum += dbm_value_1310;
printf("Calibration\r\n");
}
Optical_Calibration_Value = Optical_Sum / 10.0f; // 作均值
// 记录以及计算阈值
Optical_Calibration_Value_OnBed = Optical_Calibration_Value;
// 更新阈值
ON_BED_Threshold = Optical_Calibration_Value_OnBed - 10;
Key_Cal_Flag = 0;
opm_cal_flag = 0;
Local_ON_BED_Threshold = ON_BED_Threshold;
Local_OFF_BED_Threshold = OFF_BED_Threshold;
TIM_Cmd(TIM3, ENABLE); // 使能定时器3
Calibration_In_Bed_Done_Flag = 1;
// 喂狗 超时 32s 就复位(防止硬件设备错误以及卡死)
IWDG_Feed(); // NOTE:喂狗
// TODO: 做记录之后再次进行存储,之后直接复位。
EN25QXX_Write((u8 *)&ON_BED_Threshold, FLASH_IN_BED_THRESHOLD_ADDRESS, sizeof(ON_BED_Threshold));
EN25QXX_Write((u8 *)&OFF_BED_Threshold, FLASH_OFF_BED_THRESHOLD_ADDRESS, sizeof(OFF_BED_Threshold));
CalValue_Upload();
NVIC_SystemReset(); // 复位
}
}
}
/**
* @function: KalmarFilter
* @brief: None
* @param {float} inData
* @return {*}
* @author: lzc
*/
float KalmarFilter(float inData)
{
static float prevData = 0; // 上一个数据
static float p = 10, q = 0.005, r = 0.005, kGain = 0.5; // q 控制误差 r 控制响应速度
p = p + q;
kGain = p / (p + r); // 计算卡尔曼增益
inData = prevData + (kGain * (inData - prevData)); // 计算本次滤波估计值
p = (1 - kGain) * p; // 更新测量方差
prevData = inData;
return inData; // 返回估计值
}
/**
* @function: main
* @brief:
* @return {*}
* @author: lzc
*/
uint16_t Chip_ID_Data = 0;
uint16_t fft_HeartBeatRate_Hi = 0;
uint16_t fft_HeartBeatRate_Lo = 0;
uint16_t fft_HeartBeatRate_Result = 0;
uint16_t time_HeartBeatRate_Result = 0;
float fft_HeartBeatRate_StashBuffer[15] = {0};
int main(void)
{
VectorTableReInit();
// nnom_model_t *BH_model, *stage_model; // 两个预测模型的指针
// 睡眠报告的原始数据 可存储一天的数据 24h*60min*60sec = 7200 ;
// unsigned char SleepReportSendDataBuffer[7200] = {0};
// unsigned char SleepReportReadDataBuffer[7200] = {0};
float new_data_0,
new_data_1, new_data_2, new_data_3, new_data_4, new_data;
char index, max = 0;
int m = 0, num, it, add_g;
float md_u, md_d, md;
char FirstPowerON_Flag = 1;
struct tm *time;
time_t timestamp = 0; /* 时间戳 */
char Send_Once = 1;
int ReSendStartCommand_Count = 0;
MattressParameterInit(); // 床垫 初始化
// 初始化IIC
IIC_Init();
// 一分钟开启BLE启动状态
PowerOn_OneMinuteBLEScan();
#if 1
// 初始化看门狗
IWDG_Init();
#ifdef NNOM_USING_STATIC_MEMORY
// nnom_set_static_buf(BH_static_buf, sizeof(BH_static_buf)); // 对运行内存进行初始化
#endif
// BH_model = nnom_model_create_BH_KC(); // 调用预测睡眠和呼吸的模型函数,初始化 //显示内存使用情况。
#ifndef NOT_PRE_STAGE
#ifdef NNOM_USING_STATIC_MEMORY
nnom_set_static_buf(Stage_static_buf, sizeof(Stage_static_buf)); // 对运行内存进行初始化
#endif
stage_model = nnom_model_create(); // 调用预测睡眠周期模型函数初始化。该函数的h文件还没有加到这个工程里 //显示内存使用情况。
#endif
// 用于测试
if (TEST_SEND_BH_STAGE || TEST_SEND_SINGAL)
{
TIM_Cmd(TIM3, ENABLE); //
Key_Cal_Flag = 1;
}
Storage_Initialization(); // 存储初始化
Local_ON_BED_Threshold = ON_BED_Threshold;
Local_OFF_BED_Threshold = OFF_BED_Threshold;
// 读取ID
Chip_ID_Data = SGM58031_ReadData(ChipID_Reg, 0x90, 2);
if (SGM58031_WriteConfig(0x40e3))
printf("ADC Successfully initialized");
MyDSP_Init();
while (1)
{
// 用于测试
if (TEST_SEND_BH_STAGE)
{
#ifndef NOT_PRE_STAGE
c_BH_stage(BH_model, stage_model);
#else
// pre_bh(BH_model);
#endif
}
key_optical(); // 按键检测
if (USART_DealFlag)
{
USART_DealFlag = 0;
wifi_cmd_exe(); // 通讯交流
// 串口接收完毕时使能计算定时器
TIM_Cmd(TIM5, ENABLE);
}
else
CheckOverTimeValueClear();
if (Key_Cal_Flag == 0) // 配网成功
{
// 时间戳下发成功
if (TimeClock_Flag == 1)
{
TIM_Cmd(TIM2, ENABLE);
get_optical_power(); // 获取光功
MyFitter(); // 滤波器
// 第一次上电上报校准值
if (FirstPowerON_Flag)
{
FirstPowerON_Flag = 0;
CalValue_Upload();
delay_ms(50);
// 版本号上报
version_upload();
BreathRate = 0;
HeartBeatRate = 0;
// MySetRandom(AIN_1310);
// 生成随机值 心率和呼吸
// BreathRate = rand() % 11 + 14; // 产生14~24的随机数
// HeartBeatRate = rand() % 11 + 54; // 产生54~64的随机数
}
// 发送json数据
if (wifi_json_flg == 1)
{
// 喂狗 超时 32s 就复位(防止硬件设备错误以及卡死)
IWDG_Feed();
// TIM_Cmd(TIM2, DISABLE);
wifi_json_send();
// TIM_Cmd(TIM2, ENABLE);
wifi_json_flg = 0;
}
// 发送数据
if (wifi_len_500_flg == 1)
{
wifi_len_500_flg = 0;
// TIM_Cmd(TIM2, DISABLE);
wifi_send();
// TIM_Cmd(TIM2, ENABLE);
// 延时50ms
delay_ms(500);
}
// 计算睡眠周期框架
if (start_stage_flg == 1) // 12秒钟算一次睡眠分期
{
start_stage_flg = 0;
// NOTE: 增加睡眠部分代码
// 睡眠报告测试
if (Send_Once)
{
Send_Once = 0;
// SleepReportGenerate(timeClockCount, 720);
}
}
// 计算呼吸心跳框架
if (start_calculate_flg == 1)
{
start_calculate_flg = 0;
//------------------------------ 算法验证 ---------------------------------------//
/*
printf("\n--------------------- Start --------------------------------\n");
fft_heartDataPostProcessing(round(fft_Output(outPutFitterOPMData_Heart,
HEART_FITTER_LENGTH - HEART_IGNORE_LENGTH, TYPE_HEART)));
fft_breathDataPostProcessing(round(fft_Output(outPutFitterOPMData_Breath,
BREATH_FITTER_LENGTH - BREATH_IGNORE_LENGTH, TYPE_BREATH)));
printf("Heart Rate: %d Breath Rate: %d\n", HeartBeatRate, BreathRate);
printf("\n--------------------- End --------------------------------\n");
*/
//------------------------------ FFT算法 ---------------------------------------//
if (equipment_status_value == InBed_Status)
{
/*
// 心率相关
fft_HeartBeatRate_Hi = (round(fft_Output(outPutFitterOPMData_Heart,
HEART_FITTER_LENGTH - HEART_IGNORE_LENGTH, TYPE_HEART)));
fft_HeartBeatRate_Lo = (round(fft_Output(outPutFitterOPMData_Heart_Lo,
HEART_FITTER_LENGTH - HEART_IGNORE_LENGTH, TYPE_HEART)));
if (abs(fft_HeartBeatRate_Lo - fft_HeartBeatRate_Hi) < 15 ||
fft_HeartBeatRate_Hi <= 120 || fft_HeartBeatRate_Lo > 120)
fft_HeartBeatRate_Result = fft_HeartBeatRate_Lo;
else
fft_HeartBeatRate_Result = (fft_HeartBeatRate_Hi / 2);
fft_heartDataPostProcessing(fft_HeartBeatRate_Result);
// 呼吸相关
fft_breathDataPostProcessing(round(fft_Output(outPutFitterOPMData_Breath,
BREATH_FITTER_LENGTH - BREATH_IGNORE_LENGTH, TYPE_BREATH)));
// 记录
BreathRate_Record = BreathRate;
HeartBeatRate_Record = HeartBeatRate;
*/
switch (FFT_Calculate_State_Flag)
{
// 启动计算
case FFT_Start_Calculate:
#if 0
// 心率相关
fft_HeartBeatRate_Hi = (round(fft_Output(outPutFitterOPMData_Heart,
HEART_FITTER_LENGTH - HEART_IGNORE_LENGTH, TYPE_HEART)));
fft_HeartBeatRate_Lo = (round(fft_Output(outPutFitterOPMData_Heart_Lo,
HEART_FITTER_LENGTH - HEART_IGNORE_LENGTH, TYPE_HEART)));
if (abs(fft_HeartBeatRate_Lo - fft_HeartBeatRate_Hi) < 15 ||
fft_HeartBeatRate_Hi <= 120 || fft_HeartBeatRate_Lo > 120)
fft_HeartBeatRate_Result = fft_HeartBeatRate_Lo;
else
fft_HeartBeatRate_Result = (fft_HeartBeatRate_Hi / 2);
fft_heartDataPostProcessing(fft_HeartBeatRate_Result);
// 呼吸相关
fft_breathDataPostProcessing(round(fft_Output(outPutFitterOPMData_Breath,
BREATH_FITTER_LENGTH - BREATH_IGNORE_LENGTH, TYPE_BREATH)));
// 记录
BreathRate_Record = BreathRate;
HeartBeatRate_Record = HeartBeatRate;
if (FFT_Count_State_Flag == FFT_No_breath)
{
#if THE_VERSION
BreathRate = 0;
#else
; // BreathRate = 0;
#endif
}
#else
fft_HeartBeatCurrentFilter = FILTER_HI_TYPE;
fft_Output(outPutFitterOPMData_Heart, HEART_FITTER_LENGTH - HEART_IGNORE_LENGTH, TYPE_HEART);
memcpy(HeartValueRes2Peaks, FFT_HeartRateRes, sizeof(FFT_HeartRateRes));
fft_HeartBeatCurrentFilter = FILTER_LO_TYPE;
fft_Output(outPutFitterOPMData_Heart_Lo, HEART_FITTER_LENGTH - HEART_IGNORE_LENGTH, TYPE_HEART);
memcpy(HeartValueRes2Peaks + 2, FFT_HeartRateRes, sizeof(FFT_HeartRateRes));
time_HeartBeatRate_Result = time_domain_heart_rate(outPutFitterOPMData_Heart_Lo);
fft_HeartBeatRate_Result = MyToolSelectHp(HeartValueRes2Peaks, stash_Ratio,
fft_HeartBeatRate_StashBuffer, time_HeartBeatRate_Result);
fft_heartDataPostProcessing(fft_HeartBeatRate_Result);
// 呼吸相关
fft_breathDataPostProcessing(round(fft_Output(outPutFitterOPMData_Breath,
BREATH_FITTER_LENGTH - BREATH_IGNORE_LENGTH, TYPE_BREATH)));
// 更新数据
MyToolMoveUpdate((float *)fft_HeartBeatRate_StashBuffer, 15, HeartBeatRate);
// 记录
BreathRate_Record = BreathRate;
HeartBeatRate_Record = HeartBeatRate;
#endif
break;
// 停止计算
case FFT_Stop_Calculate:
// 有体动情况下尽快上报数据
if ((BreathRate == 0) && (HeartBeatRate == 0))
{
BreathRate_Record = 15;
HeartBeatRate_Record = 75;
}
BreathRate = BreathRate_Record;
HeartBeatRate = HeartBeatRate_Record;
break;
default:
break;
}
}
}
timestamp = timeClockCount_Send / 1000;
/* 时间补偿 */
timestamp = timestamp + ((signed char)warning_config.timeZone) * 60 * 60;
/* 调用系统函数 */
time = localtime(&timestamp);
g_mon = time->tm_mon; /* 月份 */
g_day = time->tm_mday; /* 日期 */
g_hour = time->tm_hour; /* 小时:0-23点,UTC+0时间*/
g_min = time->tm_min; /* 分钟:0-60 ,UTC+0时间 */
g_sec = time->tm_sec; /* 秒 :0-60,UTC+0时间 */
// 重新获取时间戳 (超过1小时或者每天的中午更新时间)
if (TimeClock_Recalibrate_Count >= TIME_CLOCK_MAX_TIMES)
{
TimeClock_Flag = 0;
TIM_ClearITPendingBit(TIM5, TIM_IT_Update); // 清除标志位
TIM_Cmd(TIM5, DISABLE); // 失能定时器5
TimeClock_Recalibrate_Count = TIME_CLOCK_MAX_TIMES;
// printf("\r\n!!!Recalibrate!!!\r\n");
}
// 超时或者联网成功则复位 同时发送清除BLE信息的指令
if (PowerOn_OneMinuteCount >= ONE_MINUTES_COUNT &&
PowerOn_OneMinuteCount_Start)
{
PowerOn_OneMinuteCount_Start = 0;
USART1_SendData(myReset, 5); // 清除指令
delay_ms(1500);
if (Key_Cal_Flag != 0) // 没有联网成功
NVIC_SystemReset(); // 复位
}
else if (PowerOn_OneMinuteCount < ONE_MINUTES_COUNT)
{
// 如果配网开始则count清除
if (PowerOn_StartConfigFlg)
PowerOn_OneMinuteCount = 0;
}
}
else
{
static int Value = 0;
Value++;
// LED_B=!LED_B;
LED_R = 1;
if (TimeClock_Recalibrate_Count >= TIME_CLOCK_MAX_TIMES)
{
TimeClock_Recalibrate_Count = 0;
LED_G = 0;
LED_B = 0; // 重新校准时间戳的时候青色LED闪一下
}
else
{
LED_G = 1;
LED_B = !LED_B;
}
TIM_Cmd(TIM2, DISABLE);
printf("Wait TimeStamp...\r\n");
wifi_crc_send(get_time_buf, 13);
delay_ms(500);
// 喂狗 超时 32s 就复位(防止硬件设备错误以及卡死)
IWDG_Feed();
}
}
// 等待配网
else
{
ReSendStartCommand_Count++;
// printf("Wait Net...\r\n");
// AP = 1; BLE = 0
if (!NetworkConnectionWay)
LED_R = 1;
else
LED_R = 0;
LED_G = 1;
LED_B = 0;
if (start_ConnectNet_flg)
{
delay_ms(2000);
start_ConnectNet_flg = 0;
USART1_SendData(Start_Cmd, 5); // 启动配网指令
}
// 配网超时重发机制
if (ReSendStartCommand_Count >= 1000 && start_ConnectNet_flg == 0)
{
start_ConnectNet_flg = 1;
ReSendStartCommand_Count = 0;
}
IWDG_Feed();
}
OPM_MattressCalibration();
// printf("Key_Cal_Flag is %d TimeClock_Flag is %d\n", Key_Cal_Flag,TimeClock_Flag);
IWDG_Feed();
}
#endif
}
/**
* @function: three_avg
* @brief:
* @param {unsigned short int} data
* @param {unsigned short int} max
* @param {unsigned short int} min
* @return {*}
* @author: lzc
*/
float three_avg(unsigned short int data, unsigned short int max, unsigned short int min)
{
float md_u, md_d, md;
md_u = data - min;
md_d = max - min;
md_d = md_d + 1;
md = (md_u / md_d) * 128;
return md;
}
/**
* @function:itoa_my
* @brief
* @param {int} value
* @param {char} *string
* @param {int} radix
* @return {*}
* @author: lzc
*/
char *itoa_my(long value, char *string, int radix)
{
char zm[37] = "0123456789abcdefghijklmnopqrstuvwxyz";
char aa[100] = {0};
long sum = value;
char *cp = string;
int i = 0;
if (radix < 2 || radix > 36) // 增加了对错误的检测
{
return string;
}
if (value < 0)
{
return string;
}
while (sum > 0)
{
aa[i++] = zm[sum % radix];
sum /= radix;
}
for (int j = i - 1; j >= 0; j--)
{
*cp++ = aa[j];
}
*cp = '\0';
return string;
}
float32_t IIRStateF32_Breath[4 * numStages]; /* 状态缓存 */
float32_t IIRStateF32_Heart[4 * numStages]; /* 状态缓存 */
float32_t IIRStateF32_Heart_NoCut[4 * numStages]; /* 状态缓存 */
extern BandFitterConfig_t BandFitterConfig;
// static float32_t FitterOutputData[LENGTH_SAMPLES]; /* 滤波后的输出 */
/**
* @function: MyDSP_Init
* @brief DSP库
* @return {*}
* @author: lzc
*/
int MyDSP_Init(void)
{
/* 实现IIR滤波这里每次处理1个点 */
arm_biquad_cascade_df1_init_f32(&BreathPart, numStages, (float32_t *)&IIRCoeffs32BP_Breath,
(float32_t *)&IIRStateF32_Breath[0]);
/* 实现IIR滤波这里每次处理1个点 */
arm_biquad_cascade_df1_init_f32(&HeartPart, numStages, (float32_t *)&IIRCoeffs32BP_Heart,
(float32_t *)&IIRStateF32_Heart[0]);
/* 实现IIR滤波这里每次处理1个点 */
arm_biquad_cascade_df1_init_f32(&HeartPart_NoCut, numStages, (float32_t *)&IIRCoeffs32BP_Heart_NoCut,
(float32_t *)&IIRStateF32_Heart_NoCut[0]);
/* 实现IIR滤波这里每次处理1个点 */
arm_biquad_cascade_df1_init_f32(&CheckPart, numStages, (float32_t *)&IIRCoeffs32BP_Breath,
(float32_t *)&IIRStateF32_Breath[0]);
return 0;
}
void MyFitter(void)
{
float32_t CopyHrBuffer[HEART_FITTER_LENGTH] = {0};
float32_t ResultBuffer[HEART_FITTER_LENGTH - HEART_IGNORE_LENGTH] = {0};
if (FitterCollectDoneFlag_Heart)
{
FitterCount_Heart = HEART_FITTER_LENGTH - 50;
// 高频版本滤波
memset(ResultBuffer, 0, sizeof(ResultBuffer));
arm_iir_f32_bp_stream_Heart_Output(FitterOPMData_Heart, outPutFitterOPMData_Heart);
arm_iir_f32_bp_stream_Heart_Output_NoCut(outPutFitterOPMData_Heart, ResultBuffer);
arm_iir_f32_bp_stream_Heart_Output_NoCut(ResultBuffer, outPutFitterOPMData_Heart);
// 低频版本滤波
memset(ResultBuffer, 0, sizeof(ResultBuffer));
arm_iir_f32_bp_stream_Heart_Output(FitterOPMData_Heart, outPutFitterOPMData_Heart_Lo);
arm_iir_f32_bp_stream_Heart_Output_NoCut_2(outPutFitterOPMData_Heart_Lo, ResultBuffer);
arm_iir_f32_bp_stream_Heart_Output_NoCut_2(ResultBuffer, outPutFitterOPMData_Heart_Lo);
memcpy(FitterOPMData_Heart, FitterOPMData_Heart + 50,
sizeof(float32_t) * (LENGTH_SAMPLES_HEART - 50));
FitterCollectDoneFlag_Heart = 0;
}
if (FitterCollectDoneFlag_Breath)
{
FitterCount_Breath = LENGTH_SAMPLES_BREATH - 50;
arm_iir_f32_bp_stream_Breath_Output(FitterOPMData_Breath, outPutFitterOPMData_Breath);
memcpy(FitterOPMData_Breath, FitterOPMData_Breath + 50,
sizeof(float32_t) * (LENGTH_SAMPLES_BREATH - 50));
FitterCollectDoneFlag_Breath = 0;
memcpy(ResultBuffer, outPutFitterOPMData_Breath + HEART_IGNORE_LENGTH, sizeof(ResultBuffer));
Diff = MyToolFindMaxValue(ResultBuffer, BREATH_FITTER_LENGTH - BREATH_IGNORE_LENGTH - HEART_IGNORE_LENGTH) -
MyToolFindMinValue(ResultBuffer, BREATH_FITTER_LENGTH - BREATH_IGNORE_LENGTH - HEART_IGNORE_LENGTH);
Diff_Detail = MyToolFindMaxValue(ResultBuffer + 400, BREATH_FITTER_LENGTH - BREATH_IGNORE_LENGTH - HEART_IGNORE_LENGTH - 400) -
MyToolFindMinValue(ResultBuffer + 400, BREATH_FITTER_LENGTH - BREATH_IGNORE_LENGTH - HEART_IGNORE_LENGTH - 400);
// 如果小于0.5开始计算
if (Diff_Detail < 0.3f)
FFT_Count_State_Flag = FFT_Still_state;
else if (Diff_Detail < 1.2f)
FFT_Count_State_Flag = FFT_Mild_body_motion;
else if (Diff_Detail <= 4.0f)
FFT_Count_State_Flag = FFT_Medium_body_motion;
else if (Diff_Detail > 4.0f)
FFT_Count_State_Flag = FFT_Large_body_motion;
if (Diff < 0.5f)
{
FFT_Count_State_Flag = FFT_Still_state;
FFT_Calculate_State_Flag = FFT_Start_Calculate;
//---------------------------------------------
// if (Diff < 0.06f)
// // if (i_count_No_Breath == 5)
// FFT_Count_State_Flag = FFT_No_breath;
// else if (Diff < 0.5f)
// FFT_Count_State_Flag = FFT_Still_state;
}
else
{
FFT_Calculate_State_Flag = FFT_Stop_Calculate;
}
}
if (FitterCollectDoneFlag_CheckBed)
{
FitterCollectDoneFlag_CheckBed = 0;
breathInBedCheck(FitterOPMData_CheckBed);
// memcpy(FitterOPMData_CheckBed, FitterOPMData_CheckBed + 50,
// sizeof(float32_t) * (LENGTH_SAMPLES_IN_OFF_BED - 50));
FitterCount_CheckBed = LENGTH_SAMPLES_IN_OFF_BED - 50;
}
}
/**
* @function: PowerOn_OneMinuteBLEScan
* @brief:
* @return {*}
* @author: lzc
*/
void PowerOn_OneMinuteBLEScan(void)
{
// 上电复位才进去 其他情况不会进去
if (bootResult == PowerOn_Reset)
{
PowerOn_OneMinuteCount_Start = 1;
// 发送对应的指令进入1分钟蓝牙启动
USART1_SendData(myScan, 5); // 寻网指令
for (int i = 0; i < 10; i++)
{
LED_B = !LED_B;
delay_ms(500);
}
USART1_SendData(Start_Cmd, 5); // 启动配网指令
delay_ms(500);
Key_Cal_Flag = 1;
PowerOn_OneMinuteCount = 0;
// 启动60秒倒计时
/*
while (PowerOn_OneMinuteCount < ONE_MINUTES_COUNT)
{
if (USART_DealFlag)
{
USART_DealFlag = 0;
wifi_cmd_exe(); // 通讯交流
}
// 如果配网开始则count清除
if (PowerOn_StartConfigFlg)
PowerOn_OneMinuteCount = 0;
if (Key_Cal_Flag == 0)
break;
LED_B = !LED_B;
delay_ms(500);
}*/
}
}