diff --git a/.vscode/settings.json b/.vscode/settings.json index 3677ba5..89e87ea 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,6 +4,12 @@ "parameter.h": "c", "comm.h": "c", "bl_chargcontrol.h": "c", - "comm_types.h": "c" + "comm_types.h": "c", + "hd_gpio.h": "c", + "inflash.h": "c", + "fm_tim.h": "c", + "timesliceoffset.h": "c", + "fm_gpio.h": "c", + "pdebug.h": "c" } } \ No newline at end of file diff --git a/APP/application/Inc/task.h b/APP/application/Inc/task.h new file mode 100644 index 0000000..c36225c --- /dev/null +++ b/APP/application/Inc/task.h @@ -0,0 +1,10 @@ + +#ifndef APP_TASK_H_ +#define APP_TASK_H_ + +#include "timeSliceOffset.h" + + + + +#endif diff --git a/APP/application/Src/chargControl.c b/APP/application/Src/chargControl.c index b37d090..c8a42f5 100644 --- a/APP/application/Src/chargControl.c +++ b/APP/application/Src/chargControl.c @@ -8,7 +8,7 @@ void chargControl(void) getCVData(); judgeYNBattery(); - g_otherParameter.MPPT_Mode = chargControlMode(); + chargControlMode(); if (g_otherParameter.MPPT_Mode == noWork) { return; diff --git a/APP/application/Src/start.c b/APP/application/Src/start.c index fa53097..52092e4 100644 --- a/APP/application/Src/start.c +++ b/APP/application/Src/start.c @@ -1,12 +1,12 @@ #include "start.h" - +#include "inFlash.h" void start(void) { + config_info_start(); - - + TimeSliceOffset_Start(); } diff --git a/APP/application/Src/task.c b/APP/application/Src/task.c new file mode 100644 index 0000000..1de6eed --- /dev/null +++ b/APP/application/Src/task.c @@ -0,0 +1,9 @@ + +#include "task.h" + + + + + + + diff --git a/APP/businessLogic/Inc/bl_chargControl.h b/APP/businessLogic/Inc/bl_chargControl.h index 6a47c70..cf07bc5 100644 --- a/APP/businessLogic/Inc/bl_chargControl.h +++ b/APP/businessLogic/Inc/bl_chargControl.h @@ -2,10 +2,11 @@ #define BL_CHARG_CONTROL_H_ #include "chargControlEnum.h" +#include "FM_TIM.h" void getCVData(void); void judgeYNBattery(void); -int chargControlMode(void); +void chargControlMode(void); void BatteryChargControl(void); void noBatteryChargControl(void); diff --git a/APP/businessLogic/Inc/inFlash.h b/APP/businessLogic/Inc/inFlash.h new file mode 100644 index 0000000..28234bb --- /dev/null +++ b/APP/businessLogic/Inc/inFlash.h @@ -0,0 +1,110 @@ + +#ifndef BL_IN_FLASH_H_ +#define BL_IN_FLASH_H_ + +#include "flash.h" +#include "stm32g431xx.h" + +#pragma pack(push, 1) + +/* 高字节在前,低字节在后 */ +typedef struct _recv_config_info{ + uint8_t start_Flag[2]; /* 开始标志 */ + /* SL */ + uint8_t address[7]; /* 地址 */ + uint8_t Access_Node_Type[2]; /* 接入节点类型 */ + uint8_t Communication_Methods[2]; /* 通信方式 */ + uint8_t gw485_Baud[4]; /* 串口波特率 */ + uint8_t bat485_Baud[4]; /* 串口波特率,为0代表bms不支持通信 */ + + /* HY */ + uint8_t hardwareID[6]; /* 硬件ID */ + uint8_t communicationID[4]; /* 通信ID */ + uint8_t protocolType; /* 协议类型; 0x01表示:汇源协议(波特率9600) 0x02表示:南瑞协议(波特率115200)*/ + + + // uint8_t CommunicationProtocolType; /* 0x00:SL + // 0x01:HY*/ + uint8_t onlyPower; /* 是否只充当电源板:0x00:不是 + 0x01:是*/ + + uint8_t ConstantVoltageV[2]; /* 高于该(电压 / 100)且电流大于FloatI * 100进行恒压充电 */ + uint8_t FloatI[2]; /* 高于该(电压 / 100)且电流低于FloatI * 100进行浮充充电 */ + uint8_t startSolarOpenCircuitV[2]; /* 高于该(电压 / 100)开始充电 */ + uint8_t stopSolarOpenCircuitV[2]; /* 太阳能板开路电压高于该电压停止充电 (V) */ + uint8_t constantVoltageChargeV[2]; /* 恒压充电时的输出电压 (V) */ + uint8_t FloatChargeV[2]; /* 浮充充电时的输出电压 (V) */ + uint8_t HighSideMosTemperature_stop[2]; /* 当上桥温度达到该值时,停止输出 (°C) */ + uint8_t HighSideMosTemperature_end[2]; /* 当上桥温度上升到该值时,降低功率运行 (°C) */ + uint8_t HighSideMosTemperature_start[2];/* 当上桥温度降低到该值时,按照正常情况输出 (°C) */ + + uint8_t checkSolarOpenCircuitVTime[2]; /* 启动任务中太阳能板开路电压检测间隔时间 (S) */ + uint8_t sensorEnableBroadcastTime[2]; /* 传感器运行再次注册的间隔 (S) */ + uint8_t outputAgainFlagTime[2]; /* 出现短路保护后延长该段时间再次检测是否短路,仍然短路则关闭输出 (S) */ + uint8_t excessiveLoadFlagTime[2]; /* 出现过载后,在该间隔时间中多次(2次)出现过载,则关闭输出 (S) */ + uint8_t eLAgainTime[2]; /* 出现过载过载保护后,在该间隔段时间后,再次尝试输出 (S) */ + uint8_t crc[2]; /* 校验 */ + uint8_t end_Flag; /* 结束标志 */ +}recv_config_info; +#define RECV_CONFIG_INFO sizeof(recv_config_info) + +typedef struct _config_info{ + /* SL */ + uint8_t address[7]; /* 地址 */ + uint16_t Access_Node_Type; /* 接入节点类型 */ + uint16_t Communication_Methods; /* 通信方式 */ + uint32_t gw485_Baud; /* 串口波特率,为0代表bms不支持通信 */ + uint32_t bat485_Baud; /* 串口波特率 */ + + /* HY */ + uint8_t hardwareID[6]; /* 硬件ID */ + uint8_t communicationID[4]; /* 通信ID */ + uint8_t protocolType; /* 协议类型; 0x01表示:汇源协议(波特率9600) 0x02表示:南瑞协议(波特率115200)*/ + + // uint8_t CommunicationProtocolType; /* 0x00:SL + // 0x01:HY*/ + uint8_t onlyPower; /* 是否只充当电源板:0x00:不是 + 0x01:是*/ + + float constantVoltageV; /* 电压高于ConstantVoltageV且电流大于FloatI + 0.1)进行恒压充电 */ + float floatI; /* 电压高于ConstantVoltageV且电流低于FloatI进行浮充充电 */ + float startSolarOpenCircuitV; /* 太阳能板开路电压高于该电压开始充电 */ + float stopSolarOpenCircuitV; /* 太阳能板开路电压高于该电压 停止充电 */ + float constantVoltageChargeV; /* 恒压充电时的输出电压 */ + float FloatChargeV; /* 浮充电压 */ + float HighSideMosTemperature_stop; /* 当上桥温度达到该值时,停止输出 */ + float HighSideMosTemperature_end; /* 当上桥温度上升到该值时,降低功率运行 */ + float HighSideMosTemperature_start; /* 当上桥温度降低到该值时,按照正常情况输出 */ + + uint16_t checkSolarOpenCircuitVTime; /* 启动任务中太阳能板开路电压检测时间 */ + uint16_t sensorEnableBroadcastTime; /* 传感器运行再次注册的间隔 */ + uint16_t outputAgainFlagTime; /* 出现短路保护后延长该段时间再次检测是否短路,仍然短路则关闭输出 */ + uint16_t excessiveLoadFlagTime; /* 出现过载后,在该段时间中再次出现过载,则关闭输出 */ + uint16_t eLAgainTime; /* 出现过载过载保护后,该段时间后,再次尝试输出 */ + + uint16_t crc; /* 校验 */ +}config_info; + +#define CONFIG_INFO_SIZE (sizeof(config_info)) +#pragma pack(pop) + +#define CONFIG_SAVE_addr (0) +#define CONFIG_SAVE_ADDR_BEGIN (CONFIG_INFO_SIZE) +#define CONFIG_SAVE_ADDR_END (CONFIG_INFO_SIZE + CONFIG_INFO_SIZE) +#define LoopImpedance_SAVE_addr (CONFIG_INFO_SIZE + CONFIG_INFO_SIZE + 10) +#define totalElectricityConsumption_SAVE_addr (CONFIG_INFO_SIZE + CONFIG_INFO_SIZE + 20) +#define totalChargCapacity_SAVE_addr (CONFIG_INFO_SIZE + CONFIG_INFO_SIZE + 30) + +void save_config_info(config_info *save_config_info); +void read_config_info(config_info *output_config_info); +void config_info_start(void); +// void read_and_process_config_data(void); + +void saveLoopImpedance(float *loopImpedance); +void readLoopImpedance(float *loopImpedance); +void savetotalElectricityConsumption(float *totalElectricityConsumption); +void readtotalElectricityConsumption(float *totalElectricityConsumption); +void savetotalChargCapacity(float *totalChargCapacity); +void readtotalChargCapacity(float *totalChargCapacity); + +#endif diff --git a/APP/businessLogic/Inc/parameter.h b/APP/businessLogic/Inc/parameter.h index d6e0c0a..02d6dbc 100644 --- a/APP/businessLogic/Inc/parameter.h +++ b/APP/businessLogic/Inc/parameter.h @@ -77,8 +77,6 @@ typedef struct _otherParameter{ - - float dutyRatio; /* 占空比 */ @@ -86,3 +84,5 @@ typedef struct _otherParameter{ extern otherParameter g_otherParameter; + +#endif \ No newline at end of file diff --git a/APP/businessLogic/Src/bl_chargControl.c b/APP/businessLogic/Src/bl_chargControl.c index 9adcc8f..c6a3273 100644 --- a/APP/businessLogic/Src/bl_chargControl.c +++ b/APP/businessLogic/Src/bl_chargControl.c @@ -4,10 +4,10 @@ #include "comm_types.h" static void stopChargWork(void); -static int stopChargConditions(void); -static int floatChargConditions(void); -static int mpptChargConditions(void); -static int constantVChargConditions(void); +static BOOL stopChargConditions(void); +static BOOL floatChargConditions(void); +static BOOL mpptChargConditions(void); +static BOOL constantVChargConditions(void); static void mpptCharge(void); static void constantVoltageCharge(void); static void floatCharge(void); @@ -79,26 +79,26 @@ BOOL constantVChargConditions(void) /** * @brief 判断充电控制的模式 * @param - * @retval 返回充电控制器的模式 + * @retval * */ -int chargControlMode(void) +void chargControlMode(void) { if (stopChargConditions()) { stopChargWork(); - return noWork; + g_otherParameter.MPPT_Mode = noWork; } if (floatChargConditions()) { - return floatCharg; + g_otherParameter.MPPT_Mode = floatCharg; } if (mpptChargConditions()) { - return MPPT; + g_otherParameter.MPPT_Mode = MPPT; } if (constantVChargConditions()) { - return constantVoltage; + g_otherParameter.MPPT_Mode = constantVoltage; } } @@ -179,19 +179,20 @@ void BatteryChargControl(void) { switch(g_otherParameter.MPPT_Mode) { - case CONSTANTCURRENT: + case MPPT: mpptCharge(); break; - case CONSTANTVOLTAGE: + case constantVoltage: constantVoltageCharge(); break; - case FLOAT: + case floatCharg: floatCharge(); break; default: + g_otherParameter.MPPT_Mode = noWork; stopChargWork(); break; } diff --git a/APP/businessLogic/Src/inFlash.c b/APP/businessLogic/Src/inFlash.c new file mode 100644 index 0000000..263990a --- /dev/null +++ b/APP/businessLogic/Src/inFlash.c @@ -0,0 +1,605 @@ + +#include "inFlash.h" +#include "parameter.h" +#include "pDebug.h" + +// static uint8_t config_buff[200]; +// static uint8_t config_buff_pos = 0; + +/** + * @brief 校验算法, modebus + * @param + * @retval + */ +static uint16_t configCheckFunc(uint8_t *arr_buff, uint8_t len) +{ + uint16_t crc = 0xFFFF; + uint16_t i, j; + for (j = 0; j < len; ++j) { + crc = crc ^ (*arr_buff++); + for (i = 0; i < 8; ++i) { + if ((crc&0x0001) > 0) { + crc = crc >> 1; + crc = crc ^ 0xa001; + } + else { + crc = crc >> 1; + } + } + } + return crc; +} + +/** + * @brief 保存配置信息 + * @param save_config_info 需要保存的配置信息 + * @retval None + */ +void save_config_info(config_info *save_config_info) +{ + write_Flash((uint8_t *)save_config_info, CONFIG_SAVE_ADDR_BEGIN, CONFIG_INFO_SIZE); +} + +/** + * @brief 保存配置信息到备份区 + * @param save_config_info 需要保存的配置信息 + * @retval None + */ +static void save_backups_config_info(config_info *save_config_info) +{ + write_Flash((uint8_t *)save_config_info, CONFIG_SAVE_addr, CONFIG_INFO_SIZE); +} + +/** + * @brief 读取配置信息 + * @param read_config_info 读取配置信息并保存在output_config_info中 + * @retval None + */ +void read_config_info(config_info *output_config_info) +{ + read_Flash((uint8_t *)output_config_info, CONFIG_SAVE_ADDR_BEGIN, CONFIG_INFO_SIZE); +} + +/** + * @brief 读取备份的配置信息 + * @param read_config_info 读取配置信息并保存在output_config_info中 + * @retval None + */ +static void read_backups_config_info(config_info *output_config_info) +{ + read_Flash((uint8_t *)output_config_info, CONFIG_SAVE_addr, CONFIG_INFO_SIZE); +} + +/** + * @brief 检测flash中是否有配置文件或者文件是否有损坏,若两处flash中都损坏则使用默认文件 + * @param config_info 读取的配置信息 + * @retval None + * + */ +static void readFlashContent(config_info *config_info) +{ + read_config_info(config_info); + + /* 配置文件正确就返回 */ + if (config_info->crc == configCheckFunc((uint8_t *)config_info, CONFIG_INFO_SIZE - 2)) { + return; + } + + /* 更深处的配置文件正确就返回 */ + read_backups_config_info(config_info); + if (config_info->crc == configCheckFunc((uint8_t *)config_info, CONFIG_INFO_SIZE - 2)) { + save_config_info(config_info); + return; + } + + /* 配置文件错误使用默认配置 */ + config_info->address[0] = 0x11; + config_info->address[1] = 0x11; + config_info->address[2] = 0x11; + config_info->address[3] = 0x11; + config_info->address[4] = 0x11; + config_info->address[5] = 0x11; + config_info->address[6] = 0x11; + config_info->Access_Node_Type = 0x01; + config_info->Communication_Methods = 0x02; + config_info->gw485_Baud = 9600; + config_info->bat485_Baud = 115200; + + config_info->hardwareID[0] = 0x48; + config_info->hardwareID[1] = 0x59; + config_info->hardwareID[2] = 0x30; + config_info->hardwareID[3] = 0x30; + config_info->hardwareID[4] = 0x30; + config_info->hardwareID[5] = 0x31; + config_info->communicationID[0] = 0x00; + config_info->communicationID[1] = 0x00; + config_info->communicationID[2] = 0x00; + config_info->communicationID[3] = 0x01; + config_info->protocolType = 0x01; + + // config_info->CommunicationProtocolType = 0x00; + config_info->onlyPower = 0x01; + + config_info->constantVoltageV = 14; + config_info->floatI = 0.02; + config_info->startSolarOpenCircuitV = 17; + config_info->stopSolarOpenCircuitV = 15; + config_info->constantVoltageChargeV = 14.4; + config_info->FloatChargeV = 14; + config_info->HighSideMosTemperature_stop = 100; + config_info->HighSideMosTemperature_end = 90; + config_info->HighSideMosTemperature_start = 50; + + config_info->checkSolarOpenCircuitVTime = 10; + config_info->sensorEnableBroadcastTime = 20; + config_info->outputAgainFlagTime = 10; + config_info->excessiveLoadFlagTime = 60; + config_info->eLAgainTime = 1800; +} + +/** + * @brief 通过配置文件初始化系统参数 + * @param None + * @retval None + * + */ +void config_info_start(void) +{ + Flash_Init(); + + config_info temp_configInfo; + readFlashContent(&temp_configInfo); + + g_cfgParameter.constantVoltageV = temp_configInfo.constantVoltageV; + g_cfgParameter.floatI = temp_configInfo.floatI; + g_cfgParameter.startSolarOpenCircuitV = temp_configInfo.startSolarOpenCircuitV; + g_cfgParameter.stopSolarOpenCircuitV = temp_configInfo.stopSolarOpenCircuitV; + g_cfgParameter.constantVoltageChargeV = temp_configInfo.constantVoltageChargeV; + g_cfgParameter.FloatV = temp_configInfo.FloatChargeV; + g_cfgParameter.HighSideMosTemperature_stop = temp_configInfo.HighSideMosTemperature_stop; + g_cfgParameter.HighSideMosTemperature_end = temp_configInfo.HighSideMosTemperature_end; + g_cfgParameter.HighSideMosTemperature_start = temp_configInfo.HighSideMosTemperature_start; + g_cfgParameter.sensorEnableBroadcastTime = temp_configInfo.sensorEnableBroadcastTime; + g_cfgParameter.checkSolarOpenCircuitVTime = temp_configInfo.checkSolarOpenCircuitVTime; + g_cfgParameter.outputAgainFlagTime = temp_configInfo.outputAgainFlagTime; + g_cfgParameter.excessiveLoadFlagTime = temp_configInfo.excessiveLoadFlagTime; + g_cfgParameter.eLAgainTime = temp_configInfo.eLAgainTime; + g_cfgParameter.collectOpenCircuitVoltageTime= 3600; + g_cfgParameter.address[0] = temp_configInfo.address[0]; + g_cfgParameter.address[1] = temp_configInfo.address[1]; + g_cfgParameter.address[2] = temp_configInfo.address[2]; + g_cfgParameter.address[3] = temp_configInfo.address[3]; + g_cfgParameter.address[4] = temp_configInfo.address[4]; + g_cfgParameter.address[5] = temp_configInfo.address[5]; + g_cfgParameter.address[6] = temp_configInfo.address[6]; + g_cfgParameter.Access_Node_Type = temp_configInfo.Access_Node_Type; + g_cfgParameter.Communication_Methods = temp_configInfo.Communication_Methods; + g_cfgParameter.hardwareID[0] = temp_configInfo.hardwareID[0]; + g_cfgParameter.hardwareID[1] = temp_configInfo.hardwareID[1]; + g_cfgParameter.hardwareID[2] = temp_configInfo.hardwareID[2]; + g_cfgParameter.hardwareID[3] = temp_configInfo.hardwareID[3]; + g_cfgParameter.hardwareID[4] = temp_configInfo.hardwareID[4]; + g_cfgParameter.hardwareID[5] = temp_configInfo.hardwareID[5]; + g_cfgParameter.communicationID[0] = temp_configInfo.communicationID[0]; + g_cfgParameter.communicationID[1] = temp_configInfo.communicationID[1]; + g_cfgParameter.communicationID[2] = temp_configInfo.communicationID[2]; + g_cfgParameter.communicationID[3] = temp_configInfo.communicationID[3]; + g_cfgParameter.protocolType = temp_configInfo.protocolType; + // g_cfgParameter.CommunicationProtocolType = temp_configInfo.CommunicationProtocolType; + g_cfgParameter.onlyPower = temp_configInfo.onlyPower; + + g_cfgParameter.startFlagSL[0] = 'S'; + g_cfgParameter.startFlagSL[1] = 'L'; + g_cfgParameter.endFlagSL = 0x16; + g_cfgParameter.startFlagHY = 0x68; + g_cfgParameter.endFlagHY = 0x16; + + // if (g_cfgParameter.CommunicationProtocolType == 0x00) { + // g_cfgParameter.gw485_Baud = temp_configInfo.gw485_Baud; + // g_cfgParameter.bat485_Baud = temp_configInfo.bat485_Baud; + // } else if (g_cfgParameter.CommunicationProtocolType == 0x01) { + // g_cfgParameter.bat485_Baud = temp_configInfo.bat485_Baud; + // if (g_cfgParameter.protocolType == 0x01) { + // g_cfgParameter.gw485_Baud = 9600; + // } else if (g_cfgParameter.protocolType == 0x02) { + // g_cfgParameter.gw485_Baud = 115200; + // } + // } + g_cfgParameter.gw485_Baud = 9600; + g_cfgParameter.gw485_Baud = 115200; + + float fTemp; + readLoopImpedance(&fTemp); + /* 读取的回路阻抗偏差过大则不使用 */ + if (fTemp > (float)0.005 && fTemp < (float)1) { + g_cfgParameter.loopImpedance = fTemp; + } + else { + g_cfgParameter.loopImpedance = 0; + saveLoopImpedance(&g_cfgParameter.loopImpedance); + } + readtotalElectricityConsumption(&g_otherParameter.totalElectricityConsumption); + readtotalChargCapacity(&g_otherParameter.totalChargCapacity); +} + +/** + * @brief 判断接收到的配置文件数据是否正确,正确的话存入flash中 + * @param None + * @retval None + * + */ +// #define enlargeScale 100 +// BOOL read_and_process_config_data(uint8_t *config_buff[]) +// { +// recv_config_info *pack = (recv_config_info *)*config_buff; +// config_info save_configInfo; +// while (config_buff_pos >= RECV_CONFIG_INFO) { +// /* 判断起始标志是否正确 */ +// if (pack->start_Flag[0] != g_cfgParameter.startFlagSL[0] +// || pack->start_Flag[1] != g_cfgParameter.startFlagSL[1]) { +// // debug(" start_Flag : 0x%x, 0x%x \n", pack->start_Flag[0], pack->start_Flag[1]); +// goto err; +// } + +// /* 判断接入节点类型是否正确 */ +// save_configInfo.Access_Node_Type = (uint16_t)pack->Access_Node_Type[0] << 8 +// | (uint16_t)pack->Access_Node_Type[1]; +// // debug(" Access_Node_Type : 0x%x \n", save_configInfo.Access_Node_Type); +// if (save_configInfo.Access_Node_Type != POWERBOX) { +// goto err; +// } + +// /* 判断通信方式是否正确 */ +// save_configInfo.Communication_Methods = (uint16_t)pack->Communication_Methods[0] << 8 +// | (uint16_t)pack->Communication_Methods[1]; +// // debug(" Communication_Methods : 0x%x \n", save_configInfo.Communication_Methods); +// // if (temp_u16 != RS485 || temp_u16 != RJ45) { +// if (save_configInfo.Communication_Methods != RS485) { +// goto err; +// } + +// /* 判断波特率是否正确 */ +// save_configInfo.gw485_Baud = (uint32_t)pack->gw485_Baud[0] << 24 +// | (uint32_t)pack->gw485_Baud[1] << 16 +// | (uint32_t)pack->gw485_Baud[2] << 8 +// | (uint32_t)pack->gw485_Baud[3]; +// // debug(" gw485_Baud : 0x%x, %d \n", save_configInfo.gw485_Baud, save_configInfo.gw485_Baud); +// if (save_configInfo.gw485_Baud != 9600 && save_configInfo.gw485_Baud != 115200) { +// // if (save_configInfo.gw485_Baud != 0x2580 || save_configInfo.gw485_Baud != 115200) { +// // debug(" error : %d\n", save_configInfo.gw485_Baud); +// goto err; +// } + +// save_configInfo.bat485_Baud = (uint32_t)pack->bat485_Baud[0] << 24 +// | (uint32_t)pack->bat485_Baud[1] << 16 +// | (uint32_t)pack->bat485_Baud[2] << 8 +// | (uint32_t)pack->bat485_Baud[3]; +// // debug(" bat485_Baud : 0x%x, %d \n", save_configInfo.bat485_Baud, save_configInfo.bat485_Baud); +// if (save_configInfo.bat485_Baud != 9600 && save_configInfo.bat485_Baud!= 115200 && save_configInfo.bat485_Baud!= 0) { +// goto err; +// } + +// /* 判断协议类型是否正确 */ +// if (pack->protocolType != 0x01 && pack->protocolType != 0x02) { +// goto err; +// } +// // debug(" protocolType : 0x%x \n", pack->protocolType); + + /* 判断通信协议类型是否正确 */ +/* + if (pack->CommunicationProtocolType != 0x00 && pack->CommunicationProtocolType != 0x01) { + goto err; + } +// debug(" CommunicationProtocolType : 0x%x \n", pack->CommunicationProtocolType); +*/ + +// /* 判断电源盒类型是否正确 */ +// if (pack->onlyPower != 0x00 && pack->onlyPower != 0x01) { +// goto err; +// } +// // debug(" onlyPower : 0x%x \n", pack->onlyPower); + +// /* 判断恒压充电阈值是否正确 */ +// save_configInfo.constantVoltageV = +// (float)(pack->ConstantVoltageV[0] << 8 | pack->ConstantVoltageV[1]) / enlargeScale; +// // debug(" constantVoltageV : %f \n", save_configInfo.constantVoltageV); +// if (save_configInfo.constantVoltageV > (float)14.4 || save_configInfo.constantVoltageV < (float)13.5) { +// goto err; +// } + +// /* 判断浮充充电阈值是否正确 */ +// save_configInfo.floatI = (float)(pack->FloatI[0] << 8 | pack->FloatI[1]) / enlargeScale; +// // debug(" floatI : %f \n", save_configInfo.floatI); +// if (save_configInfo.floatI > (float)0.2 || save_configInfo.floatI < (float)0) { +// goto err; +// } + +// /* 判断太阳能板开路启动电压是否正确 */ +// save_configInfo.startSolarOpenCircuitV = +// (float)(pack->startSolarOpenCircuitV[0] << 8 | pack->startSolarOpenCircuitV[1]) / enlargeScale; +// // debug(" startSolarOpenCircuitV : %f \n", save_configInfo.startSolarOpenCircuitV); +// if (save_configInfo.startSolarOpenCircuitV > 24 || save_configInfo.startSolarOpenCircuitV < 14) { +// goto err; +// } + +// /* 判断太阳能板关闭电压是否正确 */ +// save_configInfo.stopSolarOpenCircuitV = +// (float)(pack->stopSolarOpenCircuitV[0] << 8 | pack->stopSolarOpenCircuitV[1]) / enlargeScale; +// // debug(" stopSolarOpenCircuitV : %f \n", save_configInfo.stopSolarOpenCircuitV); +// if (save_configInfo.stopSolarOpenCircuitV > 17 || save_configInfo.stopSolarOpenCircuitV < 13) { +// goto err; +// } + +// /* 判断恒压充电时的输出电压是否正确 */ +// save_configInfo.constantVoltageChargeV = +// (float)(pack->constantVoltageChargeV[0] << 8 | pack->constantVoltageChargeV[1]) / enlargeScale; +// // debug(" constantVoltageChargeV : %f \n", save_configInfo.constantVoltageChargeV); +// if (save_configInfo.constantVoltageChargeV > (float)14.6 || save_configInfo.constantVoltageChargeV < (float)14) { +// goto err; +// } + +// /* 判断浮充充电时的输出电压是否正确 */ +// save_configInfo.FloatChargeV = +// (float)(pack->FloatChargeV[0] << 8 | pack->FloatChargeV[1]) / enlargeScale; +// // debug(" FloatChargeV : %f \n", save_configInfo.FloatChargeV); +// if (save_configInfo.FloatChargeV > (float)14.4 || save_configInfo.FloatChargeV < (float)13.8) { +// goto err; +// } + +// /* 判断mos管停止工作温度是否正确 */ +// save_configInfo.HighSideMosTemperature_stop = +// (float)(pack->HighSideMosTemperature_stop[0] << 8 | pack->HighSideMosTemperature_stop[1]) / enlargeScale; +// // debug(" HighSideMosTemperature_stop : %f \n", save_configInfo.HighSideMosTemperature_stop); +// if (save_configInfo.HighSideMosTemperature_stop < 60) { +// goto err; +// } + +// /* 判断mos管降低工作功率工作温度是否正确 */ +// save_configInfo.HighSideMosTemperature_end = +// (float)(pack->HighSideMosTemperature_end[0] << 8 | pack->HighSideMosTemperature_end[1]) / enlargeScale; +// // debug(" HighSideMosTemperature_end : %f \n", save_configInfo.HighSideMosTemperature_end)); +// if (save_configInfo.HighSideMosTemperature_end < 50) { +// goto err; +// } + +// /* 判断mos管完全恢复工作温度是否正确 */ +// save_configInfo.HighSideMosTemperature_start = +// (float)(pack->HighSideMosTemperature_start[0] << 8 | pack->HighSideMosTemperature_start[1]) / enlargeScale; +// // debug(" HighSideMosTemperature_start : %d \n", save_configInfo.HighSideMosTemperature_start); +// if (save_configInfo.HighSideMosTemperature_start < 40) { +// goto err; +// } + +// /* 判断启动任务中太阳能板开路电压检测间隔时间是否正确 */ +// save_configInfo.checkSolarOpenCircuitVTime = +// pack->checkSolarOpenCircuitVTime[0] << 8 | pack->checkSolarOpenCircuitVTime[1]; +// // debug(" checkSolarOpenCircuitVTime : %d \n", save_configInfo.checkSolarOpenCircuitVTime); +// if (save_configInfo.checkSolarOpenCircuitVTime > 1800 || save_configInfo.checkSolarOpenCircuitVTime < 5) { +// goto err; +// } + +// /* 判断传感器运行再次注册的间隔是否正确 */ +// save_configInfo.sensorEnableBroadcastTime = +// pack->sensorEnableBroadcastTime[0] << 8 | pack->sensorEnableBroadcastTime[1]; +// // debug(" sensorEnableBroadcastTime : %d \n", save_configInfo.sensorEnableBroadcastTime); +// if (save_configInfo.sensorEnableBroadcastTime > 60 || save_configInfo.sensorEnableBroadcastTime < 10) { +// goto err; +// } + +// /* 判断出现短路保护后延长该段时间再次检测是否短路,仍然短路则关闭输出的间隔是否正确 */ +// save_configInfo.outputAgainFlagTime = +// pack->outputAgainFlagTime[0] << 8 | pack->outputAgainFlagTime[1]; +// // debug(" outputAgainFlagTime : %d \n", save_configInfo.outputAgainFlagTime); +// if (save_configInfo.sensorEnableBroadcastTime > 30 || save_configInfo.sensorEnableBroadcastTime < 5) { +// goto err; +// } + +// /* 判断出现过载后,在该间隔时间中多次(2次)出现过载,则关闭输出的间隔是否正确 */ +// save_configInfo.excessiveLoadFlagTime = +// pack->excessiveLoadFlagTime[0] << 8 | pack->excessiveLoadFlagTime[1]; +// // debug(" excessiveLoadFlagTime : %d \n", save_configInfo.excessiveLoadFlagTime); +// if (save_configInfo.excessiveLoadFlagTime > 90 || save_configInfo.excessiveLoadFlagTime < 30) { +// goto err; +// } + +// /* 判断出现过载过载保护后,在该间隔段时间后,再次尝试输出的间隔是否正确 */ +// save_configInfo.eLAgainTime = pack->eLAgainTime[0] << 8 | pack->eLAgainTime[1]; +// // debug(" eLAgainTime : %d \n", save_configInfo.eLAgainTime); +// if (save_configInfo.eLAgainTime > 3000 || save_configInfo.eLAgainTime < 1000) { +// goto err; +// } + +// /* crc校验 */ +// save_configInfo.crc = pack->crc[0] << 8 | pack->crc[1]; +// // debug(" crc : %x%x \n", pack->crc[0], pack->crc[1]); +// if (save_configInfo.crc != configCheckFunc(config_buff, RECV_CONFIG_INFO - 3)) { +// // debug(" configCheckFunc : %x \n", configCheckFunc(config_buff, RECV_CONFIG_INFO)); +// goto err; +// } + + +// /* 结束标志 */ +// // debug(" end_Flag : %x \n", pack->end_Flag); +// if (pack->end_Flag != 0x16) { +// goto err; +// } + +// // debug("address : 0x %x %x %x %x %x %x %x\n", pack->address[0] +// // , pack->address[1], pack->address[2], pack->address[3] +// // , pack->address[4], pack->address[5], pack->address[6]); +// config_info temp_configInfo; +// read_config_info(&temp_configInfo); + +// if (pack->address[0] != 0xFF +// || pack->address[1] != 0xFF +// || pack->address[2] != 0xFF +// || pack->address[3] != 0xFF +// || pack->address[4] != 0xFF +// || pack->address[5] != 0xFF +// || pack->address[6] != 0xFF) { +// save_configInfo.address[0] = pack->address[0]; +// save_configInfo.address[1] = pack->address[1]; +// save_configInfo.address[2] = pack->address[2]; +// save_configInfo.address[3] = pack->address[3]; +// save_configInfo.address[4] = pack->address[4]; +// save_configInfo.address[5] = pack->address[5]; +// save_configInfo.address[6] = pack->address[6]; +// // debug("address : 0x %x %x %x %x %x %x %x\n", save_configInfo.address[0] +// // , save_configInfo.address[1], save_configInfo.address[2], save_configInfo.address[3] +// // , save_configInfo.address[4], save_configInfo.address[5], save_configInfo.address[6]); +// } else { +// save_configInfo.address[0] = temp_configInfo.address[0]; +// save_configInfo.address[1] = temp_configInfo.address[1]; +// save_configInfo.address[2] = temp_configInfo.address[2]; +// save_configInfo.address[3] = temp_configInfo.address[3]; +// save_configInfo.address[4] = temp_configInfo.address[4]; +// save_configInfo.address[5] = temp_configInfo.address[5]; +// save_configInfo.address[6] = temp_configInfo.address[6]; +// } + +// if (pack->hardwareID[0] != 0xFF +// || pack->hardwareID[1] != 0xFF +// || pack->hardwareID[2] != 0xFF +// || pack->hardwareID[3] != 0xFF +// || pack->hardwareID[4] != 0xFF +// || pack->hardwareID[5] != 0xFF) { +// save_configInfo.hardwareID[0] = pack->hardwareID[0]; +// save_configInfo.hardwareID[1] = pack->hardwareID[1]; +// save_configInfo.hardwareID[2] = pack->hardwareID[2]; +// save_configInfo.hardwareID[3] = pack->hardwareID[3]; +// save_configInfo.hardwareID[4] = pack->hardwareID[4]; +// save_configInfo.hardwareID[5] = pack->hardwareID[5]; +// } else { +// save_configInfo.hardwareID[0] = temp_configInfo.hardwareID[0]; +// save_configInfo.hardwareID[1] = temp_configInfo.hardwareID[1]; +// save_configInfo.hardwareID[2] = temp_configInfo.hardwareID[2]; +// save_configInfo.hardwareID[3] = temp_configInfo.hardwareID[3]; +// save_configInfo.hardwareID[4] = temp_configInfo.hardwareID[4]; +// save_configInfo.hardwareID[5] = temp_configInfo.hardwareID[5]; +// } + +// if (pack->communicationID[0] != 0xFF +// || pack->communicationID[1] != 0xFF +// || pack->communicationID[2] != 0xFF +// || pack->communicationID[3] != 0xFF) { +// save_configInfo.communicationID[0] = pack->communicationID[0]; +// save_configInfo.communicationID[1] = pack->communicationID[1]; +// save_configInfo.communicationID[2] = pack->communicationID[2]; +// save_configInfo.communicationID[3] = pack->communicationID[3]; +// } else { +// save_configInfo.communicationID[0] = temp_configInfo.communicationID[0]; +// save_configInfo.communicationID[1] = temp_configInfo.communicationID[1]; +// save_configInfo.communicationID[2] = temp_configInfo.communicationID[2]; +// save_configInfo.communicationID[3] = temp_configInfo.communicationID[3]; +// } + +// save_configInfo.protocolType = pack->protocolType; + +// save_configInfo.CommunicationProtocolType = pack->CommunicationProtocolType; + +// save_configInfo.onlyPower = pack->onlyPower; + +// save_configInfo.crc = configCheckFunc((uint8_t *)&save_configInfo, CONFIG_INFO_SIZE - 2); +// save_backups_config_info(&save_configInfo); +// save_config_info(&save_configInfo); + +// memset(config_buff, 0, sizeof(config_buff)); + +// // /* 返回更改配置文件成功 */ +// // SL_Mppt_SOther_pack SUpdateProfile_pack = {0}; + +// // SUpdateProfile_pack.start_Flag[0] = g_otherParameter.startFlagSL[0]; +// // SUpdateProfile_pack.start_Flag[1] = g_otherParameter.startFlagSL[1]; + +// // SUpdateProfile_pack.address[0] = save_configInfo.address[0]; +// // SUpdateProfile_pack.address[1] = save_configInfo.address[1]; +// // SUpdateProfile_pack.address[2] = save_configInfo.address[2]; +// // SUpdateProfile_pack.address[3] = save_configInfo.address[3]; +// // SUpdateProfile_pack.address[4] = save_configInfo.address[4]; +// // SUpdateProfile_pack.address[5] = save_configInfo.address[5]; +// // SUpdateProfile_pack.address[6] = save_configInfo.address[6]; + +// // SUpdateProfile_pack.function_Code = SL_Function_Code_Update_Profile; + +// // SUpdateProfile_pack.state = 0x01; + +// // uint16_t crc = CheckFuncSL((uint8_t *)&SUpdateProfile_pack, SL_MPPT_SOTHER_PACK_SIZE - 3); +// // SUpdateProfile_pack.check_Bit_H = crc >> 8; +// // SUpdateProfile_pack.check_Bit_L = crc; + +// // SUpdateProfile_pack.end_Flag = g_otherParameter.endFlagSL; + +// // while (1) { +// // if (!Check_485_bus_busy(g_gw485_uart4_handle)) { +// // uart_dev_write(g_gw485_uart4_handle, (uint8_t *)&SUpdateProfile_pack, SL_MPPT_SOTHER_PACK_SIZE); +// // USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); +// // break; +// // } +// // Delay_Ms(randomDelay()); +// // } + +// /* 复位 */ +// NVIC_SystemReset(); + +// return; + +// err: +// config_buff_pos--; +// memcpy(config_buff, config_buff + 1, sizeof(config_buff) - 1); +// } +// } + +/** + * @brief 保存回路阻抗在flash中 + * @param + */ +void saveLoopImpedance(float *loopImpedance) +{ + write_Flash((uint8_t *)loopImpedance, LoopImpedance_SAVE_addr, sizeof(float)); +} + +/** + * @brief 读取flash中的回路阻抗 + * @param + */ +void readLoopImpedance(float *loopImpedance) +{ + read_Flash((uint8_t *)loopImpedance, LoopImpedance_SAVE_addr, sizeof(float)); +} + +/** + * @brief 保存放电量在flash中 + * @param + */ +void savetotalElectricityConsumption(float *totalElectricityConsumption) +{ + write_Flash((uint8_t *)totalElectricityConsumption, totalElectricityConsumption_SAVE_addr, sizeof(float)); +} + +/** + * @brief 读取flash中的放电量 + * @param + */ +void readtotalElectricityConsumption(float *totalElectricityConsumption) +{ + read_Flash((uint8_t *)totalElectricityConsumption, totalElectricityConsumption_SAVE_addr, sizeof(float)); +} + +/** + * @brief 保存充电量在flash中 + * @param + */ +void savetotalChargCapacity(float *totalChargCapacity) +{ + write_Flash((uint8_t *)totalChargCapacity, totalChargCapacity_SAVE_addr, sizeof(float)); +} + +/** + * @brief 读取flash中的充电量 + * @param + */ +void readtotalChargCapacity(float *totalChargCapacity) +{ + read_Flash((uint8_t *)totalChargCapacity, totalChargCapacity_SAVE_addr, sizeof(float)); +} + diff --git a/APP/functionalModule/Inc/FM_GPIO.h b/APP/functionalModule/Inc/FM_GPIO.h new file mode 100644 index 0000000..b55dfd4 --- /dev/null +++ b/APP/functionalModule/Inc/FM_GPIO.h @@ -0,0 +1,26 @@ +#ifndef FM_GPIO_H_ +#define FM_GPIO_H_ + +#include "HD_GPIO.h" + +void FM_GPIO_Init(void); + +void POW_FF_PCON_Open(void); +void POW_FF_PCON_Close(void); + +void POW_OUT_PCON_Open(void); +void POW_OUT_PCON_Close(void); + +void RUN_LEN_Open(void); +void RUN_LEN_Close(void); + +void FFMOS_CON_Open(void); +void FFMOS_CON_Close(void); + +void EN_PWMOUT_Eable(void); +void EN_PWMOUT_Diseable(void); + +// extern void WORK_VOLT_Interrupt(void); +// extern void DSG_PROT_Interrupt(void); + +#endif diff --git a/APP/functionalModule/Inc/FM_TIM.h b/APP/functionalModule/Inc/FM_TIM.h new file mode 100644 index 0000000..1d8ea05 --- /dev/null +++ b/APP/functionalModule/Inc/FM_TIM.h @@ -0,0 +1,13 @@ + +#ifndef FM_PWM_CONTORL_H_ +#define FM_PWM_CONTORL_H_ + +#include "HD_TIM.h" + +void pwm_Init(void); +void set_pwmDutyRatio(float DutyRatio); +void set_pwmPulse(uint32_t Pulse); + +extern void chargControl(void); + +#endif diff --git a/APP/functionalModule/Inc/flash.h b/APP/functionalModule/Inc/flash.h new file mode 100644 index 0000000..5859ea5 --- /dev/null +++ b/APP/functionalModule/Inc/flash.h @@ -0,0 +1,13 @@ + +#ifndef FM_FLASH_H_ +#define FM_FLASH_H_ + +#include "main.h" +#include "w25qxx.h" + +void Flash_Init(void); +void read_Flash(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead); +void write_Flash(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite); + + +#endif \ No newline at end of file diff --git a/APP/functionalModule/Src/FM_GPIO.c b/APP/functionalModule/Src/FM_GPIO.c new file mode 100644 index 0000000..b37e4c2 --- /dev/null +++ b/APP/functionalModule/Src/FM_GPIO.c @@ -0,0 +1,127 @@ + +#include "FM_GPIO.h" + +void FM_GPIO_Init(void) +{ + HD_GPIO_Init(); +} + +/** + * @brief 打开输出防反mos管 + * @param None + * @retval None + */ +void POW_FF_PCON_Open(void) +{ + HAL_GPIO_WritePin(POW_FF_CON_GPIO_Port, POW_FF_CON_Pin, GPIO_PIN_SET); +} + +/** + * @brief 关闭输出防反mos管 + * @param None + * @retval None + */ +void POW_FF_PCON_Close(void) +{ + HAL_GPIO_WritePin(POW_FF_CON_GPIO_Port, POW_FF_CON_Pin, GPIO_PIN_RESET); +} + +/** + * @brief 打开输出mos管 + * @param None + * @retval None + */ +void POW_OUT_PCON_Open(void) +{ + HAL_GPIO_WritePin(POW_OUT_CON_GPIO_Port, POW_OUT_CON_Pin, GPIO_PIN_SET); +} + +/** + * @brief 关闭输出mos管 + * @param None + * @retval None + */ +void POW_OUT_PCON_Close(void) +{ + HAL_GPIO_WritePin(POW_OUT_CON_GPIO_Port, POW_OUT_CON_Pin, GPIO_PIN_RESET); +} + +/** + * @brief 打开LED灯 + * @param None + * @retval None + */ +void RUN_LEN_Open(void) +{ + HAL_GPIO_WritePin(RUN_LED_GPIO_Port, RUN_LED_Pin, GPIO_PIN_SET); +} + +/** + * @brief 关闭LED灯 + * @param None + * @retval None + */ +void RUN_LEN_Close(void) +{ + HAL_GPIO_WritePin(RUN_LED_GPIO_Port, RUN_LED_Pin, GPIO_PIN_RESET); +} + +/** + * @brief 打开mppt电感后的输出mos管 + * @param None + * @retval None + */ +void FFMOS_CON_Open(void) +{ + HAL_GPIO_WritePin(FFMOS_CON_GPIO_Port, FFMOS_CON_Pin, GPIO_PIN_RESET); +} + +/** + * @brief 关闭mppt电感后的输出mos管 + * @param None + * @retval None + */ +void FFMOS_CON_Close(void) +{ + HAL_GPIO_WritePin(FFMOS_CON_GPIO_Port, FFMOS_CON_Pin, GPIO_PIN_SET); +} + +/** + * @brief 下桥的mos管使能pwm输出 + * @param None + * @retval None + */ +void EN_PWMOUT_Eable(void) +{ + HAL_GPIO_WritePin(EN_PWMOUT_GPIO_Port, EN_PWMOUT_Pin, GPIO_PIN_RESET); +} + +/** + * @brief 下桥的mos管关闭pwm输出 + * @param None + * @retval None + */ +void EN_PWMOUT_Diseable(void) +{ + HAL_GPIO_WritePin(EN_PWMOUT_GPIO_Port, EN_PWMOUT_Pin, GPIO_PIN_SET); +} + +/** + * @brief GPIO外部中断的回调函数 + * @param GPIO_Pin 引发外部中断的引脚 + * @retval None + */ +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) +{ + if (GPIO_Pin == WORK_VOLT_Pin) { + // WORK_VOLT_Interrupt(); + } + + else if (GPIO_Pin == DSG_PROT_Pin) { + // DSG_PROT_Interrupt(); + } +} + + + + diff --git a/APP/functionalModule/Src/FM_TIM.c b/APP/functionalModule/Src/FM_TIM.c new file mode 100644 index 0000000..97c5231 --- /dev/null +++ b/APP/functionalModule/Src/FM_TIM.c @@ -0,0 +1,77 @@ + +#include "FM_TIM.h" +#include "timeSliceOffset.h" + +static int PWM_RESOLUTION; + +void pwm_Init(void) +{ + HD_PWM_Init(); + PWM_RESOLUTION = HAL_RCC_GetHCLKFreq() / 100000; +} + +void pwm_Stop(void) +{ + set_pwmPulse(0); + HAL_TIM_OC_MspDeInit(&htim3); +} + +/** + * @brief 设置占空比的大小 + * @param Pulse 高电平所占的数 + * @retval None + */ +void set_pwmPulse(uint32_t Pulse) +{ + if (Pulse > PWM_RESOLUTION) { + return; + } + __HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_4, Pulse); +} + +/** + * @brief 设置占空比的大小 + * @param DutyRatio 占空比 + * @retval None + */ +void set_pwmDutyRatio(float DutyRatio) +{ + if (DutyRatio > (float)0.9 || DutyRatio < (float)0.05) { + return; + } + + uint32_t Pulse = (int)(DutyRatio * PWM_RESOLUTION); + + set_pwmPulse(Pulse); +} + +/** + * @brief Period elapsed callback in non blocking mode + * @note This function is called when TIM1 interrupt took place, inside + * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment + * a global variable "uwTick" used as application time base. + * @param htim : TIM handle + * @retval None + */ + /** + * @brief 回调函数 + * @param htim 产生中断定时器 + * @retval None + */ +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + /* USER CODE BEGIN Callback 0 */ + + /* USER CODE END Callback 0 */ + if (htim->Instance == TIM1) { + HAL_IncTick(); + } + /* USER CODE BEGIN Callback 1 */ + + if (htim->Instance == TIM7) { + TimeSliceOffset_Produce(); + chargControl(); + } + + /* USER CODE END Callback 1 */ +} \ No newline at end of file diff --git a/APP/functionalModule/Src/flash.c b/APP/functionalModule/Src/flash.c new file mode 100644 index 0000000..d3c0f88 --- /dev/null +++ b/APP/functionalModule/Src/flash.c @@ -0,0 +1,43 @@ +#include "flash.h" + +/** + * @brief flash初始化 + * @param + */ +void Flash_Init(void) +{ + __HAL_RCC_GPIOA_CLK_ENABLE(); + + HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_RESET); + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + GPIO_InitStruct.Pin = FLASH_CS_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + W25QXX_Init(); +} + +/** + * @brief 读取flash中的数据 + * @param pBuffer 保存读取的数据 + * @param ReadAddr 读取数据的位置 + * @param NumByteToRead 读取数据的长度 + */ +void read_Flash(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead) +{ + W25QXX_Read(pBuffer, ReadAddr, NumByteToRead); +} + +/** + * @brief 将数据写入到flash中 + * @param pBuffer 要写入的数据 + * @param ReadAddr 要写入数据的位置 + * @param NumByteToRead 要写入数据的长度 + */ +void write_Flash(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite) +{ + W25QXX_Write(pBuffer, WriteAddr, NumByteToWrite); +} \ No newline at end of file diff --git a/APP/hardwareDriver/Inc/HD_GPIO.h b/APP/hardwareDriver/Inc/HD_GPIO.h new file mode 100644 index 0000000..d905b33 --- /dev/null +++ b/APP/hardwareDriver/Inc/HD_GPIO.h @@ -0,0 +1,12 @@ + +#ifndef HD_GPIO_H_ +#define HD_GPIO_H_ + +#include "main.h" +#include "gpio.h" +#include "stm32g431xx.h" +#include "comm_types.h" + +void HD_GPIO_Init(void); + +#endif \ No newline at end of file diff --git a/APP/hardwareDriver/Inc/HD_TIM.h b/APP/hardwareDriver/Inc/HD_TIM.h new file mode 100644 index 0000000..8dbcacd --- /dev/null +++ b/APP/hardwareDriver/Inc/HD_TIM.h @@ -0,0 +1,13 @@ + +#ifndef HD_TIM_H_ +#define HD_TIM_H_ + +#include "main.h" +#include "tim.h" +#include "stm32g431xx.h" + +void HD_PWM_Init(void); +void HD_controlTim_Init(void); + + +#endif \ No newline at end of file diff --git a/APP/hardwareDriver/Inc/w25qxx.h b/APP/hardwareDriver/Inc/w25qxx.h new file mode 100644 index 0000000..8bab1b4 --- /dev/null +++ b/APP/hardwareDriver/Inc/w25qxx.h @@ -0,0 +1,67 @@ +#ifndef __W25QXX_H +#define __W25QXX_H + +#include + +#define W25QXX_SPI_Handle (&hspi1) + +//W25X系列/Q系列芯片列表 +//W25Q80 ID 0XEF13 +//W25Q16 ID 0XEF14 +//W25Q32 ID 0XEF15 +//W25Q64 ID 0XEF16 +//W25Q128 ID 0XEF17 +#define W25Q80 0XEF13 +#define W25Q16 0XEF14 +#define W25Q32 0XEF15 +#define W25Q64 0XEF16 +#define W25Q128 0XEF17 + + +#define W25QXX_CS_L() HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_RESET) +#define W25QXX_CS_H() HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_SET) + + +extern uint16_t W25QXX_TYPE; +extern uint32_t W25QXX_SIZE; +extern uint8_t W25QXX_UID[8]; + + +// +//指令表 +#define W25X_WriteEnable 0x06 +#define W25X_WriteDisable 0x04 +#define W25X_ReadStatusReg 0x05 +#define W25X_WriteStatusReg 0x01 +#define W25X_ReadData 0x03 +#define W25X_FastReadData 0x0B +#define W25X_FastReadDual 0x3B +#define W25X_PageProgram 0x02 +#define W25X_BlockErase 0xD8 +#define W25X_SectorErase 0x20 +#define W25X_ChipErase 0xC7 +#define W25X_PowerDown 0xB9 +#define W25X_ReleasePowerDown 0xAB +#define W25X_DeviceID 0xAB +#define W25X_ManufactDeviceID 0x90 +#define W25X_JedecDeviceID 0x9F + +int W25QXX_Init(void); +void W25QXX_ReadUniqueID(uint8_t UID[8]); +uint16_t W25QXX_ReadID(void); //读取FLASH ID +uint8_t W25QXX_ReadSR(void); //读取状态寄存器 +void W25QXX_Write_SR(uint8_t sr); //写状态寄存器 +void W25QXX_Write_Enable(void); //写使能 +void W25QXX_Write_Disable(void); //写保护 +void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite); +void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead); //读取flash +void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);//写入flash +void W25QXX_Erase_Chip(void); //整片擦除 +void W25QXX_Erase_Sector(uint32_t Dst_Addr); //扇区擦除 +void W25QXX_Wait_Busy(void); //等待空闲 +void W25QXX_PowerDown(void); //进入掉电模式 +void W25QXX_WAKEUP(void); //唤醒 +uint32_t W25QXX_ReadCapacity(void); + +#endif + diff --git a/APP/hardwareDriver/Src/HD_GPIO.c b/APP/hardwareDriver/Src/HD_GPIO.c new file mode 100644 index 0000000..322fa56 --- /dev/null +++ b/APP/hardwareDriver/Src/HD_GPIO.c @@ -0,0 +1,58 @@ +#include "HD_GPIO.h" + +void HD_GPIO_Init(void) +{ + // MX_GPIO_Init(); + + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOF_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + // HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOB, WDI_INPUT_Pin|RUN_LED_Pin|POW_FF_CON_Pin|POW_OUT_CON_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOA, EN_PWMOUT_Pin|FFMOS_CON_Pin, GPIO_PIN_SET); + + /*Configure GPIO pin : DSG_PROT_Pin */ + GPIO_InitStruct.Pin = DSG_PROT_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(DSG_PROT_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pins : FLASH_CS_Pin EN_PWMOUT_Pin FFMOS_CON_Pin */ + // GPIO_InitStruct.Pin = FLASH_CS_Pin|EN_PWMOUT_Pin|FFMOS_CON_Pin; + // GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + // GPIO_InitStruct.Pull = GPIO_NOPULL; + // GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + // HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + GPIO_InitStruct.Pin = EN_PWMOUT_Pin|FFMOS_CON_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /*Configure GPIO pins : WDI_INPUT_Pin RUN_LED_Pin POW_FF_CON_Pin POW_OUT_CON_Pin */ + GPIO_InitStruct.Pin = WDI_INPUT_Pin|RUN_LED_Pin|POW_FF_CON_Pin|POW_OUT_CON_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /*Configure GPIO pin : WORK_VOLT_INT_Pin */ + GPIO_InitStruct.Pin = WORK_VOLT_INT_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(WORK_VOLT_INT_GPIO_Port, &GPIO_InitStruct); + + /* EXTI interrupt init*/ + HAL_NVIC_SetPriority(EXTI15_10_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); +} \ No newline at end of file diff --git a/APP/hardwareDriver/Src/HD_TIM.c b/APP/hardwareDriver/Src/HD_TIM.c new file mode 100644 index 0000000..4f67bf6 --- /dev/null +++ b/APP/hardwareDriver/Src/HD_TIM.c @@ -0,0 +1,11 @@ +#include "HD_TIM.h" + +void HD_PWM_Init(void) +{ + MX_TIM3_Init(); +} + +void HD_controlTim_Init(void) +{ + MX_TIM7_Init(); +} \ No newline at end of file diff --git a/APP/hardwareDriver/Src/w25qxx.c b/APP/hardwareDriver/Src/w25qxx.c new file mode 100644 index 0000000..3e5d659 --- /dev/null +++ b/APP/hardwareDriver/Src/w25qxx.c @@ -0,0 +1,334 @@ + +/** + * @file w25qxx.c + * + * @brief Create by AnKun on 2020/6/18 + * + */ + +#include "w25qxx.h" +#include "spi.h" + +uint16_t W25QXX_TYPE = 0; +uint32_t W25QXX_SIZE = 0; +uint8_t W25QXX_UID[8]; + +static void delay_us(uint32_t us) +{ + uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us); + while (delay--) + { + ; + } +} + +//SPI读写一个字节 +//TxData:要写入的字节 +//返回值:读取到的字节 +static uint8_t W25QXX_SPI_ReadWriteByte(uint8_t TxData) +{ + uint8_t RxData = 0X00; + if(HAL_SPI_TransmitReceive(W25QXX_SPI_Handle, &TxData, &RxData, 1, 10) != HAL_OK) + { + RxData = 0XFF; + } + return RxData; +} + +//4Kbytes为一个Sector +//16个扇区为1个Block +//W25Q128 +//容量为16M字节,共有128个Block,4096个Sector + +//初始化SPI FLASH的IO口 +int W25QXX_Init(void) +{ + MX_SPI1_Init(); + W25QXX_CS_L(); /* 拉低选中 */ + W25QXX_SPI_ReadWriteByte(0XFF); + W25QXX_CS_H(); /* 拉高取消 */ + W25QXX_TYPE = W25QXX_ReadID(); // 读取FLASH ID. + W25QXX_SIZE = W25QXX_ReadCapacity(); // 读取容量 + W25QXX_ReadUniqueID(W25QXX_UID); // 读取唯一ID + if((W25QXX_TYPE & 0XEF00) != 0XEF00) + { + return -1; + } + return 0; +} + +//读取W25QXX的状态寄存器 +//BIT7 6 5 4 3 2 1 0 +//SPR RV TB BP2 BP1 BP0 WEL BUSY +//SPR:默认0,状态寄存器保护位,配合WP使用 +//TB,BP2,BP1,BP0:FLASH区域写保护设置 +//WEL:写使能锁定 +//BUSY:忙标记位(1,忙;0,空闲) +//默认:0x00 +uint8_t W25QXX_ReadSR(void) +{ + uint8_t byte = 0; + W25QXX_CS_L(); //使能器件 + W25QXX_SPI_ReadWriteByte(W25X_ReadStatusReg); //发送读取状态寄存器命令 + byte = W25QXX_SPI_ReadWriteByte(0Xff); //读取一个字节 + W25QXX_CS_H(); //取消片选 + return byte; +} +//写W25QXX状态寄存器 +//只有SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)可以写!!! +void W25QXX_Write_SR(uint8_t sr) +{ + W25QXX_CS_L(); //使能器件 + W25QXX_SPI_ReadWriteByte(W25X_WriteStatusReg); //发送写取状态寄存器命令 + W25QXX_SPI_ReadWriteByte(sr); //写入一个字节 + W25QXX_CS_H(); //取消片选 +} +//W25QXX写使能 +//将WEL置位 +void W25QXX_Write_Enable(void) +{ + W25QXX_CS_L(); //使能器件 + W25QXX_SPI_ReadWriteByte(W25X_WriteEnable); //发送写使能 + W25QXX_CS_H(); //取消片选 +} +//W25QXX写禁止 +//将WEL清零 +void W25QXX_Write_Disable(void) +{ + W25QXX_CS_L(); //使能器件 + W25QXX_SPI_ReadWriteByte(W25X_WriteDisable); //发送写禁止指令 + W25QXX_CS_H(); //取消片选 +} +//读取芯片ID +//返回值如下: +//0XEF13,表示芯片型号为W25Q80 +//0XEF14,表示芯片型号为W25Q16 +//0XEF15,表示芯片型号为W25Q32 +//0XEF16,表示芯片型号为W25Q64 +//0XEF17,表示芯片型号为W25Q128 +uint16_t W25QXX_ReadID(void) +{ + uint16_t Temp = 0; + W25QXX_CS_L(); + W25QXX_SPI_ReadWriteByte(0x90); //发送读取ID命令 + W25QXX_SPI_ReadWriteByte(0x00); + W25QXX_SPI_ReadWriteByte(0x00); + W25QXX_SPI_ReadWriteByte(0x00); + Temp |= W25QXX_SPI_ReadWriteByte(0xFF) << 8; + Temp |= W25QXX_SPI_ReadWriteByte(0xFF); + W25QXX_CS_H(); + return Temp; +} + +uint32_t W25QXX_ReadCapacity(void) +{ + int i = 0; + uint8_t arr[4] = {0,0,0,0}; + W25QXX_CS_L(); + W25QXX_SPI_ReadWriteByte(0x5A); + W25QXX_SPI_ReadWriteByte(0x00); + W25QXX_SPI_ReadWriteByte(0x00); + W25QXX_SPI_ReadWriteByte(0x84); + W25QXX_SPI_ReadWriteByte(0x00); + for(i = 0; i < sizeof(arr); i++) + { + arr[i] = W25QXX_SPI_ReadWriteByte(0xFF); + } + W25QXX_CS_H(); + return ((((*(uint32_t *)arr)) + 1) >> 3); +} + +void W25QXX_ReadUniqueID(uint8_t UID[8]) +{ + int i = 0; + W25QXX_CS_L(); + W25QXX_SPI_ReadWriteByte(0x4B); + W25QXX_SPI_ReadWriteByte(0x00); + W25QXX_SPI_ReadWriteByte(0x00); + W25QXX_SPI_ReadWriteByte(0x00); + W25QXX_SPI_ReadWriteByte(0x00); + for(i = 0; i < 8; i++) + { + UID[i] = W25QXX_SPI_ReadWriteByte(0xFF); + } + W25QXX_CS_H(); +} + +//读取SPI FLASH +//在指定地址开始读取指定长度的数据 +//pBuffer:数据存储区 +//ReadAddr:开始读取的地址(24bit) +//NumByteToRead:要读取的字节数(最大65535) +void W25QXX_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) +{ + uint16_t i; + W25QXX_CS_L(); //使能器件 + W25QXX_SPI_ReadWriteByte(W25X_ReadData); //发送读取命令 + W25QXX_SPI_ReadWriteByte((uint8_t)((ReadAddr) >> 16)); //发送24bit地址 + W25QXX_SPI_ReadWriteByte((uint8_t)((ReadAddr) >> 8)); + W25QXX_SPI_ReadWriteByte((uint8_t)ReadAddr); + for (i = 0; i < NumByteToRead; i++) + { + pBuffer[i] = W25QXX_SPI_ReadWriteByte(0XFF); //循环读数 + } + W25QXX_CS_H(); +} +//SPI在一页(0~65535)内写入少于256个字节的数据 +//在指定地址开始写入最大256字节的数据 +//pBuffer:数据存储区 +//WriteAddr:开始写入的地址(24bit) +//NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!! +void W25QXX_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) +{ + uint16_t i; + W25QXX_Write_Enable(); //SET WEL + W25QXX_CS_L(); //使能器件 + W25QXX_SPI_ReadWriteByte(W25X_PageProgram); //发送写页命令 + W25QXX_SPI_ReadWriteByte((uint8_t)((WriteAddr) >> 16)); //发送24bit地址 + W25QXX_SPI_ReadWriteByte((uint8_t)((WriteAddr) >> 8)); + W25QXX_SPI_ReadWriteByte((uint8_t)WriteAddr); + for (i = 0; i < NumByteToWrite; i++) + W25QXX_SPI_ReadWriteByte(pBuffer[i]); //循环写数 + W25QXX_CS_H(); //取消片选 + W25QXX_Wait_Busy(); //等待写入结束 +} +//无检验写SPI FLASH +//必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败! +//具有自动换页功能 +//在指定地址开始写入指定长度的数据,但是要确保地址不越界! +//pBuffer:数据存储区 +//WriteAddr:开始写入的地址(24bit) +//NumByteToWrite:要写入的字节数(最大65535) +//CHECK OK +void W25QXX_Write_NoCheck(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) +{ + uint16_t pageremain; + pageremain = 256 - WriteAddr % 256; //单页剩余的字节数 + if (NumByteToWrite <= pageremain) + pageremain = NumByteToWrite; //不大于256个字节 + while (1) + { + W25QXX_Write_Page(pBuffer, WriteAddr, pageremain); + if (NumByteToWrite == pageremain) + break; //写入结束了 + else //NumByteToWrite>pageremain + { + pBuffer += pageremain; + WriteAddr += pageremain; + + NumByteToWrite -= pageremain; //减去已经写入了的字节数 + if (NumByteToWrite > 256) + pageremain = 256; //一次可以写入256个字节 + else + pageremain = NumByteToWrite; //不够256个字节了 + } + }; +} +//写SPI FLASH +//在指定地址开始写入指定长度的数据 +//该函数带擦除操作! +//pBuffer:数据存储区 +//WriteAddr:开始写入的地址(24bit) +//NumByteToWrite:要写入的字节数(最大65535) +uint8_t W25QXX_BUFFER[4096]; +void W25QXX_Write(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) +{ + uint32_t secpos; + uint16_t secoff; + uint16_t secremain; + uint16_t i; + uint8_t *W25QXX_BUF; + W25QXX_BUF = W25QXX_BUFFER; + secpos = WriteAddr / 4096; //扇区地址 + secoff = WriteAddr % 4096; //在扇区内的偏移 + secremain = 4096 - secoff; //扇区剩余空间大小 + if (NumByteToWrite <= secremain) + secremain = NumByteToWrite; //不大于4096个字节 + while (1) + { + W25QXX_Read(W25QXX_BUF, secpos * 4096, 4096); //读出整个扇区的内容 + for (i = 0; i < secremain; i++) //校验数据 + { + if (W25QXX_BUF[secoff + i] != 0XFF) + break; //需要擦除 + } + if (i < secremain) //需要擦除 + { + W25QXX_Erase_Sector(secpos); //擦除这个扇区 + for (i = 0; i < secremain; i++) //复制 + { + W25QXX_BUF[i + secoff] = pBuffer[i]; + } + W25QXX_Write_NoCheck(W25QXX_BUF, secpos * 4096, 4096); //写入整个扇区 + + } + else + W25QXX_Write_NoCheck(pBuffer, WriteAddr, secremain); //写已经擦除了的,直接写入扇区剩余区间. + if (NumByteToWrite == secremain) + break; //写入结束了 + else //写入未结束 + { + secpos++; //扇区地址增1 + secoff = 0; //偏移位置为0 + + pBuffer += secremain; //指针偏移 + WriteAddr += secremain; //写地址偏移 + NumByteToWrite -= secremain; //字节数递减 + if (NumByteToWrite > 4096) + secremain = 4096; //下一个扇区还是写不完 + else + secremain = NumByteToWrite; //下一个扇区可以写完了 + } + }; +} + +//擦除整个芯片 +//等待时间超长... +void W25QXX_Erase_Chip(void) +{ + W25QXX_Write_Enable(); //SET WEL + W25QXX_Wait_Busy(); + W25QXX_CS_L(); //使能器件 + W25QXX_SPI_ReadWriteByte(W25X_ChipErase); //发送片擦除命令 + W25QXX_CS_H(); //取消片选 + W25QXX_Wait_Busy(); //等待芯片擦除结束 +} +//擦除一个扇区 +//Dst_Addr:扇区地址 根据实际容量设置 +//擦除一个山区的最少时间:150ms +void W25QXX_Erase_Sector(uint32_t Dst_Addr) +{ + //监视falsh擦除情况,测试用 + Dst_Addr *= 4096; + W25QXX_Write_Enable(); //SET WEL + W25QXX_Wait_Busy(); + W25QXX_CS_L(); //使能器件 + W25QXX_SPI_ReadWriteByte(W25X_SectorErase); //发送扇区擦除指令 + W25QXX_SPI_ReadWriteByte((uint8_t)((Dst_Addr) >> 16)); //发送24bit地址 + W25QXX_SPI_ReadWriteByte((uint8_t)((Dst_Addr) >> 8)); + W25QXX_SPI_ReadWriteByte((uint8_t)Dst_Addr); + W25QXX_CS_H(); //取消片选 + W25QXX_Wait_Busy(); //等待擦除完成 +} +//等待空闲 +void W25QXX_Wait_Busy(void) +{ + while ((W25QXX_ReadSR() & 0x01) == 0x01); // 等待BUSY位清空 +} +//进入掉电模式 +void W25QXX_PowerDown(void) +{ + W25QXX_CS_L(); //使能器件 + W25QXX_SPI_ReadWriteByte(W25X_PowerDown); //发送掉电命令 + W25QXX_CS_H(); //取消片选 + delay_us(3); //等待TPD +} +//唤醒 +void W25QXX_WAKEUP(void) +{ + W25QXX_CS_L(); //使能器件 + W25QXX_SPI_ReadWriteByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB + W25QXX_CS_H(); //取消片选 + delay_us(3); //等待TRES1 +} + diff --git a/Core/Src/main.c b/Core/Src/main.c index d53769e..45147ad 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -173,18 +173,18 @@ void SystemClock_Config(void) * @param htim : TIM handle * @retval None */ -void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) -{ - /* USER CODE BEGIN Callback 0 */ +// void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +// { +// /* USER CODE BEGIN Callback 0 */ - /* USER CODE END Callback 0 */ - if (htim->Instance == TIM1) { - HAL_IncTick(); - } - /* USER CODE BEGIN Callback 1 */ +// /* USER CODE END Callback 0 */ +// if (htim->Instance == TIM1) { +// HAL_IncTick(); +// } +// /* USER CODE BEGIN Callback 1 */ - /* USER CODE END Callback 1 */ -} +// /* USER CODE END Callback 1 */ +// } /** * @brief This function is executed in case of error occurrence. diff --git a/EWARM/chargeController.ewp b/EWARM/chargeController.ewp index efd1f26..a26a0e4 100644 --- a/EWARM/chargeController.ewp +++ b/EWARM/chargeController.ewp @@ -365,6 +365,7 @@ $PROJ_DIR$\..\APP\hardwareDriver\Inc $PROJ_DIR$\..\tools\RingQueue $PROJ_DIR$\..\tools + $PROJ_DIR$\..\tools\TimeSliceOffset