//#define DTU3LITE #define ZEROEXPORT #include #include #include #include #include #include #include #include "rtc.h" #include "SysTick.h" #include "usart_nrf.h" #include "usart_nrf3.h" #include "usart_nrfConfig.h" #include "Memory.h" #include #include "malloc.h" #include "TimeProcessing.h" //dong 2020-0515 //Alarm serial number extern vu16 WarnSerNub[PORT_LEN]; extern vu8 RecieveDataCnt; extern vu8 AppPollCnt ; //Real-time alarm package extern volatile AlarmDataType pRealAlarm[20]; // Suspend the alarm extern volatile AlarmDataType pInformAlarm[20]; // #ifdef DTU3PRO #ifdef DTU_IAP #include "iwdg.h" #endif #else #include "stm32_wdg.h" #endif #include "crc16.h" extern vu8 connect_server ; //Connect to the server flag extern vu8 APP_Flg; //bool ifflag = 0; vu32 Index_Pro; vu32 TotalIndex_Pro; vu16 TotalIndex_Dat; vu16 Index_Dat; vu8 Uart_SendBuffer[UART_LEN]; //Send buffer vu8 Uart_ProcessBuffer[UART_LEN]; // process buffer vu8 Uart_CurSendMainCmd = 0; //The current network command sends the main command vu16 Uart_CurSendSubCmd = 0; //The current network command sends the command vu8 Uart_CurRecMainCmd = 0; //Receipt main command of current network command vu16 Uart_CurRecSubCmd = 0; //Receipt subcommand of current network command vu32 Uart_CurrentReplyState = 0; //current receipt state vu8 Uart_CurSendAddr[4]; vu8 Uart_CurrentReplyAddr[4]; //Download receipt address vu16 Uart_ReceiveBufferLen = 0; //Currently received bytes vu8 Uart_SendBufferLen = 0; //Currently send bytes BaudType Uart_CurrentDtuBaud = Device_INIT_BAUD; //Current DTU air baud rate vu32 DailyEnergyTemp[PORT_LEN] = {0}; volatile InverterMajor MIMajor[PORT_LEN]; //;Inverter main information volatile InverterReal MIReal[PORT_LEN]; //Inverter real-time data volatile InverterDetail MIDetail; //Micro inverter details volatile DtuMajor Dtu3Major; //DTU main information volatile DtuDetail Dtu3Detail; //DTU details bool RightHexFile = false; //Whether it is hex file stealing bool nRFHasCheck = false; bool HasTempRegister = false; char *string = NULL; //External ram/flash reads micro-inverse program code bool RightGridOnProFile = false; u8 *CurRowData_Dat = NULL; u8 *CurRowData_Pro = NULL; NetCmdType CurNetCmd = NET_INIT; vu16 PortNO = 0; //Number of nth components vu8 MainCmd ; //Network command main command vu16 SubCmd = 0xa5a5; //Network command subcommand vu32 LocalTime_TimeOut; vu16 Uart_ReceiveBufferLenTemp = 0; const char pro_start0[] = {'\r', '\n', '\n', ':'}; //\r\n\n: const char pro_start1[] = {'\n', '\n', '-', '-'}; //\r\n--: const char pro_start2[] = {'\r', '\n', '\r', '\n', '-'}; const char pro_start3[] = {'\r', '\n', '\r', '\n', ':'}; const char pro_pack_start[] = {'\r', '\n', ':'}; const char pro_end[] = {'0', '0', '0', '0', '0', '0', '0', '1', 'f', 'f'}; /*********************************************** ** Function name: crc check ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u16 UsartNrf_Get_crc_xor16(u16 *b_hex, u16 len) { vu16 i; vu16 crc; crc = 0; for(i = 0; i < len; i++) { crc = crc ^ (*(b_hex + i)); } return (crc); } /*********************************************** ** Function name: Get the micro-inverse type ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ InverterType UsartNrf_GetInvterType(u8 *pId) { if((u8)(((((u16)pId[0] << 8) | pId[1]) >> 4) & 0xff) == 0x26) // 0x0260 { return Inverter_Pro; // 7*300W=2100W } else if((u8)(((((u16)pId[0] << 8) | pId[1]) >> 4) & 0xff) == 0x12) // 0x0120 { return Inverter_HM_OneToOne; // 8*300W=2400W } else if((u8)(((((u16)pId[0] << 8) | pId[1]) >> 4) & 0xff) == 0x14) // 0x0140 { return Inverter_HM_OneToTwo; // 9*300W=2700W } else if((u8)(((((u16)pId[0] << 8) | pId[1]) >> 4) & 0xff) == 0x16) // 0x0160 { return Inverter_HM_OneToFour; // 10*300W=3000W } else { if(((pId[1] & 0xf0) == 0x10) || ((pId[1] & 0xf0) == 0x20)) //0x0010 || 0x0020 { if(((pId[0] == 0x10) && (pId[1] == 0x22)) || ((pId[0] == 0x11) && (pId[1] == 0x21))) // 0x1022 || 0x1121 { return Inverter_HM_OneToOne; // 8*300W=2400W } else if(((pId[0] == 0x10) && (pId[1] == 0x19)) || ((pId[0] == 0x10) && (pId[1] == 0x29))) // 0x1019 || 0x1029 { return InitInverterType; // 0*300W=0W } else // others { return Inverter_250; // 1*300W=300W } } else if(((pId[1] & 0xf0) == 0x30) || ((pId[1] & 0xf0) == 0x40)) //500w // 0x0030 || 0x0040 { if(((pId[0] == 0x10) && (pId[1] == 0x42)) || ((pId[0] == 0x11) && (pId[1] == 0x41))) // 0x1042 || 0x1141 { return Inverter_HM_OneToTwo; // 9*300W=2700W } else if(((pId[0] == 0x10) && (pId[1] == 0x39)) || ((pId[0] == 0x10) && (pId[1] == 0x49))) // 0x1039 || 0x1049 { return InitInverterType; // 0*300W=0W } else // others { return Inverter_500; // 2*300W=600W } } else if(((pId[1] & 0xf0) == 0x50) || ((pId[1] & 0xf0) == 0x60)) // 0x0050 || 0x0060 { if(((pId[0] == 0x10) && (pId[1] == 0x62)) || ((pId[0] == 0x11) && (pId[1] == 0x61))) // 0x1062 || 0x1161 { return Inverter_HM_OneToFour; // 10*300W=3000W } else if((pId[0] == 0x10) && (pId[1] == 0x69)) // 0x1069 { return InitInverterType; // 0*300W=0W } else // others { return Inverter_1000; // 4*300W=1200W } } else if((pId[0] == 0x12) && (pId[1] == 0x61)) // 0x1261 { return Inverter_Pro; // 7*300W=2100W } return InitInverterType; // 0*300W=0W } } /*********************************************** ** Function name: 2nd and 3rd generation protocol real-time data acquisition abnormal data filtering processing ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ bool UsartNrf_Process_ExceptionFilter(u8 *pBuffer, u8 Head, u8 Tail, u32 MaxValue, int32_t MinValue) { vu8 j = 0; if((Tail - Head) == 1) { if(((s16)pBuffer[Head] << 8 | pBuffer[Tail]) > MaxValue) //pv Voltage { return false; } else if(((s16)pBuffer[Head] << 8 | pBuffer[Tail]) < MinValue) { return false; } else { return true; } } else if((Tail - Head) == 3) { if((((u32)pBuffer[Head] << 24) | ((u32)pBuffer[Head + 1] << 16) | ((u32)pBuffer[Head + 2] << 8) | pBuffer[Head + 3]) > MaxValue) //pv Voltage { return false; } else { return true; } } return true; } /*********************************************** ** Function name: Initialize the microinverse software version ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_Version_InitInverter(void) { MIDetail.Property.USFWBuild_VER = 0; MIDetail.Property.AppFWBuild_VER = 0; MIDetail.Property.AppFWBuild_YYYY = 0; MIDetail.Property.AppFWBuild_MMDD = 0; MIDetail.Property.AppFWBuild_HHMM = 0; MIDetail.Property.AppFW_PNH = 0; MIDetail.Property.AppFW_PNL = 0; MIDetail.Property.HW_VER = 0; MIDetail.Property.HW_PNH = 0; MIDetail.Property.HW_PNL = 0; MIDetail.Property.HW_FB_TLmValue = 0; MIDetail.Property.HW_FB_ReSPRT = 0; MIDetail.Property.HW_GridSamp_ResValule = 0; MIDetail.Property.HW_ECapValue = 0; MIDetail.Property.Matching_AppFW_PNH = 0; MIDetail.Property.Matching_AppFW_PNL = 0; MIDetail.Property.AppFW_MINVER = 0; MIDetail.Property.HW_CRCValue = 0; MIDetail.Property.CRC_ALL = 0; } /*********************************************** ** Function name: Initialize micro-inverse Nrf software version ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_Version_InitInverterRf(void) { memset((u8 *) & (MIDetail.Property.NRF_HardVersion), 0, 4); memset((u8 *) & (MIDetail.Property.NRF_SoftVersion), 0, 4); } /*********************************************** ** Function name: Network disassembly micro-inverse id ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_InitPVPannelToMIMajor(void) { vu16 i, j; vu8 k; vu16 PortNum; PortNum = Dtu3Detail.Property.InverterNum; for(i = 0; i < PortNum; i++) { if(UsartNrf_GetInvterType((u8 *)MIMajor[i].Property.Pre_Id) >= Inverter_Pro) { if(UsartNrf_GetInvterType((u8 *)MIMajor[i].Property.Pre_Id) == Inverter_Pro) { if((MIMajor[i].Property.Port != Pro_A) && (MIMajor[i].Property.Port != Pro_B) && (MIMajor[i].Property.Port != Pro_C) && (MIMajor[i].Property.Port != Pro_D)) { for(j = PortNum - 1; j > i; j--) { memcpy((InverterReal *)&MIReal[j + 3], (InverterReal *)&MIReal[j], sizeof(MIReal[j])); memcpy((InverterMajor *)&MIMajor[j + 3], (InverterMajor *)&MIMajor[j], sizeof(MIMajor[j])); } memcpy((u8 *)&MIMajor[j + 1].Property.Id[0], (u8 *)&MIMajor[j].Property.Id[0], sizeof(MIMajor[j].Property.Id)); memcpy((u8 *)&MIMajor[j + 1].Property.Pre_Id[0], (u8 *)&MIMajor[j].Property.Pre_Id[0], sizeof(MIMajor[j].Property.Pre_Id)); memcpy((u8 *)&MIMajor[j + 2].Property.Id[0], (u8 *)&MIMajor[j].Property.Id[0], sizeof(MIMajor[j].Property.Id)); memcpy((u8 *)&MIMajor[j + 2].Property.Pre_Id[0], (u8 *)&MIMajor[j].Property.Pre_Id[0], sizeof(MIMajor[j].Property.Pre_Id)); memcpy((u8 *)&MIMajor[j + 3].Property.Id[0], (u8 *)&MIMajor[j].Property.Id[0], sizeof(MIMajor[j].Property.Id)); memcpy((u8 *)&MIMajor[j + 3].Property.Pre_Id[0], (u8 *)&MIMajor[j].Property.Pre_Id[0], sizeof(MIMajor[j].Property.Pre_Id)); MIMajor[j].Property.Port = Pro_A; MIMajor[j + 1].Property.Port = Pro_B; MIMajor[j + 2].Property.Port = Pro_C; MIMajor[j + 3].Property.Port = Pro_D; if((MIMajor[j].Property.Id_In_Phase >= 1) && (MIMajor[j].Property.Id_In_Phase <= 3)) { for(k = 0; k < 4; k++) { MIMajor[j + k].Property.Id_In_Phase = MIMajor[j].Property.Id_In_Phase; } } PortNum = PortNum + 3; i = i + 3; if(PortNum >= PORT_LEN) { PortNum = PORT_LEN; // Dtu3Detail.Property.PortNum - 4; return; } } } else if(UsartNrf_GetInvterType((u8 *)MIMajor[i].Property.Pre_Id) == Inverter_HM_OneToFour) { if((MIMajor[i].Property.Port != HM_1000W_A) && (MIMajor[i].Property.Port != HM_1000W_B) && (MIMajor[i].Property.Port != HM_1000W_C) && (MIMajor[i].Property.Port != HM_1000W_D)) { for(j = PortNum - 1; j > i; j--) { memcpy((InverterReal *)&MIReal[j + 3], (InverterReal *)&MIReal[j], sizeof(MIReal[j])); memcpy((InverterMajor *)&MIMajor[j + 3], (InverterMajor *)&MIMajor[j], sizeof(MIMajor[j])); } memcpy((u8 *)&MIMajor[j + 1].Property.Id[0], (u8 *)&MIMajor[j].Property.Id[0], sizeof(MIMajor[j].Property.Id)); memcpy((u8 *)&MIMajor[j + 1].Property.Pre_Id[0], (u8 *)&MIMajor[j].Property.Pre_Id[0], sizeof(MIMajor[j].Property.Pre_Id)); memcpy((u8 *)&MIMajor[j + 2].Property.Id[0], (u8 *)&MIMajor[j].Property.Id[0], sizeof(MIMajor[j].Property.Id)); memcpy((u8 *)&MIMajor[j + 2].Property.Pre_Id[0], (u8 *)&MIMajor[j].Property.Pre_Id[0], sizeof(MIMajor[j].Property.Pre_Id)); memcpy((u8 *)&MIMajor[j + 3].Property.Id[0], (u8 *)&MIMajor[j].Property.Id[0], sizeof(MIMajor[j].Property.Id)); memcpy((u8 *)&MIMajor[j + 3].Property.Pre_Id[0], (u8 *)&MIMajor[j].Property.Pre_Id[0], sizeof(MIMajor[j].Property.Pre_Id)); MIMajor[j].Property.Port = HM_1000W_A; MIMajor[j + 1].Property.Port = HM_1000W_B; MIMajor[j + 2].Property.Port = HM_1000W_C; MIMajor[j + 3].Property.Port = HM_1000W_D; if((MIMajor[j].Property.Id_In_Phase >= 1) && (MIMajor[j].Property.Id_In_Phase <= 3)) { for(k = 0; k < 4; k++) { MIMajor[j + k].Property.Id_In_Phase = MIMajor[j].Property.Id_In_Phase; } } PortNum = PortNum + 3; i = i + 3; if(PortNum >= PORT_LEN) { PortNum = PORT_LEN; // return; } } } else if(UsartNrf_GetInvterType((u8 *)MIMajor[i].Property.Pre_Id) == Inverter_HM_OneToTwo) { if((MIMajor[i].Property.Port != HM_500W_A) && (MIMajor[i].Property.Port != HM_500W_B)) { for(j = PortNum - 1; j > i; j--) { memcpy((InverterReal *)&MIReal[j + 1], (InverterReal *)&MIReal[j], sizeof(MIReal[j])); //When 500w is not marked with 500w type, the real-time data is as a whole to the right move one square memcpy((InverterMajor *)&MIMajor[j + 1], (InverterMajor *)&MIMajor[j], sizeof(MIMajor[j])); } memcpy((u8 *) & (MIMajor[j + 1].Property.Id[0]), (u8 *)&MIMajor[j].Property.Id[0], sizeof(MIMajor[j].Property.Id)); memcpy((u8 *) & (MIMajor[j + 1].Property.Pre_Id[0]), (u8 *)&MIMajor[j].Property.Pre_Id[0], sizeof(MIMajor[j].Property.Pre_Id)); MIMajor[j].Property.Port = HM_500W_A; MIMajor[j + 1].Property.Port = HM_500W_B; if((MIMajor[j].Property.Id_In_Phase >= 1) && (MIMajor[j].Property.Id_In_Phase <= 3)) { for(k = 0; k < 2; k++) { MIMajor[j + k].Property.Id_In_Phase = MIMajor[j].Property.Id_In_Phase; } } PortNum = PortNum + 1; i = i + 1; if(PortNum >= PORT_LEN) { PortNum = PORT_LEN;// return; } } } else if(UsartNrf_GetInvterType((u8 *)MIMajor[i].Property.Pre_Id) == Inverter_HM_OneToOne) { MIMajor[i].Property.Port = HM_250W; if((MIMajor[i].Property.Id_In_Phase >= 1) && (MIMajor[i].Property.Id_In_Phase <= 3)) { MIMajor[i].Property.Id_In_Phase = MIMajor[i].Property.Id_In_Phase; } if(PortNum >= PORT_LEN) { PortNum = PORT_LEN;// return; } } else { } } else { if(UsartNrf_GetInvterType((u8 *)MIMajor[i].Property.Pre_Id) == Inverter_500) { if((MIMajor[i].Property.Port != MI_500W_A) && (MIMajor[i].Property.Port != MI_500W_B)) { for(j = PortNum - 1; j > i; j--) { memcpy((InverterReal *)&MIReal[j + 1], (InverterReal *)&MIReal[j], sizeof(MIReal[j])); //When 500w is not marked with 500w type, the real-time data is as a whole to the right move one square memcpy((InverterMajor *)&MIMajor[j + 1], (InverterMajor *)&MIMajor[j], sizeof(MIMajor[j])); } memcpy((u8 *) & (MIMajor[j + 1].Property.Id[0]), (u8 *)&MIMajor[j].Property.Id[0], sizeof(MIMajor[j].Property.Id)); memcpy((u8 *) & (MIMajor[j + 1].Property.Pre_Id[0]), (u8 *)&MIMajor[j].Property.Pre_Id[0], sizeof(MIMajor[j].Property.Pre_Id)); MIMajor[j].Property.Port = MI_500W_A; MIMajor[j + 1].Property.Port = MI_500W_B; if((MIMajor[j].Property.Id_In_Phase >= 1) && (MIMajor[j].Property.Id_In_Phase <= 3)) { for(k = 0; k < 2; k++) { MIMajor[j + k].Property.Id_In_Phase = MIMajor[j].Property.Id_In_Phase; } } PortNum = PortNum + 1; i = i + 1; if(PortNum >= PORT_LEN) { PortNum = PORT_LEN;//Dtu3Detail.Property.PortNum - 1; return; } } } else if(UsartNrf_GetInvterType((u8 *)MIMajor[i].Property.Pre_Id) == Inverter_1000) { if((MIMajor[i].Property.Port != MI_1000W_A) && (MIMajor[i].Property.Port != MI_1000W_B) && (MIMajor[i].Property.Port != MI_1000W_C) && (MIMajor[i].Property.Port != MI_1000W_D)) { for(j = PortNum - 1; j > i; j--) { memcpy((InverterReal *)&MIReal[j + 3], (InverterReal *)&MIReal[j], sizeof(MIReal[j])); memcpy((InverterMajor *)&MIMajor[j + 3], (InverterMajor *)&MIMajor[j], sizeof(MIMajor[j])); } memcpy((u8 *)&MIMajor[j + 1].Property.Id[0], (u8 *)&MIMajor[j].Property.Id[0], sizeof(MIMajor[j].Property.Id)); memcpy((u8 *)&MIMajor[j + 1].Property.Pre_Id[0], (u8 *)&MIMajor[j].Property.Pre_Id[0], sizeof(MIMajor[j].Property.Pre_Id)); memcpy((u8 *)&MIMajor[j + 2].Property.Id[0], (u8 *)&MIMajor[j].Property.Id[0], sizeof(MIMajor[j].Property.Id)); memcpy((u8 *)&MIMajor[j + 2].Property.Pre_Id[0], (u8 *)&MIMajor[j].Property.Pre_Id[0], sizeof(MIMajor[j].Property.Pre_Id)); memcpy((u8 *)&MIMajor[j + 3].Property.Id[0], (u8 *)&MIMajor[j].Property.Id[0], sizeof(MIMajor[j].Property.Id)); memcpy((u8 *)&MIMajor[j + 3].Property.Pre_Id[0], (u8 *)&MIMajor[j].Property.Pre_Id[0], sizeof(MIMajor[j].Property.Pre_Id)); MIMajor[j].Property.Port = MI_1000W_A; MIMajor[j + 1].Property.Port = MI_1000W_B; MIMajor[j + 2].Property.Port = MI_1000W_C; MIMajor[j + 3].Property.Port = MI_1000W_D; if((MIMajor[j].Property.Id_In_Phase >= 1) && (MIMajor[j].Property.Id_In_Phase <= 3)) { for(k = 0; k < 4; k++) { MIMajor[j + k].Property.Id_In_Phase = MIMajor[j].Property.Id_In_Phase; } } PortNum = PortNum + 3; i = i + 3; if(PortNum >= PORT_LEN) { PortNum = PORT_LEN; // return; } } } else { MIMajor[i].Property.Port = MI_250W; if((MIMajor[i].Property.Id_In_Phase >= 1) && (MIMajor[i].Property.Id_In_Phase <= 3)) { MIMajor[i].Property.Id_In_Phase = MIMajor[i].Property.Id_In_Phase; } if(PortNum >= PORT_LEN) { PortNum = PORT_LEN; // return; } } } } } /*********************************************** ** Function name: Clear the MIReal structure ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_ClearMIReal(void) { vu16 i; for(i = 0; i < PORT_LEN; i++) { memset((u8 *)MIReal[i].Data.PVVol, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.PVCur, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.GridVol, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.Freque, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.Power, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.Temper, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.Run_Status, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.Fault_Code, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.Fault_Num, 0, 2 * sizeof(u8)); //MIReal[i].Data.Collec_Time = 0; MIReal[i].Data.LinkState = 0; MIReal[i].Data.Real_Time = 0; } } /*********************************************** ** Function name:Clear the daily power generation of micro-inverse ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_ClearMI_DailyEnergy(void) { vu16 i; for(i = 0; i < PORT_LEN; i++) { memset((u8 *)MIReal[i].Data.PVVol, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.PVCur, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.GridVol, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.Freque, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.Power, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.Temper, 0, 2 * sizeof(u8)); MIReal[i].Data.Collec_Time = 0; MIReal[i].Data.LinkState = 0; memset((u8 *)MIReal[i].Data.Run_Status, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.Fault_Code, 0, 2 * sizeof(u8)); memset((u8 *)MIReal[i].Data.Fault_Num, 0, 2 * sizeof(u8)); MIReal[i].Data.NetCmd = NET_INIT; MIReal[i].Data.DailyEnergy = 0; MIReal[i].Data.Real_Time = 0; MIReal[i].Data.NetStatus = NET_NOCMD; } } /*********************************************** ** Function name:Clear micro-inverse historical power generation ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_ClearMIReal_HistoryEnergy(void) { vu16 i; for(i = 0; i < PORT_LEN; i++) { MIReal[i].Data.HistoryEnergyH = 0; MIReal[i].Data.HistoryEnergyL = 0; } } /*********************************************** ** Function name:Empty the InverterMajor structure ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_ClearInverterMajor(void) { vu16 i; for(i = 0; i < PORT_LEN; i++) { memset((InverterMajor *) & (MIMajor[i]), 0, sizeof(MIMajor[i])); } } /*********************************************** ** Function name:Empty the DtuDetail structure ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_ClearDtuMajor(void) { memset((InverterMajor *) & (Dtu3Major), 0, sizeof(DtuMajor)); } /*********************************************** ** Function name: ** Descriptions: //filter port number ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ bool UsartNrf_SendLoop_GetNextSetCmd() { static vu16 PrePortNO = 0; //NET_NOT_EXECUTED if((MIReal[PortNO].Data.NetStatus == NET_NOT_EXECUTED) || (MIReal[PortNO].Data.NetStatus == LOCAL_NOT_EXECUTED)) { //Filter only the first port return true; } // There are network commands that fail to be executed. There are network commands that are completed. else if((MIReal[PortNO].Data.NetStatus == NET_EXECUTION_FAILURE) || (MIReal[PortNO].Data.NetStatus == NET_EXECUTION_COMPLETED)) { PortNO++; } else if((MIReal[PortNO].Data.NetStatus > 0) && (MIReal[PortNO].Data.NetStatus < 100)) { if(MIReal[PortNO].Data.NetCmd == NET_DOWNLOAD_PRO) { if((Uart_CurrentReplyState == 2) || (Uart_CurrentReplyState == 3)) { RightHexFile = false; } } else if(MIReal[PortNO].Data.NetCmd == NET_DOWNLOAD_DAT) { if((Uart_CurrentReplyState == 2) || (Uart_CurrentReplyState == 3)) { RightGridOnProFile = false; } } else if(MIReal[PortNO].Data.NetCmd == NET_LOCK) { } return true; } else { //return true; } PrePortNO = PortNO; for(PortNO = PortNO; PortNO < Dtu3Detail.Property.PortNum;) { if((MIMajor[PortNO].Property.Port != MI_250W) && (MIMajor[PortNO].Property.Port != MI_500W_A) && (MIMajor[PortNO].Property.Port != MI_1000W_A) && (MIMajor[PortNO].Property.Port != Pro_A)) { PortNO++; } else { if(((MIReal[PortNO].Data.NetCmd >= NET_TURN_ON) && (MIReal[PortNO].Data.NetCmd <= NET_ELE_ENERGY)) || (MIReal[PortNO].Data.NetCmd == NET_INVERTER_HW_INFOR)) { if((MIReal[PortNO].Data.NetStatus == NET_NOT_EXECUTED) || (MIReal[PortNO].Data.NetStatus == LOCAL_NOT_EXECUTED)) { if((UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id)) >= Inverter_Pro) { UsartNrf3_SendLoop_SetTaskTimeOut(false);//Set task timeout return false; } else { UsartNrf3_SendLoop_SetTaskTimeOut(true);//Set task timeout return true; //Filter only the first port } } else if((MIReal[PortNO].Data.NetStatus == NET_EXECUTION_FAILURE) || (MIReal[PortNO].Data.NetStatus == NET_EXECUTION_COMPLETED) || (MIReal[PortNO].Data.NetStatus == NET_NOCMD)) { PortNO++; } else { // return true; } } else { PortNO++; } } } for(PortNO = 0; PortNO < PrePortNO;) { if((MIMajor[PortNO].Property.Port != MI_250W) && (MIMajor[PortNO].Property.Port != MI_500W_A) && (MIMajor[PortNO].Property.Port != MI_1000W_A) && (MIMajor[PortNO].Property.Port != Pro_A)) { PortNO++; } else { if(((MIReal[PortNO].Data.NetCmd >= NET_TURN_ON) && (MIReal[PortNO].Data.NetCmd <= NET_ELE_ENERGY)) || (MIReal[PortNO].Data.NetCmd == NET_INVERTER_HW_INFOR)) { if((MIReal[PortNO].Data.NetStatus == NET_NOT_EXECUTED) || (MIReal[PortNO].Data.NetStatus == LOCAL_NOT_EXECUTED)) { if((UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id)) >= Inverter_Pro) { UsartNrf3_SendLoop_SetTaskTimeOut(false);//Set task timeout return false; } else { UsartNrf3_SendLoop_SetTaskTimeOut(true);//Set task timeout return true; //Filter only the first port } } else if((MIReal[PortNO].Data.NetStatus == NET_EXECUTION_FAILURE) || (MIReal[PortNO].Data.NetStatus == NET_EXECUTION_COMPLETED) || (MIReal[PortNO].Data.NetStatus == NET_NOCMD)) { PortNO++; } else { // return true; } } else { PortNO++; } } } if(PortNO == PrePortNO) { CurNetCmd = NET_INIT; PortNO = 0; return false; } return true; } /*********************************************** ** Function name:T1 timeout setting ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_SendLoop_SetPackageTimeOut(bool Stop) { if(Stop == true) { LocalTime_TimeOut = LOCAL_TIME_0MS; return; } if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) >= Inverter_Pro) { if((Uart_CurSendMainCmd == DOWN_DAT) || (Uart_CurSendMainCmd == DOWN_PRO)) { if((Uart_SendBuffer[10] & 0xf0) == 0x80)//Update the last packet of the grid-connected protection file 100ms { // if((LineCnt_Pro == 0) && (Uart_CurSendMainCmd == DOWN_PRO)) // { // LocalTime_TimeOut =60*LOCAL_TIME_100MS; //LOCAL_TIME_DOWNDOWN_PRO_1; // } // else // if((LineCnt_Pro == 1) && (Uart_CurSendMainCmd == DOWN_PRO)) // { // LocalTime_TimeOut = 5*LOCAL_TIME_100MS; // } // else // { LocalTime_TimeOut = LOCAL_TIME_100MS; // } } else { LocalTime_TimeOut = LOCAL_TIME_50MS; //+20; } } else if(Uart_CurSendMainCmd == REQ_ARW_DAT_ALL) { if(CurRecSendPackageDataType == InverterDevInform_All)///Full version polling single frame 100ms, full frame*** { LocalTime_TimeOut = LOCAL_TIME_INFORM_ALL; } else if((CurRecSendPackageDataType == InverterDevInform_Simple) || (CurRecSendPackageDataType == GetLossRate)) //The short version polls for 100ms { LocalTime_TimeOut = LOCAL_TIME_INFORM_SAMPLE; } else if((CurRecSendPackageDataType == RealTimeRunData_Reality) || (CurRecSendPackageDataType == RealTimeRunData_Debug)) //Running data display single frame 100ms, full frame*** { if(Uart_SendBuffer[10] != 0x80) { LocalTime_TimeOut = LOCAL_TIME_100MS; } else { LocalTime_TimeOut = LOCAL_TIME_RUNDATA_REALITY; } } else if((CurRecSendPackageDataType == AlarmData) || (CurRecSendPackageDataType == AlarmUpdate)) //Alarm data single frame 100ms, full frame**** { if(Uart_SendBuffer[10] != 0x80) { LocalTime_TimeOut = LOCAL_TIME_100MS; } else { LocalTime_TimeOut = LOCAL_TIME_ALARM; } } else if(CurRecSendPackageDataType == RecordData)//Recording data single frame 100ms, full frame*** { if(Uart_SendBuffer[10] != 0x80) { LocalTime_TimeOut = LOCAL_TIME_100MS; } else { LocalTime_TimeOut = LOCAL_TIME_RECORD_DATA; } } else if(CurRecSendPackageDataType == GridOnProFilePara) { if(Uart_SendBuffer[10] != 0x80) { LocalTime_TimeOut = LOCAL_TIME_100MS; } else { LocalTime_TimeOut = LOCAL_TIME_GRID_ON_FILE_PARA; } } else { LocalTime_TimeOut = LOCAL_TIME_100MS * 3; } } else if(Uart_CurSendMainCmd == PARASET_ALL)//parameter settings { if((Uart_SendBuffer[11] == EleEnergySet) || (Uart_SendBuffer[11] == AntitheftParaSet)) //Power generation setting { if((Uart_SendBuffer[10] & 0xf0) == 0x80)//Update the last line of the grid protection file for 100ms { LocalTime_TimeOut = LOCAL_TIME_100MS; } else { LocalTime_TimeOut = LOCAL_TIME_50MS; } } } else if(Uart_CurSendMainCmd == PARASET_ALL)//equipment control { if((Uart_SendBuffer[11] == Type_Lock) || (Uart_SendBuffer[11] == Type_Unlock)) { LocalTime_TimeOut = LOCAL_TIME_LOCK_UNLOCK; } else if((Uart_SendBuffer[11] == Type_PFSet) || (Uart_SendBuffer[11] == Type_ActivePowerContr) || (Uart_SendBuffer[11] == Type_ReactivePowerContr)) { LocalTime_TimeOut = LOCAL_TIME_PF_POWER_SET; } else if(Uart_SendBuffer[11] == Type_CleanState_LockAndAlarm) { LocalTime_TimeOut = LOCAL_TIME_CLEAR_ALARM; } else { LocalTime_TimeOut = LOCAL_TIME_100MS; } } else { LocalTime_TimeOut = LOCAL_TIME_100MS * 3; } } else { if((APP_Flg == 1) && (AppState >= 1) && (AppState <= 5)) { LocalTime_TimeOut = LOCAL_TIME_100MS * 2; } else { if((CurNetCmd == NET_INIT) || (CurNetCmd == NET_WAIT_DOWNLOAD_DAT) || (CurNetCmd == NET_WAIT_DOWNLOAD_PRO)) { if(Uart_CurrentDtuBaud == Device_250K) { LocalTime_TimeOut = LOCAL_TIME_100MS * 5; } else if(Uart_CurrentDtuBaud == Device_2M) { LocalTime_TimeOut = LOCAL_TIME_100MS * 3; } else { LocalTime_TimeOut = LOCAL_TIME_100MS * 3; } } else { if(Uart_CurSendMainCmd == BROADCAST) { LocalTime_TimeOut = 3 * LOCAL_TIME_1S; } else if(Uart_CurSendMainCmd == DOWN_PRO) { if(Uart_CurrentDtuBaud == Device_250K) { if((Uart_SendBuffer[10] & 0xf0) == 0x10) { LocalTime_TimeOut = LOCAL_TIME_100MS * 3; } else { LocalTime_TimeOut = LOCAL_TIME_100MS; } } else if(Uart_CurrentDtuBaud == Device_2M) { if((Uart_SendBuffer[10] & 0xf0) == 0x10) { LocalTime_TimeOut = LOCAL_TIME_110MS; } else { LocalTime_TimeOut = LOCAL_TIME_55MS; } } } else { if(Uart_CurrentDtuBaud == Device_250K) { LocalTime_TimeOut = LOCAL_TIME_100MS * 5; } else if(Uart_CurrentDtuBaud == Device_2M) { LocalTime_TimeOut = LOCAL_TIME_100MS * 3; } else { LocalTime_TimeOut = LOCAL_TIME_100MS * 3; } } } } } } /*********************************************** ** Function name: The second-generation protocol controls the real-time data acquisition light on and off ** Descriptions: Collect 20 rounds ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_LedShow(bool PollRealTimeState, u8 NoConllectTime) { vu16 i; if(((MIReal[0].Data.NetCmd == NET_REGISTER_ID) && (MIReal[0].Data.NetStatus == NET_NOT_EXECUTED)) || (HasTempRegister == true)) { // Dtu3Detail.Property.LedState = 1;//Can't find everything HasTempRegister = false; CurNetCmd = NET_INIT; return; } if(PollRealTimeState == false)//When polling fails { if(MIReal[PortNO].Data.Collec_Time >= NoConllectTime) { MIReal[PortNO].Data.Collec_Time = NoConllectTime; } else { MIReal[PortNO].Data.Collec_Time++; } } else //Polling data succeeded { MIReal[PortNO].Data.Collec_Time = 0; } if(CurNetCmd == NET_NOPORT) { // Dtu3Detail.Property.LedState = 0; return; } else { if(PortNO == (Dtu3Detail.Property.PortNum - 1)) { for(i = 0; i < Dtu3Detail.Property.PortNum; i++) { if(MIReal[i].Data.Collec_Time >= NoConllectTime) { MIReal[i].Data.LinkState = MIReal[i].Data.LinkState & (~MI_CONNECT); //20 rounds without 1 round of search } } // for(i = 0; i < Dtu3Detail.Property.PortNum; i++) // { // SumLinkState = SumLinkState + ((MIReal[i].Data.LinkState & MI_CONNECT) >> 1); // } // if(SumLinkState >= Dtu3Detail.Property.PortNum) // { // Dtu3Detail.Property.LedState = 2; //Search all // } // else // { // Dtu3Detail.Property.LedState = 1; //Can't find everything // } } } } /*********************************************** ** Function name:Get the number of components under this DTU ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_GetDtu3PortNum(void) { vu16 i; vu16 PortNum = 0; Dtu3Detail.Property.PortNum = 0; Dtu3Detail.Property.InverterNum = 0; Dtu3Detail.Property.Reflux_DtuPanelNum_A = 0; Dtu3Detail.Property.Reflux_DtuPanelNum_B = 0; Dtu3Detail.Property.Reflux_DtuPanelNum_C = 0; for(i = 0; i < PORT_LEN; i++) { if((MIMajor[i].Property.Pre_Id[0] & 0xf0) == 0x10) { if(((u8)(MIMajor[i].Property.Pre_Id[1] & 0xf0) == 0x10) || ((MIMajor[i].Property.Pre_Id[1] & 0xf0) == 0x20)) { if(MIMajor[i].Property.Id_In_Phase == 1) { Dtu3Detail.Property.Reflux_DtuPanelNum_A = Dtu3Detail.Property.Reflux_DtuPanelNum_A + 1; } else if(MIMajor[i].Property.Id_In_Phase == 2) { Dtu3Detail.Property.Reflux_DtuPanelNum_B = Dtu3Detail.Property.Reflux_DtuPanelNum_B + 1; } else if(MIMajor[i].Property.Id_In_Phase == 3) { Dtu3Detail.Property.Reflux_DtuPanelNum_C = Dtu3Detail.Property.Reflux_DtuPanelNum_C + 1; } else if(MIMajor[i].Property.Id_In_Phase == 0) { Dtu3Detail.Property.PortNum = Dtu3Detail.Property.PortNum + 1; } } else if(((u8)(MIMajor[i].Property.Pre_Id[1] & 0xf0) == 0x30) || ((MIMajor[i].Property.Pre_Id[1] & 0xf0) == 0x40)) { if(MIMajor[i].Property.Id_In_Phase == 1) { Dtu3Detail.Property.Reflux_DtuPanelNum_A = Dtu3Detail.Property.Reflux_DtuPanelNum_A + 2; } else if(MIMajor[i].Property.Id_In_Phase == 2) { Dtu3Detail.Property.Reflux_DtuPanelNum_B = Dtu3Detail.Property.Reflux_DtuPanelNum_B + 2; } else if(MIMajor[i].Property.Id_In_Phase == 3) { Dtu3Detail.Property.Reflux_DtuPanelNum_C = Dtu3Detail.Property.Reflux_DtuPanelNum_C + 2; } else if(MIMajor[i].Property.Id_In_Phase == 0) { Dtu3Detail.Property.PortNum = Dtu3Detail.Property.PortNum + 2; } } else if(((u8)(MIMajor[i].Property.Pre_Id[1] & 0xf0) == 0x50) || ((u8)(MIMajor[i].Property.Pre_Id[1] & 0xf0) == 0x60)) { if(MIMajor[i].Property.Id_In_Phase == 1) { Dtu3Detail.Property.Reflux_DtuPanelNum_A = Dtu3Detail.Property.Reflux_DtuPanelNum_A + 4; } else if(MIMajor[i].Property.Id_In_Phase == 2) { Dtu3Detail.Property.Reflux_DtuPanelNum_B = Dtu3Detail.Property.Reflux_DtuPanelNum_B + 4; } else if(MIMajor[i].Property.Id_In_Phase == 3) { Dtu3Detail.Property.Reflux_DtuPanelNum_C = Dtu3Detail.Property.Reflux_DtuPanelNum_C + 4; } else if(MIMajor[i].Property.Id_In_Phase == 0) { Dtu3Detail.Property.PortNum = Dtu3Detail.Property.PortNum + 4; } } } else { break; } PortNum = Dtu3Detail.Property.PortNum + Dtu3Detail.Property.Reflux_DtuPanelNum_A + Dtu3Detail.Property.Reflux_DtuPanelNum_B + Dtu3Detail.Property.Reflux_DtuPanelNum_C; Dtu3Detail.Property.InverterNum++; if(PortNum >= PORT_LEN) { Dtu3Detail.Property.PortNum = PORT_LEN; return; } else { if(Dtu3Detail.Property.InverterNum >= PORT_LEN) { Dtu3Detail.Property.InverterNum = PORT_LEN; } } } Dtu3Detail.Property.PortNum = PortNum ; } /*********************************************** ** Function name: Forward replacement before Nrf send ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ u8 ForwardSubstitution(u8 *result, u8 *source, u8 length) { vu8 i; vu8 j = 0; for(i = 0; i < length; i++) { if((*(source + i)) == 0x7d) { (*(result + j)) = 0x7d; j++; (*(result + j)) = 0x5d; j++; } else if((*(source + i)) == 0x7e) { (*(result + j)) = 0x7d; j++; (*(result + j)) = 0x5e; j++; } else if((*(source + i)) == 0x7f) { (*(result + j)) = 0x7d; j++; (*(result + j)) = 0x5f; j++; } else { (*(result + j)) = (*(source + i)); j++; } } return (j); } /*********************************************** ** Function name: Nrf XOR check before sending ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ u8 Get_crc_xor(u8 *b_hex, u16 len) { vu16 i; vu8 crc; crc = 0; #ifdef DEBUG1 if(len > 40) { printf("Get_crc_xor_len:%d\r\n", len); } #endif for(i = 0; i < len; i++) { crc = crc ^ (*(b_hex + i)); } return (crc); } /*********************************************** ** Function name: Generic instruction package ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u8 UsartNrf_Send_PackBaseCommand(u8 *target_adr, u8 *rout_adr, u8 cmd, u8 dat) { vu8 i = 0; vu8 temp_dat[UART_LEN]; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); Uart_SendBuffer[0] = STX;//start temp_dat[0] = cmd; //command memcpy((u8 *)&temp_dat[1], target_adr, 4); memcpy((u8 *)&temp_dat[5], rout_adr, 4); temp_dat[9] = dat; temp_dat[10] = Get_crc_xor((u8 *)&temp_dat[0], 10); //CRC i = ForwardSubstitution((u8 *)&Uart_SendBuffer[1], (u8 *)&temp_dat[0], 11); //Forward Substitution Uart_SendBuffer[(i + 1)] = ETX; //end memset((u8 *)temp_dat, 0, sizeof(temp_dat)); return (i + 2); } /*********************************************** ** Function name:Clear network command status at boot ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_ClearNetStatusAndCmd(void) { vu8 i; for(i = 0; i < Dtu3Detail.Property.PortNum; i++) { MIReal[i].Data.NetStatus = NET_NOCMD; MIReal[i].Data.NetCmd = NET_INIT; } } void UsartNrf_ClearCollect_TimeAndLinkState(void) { vu8 i; for(i = 0; i < Dtu3Detail.Property.PortNum; i++) { MIReal[i].Data.Collec_Time = 0; MIReal[i].Data.LinkState = 0; } } /*********************************************** ** Function name:Initialize Nrf related variables ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_MemInit(void) { vu16 i; vu8 Pre_Id[2] = {0, 0}; vu8 Id[4] = {0, 0, 0, 0}; LocalTime_TimeOut = LOCAL_TIME_100MS * 3; PortNO = 0; memcpy((u8 *)Pre_Id, (u8 *)Dtu3Major.Property.Pre_Id, 2); memcpy((u8 *)Id, (u8 *)Dtu3Major.Property.Id, 4); UsartNrf_ClearDtuMajor(); System_Info_Read_Uncheck((DtuDetail *)&Dtu3Detail, (DtuMajor *)&Dtu3Major); if(((Pre_Id[0] != 0) || (Pre_Id[1] != 0)) && ((memcmp((u8 *)Pre_Id, (u8 *)Dtu3Major.Property.Pre_Id, 2) != 0) || (memcmp((u8 *)Id, (u8 *)Dtu3Major.Property.Id, 4) != 0))) { memcpy((u8 *)Dtu3Major.Property.Pre_Id, (u8 *)Pre_Id, 2); memcpy((u8 *)Dtu3Major.Property.Id, (u8 *)Id, 4); System_Dtu_Info_Write((DtuDetail *)&Dtu3Detail, (DtuMajor *)&Dtu3Major); } memset((u8 *)Pre_Id, 0, sizeof(Pre_Id)); memset((u8 *)Id, 0, sizeof(Id)); if((memcmp((u8 *)Pre_Id, (u8 *)Dtu3Major.Property.Pre_Id, 2) == 0) && (memcmp((u8 *)Id, (u8 *)Dtu3Major.Property.Id, 4) == 0)) { //reset NVIC_SystemReset(); } UsartNrf_ClearInverterMajor(); System_MI_SN_Read((InverterMajor *)MIMajor); System_Dtu_Info_Read((DtuDetail *)&Dtu3Detail, (DtuMajor *)&Dtu3Major); UsartNrf_ClearMIReal_HistoryEnergy(); InverterReal_Read((InverterReal *)MIReal); UsartNrf_ClearMI_DailyEnergy(); UsartNrf_ClearNetStatusAndCmd(); UsartNrf_ClearCollect_TimeAndLinkState(); calendar_obj calendar, calendar2; RTC_GetTimes(&calendar); //Store the alarm number Alarm_Serial_Num_Read((u16 *)WarnSerNub, &calendar2); //Delete the self-test status storage every time you turn it on GPST_Data_Delete(); //Not a direct clear of the day if(calendar2.w_date != calendar.w_date) { memset((u16 *)WarnSerNub, 0, sizeof(WarnSerNub)); Alarm_Serial_Num_Write((u16 *)WarnSerNub, calendar); } for(i = 0; i < Dtu3Detail.Property.PortNum; i++) { DailyEnergyTemp[i] = ((((u32)(MIReal[i].Data.HistoryEnergyH)) << 16) | MIReal[i].Data.HistoryEnergyL) ; } CurNetCmd = NET_DTU_HW_INFOR_RES; } /*********************************************** ** Function name: Nrf POST ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ bool UsartNrf_NrfCheckSelf() { static vu32 SendTime; static vu8 CheckCnt = 0; vu8 DtuId[6] = {0, 0, 0, 0, 0, 0}; SendTime = LocalTime; while(1) { if((memcmp((u8 *) & (DtuId[0]), (u8 *)Dtu3Major.Property.Pre_Id, 2) == 0) && (memcmp((u8 *) & (DtuId[2]), (u8 *)Dtu3Major.Property.Id, 4) == 0)) { if(CheckCnt <= DTUID_READ_CNT) { if((LocalTime - SendTime >= (LOCAL_TIME_100MS * 3)) || ((LocalTime < SendTime) && (LOCAL_TIME_900000MS - SendTime + LocalTime >= (LOCAL_TIME_100MS * 3)))) { Uart_SendBufferLen = UsartNrf_Send_PackBaseCommand((u8 *) & (DtuId[2]), (u8 *) & (DtuId[2]), REQ_RF_RVERSISON, 0); CheckCnt++; USART_ClearITPendingBit(UsartNrf, USART_IT_TC); USART_ClearFlag(UsartNrf, USART_FLAG_TC); UsartNrf_SendLoop_SetPackageTimeOut(false); USART_SendData(UsartNrf, Uart_SendBuffer[0]); SendTime = LocalTime; } else { } } else { CheckCnt = 0; nRFHasCheck = true; return false; } } else { CheckCnt = 0; nRFHasCheck = true; return true; } } } /*********************************************** ** Function name: Initialize NRF peripheral interface ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ bool UsartNrf_NrfInit(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; #ifdef DTU3PRO RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//2 NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_USART3); GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_USART3); USART_InitStructure.USART_BaudRate = 125000; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; /* Configure Usart3*/ USART_Init(USART3, &USART_InitStructure);//Configure Usart3 USART_Cmd(USART3, ENABLE);//Open Usart3 USART_ClearITPendingBit(USART3, USART_IT_TC); USART_ClearITPendingBit(USART3, USART_FLAG_TC); /* Enable the Usart3 */ USART_ITConfig(USART3, USART_IT_TC, ENABLE); USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); #else RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //turn on gpio clock RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //Open serial clock GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 125000;//baud rate//125000-04//38400-02 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//frame length USART_InitStructure.USART_StopBits = USART_StopBits_1;//stop bit USART_InitStructure.USART_Parity = USART_Parity_No;//parity USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//hardware stream USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//Operating mode USART_Init(USART2, &USART_InitStructure);//configure usart2 USART_Cmd(USART2, ENABLE);//open usart2 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//2 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);//Serial port interrupt priority configuration /* Enable the Usart3 */ // USART_ClearFlag(USART2, USART_FLAG_TC); USART_GetFlagStatus(USART2, USART_FLAG_ORE) ; USART_ITConfig(USART2, USART_IT_TC, ENABLE); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); USART_ClearITPendingBit(USART2, USART_IT_TC); USART_ClearITPendingBit(USART2, USART_FLAG_TC); #endif return UsartNrf_NrfCheckSelf(); } /*********************************************** ** Function name:The second-generation protocol determines whether the receipt is normal ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ bool UsartNrf_SendLoop_ReplyOK(void) { if(Uart_CurSendMainCmd == REQ_A_DAT) { if((Uart_CurRecMainCmd == ANSWER_REQ_A_DAT) || (Uart_CurRecMainCmd == ANSWER_REQ_A_EVENT)) { return true; } else { return false; } } else if(Uart_CurSendMainCmd == REQ_B_DAT) { if((Uart_CurRecMainCmd == ANSWER_REQ_B_DAT) || (Uart_CurRecMainCmd == ANSWER_REQ_B_EVENT)) { return true; } else { return false; } } else if(Uart_CurSendMainCmd == REQ_A1_DAT_1000) { if(Uart_CurRecMainCmd == ANSWER_REQ_A1_DAT_1000) { return true; } else { return false; } } else if(Uart_CurSendMainCmd == REQ_B1_DAT_1000) { if(Uart_CurRecMainCmd == ANSWER_REQ_B1_DAT_1000) { return true; } else { return false; } } else if(Uart_CurSendMainCmd == REQ_A2_DAT_1000) { if(Uart_CurRecMainCmd == ANSWER_REQ_A2_DAT_1000) { return true; } else { return false; } } else if(Uart_CurSendMainCmd == REQ_B2_DAT_1000) { if(Uart_CurRecMainCmd == ANSWER_REQ_B2_DAT_1000) { return true; } else { return false; } } else if(Uart_CurSendMainCmd == CONTROL_LOCK_MI__LIMIT_POWER_ONOFF) { if(Uart_CurRecMainCmd == ANSWER_CONTROL_LOCK_MI__LIMIT_POEWR_ONOFF) { if(Uart_CurSendSubCmd == Uart_CurRecSubCmd) { if(Uart_CurRecSubCmd == CONTROL_LOCK_SUB1) { return false; } else { return true; } } else { return false; } } return false; } else { if((Uart_CurSendMainCmd | 0X80) == Uart_CurRecMainCmd) { return true; } else { return false; } } return false; } /*********************************************** ** Function name: Nrf receive processing reverse replacement ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ u8 UsartNrf_Backward_substitution1(u8 *result, u8 *source, u8 length) { vu8 i; vu8 j = 0; for(i = 0; i < length; i++) { if((*(source + i)) == 0x7d) { if(*(source + i + 1) == 0x5d) { (*(result + j)) = 0x7d; j++; } else if(*(source + i + 1) == 0x5e) { (*(result + j)) = 0x7e; j++; } else if(*(source + i + 1) == 0x5f) { (*(result + j)) = 0x7f; j++; } i++; } else { (*(result + j)) = (*(source + i)); j++; } } return j; } /*********************************************** ** Function name:Polling and packaging with lock in anti-theft mode of the second-generation protocol ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u8 UsartNrf_Send_PackPollRfWithLockCommand(u8 *target_adr, u8 *rout_adr, u8 cmd) { vu8 i = 0; vu8 temp_dat[UART_LEN]; volatile calendar_obj calendar; RTC_GetWorldTime((calendar_obj *)&calendar, Dtu3Detail.Property.timezone); memset((u8 *)temp_dat, 0, sizeof(temp_dat)); memset((u8 *)Uart_SendBuffer, 0, sizeof(Uart_SendBuffer)); Uart_SendBuffer[0] = STX;//start temp_dat[0] = cmd; //command memcpy((u8 *)&temp_dat[1], target_adr, 4); memcpy((u8 *)&temp_dat[5], rout_adr, 4); temp_dat[9] = 0; temp_dat[10] = calendar.w_date;//Rtc_Date.Day; temp_dat[11] = calendar.hour; temp_dat[12] = calendar.min; temp_dat[13] = calendar.sec;//time //password temp_dat[14] = Dtu3Detail.Property.LockNewPassword[0]; temp_dat[15] = Dtu3Detail.Property.LockNewPassword[1]; temp_dat[16] = Dtu3Detail.Property.LockNewPassword[2]; temp_dat[17] = Dtu3Detail.Property.LockNewPassword[3];//password temp_dat[18] = 0; temp_dat[19] = 0; temp_dat[20] = 0; temp_dat[21] = 0; temp_dat[22] = 0;//polling data interval temp_dat[23] = Get_crc_xor((u8 *)&temp_dat[0], 23); //CRC check i = ForwardSubstitution((u8 *)&Uart_SendBuffer[1], (u8 *)&temp_dat[0], 24); //Forward substitution Uart_SendBuffer[(i + 1)] = ETX; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); return (i + 2); } /*********************************************** ** Function name:Second-generation protocol switch machine packaging ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u8 UsartNrf_Send_PackSetTurnOnOffCommand(u8 *target_adr, u8 *rout_adr, u8 MainCmd, u16 SubCmd) { vu8 i = 0; vu8 temp_dat[UART_LEN]; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); Uart_SendBuffer[0] = STX;//start temp_dat[0] = MainCmd; //command memcpy((u8 *)&temp_dat[1], target_adr, 4); memcpy((u8 *)&temp_dat[5], rout_adr, 4); temp_dat[9] = SubCmd >> 8; temp_dat[10] = SubCmd & 0xff; temp_dat[11] = Get_crc_xor((u8 *)&temp_dat[0], 11); //CRC i = ForwardSubstitution((u8 *)&Uart_SendBuffer[1], (u8 *)&temp_dat[0], 12); //Forward substitution Uart_SendBuffer[(i + 1)] = ETX; //end memset((u8 *)temp_dat, 0, sizeof(temp_dat)); return (i + 2); } /*********************************************** ** Function name:Second-generation protocol anti-theft settings package ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u8 UsartNrf_Send_PackSetLockOnOffCommand(u8 *target_adr, u8 *rout_adr, int8_t MainCmd, u16 SubCmd) { vu8 i = 0; vu8 temp_dat[UART_LEN]; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); Uart_SendBuffer[0] = STX;// temp_dat[0] = (u8)MainCmd ; //Control micro-inverse lock memcpy((u8 *)&temp_dat[1], target_adr, 4); memcpy((u8 *)&temp_dat[5], rout_adr, 4); temp_dat[9] = SubCmd >> 8; temp_dat[10] = SubCmd & 0XFF; //Child command temp_dat[11] = Dtu3Detail.Property.LockOldPassword[0];//Dtu3Detail[PortNO].LockOldPassword[0]; temp_dat[12] = Dtu3Detail.Property.LockOldPassword[1];//Dtu3Detail[PortNO].LockOldPassword[1]; temp_dat[13] = Dtu3Detail.Property.LockOldPassword[2];//Dtu3Detail[PortNO].LockOldPassword[2]; temp_dat[14] = Dtu3Detail.Property.LockOldPassword[3];//Dtu3Detail[PortNO].LockOldPassword[3];//old password temp_dat[15] = Dtu3Detail.Property.LockNewPassword[0]; temp_dat[16] = Dtu3Detail.Property.LockNewPassword[1]; temp_dat[17] = Dtu3Detail.Property.LockNewPassword[2]; temp_dat[18] = Dtu3Detail.Property.LockNewPassword[3];//new password temp_dat[19] = Dtu3Detail.Property.Lock_Time[0]; temp_dat[20] = Dtu3Detail.Property.Lock_Time[1];//Intervals temp_dat[21] = Get_crc_xor((u8 *)&temp_dat[0], 21); //CRC i = ForwardSubstitution((u8 *)&Uart_SendBuffer[1], (u8 *)&temp_dat[0], 22); //forward substitution Uart_SendBuffer[(i + 1)] = ETX; //end memset((u8 *)temp_dat, 0, sizeof(temp_dat)); return (i + 2); } /*********************************************** ** Function name: The second-generation protocol sets the micro-inverse power package ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ u8 UsartNrf_Send_PackSetPowerLimitCommand(u8 *target_adr, u8 *rout_adr, int8_t MainCmd, u16 SubCmd) { vu8 i = 0; vu8 temp_dat[UART_LEN]; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); Uart_SendBuffer[0] = STX;//start temp_dat[0] = (u8)MainCmd; //command memcpy((u8 *)&temp_dat[1], target_adr, 4); memcpy((u8 *)&temp_dat[5], rout_adr, 4); #ifdef DTU3PRO if((Dtu3Detail.Property.Zero_Export_Switch == 1) || (Dtu3Detail.Property.DRM_Limit_Switch == 1) || (Dtu3Detail.Property.Phase_Balance_Switch == 1) || (Dtu3Detail.Property.SunSpec_Switch == 1)) { if(MIMajor[PortNO].Property.Acq_Switch == 0) { //1000w shutdown special control micro-inverse control of 1-to-4 with the last 8 digits of the ID less than 0x50000000 if((MIMajor[PortNO].Property.Id[0] < 0X50) && ((MIMajor[PortNO].Property.Pre_Id[1] == 0X60) || (MIMajor[PortNO].Property.Pre_Id[1] == 0X61))) { temp_dat[9] = (u8)(SubCmd >> 8); //5a5a temp_dat[10] = (u8)(SubCmd & 0XFF); temp_dat[11] = 11; // temp = 35*4*10=1400=0x0578; temp_dat[12] = 0X05; temp_dat[13] = 0X78; temp_dat[14] = Get_crc_xor((u8 *)&temp_dat[0], 14); //CRC i = ForwardSubstitution((u8 *)&Uart_SendBuffer[1], (u8 *)&temp_dat[0], 15); //forward substitution } else { temp_dat[9] = (u8)(CONTROL_OFF_SUB >> 8); //aa55 temp_dat[10] = (u8)(CONTROL_OFF_SUB & 0XFF); temp_dat[11] = Get_crc_xor((u8 *)&temp_dat[0], 11); //CRC i = ForwardSubstitution((u8 *)&Uart_SendBuffer[1], (u8 *)&temp_dat[0], 12); //forward substitution } } else { temp_dat[9] = (u8)(SubCmd >> 8); //5a5a temp_dat[10] = (u8)(SubCmd & 0XFF); temp_dat[11] = (u8)(MIMajor[PortNO].Property.Power_Limit * 10 / (EVERY_PORT_POWER * (UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id)))); //Power limit percentage temp_dat[12] = (u8)(MIMajor[PortNO].Property.Power_Limit >> 8); //High 8-bit power limit temp_dat[13] = (u8)(MIMajor[PortNO].Property.Power_Limit & 0x00ff); //Low power limit 8 bits temp_dat[14] = Get_crc_xor((u8 *)&temp_dat[0], 14); //CRC i = ForwardSubstitution((u8 *)&Uart_SendBuffer[1], (u8 *)&temp_dat[0], 15); //forward substitution } } else { #endif temp_dat[9] = (u8)(SubCmd >> 8); //5a5a temp_dat[10] = (u8)(SubCmd & 0XFF); temp_dat[11] = (u8)(MIMajor[PortNO].Property.Power_Limit * 10 / (EVERY_PORT_POWER * (UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id)))); //Power limit percentage temp_dat[12] = (u8)(MIMajor[PortNO].Property.Power_Limit >> 8); //High 8-bit power limit temp_dat[13] = (u8)(MIMajor[PortNO].Property.Power_Limit & 0x00ff); //Low power limit 8 bits temp_dat[14] = Get_crc_xor((u8 *)&temp_dat[0], 14); //CRC i = ForwardSubstitution((u8 *)&Uart_SendBuffer[1], (u8 *)&temp_dat[0], 15); //forward substitution #ifdef DTU3PRO } #endif Uart_SendBuffer[(i + 1)] = ETX; //end memset((u8 *)temp_dat, 0, sizeof(temp_dat)); return (i + 2); } /*********************************************** ** Function name: //The second-generation protocol sets the anti-backflow parameter packaging ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u8 UsartNrf_Send_PackSetRefluxPowerCommand(u16 reflux_power, u8 MainCmd, u16 SubCmd) { vu8 i = 0; vu16 j; vu8 temp_dat[UART_LEN]; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); Uart_SendBuffer[0] = STX;//start temp_dat[0] = MainCmd; //command memset((u8 *)&temp_dat[1], 0, 4); memset((u8 *)&temp_dat[5], 0, 4); temp_dat[9] = SubCmd & 0XFF00 >> 8; temp_dat[10] = SubCmd & 0XFF; temp_dat[11] = (u8)(reflux_power * 100 / (EVERY_PORT_POWER * 10 * Dtu3Detail.Property.PortNum)); //Power limit percentage temp_dat[12] = reflux_power >> 8; //High 8-bit power limit temp_dat[13] = reflux_power & 0x00ff; //Low power limit 8 bits temp_dat[14] = Get_crc_xor((u8 *)&temp_dat[0], 14); //CRC i = ForwardSubstitution((u8 *)&Uart_SendBuffer[1], (u8 *)&temp_dat[0], 15); //forward substitution Uart_SendBuffer[i + 1] = ETX; //end memset((u8 *)temp_dat, 0, sizeof(temp_dat)); return (i + 2); } /*********************************************** ** Function name: //Set the air baud rate ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ u8 UsartNrf_Send_PackSetNrfBaudRateInTheAir(u8 *target_adr, u8 *rout_adr, u8 Cmd, BaudType Baud) { vu8 i = 0; vu8 temp_dat[UART_LEN]; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); memset((u8 *)Uart_SendBuffer, 0, sizeof(Uart_SendBuffer)); Uart_SendBuffer[0] = STX;//start temp_dat[0] = Cmd; //command memcpy((u8 *)&temp_dat[1], target_adr, 4); memcpy((u8 *)&temp_dat[5], rout_adr, 4); temp_dat[9] = (u8)Baud; temp_dat[10] = Get_crc_xor((u8 *)&temp_dat[0], 10); //CRC i = ForwardSubstitution((u8 *)&Uart_SendBuffer[1], (u8 *)&temp_dat[0], 11); //forward substitution Uart_SendBuffer[(i + 1)] = ETX; //end memset((u8 *)temp_dat, 0, sizeof(temp_dat)); return (i + 2); } /*********************************************** ** Function name: Second-generation protocol GF search ID packaging ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ u8 UsartNrf_Send_PackSearchMiID(u8 *target_adr, u8 *rout_adr, u8 cmd) { vu8 i = 0, j = 0; vu8 temp_dat[UART_LEN]; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); Uart_SendBuffer[0] = STX;//start temp_dat[0] = cmd; //command memcpy((u8 *)&temp_dat[1], target_adr, 4); //1234 memcpy((u8 *)&temp_dat[5], rout_adr, 4); //5678 i = 0; j = 9; //0----8 8*2 temp_dat[10] = Get_crc_xor((u8 *)&temp_dat[0], ++j); //CRC i = ForwardSubstitution((u8 *)&Uart_SendBuffer[1], (u8 *)&temp_dat[0], j); //forward substitution Uart_SendBuffer[(i + 1)] = ETX; //end memset((u8 *)temp_dat, 0, sizeof(temp_dat)); return (i + 2); } /*********************************************** ** Function name:The second-generation protocol upgrade micro-inverse program (1 line packaging in hex) ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ u8 UsartNrf_Send_MiProgram_SigleFrame(u8 *target_adr, u8 *router_adr, u8 *dat, u8 nub, u8 len) { vu8 i = 0, j = 0; vu16 DatCrc = 0xffff; vu16 TempCrc = 0; vu8 temp_dat[UART_LEN]; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); memset((u8 *)Uart_SendBuffer, 0, sizeof(Uart_SendBuffer)); Uart_SendBuffer[0] = STX;//start temp_dat[0] = DOWN_PRO; //command memcpy((u8 *)&temp_dat[1], target_adr, 4); //1234 memcpy((u8 *)&temp_dat[5], router_adr, 4); //5678 temp_dat[9] = nub; i = 0; j = 10; //0----8 8*2 // if(len != 1) // { // for(i = 0; i < len; i++) // { // temp_dat[j++] = (*(dat + i)); // } // } if((nub >> 7) == 1) { if(len != 1) { for(i = 0; i < len; i++) { temp_dat[j++] = (*(dat + i)); } } for(i = 0; i < CurRowTotalLen; i++) { if(i % 2 == 1) { TempCrc = (u16)(CurRowData_Pro[i - 1] << 8) | (u8)(CurRowData_Pro[i]); DatCrc = CalcCRC16t(TempCrc, DatCrc); } } temp_dat[j++] = (u8)(DatCrc >> 8); temp_dat[j++] = (u8)DatCrc; } else { for(i = 0; i < len; i++) { temp_dat[j++] = (*(dat + i)); } } temp_dat[j] = Get_crc_xor((u8 *)temp_dat, j); //CRC i = ForwardSubstitution((u8 *) & (Uart_SendBuffer[1]), (u8 *)temp_dat, j + 1); //forward substitution Uart_SendBuffer[i + 1] = ETX; //end memset((u8 *)temp_dat, 0, sizeof(temp_dat)); return (i + 2); } /*********************************************** ** Function name:Convert single character ascii to hex ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ u8 SigleCharToHex(char dat) { vu8 i = 0; if((0x30 <= dat) && (dat <= 0x39)) { i = dat - 0x30; } if((0x41 <= dat) && (dat <= 0x46)) { i = dat - 55; } if((0x61 <= dat) && (dat <= 0x66)) { i = dat - 87; } if(i > 15) { i = 0; } return (i); } /*********************************************** ** Function name:double character ascii to hex ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void AsciiToHex(u8 *sour, u8 *dest, u8 len) { vu8 i; vu8 temp[74]; for(i = 0; i < len; i++) { temp[i] = SigleCharToHex(*(sour + i)); } for(i = 0; i < (len / 2); i++) { (*(dest + i)) = ((temp[2 * i] << 4) & 0xf0) + (temp[(2 * i) + 1] & 0x0f); } } /*********************************************** ** Function name: sum check ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ u8 UsartNrf_GetCrcValue_Sum(u8 *dat, u16 len) { vu16 i; vu8 sum; sum = 0; for(i = 0; i < len; i++) { sum = sum + (*(dat + i)); } return (sum); } /*********************************************** ** Function name:Determine whether the received hex upgrade file is ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ bool UsartNrf_IsRighUpgateHexFile(void) { while(Index_Pro <= 1024) { if((strncmp((const char *)(&string[Index_Pro]), pro_start3, 5) == 0) || (strncmp((const char *)(&string[Index_Pro]), pro_start1, 4) == 0) || (strncmp((const char *)(&string[Index_Pro]), pro_start2, 5) == 0) || (strncmp((const char *)(&string[Index_Pro]), pro_start0, 5) == 0)) { if(strncmp((const char *)(&string[Index_Pro]), pro_start0, 5) == 0) { Index_Pro = Index_Pro + 5; return true; } else if(strncmp((const char *)(&string[Index_Pro]), pro_start1, 4) == 0) { Index_Pro = Index_Pro + 4; return true; } else if(strncmp((const char *)(&string[Index_Pro]), pro_start2, 5) == 0) { Index_Pro = Index_Pro + 4; return true; } else if(strncmp((const char *)(&string[Index_Pro]), pro_start3, 4) == 0) { Index_Pro = Index_Pro + 5; return true; } } else { Index_Pro++; } } return false; } /*********************************************** ** Function name: Determine whether it is the last line of the hex upgrade file ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ bool IsLastLineInHex(void) { static vu16 CurIndex = 0; static vu16 PreIndex = 0; while(Index_Pro < 1460) { if(CurIndex - PreIndex == 24) //?12*2????1? { PreIndex = CurIndex; if(strncmp((const char *)&string[CurIndex], pro_end, 4) == 0) //\r\n--Judging the end packet { return true; } } CurIndex++; } return false; } /*********************************************** ** Function name:The second generation protocol sends the current row data ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u16 UsartNrf_Send_PackMiProgram_CurRow(u8 *target_adr, u8 *rout_adr, u16 CurRowLen) { static vu8 CurPackageNO = 0; static vu8 CurRowDataOffset = 0; vu8 PackageLastNOTemp = 0; vu8 PackageLen = 0; vu8 CurPackageNOInit = 0; if((UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id)) >= Inverter_Pro) { PackageLen = 16; PackageLastNOTemp = 0x80; CurPackageNOInit = 1; if(CurPackageNO == 0) { CurRowLen = CurRowLen - 1; } } else { PackageLen = 13; PackageLastNOTemp = 0x10; CurPackageNOInit = 0; } if(CurRowLen >= PackageLen) { if(CurRowLen == PackageLen) { Uart_SendBufferLen = UsartNrf_Send_MiProgram_SigleFrame(target_adr, rout_adr, CurRowData_Pro + CurRowDataOffset, (CurPackageNO + CurPackageNOInit), PackageLen); CurRowDataOffset = 0; CurPackageNO++; CurRowLen = 1; } else { Uart_SendBufferLen = UsartNrf_Send_MiProgram_SigleFrame(target_adr, rout_adr, CurRowData_Pro + CurRowDataOffset, (CurPackageNO + CurPackageNOInit), PackageLen); CurRowDataOffset = CurRowDataOffset + PackageLen; CurRowLen = CurRowLen - PackageLen; CurPackageNO++; } return CurRowLen; } else { Uart_SendBufferLen = UsartNrf_Send_MiProgram_SigleFrame(target_adr, rout_adr, CurRowData_Pro + CurRowDataOffset, PackageLastNOTemp | (CurPackageNO + CurPackageNOInit), (u8)CurRowLen); CurRowLen = 0; CurSendRecLastPackageNO = CurPackageNO; CurSendRecLostPackageNO = CurSendRecLastPackageNO; CurPackageNO = 0; CurRowDataOffset = 0; ProtocalLayer_Cmd = ToTransLayer_Send;//transport layer return CurRowLen; } } /*********************************************** ** Function name:The second-generation protocol prepares a hex of a 1-line upgrade file ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u16 UsartNrf_Send_GetMiProgram_CurRow(u8 *pCurRowData) { vu16 CurIndex = 0; vu8 j = 0; static vu8 Data[37 * 4]; while(CurIndex < 37 * 4) { if((strncmp((const char *) & (string[CurIndex]), pro_pack_start, 3) == 0) || (Index_Pro + 10 + 1 >= TotalIndex_Pro)) //\r\n:start of every line except line 1 { if(Index_Pro + 10 + 1 >= TotalIndex_Pro) { CurIndex = 10; } for(j = 0; j < CurIndex; j++) { if(((string[j] <= '9') && (string[j] >= '0')) || ((string[j] <= 'F') && (string[j] >= 'A')) || ((string[j] <= 'f') && (string[j] >= 'a'))) { Data[j] = string[j]; } } memset(pCurRowData, 0, 37); AsciiToHex((u8 *)Data, pCurRowData, j); memcpy((u8 *)Uart_CurSendAddr, pCurRowData, 4); UsartNrf_GetCrcValue_Sum(pCurRowData, j / 2); Index_Pro = CurIndex + Index_Pro + 3; if(Index_Pro == 0xffffffff) { Index_Pro = 0; } //CurIndex = 0; memset((u8 *)Data, 0, 37 * 4); break; } CurIndex++; } return j / 2; } /*********************************************** ** Function name:Second-generation and third-generation protocol upgrade micro-inverse ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_Send_PackUpdateMiProgram(u8 *target_adr, u8 *rout_adr) { static vu16 CurRowLen = 0; static vu32 BackUpIndex = 0; vu8 Uart_CurrentReplyStateTemp = 0; if(RightHexFile == false) { if(string == NULL) { string = mymalloc(512 * sizeof(char)); // if(string == NULL) // { // return; // } } memset(string, 0, 512 * sizeof(char)); if(CurRowData_Pro == NULL) { CurRowData_Pro = mymalloc(37 * sizeof(u8)); // if(CurRowData_Pro == NULL) // { // return; // } } memset(CurRowData_Pro, 0, 37 * sizeof(u8)); TotalIndex_Pro = MI_Program_Get_Length(); MI_Program_Read_Length(string, 0, 512); Index_Pro = 0; CurRowLen = 0; LineCnt_Pro = 0; if(UsartNrf_IsRighUpgateHexFile()) { RightHexFile = true; } else { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_FAILURE; CurNetCmd = NET_INIT; } BackUpIndex = Index_Pro; Uart_CurrentReplyState = 0xFF; } if(RightHexFile == true) { if(CurRowLen == 0) { ProtocalLayer_Cmd = InitLayer;//transport layer if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) >= Inverter_Pro) { Uart_CurrentReplyStateTemp = 0; } else { Uart_CurrentReplyStateTemp = 1; } memset(string, 0, 37 * 4); if((Uart_CurrentReplyState != Uart_CurrentReplyStateTemp) || ((Index_Pro > 0x1E) && (memcmp((u8 *)Uart_CurSendAddr, (u8 *)Uart_CurrentReplyAddr, 4) != 0)) || ((Uart_CurSendAddr[0] == Uart_CurSendAddr[1]) && (Uart_CurSendAddr[0] == Uart_CurSendAddr[2]) && (Uart_CurSendAddr[0] == Uart_CurSendAddr[3]) && (Uart_CurSendAddr[0] == 0))) { Index_Pro = BackUpIndex; } else { LineCnt_Pro++; } UsartNrf3_SendLoop_SetTaskTimeOut(false); MI_Program_Read_Length(string, Index_Pro, 37 * 4); BackUpIndex = Index_Pro; CurRowLen = UsartNrf_Send_GetMiProgram_CurRow(CurRowData_Pro); CurRowTotalLen = (u8)(CurRowLen - 1); } CurRowLen = UsartNrf_Send_PackMiProgram_CurRow(target_adr, rout_adr, CurRowLen); } } /*********************************************** ** Function name:Packing a single package of grid-connected protection files ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u8 UsartNrf_Send_PackGridOnProFile_SigleFrame(u8 *target_adr, u8 *router_adr, u8 *dat, u8 nub, u8 len) { vu8 i = 0, j = 0; vu8 temp_dat[UART_LEN]; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); memset((u8 *)Uart_SendBuffer, 0, sizeof(Uart_SendBuffer)); Uart_SendBuffer[0] = STX; temp_dat[0] = DOWN_DAT; //command memcpy((u8 *)&temp_dat[1], target_adr, 4); //1234 memcpy((u8 *)&temp_dat[5], router_adr, 4); //5678 temp_dat[9] = nub; j = 10; //0----8 8*2 for(i = 0; i < len; i++) { temp_dat[j++] = (*(dat + i)); } temp_dat[j] = Get_crc_xor((u8 *) & (temp_dat[0]), j); i = ForwardSubstitution((u8 *) & (Uart_SendBuffer[1]), (u8 *) & (temp_dat[0]), j + 1); Uart_SendBuffer[(i + 1)] = ETX; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); return (i + 2); } /*********************************************** ** Function name:The second-generation and third-generation protocols send the current grid-connected protection file ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u16 UsartNrf_Send_PackGridOnProFile_CurText(u8 *target_adr, u8 *rout_adr, u8 *pCurRowData, u16 CurRowLen) { static vu8 CurPackageNO = 0; static vu16 CurSendPackageNum = 0; vu8 PackageLastNOTemp = 0; vu8 CurPackageNOInit = 0; if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) >= Inverter_Pro) { PackageLastNOTemp = 0x80; CurPackageNOInit = 1; } else { PackageLastNOTemp = 0x10; CurPackageNOInit = 0; } if(Index_Dat == 0) { CurPackageNO = 0; CurSendPackageNum = 0; } if(CurRowLen >= 16) { Uart_SendBufferLen = UsartNrf_Send_PackGridOnProFile_SigleFrame(target_adr, rout_adr, pCurRowData, CurPackageNOInit + CurPackageNO, 16); CurPackageNO++; CurSendPackageNum = 16 * CurPackageNO; return CurSendPackageNum; } else { Uart_SendBufferLen = UsartNrf_Send_PackGridOnProFile_SigleFrame(target_adr, rout_adr, pCurRowData, (CurPackageNO + CurPackageNOInit) | PackageLastNOTemp, (u8)CurRowLen); CurSendPackageNum = CurPackageNO * 16 + CurRowLen; CurPackageNO = 0; return CurSendPackageNum; } } /*********************************************** ** Function name:Grid-connected protection file CRC check ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u16 UsartNrf_Send_CRC16_Work(u8 *CRC_Buf, u16 CRC_Leni) { vu16 i, j; vu16 CRC_Sumx; CRC_Sumx = 0xFFFF; for(i = 0; i < CRC_Leni; i++) { CRC_Sumx ^= *(CRC_Buf + i); for(j = 0; j < 8; j++) { if(CRC_Sumx & 0x01) { CRC_Sumx >>= 1; CRC_Sumx ^= 0xA001; } else { CRC_Sumx >>= 1; } } } return (CRC_Sumx); } /*********************************************** ** Function name:Second-generation protocol packaging and grid-connected protection program ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u8 UsartNrf_Send_PackUpdateGridOnProFile(u8 *target_adr, u8 *rout_adr) { vu16 CurRowData_16; if(RightGridOnProFile == false) { if(CurRowData_Dat == NULL) { CurRowData_Dat = mymalloc(300 * sizeof(u8)); // if(CurRowData_Dat == NULL) // { // return 0; // } } memset(CurRowData_Dat, 0, 300 * sizeof(u8)); TotalIndex_Dat = (u16)Grid_Profiles_Data_Get_Length(); Grid_Profiles_Data_Read((char *)CurRowData_Dat, TotalIndex_Dat, 0); Index_Dat = 0; if(TotalIndex_Dat <= 2) { //RightGridOnProFile = false; if(CurRowData_Dat != NULL) { myfree(CurRowData_Dat); CurRowData_Dat = NULL; } RightGridOnProFile = false; CurNetCmd = NET_INIT; MIReal[PortNO].Data.NetStatus = NET_EXECUTION_FAILURE; return 0; } if((UsartNrf_Send_CRC16_Work(CurRowData_Dat, TotalIndex_Dat - 2)) == (u16)((CurRowData_Dat[TotalIndex_Dat - 2] << 8) | (CurRowData_Dat[TotalIndex_Dat - 1]))) { if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) >= Inverter_Pro) { } else { CurRowData_16 = UsartNrf_Get_crc_xor16((u16 *)CurRowData_Dat, (TotalIndex_Dat - 2) / 2); CurRowData_Dat[TotalIndex_Dat - 1] = (u8)(CurRowData_16 >> 8); //low in front high in back CurRowData_Dat[TotalIndex_Dat - 2] = (u8)CurRowData_16; } RightGridOnProFile = true; } else { RightGridOnProFile = false; CurNetCmd = NET_INIT; MIReal[PortNO].Data.NetStatus = NET_EXECUTION_FAILURE; if(CurRowData_Dat != NULL) { myfree(CurRowData_Dat); CurRowData_Dat = NULL; } return 0; } } if(RightGridOnProFile == true) { Index_Dat = UsartNrf_Send_PackGridOnProFile_CurText(target_adr, rout_adr, CurRowData_Dat + Index_Dat, TotalIndex_Dat - Index_Dat); if(TotalIndex_Dat <= (1 + Index_Dat)) { if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) >= Inverter_Pro) { ProtocalLayer_Cmd = ToTransLayer_Send;//����� CurSendRecLastPackageNO = (u8)(TotalIndex_Dat / 16); CurSendRecLostPackageNO = CurSendRecLastPackageNO; memset((u8 *)SubData3, 0, MAX_TRANS_DAT_DATA_LEN); } } } return (u8)TotalIndex_Dat; } /*********************************************** ** Function name: Determine the air baud rate based on the micro-inverter ID ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ BaudType GetInveterBaudType(u8 *DeviceId) { if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) == Inverter_Pro) { return Device_250K ; } else if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) > Inverter_Pro) { return Device_250K ; } else { if((DeviceId[1] & 0x0f) == 1) { return Device_250K ; } else if((DeviceId[1] & 0x0f) == 0) { return Device_2M; } } return Device_INIT_BAUD; } /*********************************************** ** Function name: Second-generation protocol polling and resending mechanism ** Descriptions: ** input parameters: false--> next loop true--> next component ** output parameters: ? ** Returned value: ? *************************************************/ bool UsartNrf_HasPollCurInverterPort(void) { static vu8 PollCnt = 0; vu8 PollCntTemp; vu16 i; for(i = 0; i < Dtu3Detail.Property.PortNum; i++) { if(((MIReal[i].Data.NetCmd >= NET_TURN_ON) && (MIReal[i].Data.NetCmd <= NET_ELE_ENERGY) && ((MIReal[i].Data.NetCmd != NET_WAIT_DOWNLOAD_DAT) && (MIReal[i].Data.NetCmd != NET_WAIT_DOWNLOAD_PRO))) && ((MIReal[i].Data.NetStatus == LOCAL_NOT_EXECUTED) || (MIReal[i].Data.NetStatus == NET_NOT_EXECUTED))) { PortNO = i; CurRecSendLostPackageState = 0; TotalPackageNum = 0; CurNetCmd = MIReal[i].Data.NetCmd; UsartNrf3_SendLoop_SetTaskTimeOut(false);//Set the task timeout return false; } } if(((UsartNrf_SendLoop_ReplyOK() == true) && (PollCnt <= 1)) || ((PollCnt >= 1) && (UsartNrf_SendLoop_ReplyOK() == false))) { PollCntTemp = PollCnt; PollCnt = 0; if((Uart_CurSendMainCmd != 0) && (Uart_CurSendMainCmd != CHANGE_MOD_2M_250K)) { if(CurAlarmState == AlarmInforUpdate_App) { if(PollCntTemp == 0) { return UsartNrf3_AppStateSwitch(1, 1); } else { PollCntTemp = 0; if(UsartNrf_SendLoop_ReplyOK() == true) { return UsartNrf3_AppStateSwitch(2, 1); } else { return UsartNrf3_AppStateSwitch(2, 0); } } } else if(CurAlarmState == AlarmInforUpdate_Server) { return UsartNrf3_AlarmInformationSearch(); } else { return UsartNrf3_PollRealTimeWithVersion(); } } // UsartNrf_Process_LedShow(false, 10); return true;//next component } else { PollCnt++; return true; } return true; } /*********************************************** ** Function name: The second-generation protocol obtains the type of the micro-reverse polling component ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u8 UsartNrf_GetPollCmdOfRealTime(void) { vu8 Cmd; if(CurNetCmd == NET_MI_VERSION) { Cmd = REQ_VERSISON;// terminal inverter software and hardware information } else { switch(MIMajor[PortNO].Property.Port) { case MI_250W: Cmd = REQ_A_DAT; break; case MI_500W_A: Cmd = REQ_A_DAT; break; case MI_500W_B: Cmd = REQ_B_DAT; break; case MI_1000W_A: Cmd = REQ_A1_DAT_1000; break; case MI_1000W_B: Cmd = REQ_A2_DAT_1000; break; case MI_1000W_C: Cmd = REQ_B1_DAT_1000; break; case MI_1000W_D: Cmd = REQ_B2_DAT_1000; break; default: break; } } return Cmd; } /*********************************************** ** Function name: Clean up the execution status of the micro-inverse software version ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_ClearVersionActionState(void) { vu16 i = 0, j = 0; for(i = 0; i < Dtu3Detail.Property.PortNum; i++) { if((MIReal[i].Data.NetStatus == NET_NOT_EXECUTED) && ((MIReal[i].Data.NetCmd == NET_INVERTER_HW_INFOR) || (MIReal[i].Data.NetCmd == NET_TERMINAL_INFOR))) { j++; } } if(j <= 0) { Dtu3Detail.Property.PolledVerState = 1; UsartNrf_ClearNetStatusAndCmd(); if(CurNetCmd != NET_MI_VERSION) { CurNetCmd = NET_INIT; } } else { j = 0; } } /*********************************************** ** Function name: Second-generation protocol device control command resend mechanism ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ bool UsartNrf_HasSetCurrentInverterOk(void) { static vu8 NotMatchCnt = 0; static vu8 NotMatchDownDatCnt = 0; static vu16 NotMatchDownProCnt = 0; if(((UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) < Inverter_Pro) && (UsartNrf_SendLoop_ReplyOK() == true)) || ((UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) >= Inverter_Pro) && (UsartNrf3_SendLoop_ReplyOK() == true))) { NotMatchDownDatCnt = 0; NotMatchDownProCnt = 0; Uart_CurRecMainCmd = 0; Uart_SendBufferLen = 0; NotMatchCnt = 0; if((Uart_CurSendMainCmd != 0) && (Uart_CurSendMainCmd != CHANGE_MOD_2M_250K) && ((Uart_CurSendMainCmd != BROADCAST))) { Uart_CurSendMainCmd = 0; return UsartNrf_SendLoop_GetNextSetCmd(); } else if(Uart_CurSendMainCmd == BROADCAST) { CurNetCmd = NET_INIT; PortNO = 0; return false;// } else { Uart_CurSendMainCmd = 0; Uart_CurRecMainCmd = 0; return true;//Baud rate You need to send a network command after receiving the receipt } } else { if((Uart_CurSendMainCmd != 0) && (Uart_CurSendMainCmd != CHANGE_MOD_2M_250K)) { if((Uart_CurSendMainCmd == DOWN_PRO) && (MIReal[PortNO].Data.NetCmd != NET_RESTART)) { if(Uart_CurrentReplyState == 3) { NotMatchDownProCnt = NotMatchDownProCnt + 10; } else { NotMatchDownProCnt++; } MIReal[PortNO].Data.NetStatus = (u8)((Index_Pro * 100) / TotalIndex_Pro); if(MIReal[PortNO].Data.NetStatus == 0) { MIReal[PortNO].Data.NetStatus = 1; } if(NotMatchDownProCnt > 300)//If you do not receive a receipt for 300 consecutive times, skip the micro-inverse { NotMatchDownProCnt = 0; MIReal[PortNO].Data.NetStatus = NET_EXECUTION_FAILURE; CurNetCmd = NET_INIT; RightHexFile = false; if(CurRowData_Pro != NULL) { myfree(CurRowData_Pro); CurRowData_Pro = NULL; } if(string != NULL) { myfree(string); string = NULL; } Uart_CurrentReplyState = 0; return UsartNrf_SendLoop_GetNextSetCmd(); } else { MIReal[PortNO].Data.NetStatus = (u8)((Index_Pro * 100) / TotalIndex_Pro); if(MIReal[PortNO].Data.NetStatus == 0) { MIReal[PortNO].Data.NetStatus = 1; } return true; } } else if(MIReal[PortNO].Data.NetCmd == NET_DOWNLOAD_DAT) { if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) >= Inverter_Pro) { return true; } NotMatchDownDatCnt++; if(NotMatchDownDatCnt > 30) { NotMatchDownDatCnt = 0; MIReal[PortNO].Data.NetStatus = NET_EXECUTION_FAILURE; RightGridOnProFile = false; if(CurRowData_Dat != NULL) { myfree(CurRowData_Dat); CurRowData_Dat = NULL; } Uart_CurrentReplyState = 0; return UsartNrf_SendLoop_GetNextSetCmd(); } else { MIReal[PortNO].Data.NetStatus = (u8)((Index_Dat * 100) / TotalIndex_Dat); if(MIReal[PortNO].Data.NetStatus == 0) { MIReal[PortNO].Data.NetStatus = 1; } return true; } } else if(MIReal[PortNO].Data.NetCmd == NET_LOCK) { NotMatchCnt++; if(NotMatchCnt > 10)// { NotMatchCnt = 0; MIReal[PortNO].Data.NetStatus = NET_EXECUTION_FAILURE; CurNetCmd = NET_INIT; return UsartNrf_SendLoop_GetNextSetCmd(); } return true; } else if((MIReal[PortNO].Data.NetCmd == NET_INVERTER_HW_INFOR) || (MIReal[PortNO].Data.NetCmd == NET_TERMINAL_INFOR)) { NotMatchCnt++; if(NotMatchCnt > 3) { NotMatchCnt = 0; if(MIReal[PortNO].Data.NetCmd == NET_INVERTER_HW_INFOR) { if(MIReal[PortNO].Data.NetStatus == NET_NOT_EXECUTED) { MIReal[PortNO].Data.NetStatus = NET_NOT_EXECUTED; MIReal[PortNO].Data.NetCmd = NET_TERMINAL_INFOR; } memset((InverterDetail *)&MIDetail, 0, sizeof(InverterDetail)); //Clear MIDetail InverterDetail_Read((InverterDetail *)&MIDetail, PortNO, 1); //Read UsartNrf_Process_Version_InitInverter();//Fill in 0 InverterDetail_Write((InverterDetail *)&MIDetail, PortNO, 1); //Write 0 return UsartNrf_SendLoop_GetNextSetCmd(); } else if(MIReal[PortNO].Data.NetCmd == NET_TERMINAL_INFOR) { if(MIReal[PortNO].Data.NetStatus == NET_NOT_EXECUTED) { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_FAILURE; UsartNrf_ClearVersionActionState(); } memset((InverterDetail *)&MIDetail, 0, sizeof(InverterDetail)); //Clear MIDetail InverterDetail_Read((InverterDetail *)&MIDetail, PortNO, 1); //Read UsartNrf_Process_Version_InitInverterRf();//Fill in 0 InverterDetail_Write((InverterDetail *)&MIDetail, PortNO, 1); //Write 0 return UsartNrf_SendLoop_GetNextSetCmd(); } } } else if(MIReal[PortNO].Data.NetCmd == NET_LIMIT_POEWR) { NotMatchCnt++; if(NotMatchCnt > 3) { NotMatchCnt = 0; if(MIReal[PortNO].Data.NetStatus == LOCAL_NOT_EXECUTED) { MIReal[PortNO].Data.NetStatus = NET_NOCMD; } else { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_FAILURE; } return UsartNrf_SendLoop_GetNextSetCmd(); } } else { if((Uart_CurSendMainCmd == REQ_A_DAT) || (Uart_CurSendMainCmd == REQ_B_DAT) || (Uart_CurSendMainCmd == REQ_A1_DAT_1000) || (Uart_CurSendMainCmd == REQ_B1_DAT_1000) || (Uart_CurSendMainCmd == REQ_A2_DAT_1000) || (Uart_CurSendMainCmd == REQ_B2_DAT_1000)) { NotMatchCnt = 0; } else { NotMatchCnt++; } if(NotMatchCnt > 5)//Resend 5 times without response { NotMatchCnt = 0; MIReal[PortNO].Data.NetStatus = NET_EXECUTION_FAILURE; CurNetCmd = NET_INIT; return UsartNrf_SendLoop_GetNextSetCmd(); } return true; } } else { Uart_CurSendMainCmd = 0; Uart_CurRecMainCmd = 0; return true; } } return true;//�ط� } /*********************************************** ** Function name: Second-generation protocol network command to Nrf command ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_Send_NetCmdToNrfCmd(void) { if((CurNetCmd == NET_DTU_HW_INFOR_RES) || (CurNetCmd == NET_DTU_HW_INFOR)) { MainCmd = REQ_RF_RVERSISON; SubCmd = 0; } else if((CurNetCmd >= NET_TURN_ON) && (CurNetCmd <= NET_ELE_ENERGY)) { switch(MIReal[PortNO].Data.NetCmd) { case NET_TURN_ON: SubCmd = CONTROL_ON_SUB;//Boot MainCmd = CONTROL_LOCK_MI__LIMIT_POWER_ONOFF; break; case NET_TURN_OFF: SubCmd = CONTROL_OFF_SUB;//Shut down MainCmd = CONTROL_LOCK_MI__LIMIT_POWER_ONOFF; break; case NET_LIMIT_POEWR: case NET_LIMIT_ACTIVE_POEWR: SubCmd = CONTROL_LIMIT_POWER_SUB ;// Limit power MainCmd = CONTROL_LOCK_MI__LIMIT_POWER_ONOFF; break; case NET_SET_PASSWORD: case NET_CANCEL_GUARD: SubCmd = CONTROL_LOCK_MI_SUB;//Set password MainCmd = CONTROL_LOCK_MI__LIMIT_POWER_ONOFF; break; case NET_ZERO_EXPORT://Anti-countercurrent MainCmd = CONTROL_LOCK_MI__LIMIT_POWER_ONOFF; SubCmd = CONTROL_LIMIT_POWER_SUB; break; case NET_DOWNLOAD_DAT: //Download the grid-connected protection file MainCmd = DOWN_DAT; SubCmd = 0; break; case NET_DOWNLOAD_PRO: case NET_RESTART: // Download program / reset MainCmd = DOWN_PRO; SubCmd = 0; break; case NET_CLEAN_GFDI: // Clear ground fault MainCmd = CLEAR_GFDI; SubCmd = 0; break; case NET_SEARCH_ID: //Search ID MainCmd = BROADCAST; SubCmd = 0; break; case NET_SET_ENERGY://Set the power generation capacity case NET_ELE_ENERGY: MainCmd = RE_FISRT__CONFIRM_SET_ENERGY; SubCmd = RE_CONFIRM_SET_ENERGY_SUB; SubCmd = RE_FISRT_SET_ENERGY_SUB;// break; case NET_INVERTER_HW_INFOR:///Query inverter rf hardware information MainCmd = REQ_RF_SVERSISON; SubCmd = 0; break; case NET_DTU_HW_INFOR: MainCmd = REQ_RF_RVERSISON; SubCmd = 0; break; case NET_TERMINAL_INFOR: MainCmd = REQ_VERSISON;// Terminal inverter hardware and software information SubCmd = 0; break; case NET_SWITCH_BAUD: MainCmd = CHANGE_MOD_2M_250K; SubCmd = 0; break; case NET_UNLOCK: MainCmd = CONTROL_LOCK_MI__LIMIT_POWER_ONOFF; SubCmd = CONTROL_UNLOCK_SUB; break; case NET_LOCK: MainCmd = CONTROL_LOCK_MI__LIMIT_POWER_ONOFF; if(MIReal[PortNO].Data.NetStatus == 50) { SubCmd = CONTROL_LOCK_SUB2; } else { SubCmd = CONTROL_LOCK_SUB1; } break; default: break; } } } /*********************************************** ** Function name: Second-generation protocol packaging reset command ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u16 UartNrf_Send_PackResertMi(u8 *target_adr, u8 *rout_adr, u8 cmd) { vu8 i = 0; vu8 temp_dat[UART_LEN]; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); Uart_SendBuffer[0] = STX;//start temp_dat[0] = DOWN_PRO; //command memcpy((u8 *)&temp_dat[1], target_adr, 4); //1234 memcpy((u8 *)&temp_dat[5], rout_adr, 4); //5678 temp_dat[9] = 0x10; // temp_dat[10] = 0; temp_dat[11] = 0; temp_dat[12] = 0; // temp_dat[13] = 0x12; temp_dat[14] = 0xee; //CRC temp_dat[15] = Get_crc_xor((u8 *)&temp_dat[0], 15); //forward substitution i = ForwardSubstitution((u8 *) & (Uart_SendBuffer[1]), (u8 *)temp_dat, 16); //forward substitution Uart_SendBuffer[17] = ETX; //end memset((u8 *)temp_dat, 0, sizeof(temp_dat)); return 18; } /*********************************************** ** Function name: Second-generation protocol packaging lock/unlock command ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u8 UsartNrf_Send_PackLockAndUnlockCommand(u8 *target_adr, u8 *rout_adr, int8_t MainCmd, u16 SubCmd) { vu8 i = 0; vu8 temp_dat[UART_LEN]; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); Uart_SendBuffer[0] = STX;// temp_dat[0] = (u8)MainCmd ; //Control micro-inverse lock memcpy((u8 *)&temp_dat[1], target_adr, 4); memcpy((u8 *)&temp_dat[5], rout_adr, 4); temp_dat[9] = SubCmd >> 8; temp_dat[10] = SubCmd & 0XFF; //Sub-command temp_dat[11] = Get_crc_xor((u8 *)&temp_dat[0], 11); //CRC i = ForwardSubstitution((u8 *)&Uart_SendBuffer[1], (u8 *)&temp_dat[0], 12); //forward substitution Uart_SendBuffer[(i + 1)] = ETX; //end memset((u8 *)temp_dat, 0, sizeof(temp_dat)); return (i + 2); } /*********************************************** ** Function name://Host computer DTU information polling and packaging ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ u8 UsartNrf_Send_Pack_DTU_DTUPara(u8 *target_adr, u8 *rout_adr, u8 MainCmd, u8 SubCmd) { vu8 i = 0; vu8 temp_dat[UART_LEN]; vu8 temp_wifi_ver[3]; vu8 temp_gprs_ver[4]; memset((u8 *)temp_dat, 0, sizeof(temp_dat)); Uart_SendBuffer[0] = STX;// temp_dat[0] = MainCmd ; memcpy((u8 *)&temp_dat[1], target_adr, 4); memcpy((u8 *)&temp_dat[5], rout_adr, 4); temp_dat[9] = SubCmd; memcpy((u8 *)&temp_dat[10], (u8 *) & (Dtu3Major.Property.DtuHw_Ver[0]), 2); memcpy((u8 *)&temp_dat[12], (u8 *) & (Dtu3Major.Property.DtuSw_Ver[0]), 2); memcpy((u8 *)&temp_dat[14], (u8 *) & (Dtu3Major.Property.RfHw_Ver[2]), 2); memcpy((u8 *)&temp_dat[16], (u8 *) & (Dtu3Major.Property.RfFw_Ver[2]), 2); if(Dtu3Major.Property.Wifi_Vsn[0] > '0') { temp_wifi_ver[0] = Dtu3Major.Property.Wifi_Vsn[0] - '0'; } else { temp_wifi_ver[0] = 0; } if(Dtu3Major.Property.Wifi_Vsn[2] > '0') { temp_wifi_ver[1] = Dtu3Major.Property.Wifi_Vsn[2] - '0'; } else { temp_wifi_ver[1] = 0; } if(Dtu3Major.Property.Wifi_Vsn[4] > '0') { temp_wifi_ver[2] = Dtu3Major.Property.Wifi_Vsn[4] - '0'; } else { temp_wifi_ver[2] = 0; } memcpy((u8 *)&temp_dat[18], (u8 *)&temp_wifi_ver[0], 3); //GPRS software version number if(Dtu3Major.Property.Gprs_Ver[7] > '0') { temp_gprs_ver[0] = Dtu3Major.Property.Gprs_Ver[7] - '0'; } else { temp_gprs_ver[0] = 0; } if(Dtu3Major.Property.Gprs_Ver[8] > '0') { temp_gprs_ver[1] = Dtu3Major.Property.Gprs_Ver[8] - '0'; } else { temp_gprs_ver[1] = 0; } if(Dtu3Major.Property.Gprs_Ver[9] > '0') { temp_gprs_ver[2] = Dtu3Major.Property.Gprs_Ver[9] - '0'; } else { temp_gprs_ver[2] = 0; } if(Dtu3Major.Property.Gprs_Ver[10] > '0') { temp_gprs_ver[3] = Dtu3Major.Property.Gprs_Ver[10] - '0'; } else { temp_gprs_ver[3] = 0; } memcpy((u8 *)&temp_dat[21], (u8 *)&temp_gprs_ver[2], 2); temp_dat[23] = Dtu3Major.Property.wifi_RSSI; temp_dat[24] = connect_server; temp_dat[25] = Dtu3Major.Property.GPRS_CSQ; temp_dat[26] = Get_crc_xor((u8 *)&temp_dat[0], 26); //CRC i = ForwardSubstitution((u8 *)&Uart_SendBuffer[1], (u8 *)&temp_dat[0], 27); //forward substitution Uart_SendBuffer[(i + 1)] = ETX; //end memset((u8 *)temp_dat, 0, sizeof(temp_dat)); return (i + 2); } /*********************************************** ** Function name: The second-generation protocol is controlled according to network commands ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_Send_PackNrfCmd(void) { vu16 j; vu8 LockPasswordTemp[4] = {0, 0, 0, 0}; switch(MIReal[PortNO].Data.NetCmd) { case NET_TURN_ON: //CONTROL_LOCK_MI__LIMIT_POWER_ONOFF://BOOT { if(UsartNrf_HasSetCurrentInverterOk()) { Uart_SendBufferLen = UsartNrf_Send_PackSetTurnOnOffCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, MainCmd, SubCmd); } break; } case NET_TURN_OFF://Shut down { if(UsartNrf_HasSetCurrentInverterOk()) { Uart_SendBufferLen = UsartNrf_Send_PackSetTurnOnOffCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, MainCmd, SubCmd); } break; } case NET_LIMIT_POEWR://Limit power case NET_LIMIT_ACTIVE_POEWR: { if(UsartNrf_HasSetCurrentInverterOk()) { Uart_SendBufferLen = UsartNrf_Send_PackSetPowerLimitCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, (int8_t)MainCmd, SubCmd); } break; } case NET_LOCK: case NET_UNLOCK: { if(UsartNrf_HasSetCurrentInverterOk()) { Uart_SendBufferLen = UsartNrf_Send_PackLockAndUnlockCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, (int8_t)MainCmd, SubCmd); //������ѯcommand } break; } case NET_SET_PASSWORD: case NET_CANCEL_GUARD://Set password { if((Dtu3Detail.Property.Anti_Theft_Switch == 0) && (memcmp((u8 *)LockPasswordTemp, (u8 *)Dtu3Detail.Property.LockNewPassword, 4) != 0)) { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_FAILURE; CurNetCmd = NET_INIT; return; } else { if(UsartNrf_HasSetCurrentInverterOk()) { if(memcmp((u8 *)LockPasswordTemp, (u8 *)Dtu3Detail.Property.LockNewPassword, 4) == 0) { if(MIReal[PortNO].Data.NetCmd == NET_CANCEL_GUARD) { memset((u8 *)Dtu3Detail.Property.LockOldPassword, 0, 4); memset((u8 *)Dtu3Detail.Property.LockNewPassword, 0, 4); memset((u8 *)Dtu3Detail.Property.Lock_Time, 0, 2); Uart_SendBufferLen = UsartNrf_Send_PackSetLockOnOffCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, (int8_t)MainCmd, SubCmd); } } else { if(MIReal[PortNO].Data.NetCmd == NET_SET_PASSWORD) { Uart_SendBufferLen = UsartNrf_Send_PackSetLockOnOffCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, (int8_t)MainCmd, SubCmd); } } } } break; } #ifdef ZEROEXPORT case NET_ZERO_EXPORT://Anti-countercurrent { if(Dtu3Detail.Property.Zero_Export_Switch == 0) { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_FAILURE; CurNetCmd = NET_INIT; return; } if(UsartNrf_HasSetCurrentInverterOk()) { Uart_SendBufferLen = UsartNrf_Send_PackSetRefluxPowerCommand((u16)Dtu3Detail.Property.LimitPower_MyPower[0], MainCmd, SubCmd); } } break; #endif case NET_DOWNLOAD_DAT://DOWN_DAT when downloading the network-connected protection file { if(UsartNrf_HasSetCurrentInverterOk()) { UsartNrf_Send_PackUpdateGridOnProFile((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id); } break; } case NET_DOWNLOAD_PRO://DOWN_PRO download program { if(UsartNrf_HasSetCurrentInverterOk()) { UsartNrf_Send_PackUpdateMiProgram((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id); } break; } case NET_SEARCH_ID://Search Id (Guangfa command) { if(UsartNrf_HasSetCurrentInverterOk()) { for(j = Dtu3Detail.Property.PortNum; j < PORT_LEN; j++) { memset((u8 *)MIMajor[j].Property.Pre_Id, 0, 2); memset((u8 *)MIMajor[j].Property.Id, 0, 4); MIMajor[j].Property.Port = MI_NO; } Uart_SendBufferLen = UsartNrf_Send_PackBaseCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, MainCmd, 0); } break; } case NET_CLEAN_GFDI: case NET_ELE_ENERGY: { if(UsartNrf_HasSetCurrentInverterOk()) { Uart_SendBufferLen = UsartNrf_Send_PackBaseCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, MainCmd, (u8)SubCmd); } break; } case NET_RESTART: { if(UsartNrf_HasSetCurrentInverterOk()) { Uart_SendBufferLen = (u8)UartNrf_Send_PackResertMi((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, MainCmd); } break; } case NET_TERMINAL_INFOR: case NET_INVERTER_HW_INFOR: //Collect version number { if(UsartNrf_HasSetCurrentInverterOk()) { Uart_SendBufferLen = UsartNrf_Send_PackBaseCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, MainCmd, (u8)SubCmd); } break; } default: break; } } /*********************************************** ** Function name: Second and third generation protocol polling real-time data packaging ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_Send_PackPollRealTimeData(void) { if((GetInveterBaudType((u8 *)MIMajor[PortNO].Property.Pre_Id) != Uart_CurrentDtuBaud) || (Uart_CurrentDtuBaud == Device_INIT_BAUD)) // Determine whether the current dtu baud rate and the inverter baud rate match { Uart_CurSendMainCmd = CHANGE_MOD_2M_250K; Uart_SendBufferLen = UsartNrf_Send_PackSetNrfBaudRateInTheAir((u8 *)Dtu3Major.Property.Id, (u8 *)Dtu3Major.Property.Id, Uart_CurSendMainCmd, GetInveterBaudType((u8 *)MIMajor[PortNO].Property.Pre_Id)); } //dong packet loss rate statistics if((APP_Flg == 1) && ((AppState == AllMiLossRate) || (AppState == ManuSigleLossRate))) { Uart_SendBufferLen = UsartNrf3_Send_Mi_Nrf_VER((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id); if(AppPollCnt < 100) { AppPollCnt++; } #ifdef DEBUGSIGNAL printf("SSS:T:%d-D:%d-S:%d-R:%d\n\r", LocalTime, PortNO, AppPollCnt, RecieveDataCnt); #endif } else { if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) >= Inverter_Pro) // Three-generation protocol { UsartNrf3_Send_NetCmdToNrfCmd(); //dong 2020-06-23 // if(CurNetCmd == NET_GET_LOSS_RATE) // { // UsartNrf3_Send_Mi_Nrf_VER((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id); // return ; // } //dong ??? if((TotalPackageNum <= 0) && (CurRecSendLostPackageState != 0)) { Uart_SendBufferLen = UsartNrf3_Send_PackPollSigleDataCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, 0x7f); } else { if(CurRecSendLostPackageState != 0) { Uart_SendBufferLen = UsartNrf3_Send_PackPollSigleDataCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, CurRecSendLostPackageNO + 1); } else { //dong 2020-06-16 if(MIReal[PortNO].Data.NetCmd == NET_SELF_STAUS) { SubCmd = GetSelfCheckState; } Uart_SendBufferLen = UsartNrf3_Send_PackPollMultiDataCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, (u8)SubCmd, 0, (u8 *)Dtu3Detail.Property.LockNewPassword); } } Uart_CurSendMainCmd = MainCmd; Uart_CurSendSubCmd = SubCmd; } else //Second-generation protocol polling { Uart_CurSendMainCmd = UsartNrf_GetPollCmdOfRealTime();//Get polling instruction if(Dtu3Detail.Property.Anti_Theft_Switch == 1) { Uart_SendBufferLen = UsartNrf_Send_PackPollRfWithLockCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, Uart_CurSendMainCmd); } else { Uart_SendBufferLen = UsartNrf_Send_PackBaseCommand((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, Uart_CurSendMainCmd, 0); // Send polling command } } ProtocalLayer_Poll = ToTransLayer_Send; } } /*********************************************** ** Function name: Second-generation and third-generation protocol networking command packaging ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_Send_Register(void) { #ifndef DTU3PRO IWDG_Feed(); //Feed the dog #endif calendar_obj calendar; InverterDetail_Delete(); UsartNrf_GetDtu3PortNum();//Get the total number of components System_Dtu_Info_Write((DtuDetail *)&Dtu3Detail, (DtuMajor *)&Dtu3Major);//Number of storage components UsartNrf_InitPVPannelToMIMajor();//Arrange Id bits System_MI_SN_Write((InverterMajor *)MIMajor);//Write the InverterMajor file System_MI_SN_Write((InverterMajor *)MIMajor); InverterReal_Delete();// Erase real-time data //Clear real-time alarm data Alarm_Data_Delete(); //Clear temporary alarm AlarmInfo_Delete(); memset((AlarmDataType *)&pRealAlarm, 0, 20 * sizeof(AlarmDataType)); memset((AlarmDataType *)&pInformAlarm, 0, 20 * sizeof(AlarmDataType)); memset((u16 *)WarnSerNub, 0, sizeof(WarnSerNub)); Alarm_Serial_Num_Write((u16 *)WarnSerNub, calendar); #ifdef DTU3PRO #ifndef DEBUG #ifdef DTU_IAP IWDG_Feed(); #endif #endif #else IWDG_Feed(); //Feed the dog #endif DeleteHistoryData(); //Historical data #ifdef DTU3PRO #ifndef DEBUG #ifdef DTU_IAP IWDG_Feed(); #endif #endif #else IWDG_Feed(); //Feed the dog #endif UsartNrf_ClearMI_DailyEnergy();//Clear all real-time data UsartNrf_ClearMIReal_HistoryEnergy();//Clear historical power generation UsartNrf_ClearNetStatusAndCmd();//Clear the number of connections and connection flags if(Dtu3Detail.Property.PortNum > 0) { if(UsartNrf_GetInvterType((u8 *)MIMajor[0].Property.Pre_Id) >= Inverter_Pro) { // UsartNrf3_Process_LedShow(true); } else { UsartNrf_Process_LedShow(true, 10); } } Dtu3Detail.Property.PolledVerState = 0; } /*********************************************** ** Function name: Polling and packaging of the second-generation protocol version ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Send_PackPollVersionCmd(void) { if(UsartNrf_HasSetCurrentInverterOk()) { Uart_SendBufferLen = UsartNrf_Send_PackBaseCommand((u8 *)Dtu3Major.Property.Id, (u8 *)Dtu3Major.Property.Id, MainCmd, (u8)SubCmd); } } /*********************************************** ** Function name: Serial port to send data switch ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ bool UsartNrf_Send_Loop_IsEnable(void) { if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) >= Inverter_Pro) { if(Uart_CurSendMainCmd == REQ_ARW_DAT_ALL) { if(CurRecSendPackageDataType == RealTimeRunData_Reality) { if((RTC_GetWorldSecond(Dtu3Detail.Property.timezone) % (15 * 60)) < 10) { return false; } } } } return true; } /*********************************************** ** Function name: Serial port to send data ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Send_Loop() { static vu32 SendTime = 0; vu8 i; vu8 NrfContrlNum = 0; vu8 NrfCompleteNum = 0; //u8 Uart_SendBuffer1[] = {0x7e, 0x15, 0x50, 0x80, 0x55, 0x56, 0x50, 0x80, 0x55, 0x56, 0x80, 0x02, 0x00, 0x5E, 0x04, 0x7D, 0x5E, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5B, 0x10, 0xD2, 0x7f}; //u8 Uart_SendBuffer1[] = {0x7e,0x15,0x50,0x80,0x55,0x55,0x50,0x80,0x55,0x55,0x80,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xb9,0x2d,0x7f}; bool GoingPolling = false; vu8 HasNoId[4] = {0, 0, 0, 0}; // dong 2020-05-19 // if((LocalTime - SendTime >= LocalTime_TimeOut) || ((LocalTime < SendTime) && (LOCAL_TIME_900000MS - SendTime + LocalTime >= LocalTime_TimeOut)) // Will this happen? ) if(LocalTime - SendTime >= LocalTime_TimeOut) { if((CurNetCmd == NET_NOPORT) && (MIReal[0].Data.NetCmd != NET_REGISTER_ID) && (MIReal[0].Data.NetStatus != NET_NOT_EXECUTED)) { if(Dtu3Detail.Property.PortNum > 0)//Tooling registration id { CurNetCmd = NET_INIT; // Poll as usual } else { return; } } else { //APP mode rotation training status judgment if((APP_Flg == 1) && (AppState != OtherNetCmdState)) { CurAlarmState = AlarmInforUpdate_App; //The current polling is the debugging data time flag CurPollIsDebugDataTime = true; } // else if(Dtu3Detail.Property.Zero_Export_Switch == 1) { CurPollIsDebugDataTime = true; } else { if(CurAlarmState == AlarmInforUpdate_App) { CurAlarmState = InitState; } //The effect is the same dong 2020-05-12 if(LocalTime > (10 * LOCAL_TIME_1MIN)) { //CurPollIsDebugDataTime = false; CurPollIsDebugDataTime = true; } else { CurPollIsDebugDataTime = true; } } //Abort command execution if((MIReal[0].Data.NetCmd == NET_ABORTCONTROL) && (MIReal[0].Data.NetStatus == NET_NOT_EXECUTED)) { CurNetCmd = NET_INIT; } //Registration ID else if((MIReal[0].Data.NetCmd == NET_REGISTER_ID) && (MIReal[0].Data.NetStatus == NET_NOT_EXECUTED)) { CurNetCmd = NET_REGISTER_ID; MIReal[0].Data.NetCmd = NET_INIT; MIReal[0].Data.NetStatus = NET_EXECUTION_COMPLETED; } //Search ID else if((MIReal[0].Data.NetCmd == NET_SEARCH_ID) && (MIReal[0].Data.NetStatus == NET_NOT_EXECUTED)) { CurNetCmd = NET_SEARCH_ID; MIReal[0].Data.NetCmd = NET_INIT; MIReal[0].Data.NetStatus = NET_EXECUTION_COMPLETED; } //Turn on and off. else if(((MIReal[PortNO].Data.NetCmd >= NET_TURN_ON) && (MIReal[PortNO].Data.NetCmd <= NET_ELE_ENERGY)) && ((MIReal[PortNO].Data.NetStatus == NET_NOT_EXECUTED) || (MIReal[PortNO].Data.NetStatus == LOCAL_NOT_EXECUTED))) { CurNetCmd = MIReal[PortNO].Data.NetCmd; } //Waiting to download the grid-connected protection file-waiting to download the rf program else if(((MIReal[PortNO].Data.NetCmd == NET_WAIT_DOWNLOAD_DAT) || (MIReal[PortNO].Data.NetCmd == NET_WAIT_DOWNLOAD_PRO)) && (MIReal[PortNO].Data.NetStatus == NET_NOT_EXECUTED)) { //CurNetCmd = NET_INIT; } } //Registration ID if((CurAlarmState != AlarmInforUpdate_App) && (CurNetCmd == NET_REGISTER_ID)) { UsartNrf_Send_Register();//Registration ID if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) >= Inverter_Pro) // Three-generation protocol { UsartNrf3_SendLoop_SetTaskTimeOut(false); //Set the task timeout } else { UsartNrf3_SendLoop_SetTaskTimeOut(true); //Set the task timeout } Uart_CurSendMainCmd = 0; Uart_CurRecMainCmd = 0; CurNetCmd = NET_DTU_HW_INFOR; NeedLostPackageState = 0; TotalPackageNum = 0; PortNO = 0; return ; } else if((CurAlarmState != AlarmInforUpdate_App) && ((CurNetCmd >= NET_TURN_ON) && (CurNetCmd <= NET_ELE_ENERGY) && (CurNetCmd != NET_WAIT_DOWNLOAD_DAT) && (CurNetCmd != NET_WAIT_DOWNLOAD_PRO))) { if((GetInveterBaudType((u8 *)MIMajor[PortNO].Property.Pre_Id) != Uart_CurrentDtuBaud) || (Uart_CurrentDtuBaud == Device_INIT_BAUD)) // Determine whether the current dtu baud rate and the inverter baud rate match { Uart_SendBufferLen = UsartNrf_Send_PackSetNrfBaudRateInTheAir((u8 *)MIMajor[PortNO].Property.Id, (u8 *)MIMajor[PortNO].Property.Id, CHANGE_MOD_2M_250K, GetInveterBaudType((u8 *)MIMajor[PortNO].Property.Pre_Id)); Uart_CurSendMainCmd = CHANGE_MOD_2M_250K; // Cut baud rate } else { if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) >= Inverter_Pro)// Three-generation protocol { UsartNrf3_Send_NetCmdToNrfCmd(); // Network command to nrf command UsartNrf3_Send_PackNrfCmd();// Package network command package } else // Three-generation protocol { UsartNrf_Send_NetCmdToNrfCmd(); // Network command to nrf command UsartNrf_Send_PackNrfCmd();// Package network command package } } Uart_CurSendMainCmd = MainCmd; Uart_CurSendSubCmd = SubCmd; } //When restarting and networking, poll dtu--id else if((CurAlarmState != AlarmInforUpdate_App) && ((CurNetCmd == NET_DTU_HW_INFOR_RES) || (CurNetCmd == NET_DTU_HW_INFOR))) { UsartNrf_Send_NetCmdToNrfCmd(); // Network command to nrf command UsartNrf_Send_PackPollVersionCmd();// Second-generation /third-generation shared DTU package version packaging Uart_CurSendMainCmd = MainCmd; Uart_CurSendSubCmd = SubCmd; } else { if((Dtu3Detail.Property.PortNum <= 0) || ((memcmp((u8 *)&MIMajor[PortNO].Property.Pre_Id[0], (u8 *)HasNoId, 2) == 0) && (memcmp((u8 *)&MIMajor[PortNO].Property.Id[0], (u8 *)HasNoId, 4) == 0))) { return; } else { if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) >= Inverter_Pro) // Three-generation protocol { GoingPolling = UsartNrf3_HasPollCurInverterPort(); } else { GoingPolling = UsartNrf_HasPollCurInverterPort(); // Three-generation protocol } //Send if(GoingPolling) { UsartNrf_Send_PackPollRealTimeData(); //Polling real-time data } else { return; } } } // if((Uart_CurrentDtuBaud == Uart_CurrentDtuBaud) && (ifflag)) // { // // LocalTime_TimeOut = 1200;//1200ms time interval // LocalTime_TimeOut = 6000;//1200ms time interval // //memcpy(Uart_SendBuffer, Uart_SendBuffer1, 29); // memcpy(Uart_SendBuffer, Uart_SendBuffer1, 30); // //Uart_SendBufferLen = 29; // Uart_SendBufferLen = 30; // CurRecSendPackageDataType = Uart_SendBuffer[11]; // PortNO = 0 ; // } if(Uart_SendBufferLen <= 0) { return; } else { if(UsartNrf_Send_Loop_IsEnable()) { USART_ClearITPendingBit(UsartNrf, USART_IT_TC); USART_ClearFlag(UsartNrf, USART_FLAG_TC); UsartNrf_SendLoop_SetPackageTimeOut(false); USART_SendData(UsartNrf, Uart_SendBuffer[0]); } SendTime = LocalTime; } } } /*********************************************** ** Function name: Save historical power generation in the middle of the night ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_SaveHistoryEnergy(void) { static bool HasReset = true; volatile calendar_obj calendar; RTC_GetWorldTime((calendar_obj *)&calendar, Dtu3Detail.Property.timezone); if((HasReset == true) && (((calendar.hour == 23) && ((calendar.min >= 50) && (calendar.min <= 59))) && (PortNO >= Dtu3Detail.Property.PortNum - 1))) { UsartNrf_ClearMI_DailyEnergy(); InverterReal_Write((InverterReal *)MIReal, Dtu3Detail.Property.PortNum); HasReset = false; } } /*********************************************** ** Function name: Real-time data collection of a single component of the second-generation protocol ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_BaseDataPort(u8 *pBuffer, u8 i) { static vs16 DailyEnergy1 = 0; static vs16 DailyEnergy2 = 0; vu8 j; vu16 k; UsartNrf_Process_LedShow(true, 10); switch(MIMajor[PortNO].Property.Port) { case MI_250W: case MI_500W_A: case MI_1000W_A: { j = 0; break; } case MI_500W_B: case MI_1000W_B: { j = 1; break; } case MI_1000W_C: { j = 2; break; } case MI_1000W_D: { j = 3; break; } default: break; } if(UsartNrf_Process_ExceptionFilter(pBuffer, 10, 11, 700, 0) == true) //PV voltage { memcpy((u8 *) & (MIReal[PortNO - j + i].Data.PVVol[0]), &(pBuffer[10]), 2); } if(UsartNrf_Process_ExceptionFilter(pBuffer, 12, 13, 150, 0) == true) //PV current { memcpy((u8 *) & (MIReal[PortNO - j + i].Data.PVCur[0]), &(pBuffer[12]), 2); } if(UsartNrf_Process_ExceptionFilter(pBuffer, 14, 15, 4000, 0) == true) //Grid voltage { memcpy((u8 *) & (MIReal[PortNO - j + i].Data.GridVol[0]), &(pBuffer[14]), 2); } if(UsartNrf_Process_ExceptionFilter(pBuffer, 16, 17, 7000, 0) == true) //Grid frequency { memcpy((u8 *) & (MIReal[PortNO - j + i].Data.Freque[0]), &(pBuffer[16]), 2); } if(UsartNrf_Process_ExceptionFilter(pBuffer, 18, 19, 5000, 0) == true) //Output power { memcpy((u8 *) & (MIReal[PortNO - j + i].Data.Power[0]), &(pBuffer[18]), 2); } if(UsartNrf_Process_ExceptionFilter(pBuffer, 20, 21, 3000, 0) == true) // Power generation on the day { DailyEnergy1 = DailyEnergy2; DailyEnergy2 = (s16)((s16)pBuffer[20] << 8 | pBuffer[21]); } if(UsartNrf_Process_ExceptionFilter(pBuffer, 22, 23, 2000, 0) == true) //temperature { memcpy((u8 *) & (MIReal[PortNO - j + i].Data.Temper[0]), &(pBuffer[22]), 2); } if((pBuffer[1] >= ANSWER_REQ_A1_DAT_1000) && (pBuffer[1] <= ANSWER_REQ_B2_DAT_1000)) { MIReal[PortNO - j + i].Data.Run_Status[1] = pBuffer[24]; MIReal[PortNO - j + i].Data.Fault_Code[1] = pBuffer[25]; MIReal[PortNO - j + i].Data.Fault_Num[1] = pBuffer[26]; } if((APP_Flg == 1) && (AppState == ManuSigleLossRate)) { MIReal[PortNO - j + i].Data.Real_Time = MIReal[PortNO - j + i].Data.Real_Time; } else { MIReal[PortNO - j + i].Data.Real_Time = RTC_Getsecond(); } // if(((PortNO == 0) || (PortNO == 1)) && (DailyEnergy > 0)) // { //printf("1"); // } //MI daily power generation if((DailyEnergy2 > MIReal[PortNO - j + i].Data.DailyEnergy) && (abs(DailyEnergy2 - DailyEnergy1) <= 500)) { MIReal[PortNO - j + i].Data.DailyEnergy = (u16)DailyEnergy2; //////////////////////////////DEBUG information///////////// //////// if((((uint32_t)MIReal[PortNO - j + i].Data.HistoryEnergyH) << 16 | ((uint32_t)MIReal[PortNO - j + i].Data.HistoryEnergyL)) > (DailyEnergyTemp[PortNO - j + i] + MIReal[PortNO - j + i].Data.DailyEnergy)) { #ifdef DEBUG_ZHOULEI printf("error code1:"); printf("HistoryEnergyHL:%x", (((uint32_t)MIReal[PortNO - j + i].Data.HistoryEnergyH) << 16 | ((uint32_t)MIReal[PortNO - j + i].Data.HistoryEnergyL))); printf("\n"); for(k = 0; k < 50; k++) { if(pBuffer[k] <= 0x0f) { printf("0"); printf("%x", pBuffer[k]); printf(" "); } else { printf("%x", pBuffer[k]); printf(" "); } } printf("\n"); #endif } //////////////////////////////DEBUG information///////////////////// //////// MIReal[PortNO - j + i].Data.HistoryEnergyH = (DailyEnergyTemp[PortNO - j + i] + MIReal[PortNO - j + i].Data.DailyEnergy) >> 16; MIReal[PortNO - j + i].Data.HistoryEnergyL = (DailyEnergyTemp[PortNO - j + i] + MIReal[PortNO - j + i].Data.DailyEnergy) & 0xffff; } MIReal[PortNO].Data.LinkState = MIReal[PortNO].Data.LinkState | MI_CONNECT; } /*********************************************** ** Function name: Second-generation protocol single component data current event collection ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_BaseEventPort(u8 *pBuffer, u8 i) { vu8 j; switch(MIMajor[PortNO].Property.Port) { case MI_250W: case MI_500W_A: { j = 0; break; } case MI_500W_B: { j = 1; break; } default: break; } memcpy((u8 *) & (MIReal[PortNO - j + i].Data.Run_Status[0]), &(pBuffer[10]), 2); memcpy((u8 *) & (MIReal[PortNO - j + i].Data.Fault_Code[0]), &(pBuffer[12]), 2); memcpy((u8 *) & (MIReal[PortNO - j + i].Data.Fault_Num), &(pBuffer[14]), 2); } /*********************************************** ** Function name: The second-generation protocol processes 250w micro-inverse receipt data ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_Inverter250_RealTimeData(u8 *pBuffer) { switch(pBuffer[1]) { case ANSWER_REQ_A_DAT: UsartNrf_Process_BaseDataPort(pBuffer, 0); break; case ANSWER_REQ_A_EVENT: UsartNrf_Process_BaseEventPort(pBuffer, 0); break; default: break; } } /*********************************************** ** Function name: The second-generation protocol processes 500w micro-inverse receipt data ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_Inverter500_RealTimeData(u8 *pBuffer) { switch(pBuffer[1]) { case ANSWER_REQ_A_DAT: // 0x89 UsartNrf_Process_BaseDataPort(pBuffer, 0); break; case ANSWER_REQ_A_EVENT: // 0x88 UsartNrf_Process_BaseEventPort(pBuffer, 0); break; case ANSWER_REQ_B_DAT: // 0x91 UsartNrf_Process_BaseDataPort(pBuffer, 1); break; case ANSWER_REQ_B_EVENT: // 0x92 UsartNrf_Process_BaseEventPort(pBuffer, 1); break; default: break; } } /*********************************************** ** Function name: Second-generation protocol, broadcast command, search id, receive receipt processing ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_Inverter_NetCmd_SearchId(u8 *pBuffer) { static vu16 PortCnt = 0; vu16 i; if(PortCnt == 0) { PortCnt = Dtu3Detail.Property.PortNum;//Total number of connections } for(i = 0; i < PortCnt; i++) { if(((memcmp(&(pBuffer[10]), (u8 *)MIMajor[i].Property.Pre_Id, 2) != 0) || (memcmp(&(pBuffer[12]), (u8 *)MIMajor[i].Property.Id, 4) != 0)) && ((pBuffer[11] & 0xf0) <= 0x60)) { memcpy((u8 *)MIMajor[PortCnt].Property.Pre_Id, (&pBuffer[10]), 2); memcpy((u8 *)MIMajor[PortCnt].Property.Id, (&pBuffer[2]), 4);// The original network id remains unchanged, and the subsequent insert id if(UsartNrf_GetInvterType((u8 *)MIMajor[PortCnt].Property.Pre_Id) == Inverter_500) { if((MIMajor[PortCnt].Property.Port != MI_500W_A) && (MIMajor[PortCnt].Property.Port != MI_500W_B)) { memcpy((u8 *) & (MIMajor[PortCnt + 1].Property.Id[0]), (u8 *)&MIMajor[PortCnt].Property.Id[0], sizeof(MIMajor[PortCnt].Property.Id)); memcpy((u8 *) & (MIMajor[PortCnt + 1].Property.Pre_Id[0]), (u8 *)&MIMajor[PortCnt].Property.Pre_Id[0], sizeof(MIMajor[PortCnt].Property.Pre_Id)); MIMajor[PortCnt].Property.Port = MI_500W_A; MIMajor[PortCnt + 1].Property.Port = MI_500W_B; Dtu3Detail.Property.PortNum = Dtu3Detail.Property.PortNum + 2; } } else if(UsartNrf_GetInvterType((u8 *)MIMajor[PortCnt].Property.Pre_Id) == Inverter_1000) { if((MIMajor[PortCnt].Property.Port != MI_1000W_A) && (MIMajor[PortCnt].Property.Port != MI_1000W_B) && (MIMajor[PortCnt].Property.Port != MI_1000W_C) && (MIMajor[PortCnt].Property.Port != MI_1000W_D)) { memcpy((u8 *)&MIMajor[PortCnt + 1].Property.Id[0], (u8 *)&MIMajor[PortCnt].Property.Id[0], sizeof(MIMajor[PortCnt].Property.Id)); memcpy((u8 *)&MIMajor[PortCnt + 1].Property.Pre_Id[0], (u8 *)&MIMajor[PortCnt].Property.Pre_Id[0], sizeof(MIMajor[PortCnt].Property.Pre_Id)); memcpy((u8 *)&MIMajor[PortCnt + 2].Property.Id[0], (u8 *)&MIMajor[PortCnt].Property.Id[0], sizeof(MIMajor[PortCnt].Property.Id)); memcpy((u8 *)&MIMajor[PortCnt + 2].Property.Pre_Id[0], (u8 *)&MIMajor[PortCnt].Property.Pre_Id[0], sizeof(MIMajor[PortCnt].Property.Pre_Id)); memcpy((u8 *)&MIMajor[PortCnt + 3].Property.Id[0], (u8 *)&MIMajor[PortCnt].Property.Id[0], sizeof(MIMajor[PortCnt].Property.Id)); memcpy((u8 *)&MIMajor[PortCnt + 3].Property.Pre_Id[0], (u8 *)&MIMajor[PortCnt].Property.Pre_Id[0], sizeof(MIMajor[PortCnt].Property.Pre_Id)); MIMajor[PortCnt].Property.Port = MI_1000W_A; MIMajor[PortCnt + 1].Property.Port = MI_1000W_B; MIMajor[PortCnt + 2].Property.Port = MI_1000W_C; MIMajor[PortCnt + 3].Property.Port = MI_1000W_D; Dtu3Detail.Property.PortNum = Dtu3Detail.Property.PortNum + 4; } } else if(UsartNrf_GetInvterType((u8 *)MIMajor[PortCnt].Property.Pre_Id) == Inverter_250) { MIMajor[PortCnt].Property.Port = MI_250W; Dtu3Detail.Property.PortNum = Dtu3Detail.Property.PortNum + 1; } if(UsartNrf_GetInvterType((u8 *)MIMajor[PortCnt].Property.Pre_Id) == Inverter_250) { PortCnt = PortCnt + 1; i = i + 1; } else if(UsartNrf_GetInvterType((u8 *)MIMajor[PortCnt].Property.Pre_Id) == Inverter_500) { PortCnt = PortCnt + 2; i = i + 2; } else if(UsartNrf_GetInvterType((u8 *)MIMajor[PortCnt].Property.Pre_Id) == Inverter_1000) { PortCnt = PortCnt + 4; i = i + 4; } MIReal[PortNO].Data.NetStatus = (u8)((PortCnt * 100) / PORT_LEN); if(PortCnt >= PORT_LEN) { return; } return; } } return ; } /*********************************************** ** Function name: Second-generation protocol micro-inverse version reception and processing ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_Version_Inverter(u8 *pBuffer) { InverterDetail_Read((InverterDetail *)&MIDetail, PortNO, 1); if(pBuffer[10] == 0x00) { MIDetail.Property.USFWBuild_VER = (u16)(pBuffer[11] << 8) | (u16)pBuffer[12]; MIDetail.Property.AppFWBuild_VER = (u16)(pBuffer[13] << 8) | (u16)pBuffer[14]; MIDetail.Property.AppFWBuild_YYYY = (u16)(pBuffer[15] << 8) | (u16)pBuffer[16]; MIDetail.Property.AppFWBuild_MMDD = (u16)(pBuffer[17] << 8) | (u16)pBuffer[18]; MIDetail.Property.AppFWBuild_HHMM = (u16)(pBuffer[19] << 8) | (u16)pBuffer[20]; MIDetail.Property.AppFW_PNH = (u16)(pBuffer[21] << 8) | (u16)pBuffer[22]; MIDetail.Property.AppFW_PNL = (u16)(pBuffer[23] << 8) | (u16)pBuffer[24]; MIDetail.Property.HW_VER = (u16)(pBuffer[25] << 8) | (u16)pBuffer[26]; InverterDetail_Write((InverterDetail *)&MIDetail, PortNO, 1); } else if(pBuffer[10] == 0x01) { MIDetail.Property.HW_PNH = (u16)(pBuffer[11] << 8) | (u16)pBuffer[12]; MIDetail.Property.HW_PNL = (u16)(pBuffer[13] << 8) | (u16)pBuffer[14]; MIDetail.Property.HW_FB_TLmValue = (u16)(pBuffer[15] << 8) | (u16)pBuffer[16]; MIDetail.Property.HW_FB_ReSPRT = (u16)(pBuffer[17] << 8) | (u16)pBuffer[18]; MIDetail.Property.HW_GridSamp_ResValule = (u16)(pBuffer[19] << 8) | (u16)pBuffer[20]; MIDetail.Property.HW_ECapValue = (u16)(pBuffer[21] << 8) | (u16)pBuffer[22]; MIDetail.Property.Matching_AppFW_PNH = (u16)(pBuffer[23] << 8) | (u16)pBuffer[24]; MIDetail.Property.Matching_AppFW_PNL = (u16)(pBuffer[25] << 8) | (u16)pBuffer[26]; InverterDetail_Write((InverterDetail *)&MIDetail, PortNO, 1); } else if(pBuffer[10] == 0x12) { MIDetail.Property.AppFW_MINVER = (u16)(pBuffer[11] << 8) | (u16)pBuffer[12]; MIDetail.Property.HW_CRCValue = (u16)(pBuffer[13] << 8) | (u16)pBuffer[14]; MIDetail.Property.CRC_ALL = (u16)(pBuffer[15] << 8) | (u16)pBuffer[16]; InverterDetail_Write((InverterDetail *)&MIDetail, PortNO, 1); } if(MIReal[PortNO].Data.NetStatus == NET_NOT_EXECUTED) { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_COMPLETED; UsartNrf_ClearVersionActionState(); } else { Dtu3Detail.Property.PolledVerState = 2; } } /*********************************************** ** Function name: DTU version number receiving and processing ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_Inverter_Version_DtuRf(u8 *pBuffer) { memcpy((u8 *) & (Dtu3Major.Property.Id), &(pBuffer[13]), 4); memcpy((u8 *) & (Dtu3Major.Property.Pre_Id), &(pBuffer[11]), 2); if(memcmp(&(pBuffer[18]), (u8 *)Dtu3Major.Property.RfHw_Ver, 4) != 0) { memcpy((u8 *) & (Dtu3Major.Property.RfHw_Ver), &(pBuffer[17]), 4); } if(memcmp(&(pBuffer[21]), (u8 *)Dtu3Major.Property.RfFw_Ver, 4) != 0) { memcpy((u8 *) & (Dtu3Major.Property.RfFw_Ver), &(pBuffer[21]), 4); } if(CurNetCmd == NET_DTU_HW_INFOR_RES)//When restarting { if(Dtu3Detail.Property.PortNum <= 0) { CurNetCmd = NET_NOPORT; } else { CurNetCmd = NET_INIT; UsartNrf3_SendLoop_SetTaskTimeOut(false);//Set the task timeout } } else if(CurNetCmd == NET_DTU_HW_INFOR)//When restarting { for(PortNO = 0; PortNO <= Dtu3Detail.Property.PortNum; PortNO++) { if(PORT_NUMBER_CONFIRMATION(PortNO)) { MIReal[PortNO].Data.NetCmd = NET_INVERTER_HW_INFOR; MIReal[PortNO].Data.NetStatus = NET_NOT_EXECUTED; } } CurNetCmd = NET_INIT; UsartNrf3_SendLoop_SetTaskTimeOut(false);//Set the task timeout } PortNO = 0; System_Dtu_Info_Write((DtuDetail *)&Dtu3Detail, (DtuMajor *)&Dtu3Major); } /*********************************************** ** Function name: Second-generation protocol micro-inverse Nrf version number reception and processing ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_Inverter_Version_InverterRf(u8 *pBuffer) { if((AppState == AllMiLossRate) || (AppState == ManuSigleLossRate)) { //dong if(RecieveDataCnt < 100) { RecieveDataCnt++; return; #ifdef DEBUGSIGNAL printf("4310-RRR:T:%d-D:%d-S:%d-R:%d\n\r", LocalTime, PortNO, AppPollCnt, RecieveDataCnt); #endif } } InverterDetail_Read((InverterDetail *)&MIDetail, PortNO, 1);//Inverter RF hardware and software version memcpy((u8 *) & (MIDetail.Property.NRF_HardVersion), &(pBuffer[17]), 4); memcpy((u8 *) & (MIDetail.Property.NRF_SoftVersion), &(pBuffer[21]), 4); InverterDetail_Write((InverterDetail *)&MIDetail, PortNO, 1);//Inverter RF hardware and software version MIReal[PortNO].Data.NetCmd = NET_TERMINAL_INFOR; MIReal[PortNO].Data.NetStatus = NET_NOT_EXECUTED; } /*********************************************** ** Function name: Polling receipt processing for the micro-inverse version of the second-generation protocol ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_Inverter_Version(u8 *pBuffer) { switch(pBuffer[1]) { case ANSWER_REQ_VERSISON:// Micro-inverse version number UsartNrf_Process_Version_Inverter(pBuffer); break; case ANSWER_REQ_RF_SVERSISON:// Micro inverse rf version UsartNrf_Process_Inverter_Version_InverterRf(pBuffer); break; default: break; } } /*********************************************** ** Function name:// Nrf command receipt processing of the second-generation protocol with commands (switch on and off, power limit, lock, unlock) ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UartNrf_Process_Inverter_NetCmd_MultiCommand(u8 *pBuffer) { Uart_CurRecSubCmd = (u16)(pBuffer[10] << 8) | (u16)pBuffer[11]; if((((u16)pBuffer[10] << 8) | pBuffer[11]) == CONTROL_LOCK_MI_SUB)// Anti-theft { if(pBuffer[12] == 0) { memcpy((u8 *)Dtu3Detail.Property.LockNewPassword, &(pBuffer[13]), 4); memcpy((u8 *)Dtu3Detail.Property.Lock_Time, &(pBuffer[17]), 2); MIReal[PortNO].Data.NetStatus = NET_EXECUTION_COMPLETED;// CurNetCmd = NET_INIT; System_Dtu_Info_Write((DtuDetail *)&Dtu3Detail, (DtuMajor *)&Dtu3Major); } //Receipt lock micro inverter sub-command else { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_FAILURE; } } else if((((u16)pBuffer[10] << 8) | pBuffer[11]) == CONTROL_LIMIT_POWER_SUB) { if((MIReal[PortNO].Data.NetCmd == NET_LIMIT_POEWR) && (MIReal[PortNO].Data.NetStatus == LOCAL_NOT_EXECUTED)) // Power limit local command { MIReal[PortNO].Data.NetStatus = NET_NOCMD; } else { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_COMPLETED; //Receipt limit power sub-command } } else if((((u16)pBuffer[10] << 8) | pBuffer[11]) == CONTROL_ON_SUB) { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_COMPLETED;//Boot sub-command } else if((((u16)pBuffer[10] << 8) | pBuffer[11]) == CONTROL_OFF_SUB) { if((MIReal[PortNO].Data.NetCmd == NET_LIMIT_POEWR) && (MIReal[PortNO].Data.NetStatus == LOCAL_NOT_EXECUTED)) // Power limit local command { MIReal[PortNO].Data.NetStatus = NET_NOCMD; } else { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_COMPLETED; //Shutdown sub-command } } else if((((u16)pBuffer[10] << 8) | pBuffer[11]) == CONTROL_LOCK_SUB1) { MIReal[PortNO].Data.NetStatus = 50; } else if((((u16)pBuffer[10] << 8) | pBuffer[11]) == CONTROL_LOCK_SUB2) { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_COMPLETED; } else if((((u16)pBuffer[10] << 8) | pBuffer[11]) == CONTROL_UNLOCK_SUB) { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_COMPLETED; } } /*********************************************** ** Function name: Second-generation protocol processing download program command ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_Process_Inverter_NetCmd_DownloadDat(u8 *pBuffer) { Uart_CurrentReplyState = pBuffer[10]; if(pBuffer[10] == 1) { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_COMPLETED; } else { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_FAILURE; } CurNetCmd = NET_INIT; } /*********************************************** ** Function name: The second-generation protocol handles network-connected protection files ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_Process_Inverter_NetCmd_DownloadPro(u8 *pBuffer) { if(MIReal[PortNO].Data.NetCmd == NET_DOWNLOAD_PRO) { if(Index_Pro <= 0x1E) { Uart_CurrentReplyState = 1; } else { Uart_CurrentReplyState = pBuffer[14]; memcpy((u8 *)Uart_CurrentReplyAddr, &(pBuffer[10]), 4); } if(Uart_CurrentReplyState == 1) { MIReal[PortNO].Data.NetStatus = (u8)((Index_Pro * 100) / TotalIndex_Pro); if(MIReal[PortNO].Data.NetStatus == 0) { MIReal[PortNO].Data.NetStatus = 1; } if((memcmp((u8 *)Uart_CurSendAddr, (u8 *)Uart_CurrentReplyAddr, 4) == 0) && ((Uart_CurrentReplyAddr[0] == 0) && (Uart_CurrentReplyAddr[1] == 0) && (Uart_CurrentReplyAddr[2] == 0) && (Uart_CurrentReplyAddr[3] == 0x01))) { memset((u8 *)Uart_CurSendAddr, 0, 4); UsartNrf3_Process_ClearMIVersion(); InverterDetail_Write((InverterDetail *)&MIDetail, PortNO, 1);//Inverter RF hardware and software version MIDetail.Property.HW_VER = 0; Uart_CurrentReplyState = 0; RightHexFile = false; } else { UsartNrf_SendLoop_SetPackageTimeOut(true); MIReal[PortNO].Data.NetStatus = (u8)((Index_Pro * 100) / TotalIndex_Pro); if(MIReal[PortNO].Data.NetStatus == 0) { MIReal[PortNO].Data.NetStatus = 1; } } } else { MIReal[PortNO].Data.NetStatus = (u8)((Index_Pro * 100) / TotalIndex_Pro); if(MIReal[PortNO].Data.NetStatus == 0) { MIReal[PortNO].Data.NetStatus = 1; } } } else if(MIReal[PortNO].Data.NetCmd == NET_RESTART) { MIReal[PortNO].Data.NetStatus = NET_EXECUTION_COMPLETED; } } /*********************************************** ** Function name: Tooling to obtain DTU parameter processing ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_Process_DTU_DTUPara(u8 *pBuffer) { if((pBuffer[10] == REQ_GET_DTU_PARA_SUB) && (pBuffer[1] == REQ_GET_DTU_PARA)) { memcpy((u8 *)Dtu3Major.Property.DtuToolAddr, (&pBuffer[6]), 4); } } /*********************************************** ** Function name: Second-generation protocol setting, power generation receipt processing ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_Process_Inverter_NetCmd_SetEnergy(u8 *pBuffer) { if(pBuffer[10] == RE_FISRT_SET_ENERGY_SUB) { ;//Set the power generation sub-command for the first time } else if(pBuffer[10] == RE_CONFIRM_SET_ENERGY_SUB) { ;//Confirm the setting of the power generation sub-command } } /*********************************************** ** Function name: Second-generation protocol parameter setting receipt processing ** Descriptions: ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_Process_Inverter_NetCmd(u8 *pBuffer) { switch(pBuffer[1]) { case ANSWER_DOWN_DAT: UsartNrf_Process_Inverter_NetCmd_DownloadDat(pBuffer); break; case ANSWER_DOWN_PRO: UsartNrf_Process_Inverter_NetCmd_DownloadPro(pBuffer); break; case ANSWER_CONTROL_LOCK_MI__LIMIT_POEWR_ONOFF: UartNrf_Process_Inverter_NetCmd_MultiCommand(pBuffer); break; case ANSWER_SET__CONFIRM_ENERGY: UsartNrf_Process_Inverter_NetCmd_SetEnergy(pBuffer); break; case ANSWER_CLEAR_GFDI: MIReal[PortNO].Data.NetStatus = NET_EXECUTION_COMPLETED; break; default: break; } } /*********************************************** ** Function name: Second-generation protocol processing 1000w micro-inverse data receipt ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_Inverter1000_RealTimeData(u8 *pBuffer) { switch(pBuffer[1]) { case ANSWER_REQ_A1_DAT_1000: UsartNrf_Process_BaseDataPort(pBuffer, 0); break; case ANSWER_REQ_B1_DAT_1000: UsartNrf_Process_BaseDataPort(pBuffer, 2); break; case ANSWER_REQ_A2_DAT_1000: UsartNrf_Process_BaseDataPort(pBuffer, 1); break; case ANSWER_REQ_B2_DAT_1000: UsartNrf_Process_BaseDataPort(pBuffer, 3); break; default: break; } } /*********************************************** ** Function name: Second-generation agreement & third-generation agreement receipt processing cycle ** Descriptions: ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_Process_Loop() { vu8 SubData[MAX_SUB_DAT_DATA_LEN]; vu8 DataLength; static vu32 SendTime = 0; if((Uart_ProcessBuffer[0] == STX) && (Uart_ProcessBuffer[Uart_ReceiveBufferLen - 1] == ETX)) // { #ifdef DEBUGSIGNAL if(CurRecSendPackageDataType == GetLossRate) { for(SendTime = 0; SendTime < Uart_ReceiveBufferLen; SendTime++) { printf("%02x", Uart_ProcessBuffer[SendTime]); } printf("\n\r"); } #endif #ifdef solar if(CurRecSendPackageDataType == GetSelfCheckState) { for(SendTime = 0; SendTime < Uart_ReceiveBufferLen; SendTime++) { printf("%02x", Uart_ProcessBuffer[SendTime]); } printf("\n\r"); } #endif SendTime = LocalTime; memset((u8 *)SubData, 0, MAX_SUB_DAT_DATA_LEN); DataLength = UsartNrf_Backward_substitution1((u8 *) & (SubData[1]), (u8 *)&Uart_ProcessBuffer[1], (u8)Uart_ReceiveBufferLen - 2); Uart_ReceiveBufferLen = 0; SubData[0] = STX; SubData[DataLength + 1] = ETX; if(Get_crc_xor((u8 *) & (SubData[1]), DataLength - 1) == SubData[DataLength]) // { if(SubData[1] == REQ_GET_DTU_PARA) { UsartNrf_Process_DTU_DTUPara((u8 *)SubData);//Tooling board test program Uart_SendBufferLen = UsartNrf_Send_Pack_DTU_DTUPara((u8 *)Dtu3Major.Property.Id, (u8 *)Dtu3Major.Property.DtuToolAddr, ANSWER_REQ_GET_DTU_PARA, ANSWER_REQ_GET_DTU_PARA_SUB); USART_ClearITPendingBit(UsartNrf, USART_IT_TC); USART_ClearFlag(UsartNrf, USART_FLAG_TC); UsartNrf_SendLoop_SetPackageTimeOut(false); USART_SendData(UsartNrf, Uart_SendBuffer[0]); Uart_CurRecMainCmd = REQ_GET_DTU_PARA; } else { if((((u32)MIMajor[PortNO].Property.Id[0]) | MIMajor[PortNO].Property.Id[1] | MIMajor[PortNO].Property.Id[2] | MIMajor[PortNO].Property.Id[3] == 0) || (memcmp((u8 *)Dtu3Major.Property.Id, (u8 *) & (SubData[2]), 4) == 0) || (memcmp((u8 *)MIMajor[PortNO].Property.Id, (u8 *) & (SubData[2]), 4) == 0)) { Uart_CurRecMainCmd = SubData[1]; if(Uart_CurRecMainCmd == ANSWER_REQ_RF_RVERSISON) { UsartNrf_Process_Inverter_Version_DtuRf((u8 *)SubData); return; } else if(Uart_CurRecMainCmd == BROADCAST) { UsartNrf_Process_Inverter_NetCmd_SearchId((u8 *)SubData); return; } else if(Uart_CurRecMainCmd == ANSWER_CHANGE_MOD_2M_250K) { Uart_CurrentDtuBaud = SubData[10]; return; } if(UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id) == Inverter_250) { UsartNrf_Process_Inverter250_RealTimeData((u8 *)SubData); UsartNrf_Process_Inverter_NetCmd((u8 *)SubData); UsartNrf_Process_Inverter_Version((u8 *)SubData); } else if((UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id)) == Inverter_500) { UsartNrf_Process_Inverter500_RealTimeData((u8 *)SubData); UsartNrf_Process_Inverter_NetCmd((u8 *)SubData); UsartNrf_Process_Inverter_Version((u8 *)SubData); } else if((UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id)) == Inverter_1000) { UsartNrf_Process_Inverter1000_RealTimeData((u8 *)SubData); UsartNrf_Process_Inverter_NetCmd((u8 *)SubData); UsartNrf_Process_Inverter_Version((u8 *)SubData); } else if((UsartNrf_GetInvterType((u8 *)MIMajor[PortNO].Property.Pre_Id)) >= Inverter_Pro) { UsartNrf3_Process_Pro((u8 *)SubData);// Three-generation protocol } } } } } else { if(Uart_CurRecMainCmd == REQ_GET_DTU_PARA) { if((LocalTime - SendTime >= LOCAL_TIME_1S) || ((LocalTime < SendTime) && (LOCAL_TIME_900000MS - SendTime + LocalTime >= LOCAL_TIME_1S))) { SendTime = LocalTime; Uart_CurRecMainCmd = ANSWER_REQ_GET_DTU_PARA; } } } UsartNrf_Process_SaveHistoryEnergy(); } /*********************************************** ** Function name: ** Descriptions: Serial port self-check Dtuid at boot time ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void UsartNrf_Process_PowerOnGetDtuId() { vu8 SubData[MAX_SUB_DAT_DATA_LEN]; vu8 DataLength; DataLength = UsartNrf_Backward_substitution1((u8 *) & (SubData[1]), (u8 *)&Uart_ProcessBuffer[1], (u8)Uart_ReceiveBufferLen - 2); Uart_ReceiveBufferLen = 0; SubData[0] = STX; SubData[DataLength + 1] = ETX; #ifdef DEBUG1 if(0 == DataLength) { printf("Get_crc_xor15\r\n"); } #endif if(Get_crc_xor((u8 *) & (SubData[1]), DataLength - 1) == SubData[DataLength]) // { if(SubData[1] == ANSWER_REQ_RF_RVERSISON) { nRFHasCheck = true; memcpy((u8 *) & (Dtu3Major.Property.Id), (u8 *) & (SubData[13]), 4); memcpy((u8 *) & (Dtu3Major.Property.Pre_Id), (u8 *) & (SubData[11]), 2); } } } /*********************************************** ** Function name: ** Descriptions: // DTU3pro serial port interrupt handling ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ #ifdef DTU3PRO void USART3_IRQHandler() { static vu8 Uart_ReceiveBuffer[UART_LEN]; static vu8 *pData = Uart_ReceiveBuffer; static vu8 i = 1; vu8 j = 0; if(USART_GetFlagStatus(USART3, USART_IT_RXNE) != RESET) { *(pData) = (u8)USART_ReceiveData(USART3); if(Uart_ReceiveBuffer[0] == STX) { if(*pData == ETX) { Uart_ReceiveBufferLenTemp++; memset((u8 *)Uart_ProcessBuffer, 0, UART_LEN); for(j = 0; j < Uart_ReceiveBufferLenTemp; j++) { if((Uart_ReceiveBuffer[j] == STX) && (Uart_ReceiveBuffer[j + 1] == STX)) { Uart_ReceiveBufferLenTemp--; memcpy((u8 *)&Uart_ReceiveBuffer[j], (u8 *)&Uart_ReceiveBuffer[j + 1], Uart_ReceiveBufferLenTemp); } } memcpy((u8 *)Uart_ProcessBuffer, (u8 *)Uart_ReceiveBuffer, Uart_ReceiveBufferLenTemp); memset((u8 *)Uart_ReceiveBuffer, 0, UART_LEN); Uart_ReceiveBufferLen = Uart_ReceiveBufferLenTemp; Uart_ReceiveBufferLenTemp = 0; pData = Uart_ReceiveBuffer; if(Uart_ReceiveBufferLen <= 4) { memset((u8 *)Uart_ReceiveBuffer, 0, UART_LEN); pData = Uart_ReceiveBuffer; Uart_ReceiveBufferLen = 0; } if(nRFHasCheck != true) { UsartNrf_Process_PowerOnGetDtuId(); } } else { pData++; Uart_ReceiveBufferLenTemp++; if(Uart_ReceiveBufferLenTemp >= UART_LEN) { memset((u8 *)Uart_ReceiveBuffer, 0, UART_LEN); pData = Uart_ReceiveBuffer; Uart_ReceiveBufferLenTemp = 0; } } } else { Uart_ReceiveBufferLenTemp = 0; pData = Uart_ReceiveBuffer; } USART_ClearITPendingBit(USART3, USART_IT_RXNE); USART_ClearITPendingBit(USART3, USART_FLAG_RXNE); } if(USART_GetFlagStatus(USART3, USART_FLAG_TC) != RESET) { if(i < (Uart_SendBufferLen)) { USART_SendData(USART3, Uart_SendBuffer[i]); i++; } else { i = 1; Uart_SendBufferLen = 0; } USART_ClearITPendingBit(USART3, USART_IT_TC); USART_ClearITPendingBit(USART3, USART_FLAG_TC); } USART_ClearITPendingBit(USART3, USART_IT_ORE); USART_ClearITPendingBit(USART3, USART_IT_IDLE); USART3->DR; // Whether you need to make relevant configuration during initialization to use the serial port interrupt. } #else /*********************************************** ** Function name: ** Descriptions: // DTU3Lite serial port interrupt handling ** input parameters: ? ** output parameters: ? ** Returned value: ? *************************************************/ void USART2_IRQHandler() { static vu8 Uart_ReceiveBuffer[UART_LEN]; static vu8 *pData = Uart_ReceiveBuffer; static vu8 i = 1; vu8 j = 0; if(USART_GetFlagStatus(USART2, USART_IT_RXNE) != RESET) { *(pData) = USART_ReceiveData(USART2); if(Uart_ReceiveBuffer[0] == STX) { if(*pData == ETX) { Uart_ReceiveBufferLenTemp++; memset((u8 *)Uart_ProcessBuffer, 0, UART_LEN); for(j = 0; j < Uart_ReceiveBufferLenTemp; j++) { if((Uart_ReceiveBuffer[j] == STX) && (Uart_ReceiveBuffer[j + 1] == STX)) { Uart_ReceiveBufferLenTemp--; memcpy((u8 *)&Uart_ReceiveBuffer[j], (u8 *)&Uart_ReceiveBuffer[j + 1], Uart_ReceiveBufferLenTemp); } } memcpy((u8 *)Uart_ProcessBuffer, (u8 *)Uart_ReceiveBuffer, Uart_ReceiveBufferLenTemp); memset((u8 *)Uart_ReceiveBuffer, 0, UART_LEN); Uart_ReceiveBufferLen = Uart_ReceiveBufferLenTemp; Uart_ReceiveBufferLenTemp = 0; pData = Uart_ReceiveBuffer; if(Uart_ReceiveBufferLen <= 4) { memset((u8 *)Uart_ReceiveBuffer, 0, UART_LEN); pData = Uart_ReceiveBuffer; Uart_ReceiveBufferLen = 0; } if(nRFHasCheck != true) { UsartNrf_Process_PowerOnGetDtuId(); } } else { pData++; Uart_ReceiveBufferLenTemp++; if(Uart_ReceiveBufferLenTemp >= UART_LEN) { memset((u8 *)Uart_ReceiveBuffer, 0, UART_LEN); pData = Uart_ReceiveBuffer; Uart_ReceiveBufferLenTemp = 0; } } } else { Uart_ReceiveBufferLenTemp = 0; pData = Uart_ReceiveBuffer; } USART_ClearITPendingBit(USART2, USART_IT_RXNE); USART_ClearITPendingBit(USART2, USART_FLAG_RXNE); } if(USART_GetFlagStatus(USART2, USART_FLAG_TC) != RESET) { if(i < (Uart_SendBufferLen)) { USART_SendData(USART2, Uart_SendBuffer[i]); i++; } else { i = 1; Uart_SendBufferLen = 0; } USART_ClearITPendingBit(USART2, USART_IT_TC); USART_ClearITPendingBit(USART2, USART_FLAG_TC); } USART_ClearITPendingBit(USART2, USART_IT_ORE); USART_ClearITPendingBit(USART2, USART_IT_IDLE); USART2->DR; // Whether you need to make relevant configuration during initialization to use the serial port interrupt. } #endif /*********************************************** ** Function name: ** Descriptions: Nrf send and receive main loop function ** input parameters: ** output parameters: ** Returned value: *************************************************/ void UsartNrf_SendProcessLoop() { UsartNrf_Send_Loop(); UsartNrf_Process_Loop(); }