diff --git a/APP/businessLogic/Inc/SOE.h b/APP/businessLogic/Inc/SOE.h index 094f337..f494469 100644 --- a/APP/businessLogic/Inc/SOE.h +++ b/APP/businessLogic/Inc/SOE.h @@ -10,9 +10,10 @@ void eventsOrderRecordStartInit(void); void setEventsOrderRecord(void); -void printfEventsOrderRecord(void); +void readEventsOrderRecord(uint16_t offset, uint8_t *data); void insertEventsOrderRecord(eventsOrderRecordMode mode); +uint16_t getSoeDataInfoSize(void); #endif diff --git a/APP/businessLogic/Src/Init.c b/APP/businessLogic/Src/Init.c index 6555020..9362f47 100644 --- a/APP/businessLogic/Src/Init.c +++ b/APP/businessLogic/Src/Init.c @@ -10,6 +10,7 @@ #include "pDebug.h" #include "interruptSend.h" #include "FM_RTC.h" +#include "SOE.h" /** * @brief 初始化外设,同时通过配置文件初始化系统参数 @@ -41,6 +42,8 @@ void Init(void) start_bat485Rx_It(); send_init(); + eventsOrderRecordStartInit(); + // POW_FF_PCON_Open(); // POW_OUT_PCON_Open(); HAL_Delay(100); diff --git a/APP/businessLogic/Src/SOE.c b/APP/businessLogic/Src/SOE.c index 0103d11..89b12a5 100644 --- a/APP/businessLogic/Src/SOE.c +++ b/APP/businessLogic/Src/SOE.c @@ -25,14 +25,21 @@ typedef struct _soeSaveInfo { } soeSaveInfo; typedef struct _soeStorageParameters { - uint16_t len; //soe记录次数 + uint16_t len; //soe下次记录距离0的偏移量 uint16_t pos; //下次soe记录的位置 } soeStorageParameters; static soeSaveInfo soeInfo = {0}; static soeStorageParameters soeParameters = {0}; - +/** + * @brief 得到一次时间记录的长度 + * @param + */ +uint16_t getSoeDataInfoSize(void) +{ + return soeDataInfoSize; +} /** * @brief 初始化事件顺序记录 @@ -40,13 +47,26 @@ static soeStorageParameters soeParameters = {0}; */ void eventsOrderRecordStartInit(void) { + read_Flash((uint8_t *)(&soeParameters), eventsOrderRecordStartAddr, sizeof(soeParameters)); + + if (soeParameters.len == 0xFFFF && soeParameters.pos == 0xFFFF) { + soeParameters.len = 0; + soeParameters.pos = eventsOrderRecordStartAddr + sizeof(soeParameters); + write_Flash((uint8_t *)(&soeParameters), eventsOrderRecordStartAddr, sizeof(soeParameters)); + } + + else if (soeParameters.len > 100 + || soeParameters.pos != eventsOrderRecordStartAddr + sizeof(soeParameters) + soeParameters.len * soeDataInfoSize) { + soeParameters.len = 0; + soeParameters.pos = eventsOrderRecordStartAddr + sizeof(soeParameters); + write_Flash((uint8_t *)(&soeParameters), eventsOrderRecordStartAddr, sizeof(soeParameters)); + } + soeInfo.count = 5; soeInfo.insertPos = 0; soeInfo.outPos = 0; soeInfo.outData = NULL; soeInfo.insertData = &soeInfo.data[soeInfo.insertPos]; - - // read_Flash((uint8_t *)(&soeParameters), sizeof(soeParameters)); } /** @@ -103,6 +123,14 @@ void insertEventsOrderRecord(eventsOrderRecordMode mode) soeInfo.insertData->temp = getChargCurrent(); } + else if (mode == overInputVolt) { + soeInfo.insertData->temp = getSolarInCircuitVoltage(); + } + + else { + soeInfo.count++; + return; + } soeInfo.insertPos++; if (soeInfo.insertPos >= 5) { @@ -128,8 +156,15 @@ void setEventsOrderRecord(void) if (soeInfo.outData == NULL || soeInfo.count >= 5) { return; } + + write_Flash((uint8_t *)(&soeInfo.outData), soeParameters.pos, soeDataInfoSize); - // write_Flash((uint8_t *)(&soeInfo.outData), soeDataInfoSize); + soeParameters.len++; + if (soeParameters.len >= 100) { + soeParameters.len = 0; + } + soeParameters.pos += soeDataInfoSize; + write_Flash((uint8_t *)(&soeParameters), eventsOrderRecordStartAddr, sizeof(soeStorageParameters)); soeInfo.outPos++; if (soeInfo.outPos >= 5) { @@ -145,17 +180,28 @@ void setEventsOrderRecord(void) if (soeInfo.insertData == NULL) { soeInfo.insertData = &soeInfo.data[soeInfo.insertPos]; - } + } } /** - * @brief 将事件从flash中依次读取出来 - * @param + * @brief 将事件从flash中依次读取出来 + * @param offset : 距离下次写入数据的偏移量 + * *data : 数据的储存位置 */ -void printfEventsOrderRecord(void) +void readEventsOrderRecord(uint16_t offset, uint8_t *data) { + uint16_t addr; + if (soeParameters.len + 1 - offset < 0) { + addr = eventsOrderRecordStartAddr + sizeof(soeStorageParameters) + + (100 + soeParameters.len + 1 - offset) * soeDataInfoSize; + } else { + addr = eventsOrderRecordStartAddr + sizeof(soeStorageParameters) + + (soeParameters.len + 1 - offset) * soeDataInfoSize; + } + + read_Flash(data, addr, soeDataInfoSize); } diff --git a/APP/businessLogic/Src/abnormalManage.c b/APP/businessLogic/Src/abnormalManage.c index 23c7ca8..f1f0efe 100644 --- a/APP/businessLogic/Src/abnormalManage.c +++ b/APP/businessLogic/Src/abnormalManage.c @@ -8,6 +8,7 @@ #include "configParameter.h" #include "capture.h" #include "bl_chargControl.h" +#include "SOE.h" //static int checkMode = 0; @@ -45,7 +46,8 @@ void setDisChargOverLoad(void) if (num1 >= g_cfgParameter.thirdStageProtectionDelay) { num1 = 0; setPowerOutput(FALSE); - disChargOverLoad = TRUE; + disChargOverLoad = TRUE; + insertEventsOrderRecord(thirdStageProtection); } @@ -62,6 +64,7 @@ void setDisChargOverLoad(void) num2 = 0; setPowerOutput(FALSE); disChargOverLoad = TRUE; + insertEventsOrderRecord(secondStageProtection); } } @@ -94,6 +97,7 @@ void setSoftShortCircuit(uint16_t disChargCurrAdcNum) setPowerOutput(FALSE); shortCircuitFlag = TRUE; shortCircuit++; + insertEventsOrderRecord(firstStageProtection); startSoftShortCircuitProtection(); } } @@ -340,6 +344,7 @@ void setOverLoad(void) /* 多次进入输出过载,关闭输出 */ if (getExcessiveLoad() > 2) { zeroExcessiveLoad(); + insertEventsOrderRecord(lowInputLoad); } } @@ -376,6 +381,7 @@ void judgeChargCurr(void) { if (getChargCurrent() > g_cfgParameter.maxChargCurr) { stopChargWork(); + insertEventsOrderRecord(overchargCurr); } } diff --git a/APP/businessLogic/Src/bl_usart.c b/APP/businessLogic/Src/bl_usart.c index 7476793..9a285a2 100644 --- a/APP/businessLogic/Src/bl_usart.c +++ b/APP/businessLogic/Src/bl_usart.c @@ -8,6 +8,7 @@ #include "bl_chargControl.h" #include "interruptSend.h" #include "inFlash.h" +#include "SOE.h" /* 状态机 */ typedef enum { @@ -26,7 +27,8 @@ typedef enum { cfgFramesNumSL, /* 接收到SL配置文件帧数 */ cfgLengthSL, /* 接收到SL配置文件长度 */ readCfgLengthSL, /* 接收到SL读取配置文件长度 */ - + readSOEStartAddr, /* 接收到SOE起始读取位 */ + readSOELength, /* 接收到SOE读取长度 */ } uartStateMachine; /* 功能码 */ @@ -38,6 +40,7 @@ typedef enum SL_Function_Code_Registration_request = 0xA1, /* 注册请求 */ SL_Function_Code_Distribution_Profile = 0xD0, /* 配置文件下发 */ SL_Function_Code_Read_Profile = 0xD1, /* 配置文件读取 */ + SL_Function_Code_Read_SOE = 0x05, /* 读取SOE */ }SL_MsgFunctionCode; /* 寄存器地址 */ @@ -134,6 +137,8 @@ static BOOL analysisRegStatusSL(void); static BOOL analysisCfgFramesNumSL(void); static BOOL analysiscfgLengthSL(void); static BOOL analysisReadCfgLengthSL(void); +static BOOL analysisReadSOEStartAddr(void); +static BOOL analysisReadSOELength(void); /* SL协议寄存器解析 */ @@ -205,6 +210,7 @@ static void SL_MsgProcFunc_Broadcast_Scan(device_handle device, void *pMsg, uint static void SL_MsgProcFunc_Registration_request(device_handle device, void *pMsg, uint32_t MsgLen); static void SL_MsgProcFunc_Distribution_Profile(device_handle device, void *pMsg, uint32_t MsgLen); static void SL_MsgProcFunc_Read_Profile(device_handle device, void *pMsg, uint32_t MsgLen); +static void SL_MsgProcFunc_Read_SOE(device_handle device, void *pMsg, uint32_t MsgLen); @@ -341,6 +347,14 @@ void stateMachine(device_handle device) else if (state == readCfgLengthSL) { analysisReadCfgLengthSL(); } + + else if (state == readSOEStartAddr) { + analysisReadSOEStartAddr(); + } + + else if (state == readSOELength) { + analysisReadSOELength(); + } } void gw485DataAnalysis(device_handle device) @@ -365,13 +379,17 @@ void gw485DataAnalysis(device_handle device) gw485CfgFlag = 2; } } - while (uart_dev_char_present(device) == 1 && ((HAL_GetTick() - tickstart) < 5)) { gw485RxBuffer[gw485RxBufferIndex++] = uart_dev_in_char(device); stateMachine(device); } - stateMachine(device); + +// tickstart = HAL_GetTick(); +// while (gw485RxBufferIndex != 0 && ((HAL_GetTick() - tickstart) < 5) ) { + stateMachine(device); +// } + } /** @@ -478,7 +496,8 @@ BOOL analysisAddressSL(void) || gw485RxBuffer[9] == SL_Function_Code_Write_Register || gw485RxBuffer[9] == SL_Function_Code_Registration_request || gw485RxBuffer[9] == SL_Function_Code_Distribution_Profile - || gw485RxBuffer[9] == SL_Function_Code_Read_Profile ) { + || gw485RxBuffer[9] == SL_Function_Code_Read_Profile + || gw485RxBuffer[9] == SL_Function_Code_Read_SOE){ state = functionCodeSL; return TRUE; @@ -575,6 +594,17 @@ BOOL analysisFunctionCodeSL(void) return TRUE; } } + + /* 解析SOE读取的起始读取位 */ + // if ((gw485RxBufferIndex >= 11) && (gw485RxBuffer[9] == SL_Function_Code_Read_SOE)) { + if (gw485RxBuffer[9] == SL_Function_Code_Read_SOE) { + // if (gw485RxBuffer[10] < 100 && gw485RxBuffer[10] >= 0) { + if (gw485RxBuffer[10] < 100) { + state = readSOEStartAddr; + frameLength = 15; + return TRUE; + } + } if (gw485RxBufferIndex < maxLen) { return FALSE; @@ -703,6 +733,11 @@ void analysisEndFlagSL(device_handle device) else if (gw485RxBuffer[9] == SL_Function_Code_Read_Profile) { SL_MsgProcFunc_Read_Profile(device, gw485RxBuffer, frameLength); } + + /* 数据为读取SOE */ + else if (gw485RxBuffer[9] == SL_Function_Code_Read_SOE) { + SL_MsgProcFunc_Read_SOE(device, gw485RxBuffer, frameLength); + } state = wait; gw485RxBufferIndex = 0; @@ -915,6 +950,35 @@ BOOL analysisReadCfgLengthSL(void) return checkCrcSl(); } +/** + * @brief 状态 readSOEStartAddr + * @param + * @retval TRUE:解析成功 FALSE:解析失败 + */ +BOOL analysisReadSOEStartAddr(void) +{ + if (gw485RxBuffer[10] + gw485RxBuffer[11] < 100 && gw485RxBuffer[11] > 0){ + state = readSOELength; + return TRUE; + } + + state = wait; + gw485RxBufferIndex--; + memcpy(gw485RxBuffer, gw485RxBuffer + 1, gw485RxBufferIndex); + return FALSE; +} + +/** + * @brief 状态 readSOELength + * @param + * @retval TRUE:解析成功 FALSE:解析失败 + */ +BOOL analysisReadSOELength(void) +{ + return checkCrcSl(); +} + + /* 读取寄存器 */ @@ -1853,16 +1917,16 @@ void SL_MsgProcFunc_Read_Register(device_handle device, void *pMsg, uint32_t Msg /* 回复字节数长度 */ replay_pack += 1; - *replay_pack = (Register_Number_16 >> 8); - *(replay_pack + 1) = (Register_Number_16); + *replay_pack = (uint8_t)((Register_Number_16 * 2) >> 8); + *(replay_pack + 1) = (uint8_t)(Register_Number_16 * 2); /* 回复数据内容 */ replay_pack += 2; for (uint8_t var = 0; var < Register_Number_16 * 2; var++) { if (0 == (var & 0x01)) { - *(replay_pack + var) = (reply_Data_Content[var / 2] >> 8); + *(replay_pack + var) = (uint8_t)(reply_Data_Content[var / 2] >> 8); } else { - *(replay_pack + var) = (reply_Data_Content[var / 2]); + *(replay_pack + var) = (uint8_t)(reply_Data_Content[var / 2]); } } @@ -2195,4 +2259,65 @@ void SL_MsgProcFunc_Read_Profile(device_handle device, void *pMsg, uint32_t MsgL *replay_pack = g_cfgParameter.endFlagSL; uart_insertDataSend(device, 15 + replayPackDatalen); -} \ No newline at end of file +} + +/** + * @brief 赛联协议读取SOE + * @param device 串口设备 + * pMsg 数据内容 + * MsgLen 数据长度 + * @retval + */ +void SL_MsgProcFunc_Read_SOE(device_handle device, void *pMsg, uint32_t MsgLen) +{ + debug_printf("SL_MsgProcFunc_Read_SOE\n"); + uint8_t *replay_pack = getInsertData(); + if (replay_pack == NULL) { + return; + } + + /* 起始标志 */ + *(replay_pack) = g_cfgParameter.startFlagSL[0]; + *(replay_pack + 1) = g_cfgParameter.startFlagSL[1]; + + /* 地址 */ + replay_pack += 2; + *(replay_pack) = g_cfgParameter.uniqueDeviceID[0]; + *(replay_pack + 1) = g_cfgParameter.uniqueDeviceID[1]; + *(replay_pack + 2) = g_cfgParameter.uniqueDeviceID[2]; + *(replay_pack + 3) = g_cfgParameter.uniqueDeviceID[3]; + *(replay_pack + 4) = g_cfgParameter.uniqueDeviceID[4]; + *(replay_pack + 5) = g_cfgParameter.uniqueDeviceID[5]; + *(replay_pack + 6) = g_cfgParameter.uniqueDeviceID[6]; + + /* 功能码 */ + replay_pack += 7; + *replay_pack = SL_Function_Code_Read_SOE; + + /* 数据内容长度 */ + uint16_t replayPackDatalen = (*((uint8_t *)pMsg + 11)) * getSoeDataInfoSize(); + replay_pack += 1; + *replay_pack = (uint8_t)(replayPackDatalen >> 8); + replay_pack += 1; + *replay_pack = (uint8_t)replayPackDatalen; + + /* 数据内容 */ + replay_pack += 1; + for (uint16_t i = 1; i <= (*((uint8_t *)pMsg + 11)); i++) { + readEventsOrderRecord((*((uint8_t *)pMsg + 10)) + i, replay_pack); + replay_pack += getSoeDataInfoSize(); + } + + /* 校验位 */ + uint16_t crc_temp = checkModebusCrc(getInsertData(), 12 + replayPackDatalen); + *replay_pack = (uint8_t)(crc_temp >> 8); + replay_pack += 1; + *replay_pack = (uint8_t)crc_temp; + + /* 结束标志 */ + replay_pack += 1; + *replay_pack = g_cfgParameter.endFlagSL; + + uart_insertDataSend(device, 15 + replayPackDatalen); +} + diff --git a/APP/businessLogic/Src/task.c b/APP/businessLogic/Src/task.c index 95bb555..4e73223 100644 --- a/APP/businessLogic/Src/task.c +++ b/APP/businessLogic/Src/task.c @@ -13,6 +13,8 @@ #include "configParameter.h" #include "capture.h" #include "bl_usart.h" +#include "SOE.h" + #include @@ -131,6 +133,14 @@ void Task_softShortCircuit(void); STR_TimeSliceOffset m_uart; void Task_uart(void); +/* 将记录下来的时间存入flash中 */ +#define SOE_reloadVal 3000 /* 任务执行间隔 */ +#define SOE_offset 100 /* 任务执行偏移量 */ +STR_TimeSliceOffset m_SOE; +void Task_SOE(void); + + + /** * @brief 启动时初始化各任务 * @param None @@ -148,7 +158,9 @@ void task_Init(void) , collectOpenCircuitVoltage_reloadVal, collectOpenCircuitVoltage_offset); TimeSliceOffset_Register(&m_uart, Task_uart, uart_reloadVal, uart_offset); - TimeSliceOffset_Register(&m_busFree, Task_busFree, busFree_reloadVal, busFree_offset); + TimeSliceOffset_Register(&m_busFree, Task_busFree, busFree_reloadVal, busFree_offset); + + TimeSliceOffset_Register(&m_SOE, Task_SOE, SOE_reloadVal, SOE_offset); } /** @@ -311,12 +323,14 @@ void Task_refreshJudgeData(void) else if ((getMosTemperState() == mosTemperFull) && getHighSideMosTemperature() > g_cfgParameter.reducePowerOutputTemperature) { setMosTemperState(mosTemperReduce); + insertEventsOrderRecord(overTemperature); } else if ((getMosTemperState() == mosTemperReduce) && getHighSideMosTemperature() > g_cfgParameter.stopPowerOutputTemperature) { setMosTemperState(mosTemperStop); /* 停止充电 */ stopChargWork(); + insertEventsOrderRecord(stopTemperature); } } @@ -348,6 +362,11 @@ void Task_startControl(void) /* 启动软起动任务 */ TimeSliceOffset_Register(&m_softStart, Task_softStart, softStart_reloadVal, softStart_offset); } + + if (getSolarInCircuitVoltage() >= g_cfgParameter.maxOpenSolarOutputCircuitV) { + insertEventsOrderRecord(overInputVolt); + } + } /** * @brief 打开启动任务 @@ -803,3 +822,15 @@ void Task_uart(void) { gw485DataAnalysis(g_gw485_uart2_handle); } + + +/** + * @brief 将记录下来的事件存入flash中 + * @param + * @retval + */ +void Task_SOE(void) +{ + setEventsOrderRecord(); +} + diff --git a/tools/chargControlTypes.h b/tools/chargControlTypes.h index 1c98f49..b6f03e4 100644 --- a/tools/chargControlTypes.h +++ b/tools/chargControlTypes.h @@ -64,6 +64,7 @@ typedef enum { overTemperature, //过温保护 stopTemperature, //停止温度保护 overchargCurr, //充电电流过大保护 + overInputVolt, //太阳能输入电压过大保护 }eventsOrderRecordMode;