Files
CCU621M/app/mdu_comm/mdu_comm_task.c
T

1157 lines
47 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "mdu_comm/mdu_comm_task.h"
#include "app_init/app_init.h"
#if MDU_UULN_EN
#include "mdu_comm/mdu_uuln_comm.h"
#endif
#include "mdu_comm/mdu_stm_status_comm.h"
#include "PCM_comm.h"
#include "app_init/task_lock.h"
#include "mylog/mylog.h"
#include "publicdata/publicdata.h"
#include "wdt_task/wdt_task.h"
#include "bsp_include.h"
#include "flowctrl/flow_interface.h"
#define MDUCOMM_TASK_ID (TASK_ID_MduComm)
#define MDUCOMM_SLEEP_TIME_MS() (MY_GET_SLEEP_TIME(MDUCOMM_TASK_ID))
#define MDUCOMM_LOCK_INIT() (u8_task_lock_ctrl(MDUCOMM_TASK_ID, TASK_LOCK_OP_INIT))
#define MDUCOMM_LOCK_TAKE() (u8_task_lock_ctrl(MDUCOMM_TASK_ID, TASK_LOCK_OP_TAKE))
#define MDUCOMM_LOCK_GIVE() (u8_task_lock_ctrl(MDUCOMM_TASK_ID, TASK_LOCK_OP_GIVE))
#define MDUCOMM_FEED_DOG() (v_wdt_setFlag(MDUCOMM_TASK_ID))
#define MDUCOMM_LOG(fmt, ...) MYLOG_MSG(MDUCOMM_TASK_ID, (fmt), ##__VA_ARGS__)
/******************************************************************************************
* 文件名称 : mdu_comm_task.c
* 创建时间 : 2025-07-02 15:38:10
* 功能负责人 : jiankalka
* 文件功能说明 : 本文件用于...
*
* @修改记录
* 修改时间 修改人 修改说明
* 2025-07-02 15:38:10 jiankalka 首次创建
*******************************************************************************************/
#define CAN_SEND_SLEEP (5) //报文发送睡眠时间 用于间隔报文发送
S_MDU_DATA s_mdu_data;
#if 1 //
/**
* ************************************************************************
* @brief -CAN
* @brief -模块任务CAN数据发送函数接口
*
* @param[in] can_data -发送报文结构体指针
*
* @author jiankalka
*
* @date 2025-07-02
* ************************************************************************
*/
void v_MduCanMsg_send(CAN_DATA* can_data)
{
v_can_tx(MDU_CAN_ID, can_data);
mSleep(CAN_SEND_SLEEP);
s_mdu_data.u8_can_send_cnt++;
#if MDU_CAN_PRINT_FLAG
v_print_can_data(MDU_CAN_PRINT_FLAG,"mdu send", can_data); // 添加了消息前缀
#endif
}
/**
* ************************************************************************
* @brief -模块任务CAN数据接收函数接口
*
* @param[in] rx_can_data -接收CAN数据结构体指针,此为结构体数组 可返回多个can报文数据
*
* @return U32_T -返回接收报文数量
* @author jiankalka
* @date 2025-07-02
* ************************************************************************
*/
U8_T u8_MduCanMsg_recv(CAN_DATA *rx_can_data)
{
U8_T ret = u8_can_rx(MDU_CAN_ID, rx_can_data);
#if MDU_CAN_PRINT_FLAG
U8_T k; // 使用U8_T而不是size_t以保持一致性
for (k = 0; k < ret; k++)
{
v_print_can_data(MDU_CAN_PRINT_FLAG,"mdu recv", &rx_can_data[k]); // 添加了消息前缀
}
#endif
return ret;
}
#endif
#if 1 //报文组帧
/**
* ************************************************************************
* @brief -组心跳帧
*
*
*
* @author jiankalka
* @date 2025-07-03
* ************************************************************************
*/
void v_mdu_send_Heartbeat()
{
CAN_DATA can_data;
memset(&can_data , 0 , sizeof(CAN_DATA));
can_data.ID = u32_get_can_ID(0x06,MODULE_CMD_HEARTBEAT,MODULE_BROADCAST_ADDR,MODULE_PILE_ADDR); //组帧ID
can_data.Len = 8;
v_MduCanMsg_send(&can_data);
}
/**
* ************************************************************************
* @brief -设置模块为动态分组
*
* @param[in] u8_id -设置模块地址序号 0-N
* @param[in] type -设置信息 1固定分组,2动态分组
*
*
* @author jiankalka
* @date 2025-07-03
* ************************************************************************
*/
void v_mdu_send_setGroupMode(U8_T u8_id,U8_T type)
{
CAN_DATA can_data;
U8_T u8_mdu_addr = s_mdu_data.s_mdu[u8_id].u8_mdu_addr;
memset(&can_data , 0 , sizeof(CAN_DATA));
can_data.ID = u32_get_can_ID(0x06,MODULE_CMD_SETTING,u8_mdu_addr,MODULE_PILE_ADDR); //组帧ID
can_data.Len = 8;
can_data.Data[0] = 0x01; //第一帧报文序号
can_data.Data[1] = 0x02; //总报文数
can_data.Data[2] = 0x07; //报文长度=7
can_data.Data[3] = 0x00;
can_data.Data[4] = 0x00; //接口标识
can_data.Data[5] = 0x04; //设备类型:4=充电模块
can_data.Data[6] = u8_mdu_addr; //设备通信地址
can_data.Data[7] = 0x0D; //定值序号:13=设置分组模式
v_MduCanMsg_send(&can_data);
can_data.Data[0] = 0x02; //第二帧报文序号
can_data.Data[1] = 0x00; //定值序号
can_data.Data[2] = 0x00; //预留
can_data.Data[3] = type; //定值信息:1固定分组,2动态分组
can_data.Data[4] = 0x1A + type + u8_mdu_addr; //和校验
can_data.Data[5] = 0x00;
can_data.Data[6] = 0x00;
can_data.Data[7] = 0x00;
v_MduCanMsg_send(&can_data);
}
/**
* ************************************************************************
* @brief -广播读取模块温度
*
*
*
* @author YZG
* @date 2025-09-15
* ************************************************************************
*/
void v_mdu_temp_read()
{
CAN_DATA can_data;
memset(&can_data , 0 , sizeof(CAN_DATA));
can_data.ID = u32_get_can_ID(0x06,MODULE_CMD_TEMP,MODULE_BROADCAST_ADDR,MODULE_PILE_ADDR); //组帧ID
can_data.Len = 8;
v_MduCanMsg_send(&can_data);
}
void v_mdu_send_getMduPara(U8_T u8_id,U8_T type)
{
CAN_DATA can_data;
U8_T u8_mdu_addr = s_mdu_data.s_mdu[u8_id].u8_mdu_addr;
U8_T u8_data_id = 17+type;
memset(&can_data , 0 , sizeof(CAN_DATA));
can_data.ID = u32_get_can_ID(0x06,MODULE_CMD_GETTING,u8_mdu_addr,MODULE_PILE_ADDR); //组帧ID
can_data.Len = 8;
can_data.Data[0] = 0x01; //第一帧报文序号
can_data.Data[1] = 0x02; //总报文数
can_data.Data[2] = 0x05; //报文长度=5
can_data.Data[3] = 0x00;
can_data.Data[4] = 0x00; //接口标识
can_data.Data[5] = 0x04; //设备类型:4=充电模块
can_data.Data[6] = u8_mdu_addr; //设备通信地址
can_data.Data[7] = u8_data_id; //定值序号:17 最大电压
v_MduCanMsg_send(&can_data);
can_data.Data[0] = 0x02; //第二帧报文序号
can_data.Data[1] = 0x00; //定值序号
can_data.Data[2] = 0x0B + u8_data_id + u8_mdu_addr; //和校验
can_data.Data[3] = 0x00;
can_data.Data[4] = 0x00;
can_data.Data[5] = 0x00;
can_data.Data[6] = 0x00;
can_data.Data[7] = 0x00;
v_MduCanMsg_send(&can_data);
}
/**
* ************************************************************************
* @brief -设置模块组号
*
* @param[in] u8_id - 设置模块地址序号 0-N
* @param[in] NewgrpID - 新设置模块组号 1-N type == 1时有效)
* @param[in] type - 设置类型 0取消设置,1设置组号
*
*
* @author jiankalka
* @date 2025-07-18
* ************************************************************************
*/
void v_mdu_send_setGroupId(U8_T u8_id, U8_T NewgrpID, U8_T type) //动态分组,设置组号
{
CAN_DATA can_data;
U8_T u8_mdu_addr = s_mdu_data.s_mdu[u8_id].u8_mdu_addr;
memset(&can_data , 0 , sizeof(CAN_DATA));
can_data.ID = u32_get_can_ID(0x06,MODULE_CMD_GROUP_SET,u8_mdu_addr,MODULE_PILE_ADDR); //组帧ID
can_data.Len = 8;
if(type == 1)
can_data.Data[0] = 0x30; //命令码,分组设置,间断地址
else
can_data.Data[0] = 0x50; //命令码,分组撤销,间断地址
can_data.Data[1] = NewgrpID; //组号
can_data.Data[2] = 0x01; //地址数目
can_data.Data[3] = u8_mdu_addr;
can_data.Data[4] = 0x00;
can_data.Data[5] = 0x00;
can_data.Data[6] = 0x00;
can_data.Data[7] = 0x00;
v_MduCanMsg_send(&can_data);
}
/**
* ************************************************************************
* @brief - 模块发送遥控命令
*
* @param[in] e_mode - 命令模式 SEND_MODE_UNICAST, ///< 单点发送:命令发送给特定目标设备 SEND_MODE_BROADCAST ///< 广播发送:命令发送给所有设备
* @param[in] u8_addr - 发送地址 如果是广播,则此地址为组号 1-N ;如果不是广播,则此地址为模块序号
* @param[in] e_kyType - 控制指令 MDU_YK_FASTBOOT=1, //快速开机(绝缘检测阶段使用)
MDU_YK_STOP_SUSPEND, //停止充电(保留分组信息)
MDU_YK_SOFTSTART, //软启开机(预启动阶段使用)
MDU_YK_SHOWADDR, //显示地址(显示模块通信地址)
MDU_YK_SETPARA, //参数修改
MDU_YK_STOP, //停止充电(自动清除分组信息)
* @param[in] s_data - 遥控数据 包含两个接触器状态 和 需求电压、需求电流、电池电压 精度0.1;当为NULL时,全部数据默认为0
*
*
* @author jiankalka
* @date 2025-07-03
* ************************************************************************
*/
void v_mdu_send_RemoteCtlr(E_CommandSendMode e_mode, U8_T u8_addr, E_MDU_YK_TYPE e_kyType, S_MDU_RemoteCtlrData *s_data)
{
CAN_DATA can_data;
WordAlign Temp;
U_MDU_YK_DEVICE_STATUS status;
U16_T u16_needVol,u16_needCur,u16_battVol;
U8_T GrpID = (e_mode == SEND_MODE_BROADCAST)?u8_addr:s_mdu_data.s_mdu[u8_addr].s_state.u8_groupNo; //组号 如果是广播,则直接使用传递的组号;如果是单点,或者模块对应的组号
U8_T desAddr = (e_mode == SEND_MODE_BROADCAST)? MODULE_BROADCAST_ADDR:s_mdu_data.s_mdu[u8_addr].u8_mdu_addr; //目的地址 是广播还是组号
memset(&can_data , 0 , sizeof(CAN_DATA));
can_data.ID = u32_get_can_ID(0x06,MODULE_CMD_REMOTE_CONTROL,desAddr,MODULE_PILE_ADDR); //组帧ID
can_data.Len = 8;
if(s_data != NULL){ //不为空则赋值
//设置状态值
status.raw = s_data->u_dev_state.raw; //除遥控命令外 都初始化好了
status.bits.operationCommand = (U8_T)e_kyType; // Bit3~0: 遥控命令
u16_needVol = s_data->u16_needVol;
u16_needCur = s_data->u16_oneMdu_needCur;
u16_battVol = s_data->u16_battVol;
#if( MDU_PARA_READ_EN == 1) //模块参数读取使能
if(u16_needVol > s_mdu_data.u16_mduPara_MaxOutVol && s_mdu_data.u16_mduPara_MaxOutVol != 0)
u16_needVol = s_mdu_data.u16_mduPara_MaxOutVol;
else if (u16_needVol < s_mdu_data.u16_mduPara_MinOutVol && s_mdu_data.u16_mduPara_MinOutVol != 0)
u16_needVol = s_mdu_data.u16_mduPara_MinOutVol;
if(u16_battVol > s_mdu_data.u16_mduPara_MaxOutVol && s_mdu_data.u16_mduPara_MaxOutVol != 0)
u16_battVol = s_mdu_data.u16_mduPara_MaxOutVol;
else if (u16_battVol < s_mdu_data.u16_mduPara_MinOutVol && s_mdu_data.u16_mduPara_MinOutVol != 0)
u16_battVol = s_mdu_data.u16_mduPara_MinOutVol;
if(u16_needCur > s_mdu_data.u16_mduPara_MaxOutCur && s_mdu_data.u16_mduPara_MaxOutCur != 0)
u16_needCur = s_mdu_data.u16_mduPara_MaxOutCur;
else if (u16_needCur < s_mdu_data.u16_mduPara_MinOutCur && s_mdu_data.u16_mduPara_MinOutCur != 0)
u16_needCur = s_mdu_data.u16_mduPara_MinOutCur;
#endif
}
else{ //为空则清零
status.raw = 0;
status.bits.operationCommand = (U8_T)e_kyType; // Bit3~0: 遥控命令
u16_needVol = 0;
u16_needCur = 0;
u16_battVol = 0;
}
can_data.Data[0] = status.raw;
can_data.Data[1] = GrpID;
Temp.word = u16_needVol;
can_data.Data[2] = Temp.byte.ucLow; //设定电压
can_data.Data[3] = Temp.byte.ucHi;
Temp.word = u16_needCur*10;
can_data.Data[4] = Temp.byte.ucLow; //需求电流
can_data.Data[5] = Temp.byte.ucHi;
Temp.word = u16_battVol;
can_data.Data[6] = Temp.byte.ucLow; //电池电压
can_data.Data[7] = Temp.byte.ucHi;
v_MduCanMsg_send(&can_data);
}
#endif
#if 1 //f发送相关
/**
* ************************************************************************
* @brief -检查模块分组模式 如不是动态分组模块。则改为动态分组模式
*
*
*
* @author jiankalka
* @date 2025-07-03
* ************************************************************************
*/
void v_mdu_group_mode_check()
{
U8_T i,u8_mdu_num = s_mdu_data.u8_mdu_num; //模块数量
for(i=0;i<u8_mdu_num;i++)
{
if(s_mdu_data.s_mdu[i].s_state.e_state == E_MDU_STATE_NONE) //此处没模块
continue;
if(s_mdu_data.s_mdu[i].s_state.u8_GrpMode == 0) //固定分组
v_mdu_send_setGroupMode(i,2); //修改为动态分组
}
}
/**
* ************************************************************************
* @brief -模块分组情况检查,检查模块分组组号是否正确
*
*
*
* @author jiankalka
* @date 2025-07-03
* ************************************************************************
*/
void v_mdu_group_check()
{
U8_T i;
S_MDU_CTRL *s_mdu_ctrl = NULL; //模块控制
S_MDU_STATE *s_mdu_state = NULL; //模块状态
for ( i = 0; i < s_mdu_data.u8_mdu_num; i++) //遍历所有模块
{
s_mdu_ctrl = &s_mdu_data.s_mdu[i].s_ctrl; //i号模块 控制数据结构体
s_mdu_state = &s_mdu_data.s_mdu[i].s_state; //i号模块 状态数据结构体
if(s_mdu_ctrl->u8_mdu_in_pile == 0){ //清空模块归属 检查模块运行状态后清空
if(s_mdu_state->u8_groupNo != 0){
if(s_mdu_state->e_work_state == E_MDU_WORK) //模块工作中 发送停止充电命令 -
v_mdu_send_RemoteCtlr(SEND_MODE_UNICAST,i, MDU_YK_STOP, NULL); //单播控制 控制模块停止(清除分组)
else
v_mdu_send_setGroupId(i,0,0); //模块未工作 清空分组
}
}
else if(s_mdu_state->u8_groupNo != s_mdu_ctrl->u8_mdu_in_pile ) //模块状态与设置分组不一致 则设置模块分组
{
v_mdu_send_setGroupId(i,s_mdu_ctrl->u8_mdu_in_pile,1);
}
}
}
/**
* ************************************************************************
* @brief -模块数据汇总 用于统计 模块在用数量、剩余可用数量、组内模块数量、模块组输出电压、输出电流等信息,获取模块的控制的数据
*
*
*
* @author jiankalka
* @date 2025-07-18
*
*
*
* ************************************************************************
*/
void v_mdu_data_summ()
{
U8_T i,u8_groupNo;
S_MDU_GROUP_DATA *s_mdu_group = NULL; //模块组数据
U8_T u8_gunState[GUN_MAX_CNT];
for ( i = 0; i < s_mdu_data.u8_mdu_group_num; i++) //遍历所有模块组 获取数据
{
s_mdu_group = &s_mdu_data.s_mdu_group[i]; //获取i模块组数据结构体
memset(s_mdu_group , 0 ,sizeof(S_MDU_GROUP_DATA)); //清空
s_mdu_group->u_yk_dev_state.bits.mainContactor = u16_mdu_get_charge_need(i, E_MDU_GET_DATA_MAIN_KY); //主回路接触器状态 - 组内模块 有一个继电器没闭合 就是断开的
s_mdu_group->u_yk_dev_state.bits.powerContactor =u16_mdu_get_charge_need(i, E_MDU_GET_DATA_POWER_KY); //功率回路接触器状 - 组内模块 有一个继电器没闭合 就是断开的
s_mdu_group->u16_needVol = u16_mdu_get_charge_need(i, E_MDU_GET_DATA_NEED_VOL); //需求电压 0.1V
s_mdu_group->u16_oneMdu_needCur = u16_mdu_get_charge_need(i, E_MDU_GET_DATA_NEED_CUR_ONE); //需求电流 0.1A
s_mdu_group->u16_battVol = u16_mdu_get_charge_need(i, E_MDU_GET_DATA_BAAT_VOL); //电池电压 0.1V
if(s_mdu_group->u16_needVol > 5000) //500V 为高压
s_mdu_group->u_yk_dev_state.bits.voltageRange = 1;
u8_gunState[i] = u16_mdu_get_charge_need(i, E_MDU_GET_DATA_GUN_CMD) ; //枪状态 0无 1快速启机 2快速启机停(不清空分组) 3软启开机 4充电停止(清空分组)
}
//更新可用模块数量 在用模块数量信息
s_mdu_data.u8_mdu_usable_num = 0;
s_mdu_data.u8_mdu_using_num = 0;
for ( i = 0; i < s_mdu_data.u8_mdu_num; i++) //遍历所有模块
{
//更新模块控制信息
s_mdu_data.s_mdu[i].s_ctrl.u8_mdu_in_pile = u16_mdu_get_charge_need(i,E_MDU_GET_DATA_IN_PILE_ID ); //模块对应开关闭合标志
s_mdu_data.s_mdu[i].s_ctrl.u8_swh_flag = s_mdu_data.s_mdu[i].s_ctrl.e_mdu_start_flag;//u16_mdu_get_charge_need(i,E_MDU_GET_DATA_SHW_ON_FLAG); //模块归属终端号
if(s_mdu_data.s_mdu[i].s_ctrl.u8_mdu_in_pile != 0)
{
U8_T u8_inGun = s_mdu_data.s_mdu[i].s_ctrl.u8_mdu_in_pile - 1;
if(u8_gunState[u8_inGun] == 1 || u8_gunState[u8_inGun] == 3) //终端启动 则控制启动
s_mdu_data.s_mdu[i].s_ctrl.e_mdu_start_flag = (E_CMD)1; //模块启停状态
else
s_mdu_data.s_mdu[i].s_ctrl.e_mdu_start_flag = (E_CMD)0;
}
if(s_mdu_data.s_mdu[i].s_state.e_state == E_MDU_STATE_NORMAL) //通信正常 且不是故障
{
s_mdu_data.u8_mdu_usable_num ++;
if(s_mdu_data.s_mdu[i].s_ctrl.u8_mdu_in_pile != 0) //模块已分配
s_mdu_data.u8_mdu_using_num ++;
}
//更新模块组运行模块数量、输出电压、输出电流等数据
u8_groupNo = s_mdu_data.s_mdu[i].s_state.u8_groupNo; //获取模块组号
if(u8_groupNo != 0 && u8_groupNo <= GUN_MAX_CNT) //模块组号不为0 且组号在枪数量范围内
{
s_mdu_data.s_mdu_group[u8_groupNo-1].u8_on_group_num++;
if(s_mdu_data.s_mdu[i].s_state.e_work_state == 1) //组内有一个模块工作 则状态为工作
s_mdu_data.s_mdu_group[u8_groupNo-1].u8_work_state = 1;
if(s_mdu_data.s_mdu_group[u8_groupNo-1].u16_outVol < NUM_500 && //如果模块组输出电压未赋值
s_mdu_data.s_mdu[i].s_ctrl.u8_swh_flag == 1) //且 模块对应继电器回路已经闭合 则赋值模块组电压
{
s_mdu_data.s_mdu_group[u8_groupNo-1].u16_outVol = s_mdu_data.s_mdu[i].s_state.u16_outVol;
}
s_mdu_data.s_mdu_group[u8_groupNo-1].u16_outCur += s_mdu_data.s_mdu[i].s_state.u16_outCur; //组内模块输出电流累加
}
}
}
/**
* ************************************************************************
* @brief - 检查组内模块运行状态 ;检查该组号下模块的启停情况,若有一模块未启动,则下发启动命令
* 当模块启动标志为1,模块运行状态为0或者 回路继电器闭合标志为0 则需要启动;当模块启动状态为0,模块运行状态为1时,则控制停止
*
* @param[in] u8_group - 组号
*
* @return S8_T - 0 没有模块需要控制 >0 该起没起的第一个模块号 <0 该停没停的第一个模块号;例如返回2,表示存在该起未起的模块,模块号为2;返回-2,表示存在该停未停的模块,模块号为2;
*
* @author jiankalka
* @date 2025-07-07
* ************************************************************************
*/
S8_T s8_mdu_check_grp_running(U8_T u8_group)
{
S8_T s8_res = 0;
U8_T i;
S_MDU_CTRL *s_mdu_ctrl = NULL; //模块控制
S_MDU_STATE *s_mdu_state = NULL; //模块状态
for ( i = 0; i < s_mdu_data.u8_mdu_num; i++) //遍历所有模块
{
s_mdu_ctrl = &s_mdu_data.s_mdu[i].s_ctrl; //i号模块 控制数据结构体
s_mdu_state = &s_mdu_data.s_mdu[i].s_state; //i号模块 状态数据结构体
if(s_mdu_state->u8_groupNo == u8_group) //如果模块归属该枪
{
if(s_mdu_ctrl->e_mdu_start_flag ==1 && (s_mdu_state->e_work_state ==0 || s_mdu_ctrl->u8_swh_flag == 0)) //控起未起 模块启动标志为1,模块运行状态为0或者 回路继电器闭合标志为0 则需要启动
{
s8_res = i+1;
break;
}
else if(s_mdu_ctrl->e_mdu_start_flag ==0 &&s_mdu_state->e_work_state ==1) //控停未停
{
s8_res = -i-1;
break;
}
}
}
return s8_res;
}
/**
* ************************************************************************
* @brief -模块遥控指令发送 周期发送遥控指令 250ms一个周期
*
*
*
* @author jiankalka
* @date 2025-07-03
* ************************************************************************
*/
void v_mdu_remote_control_send()
{
U8_T gunNo,u8_gunState;
S8_T s8_mduNo;
S_MDU_RemoteCtlrData s_RemoteCtlrData; //遥控命令数据 包含两个接触器状态 和 需求电压、需求电流、电池电压 精度0.1
S_MDU_GROUP_DATA *s_mdu_group = NULL; //模块组数据
v_mdu_data_summ(); //模块和模块组信息更新
for (gunNo = 0; gunNo < s_mdu_data.u8_mdu_group_num; gunNo++) //变量所有模块组状态 /枪状态
{
memset(&s_RemoteCtlrData, 0, sizeof(S_MDU_RemoteCtlrData));
s_mdu_group = &s_mdu_data.s_mdu_group[gunNo]; //获取i模块组数据结构体
if(s_mdu_group->u8_on_group_num == 0) //归属于本枪的模块数量为0 不发送遥控指令;模块组为0,模块未停止情况 在模块数据检查中处理
continue;
s_RemoteCtlrData.u_dev_state.raw = s_mdu_group->u_yk_dev_state.raw; //设备状态
s_RemoteCtlrData.u16_needVol = s_mdu_group->u16_needVol;
s_RemoteCtlrData.u16_battVol = s_mdu_group->u16_battVol;
s_RemoteCtlrData.u16_oneMdu_needCur = s_mdu_group->u16_oneMdu_needCur;
u8_gunState = u16_mdu_get_charge_need(gunNo, E_MDU_GET_DATA_GUN_CMD) ; //枪状态 0无 1快速启机 2快速启机停(不清空分组) 3软启开机 4充电停止(清空分组)
#if 1 //双枪母联使用 直接按组控
switch (u8_gunState)
{
case 1: //枪状态 1快速启机
{
//检测该组内模块启动状态 - 未启动 则控制启动,启动则修改参数
s8_mduNo = s8_mdu_check_grp_running(gunNo+1);
if(s8_mduNo > 0) //检测该组内模块启动状态 - 未启动 则控制启动;都已经启动,发送参数修改
v_mdu_send_RemoteCtlr(SEND_MODE_BROADCAST,gunNo+1,MDU_YK_FASTBOOT,&s_RemoteCtlrData); //快速启机
else
v_mdu_send_RemoteCtlr(SEND_MODE_BROADCAST,gunNo+1,MDU_YK_SETPARA,&s_RemoteCtlrData); //参数修改
}
break;
case 2: //枪状态 2快速启机停
{
v_mdu_send_RemoteCtlr(SEND_MODE_BROADCAST,gunNo+1, MDU_YK_STOP_SUSPEND, NULL); //广播命令, 快速启动停止、
}
break;
case 3: //枪状态 3软启开机
{
//检测该组内模块启动状态 - 未启动 则控制启动,启动则修改参数
s8_mduNo = s8_mdu_check_grp_running(gunNo+1);
if(s8_mduNo > 0) //检测该组内模块启动状态 - 未启动 则控制启动;都已经启动,发送参数修改
v_mdu_send_RemoteCtlr(SEND_MODE_BROADCAST,gunNo+1,MDU_YK_SOFTSTART,&s_RemoteCtlrData); //快速启机
else
v_mdu_send_RemoteCtlr(SEND_MODE_BROADCAST,gunNo+1,MDU_YK_SETPARA,&s_RemoteCtlrData); //参数修改
}
break;
case 0: //枪状态 0无
case 4: //枪状态 4软停
{
if(s_mdu_group->u16_outVol > NUM_500) //组内输出电压 大于5V 则发送停止命令;否则不执行
v_mdu_send_RemoteCtlr(SEND_MODE_BROADCAST,gunNo+1, MDU_YK_STOP, NULL); //广播命令, 快速启动停止、
}
break;
}
#endif
#if 0
switch (u8_gunState)
{
case 1: //枪状态 1快速启机
{
//检测该组内模块启动状态 - 未启动 则控制启动,启动则修改参数
s8_mduNo = s8_mdu_check_grp_running(gunNo+1);
if(s8_mduNo > 0) //检测该组内模块启动状态 - 未启动 则控制启动;都已经启动,发送参数修改
v_mdu_send_RemoteCtlr(SEND_MODE_BROADCAST,gunNo+1,MDU_YK_FASTBOOT,&s_RemoteCtlrData); //快速启机
else
v_mdu_send_RemoteCtlr(SEND_MODE_BROADCAST,gunNo+1,MDU_YK_SETPARA,&s_RemoteCtlrData); //参数修改
}
break;
case 2: //枪状态 2快速启机停
{
v_mdu_send_RemoteCtlr(SEND_MODE_BROADCAST,gunNo+1, MDU_YK_STOP_SUSPEND, NULL); //广播命令, 快速启动停止、
}
break;
case 3: //枪状态 3软启开机
s8_mduNo = s8_mdu_check_grp_running(gunNo+1);
if(s8_mduNo > 0) //检测该组内模块启动状态 - 有该起没起的,控制启动;有该停没停的,控制停止;不需要操作的,发送参数修改广播
{
//单点其余正常使用模块 参数修改
for(j=0;j<s_mdu_data.u8_mdu_num;j++)
{
s_mdu_state = &s_mdu_data.s_mdu[j].s_state;
if(s_mdu_state->u8_groupNo == gunNo+1 && //模块归属本枪
s_mdu_state->u16_outVol > NUM_500 && //模块输出电压大于5V
j!=(-s8_mduNo-1)) //不为控制停止的模块
{
v_mdu_send_RemoteCtlr(SEND_MODE_UNICAST,j,MDU_YK_SETPARA,&s_RemoteCtlrData); //参数修改
}
}
if(s_mdu_group->u16_outVol > NUM_500) //组内输出电压 大于50V 则使用组内输出电压控制模块启动;否则则按需求启动
{
s_RemoteCtlrData.u16_needVol = s_mdu_group->u16_outVol;
s_RemoteCtlrData.u16_battVol = s_mdu_group->u16_outVol;
s_RemoteCtlrData.u16_oneMdu_needCur = NUM_5;
}
//单点控制启动的模块 启动
if(s_mdu_data.s_mdu[s8_mduNo-1].s_state.e_work_state == 0)
v_mdu_send_RemoteCtlr(SEND_MODE_UNICAST,s8_mduNo-1,MDU_YK_SOFTSTART,&s_RemoteCtlrData); //软启开机
else
v_mdu_send_RemoteCtlr(SEND_MODE_UNICAST,s8_mduNo-1,MDU_YK_SETPARA,&s_RemoteCtlrData); //软启开机
}
else if(s8_mduNo < 0)
{
//单点控停的模块 停止
v_mdu_send_RemoteCtlr(SEND_MODE_UNICAST,-s8_mduNo-1,MDU_YK_STOP_SUSPEND,&s_RemoteCtlrData);
//单点其余正常使用模块 参数修改
for(j=0;j<s_mdu_data.u8_mdu_num;j++)
{
s_mdu_state = &s_mdu_data.s_mdu[j].s_state;
if(s_mdu_state->u8_groupNo == gunNo+1 && //模块归属本枪
s_mdu_state->u16_outVol > NUM_500 && //模块输出电压大于5V
j!=(-s8_mduNo-1)) //不为控制停止的模块
{
v_mdu_send_RemoteCtlr(SEND_MODE_UNICAST,j,MDU_YK_SETPARA,&s_RemoteCtlrData); //参数修改
}
}
}
else
v_mdu_send_RemoteCtlr(SEND_MODE_BROADCAST,gunNo+1,MDU_YK_SETPARA,&s_RemoteCtlrData); //参数修改
break;
case 0: //枪状态 0无
case 4: //枪状态 4软停
{
if(s_mdu_group->u16_outVol > NUM_500) //组内输出电压 大于5V 则发送停止命令;否则不执行
v_mdu_send_RemoteCtlr(SEND_MODE_BROADCAST,gunNo+1, MDU_YK_STOP, NULL); //广播命令, 快速启动停止、
}
break;
default:
break;
}
#endif
}
}
/**
* ************************************************************************
* @brief -模块参数获取 - 自动查询第一个模块的
*
*
*
* @author jiankalka
* @date 2025-07-22
* ************************************************************************
*/
void v_mdu_para_check()
{
U8_T i,type,u8_mdu_num = s_mdu_data.u8_mdu_num; //模块数量
if(s_mdu_data.u16_mduPara_MaxOutVol == 0xFF){
type = 0;
}
else if(s_mdu_data.u16_mduPara_MinOutVol == 0xFF){
type = 1;
}
else if(s_mdu_data.u16_mduPara_MaxOutCur == 0xFF){
type = 2;
}
else if(s_mdu_data.u16_mduPara_MinOutCur == 0xFF){
type = 3;
}
else
return;
for(i=0;i<u8_mdu_num;i++)
{
if(s_mdu_data.s_mdu[i].s_state.e_state == E_MDU_STATE_NONE) //此处没模块
continue;
v_mdu_send_getMduPara(i , type);
break;
}
}
/**
* ************************************************************************
* @brief -模块通信发送控制函数
*
*
*
* @author jiankalka
* @date 2025-07-03
* ************************************************************************
*/
void v_mdu_comm_send_ctrl(U16_T u16_sleepTime)
{
if(s_mdu_data.u16_timer % NUM_2000 == 0) //2秒
{
v_mdu_send_Heartbeat(); //心跳帧发送
v_mdu_group_mode_check(); //检查模块分组模块 不是动态分组,改为动态分组
#if( MDU_TEMP_READ_EN == 1)
v_mdu_temp_read(); //充电模块温度读取,广播读取,2S一次
#endif
}
if(s_mdu_data.u16_timer % NUM_250 == 0) //250ms
{
v_mdu_group_check(); //模块分组检查
v_mdu_remote_control_send(); //模块遥控发送
#if( MDU_PARA_READ_EN == 1) //模块参数读取使能
v_mdu_para_check(); //获取模块最大最小输出电压 电流参数
#endif
}
}
#endif
U16_T test_cnt = 0;
#if 1 //报文接收解析
void v_mdu_rx_unpack(CAN_DATA *rxMsg)
{
U8_T u8_cmd, u8_oriAddr,u8_desAddr, u8_boxid;
U16_T u16_data; //临时变量 使用时注意赋值
WordAlign temp; //临时变量 使用时注意赋值
S_MDU_STATE *s_mdu_state = NULL;
/* 抢连接/DI 状态:交给 STM 状态通信模块解析(ID 0x1801AABB */
#if (GUN_LINK_COMM_EN)
if (u8_stm_gb_enable() && u8_stm_status_can_rx(rxMsg))
return;
#endif
if(u8_can_ID_unpack(rxMsg->ID, NULL , &u8_cmd, &u8_desAddr , &u8_oriAddr) == 0) //解析帧id
return;
if(u8_desAddr != MODULE_PILE_ADDR) //判断目的地址是否一致
return;
u8_boxid = u8_oriAddr - MODULE_MDU_FIRST_ADDR ; //充电模块号;
if(u8_boxid > s_mdu_data.u8_mdu_num || u8_boxid > MDU_MAX_NUM) //地址范围合法性判断
return;
s_mdu_state = &s_mdu_data.s_mdu[u8_boxid].s_state; //获取模块状态
s_mdu_state->u16_outtimecnt = 0; //超时计数 清零
switch(u8_cmd)
{
case MODULE_CMD_HEARTBEAT_ACK: //0x41 心跳应答 广播心跳不应答
{
return;
}
case MODULE_CMD_YXYC_20: //0x20 遥信遥测 0x20帧
{
s_mdu_state->u8_GrpMode = ISBITSET(rxMsg->Data[0],3); //模块分组模式 0固定分组 1动态分组
if(ISBITSET(rxMsg->Data[0],4) || ISBITSET(rxMsg->Data[0],5)) //故障状态 或者告警状态置一
{
if(s_mdu_state->e_state != E_MDU_STATE_NONE)
s_mdu_state->e_state = E_MDU_STATE_FAULT; //故障状态
}
else
{
if(s_mdu_state->e_state == E_MDU_STATE_FAULT)
s_mdu_state->e_state = E_MDU_STATE_NONE;
}
if (ISBITSET(rxMsg->Data[0],7)) //工作状态,1待机,2工作
s_mdu_state->e_work_state = E_MDU_WORK;
else
s_mdu_state->e_work_state = E_MDU_IDLE;
temp.byte.ucLow = rxMsg->Data[2];
temp.byte.ucHi = rxMsg->Data[3];
s_mdu_state->u16_outVol = temp.word; //直流输出电压 0.1V
temp.byte.ucLow= rxMsg->Data[4];
temp.byte.ucHi = rxMsg->Data[5];
s_mdu_state->u16_outCur = temp.word/10; //直流输出电流 0.1A
s_mdu_state->u8_groupNo = rxMsg->Data[6]; //组号
s_mdu_state->u_alarm_data.bit_mdu_alarm.b0_other = ISBITSET(rxMsg->Data[1],0); //其他故障,0正常,1故障
s_mdu_state->u_alarm_data.bit_mdu_alarm.b1_relief = ISBITSET(rxMsg->Data[1],1); //泄放故障
s_mdu_state->u_alarm_data.bit_mdu_alarm.b2_fan = ISBITSET(rxMsg->Data[1],2); //风扇故障
s_mdu_state->u_alarm_data.bit_mdu_alarm.b3_DC_short = ISBITSET(rxMsg->Data[1],3); //直流输出短路
s_mdu_state->u_alarm_data.bit_mdu_alarm.b4_overTemp = ISBITSET(rxMsg->Data[1],4); //过温
s_mdu_state->u_alarm_data.bit_mdu_alarm.b5_DC_UV = ISBITSET(rxMsg->Data[1],5); //直流输出欠压
s_mdu_state->u_alarm_data.bit_mdu_alarm.b6_DC_OV = ISBITSET(rxMsg->Data[1],6); //直流输出过压
s_mdu_state->u_alarm_data.bit_mdu_alarm.b7_AC_IN = ISBITSET(rxMsg->Data[1],7); //交流输入故障
return;
}
case MODULE_CMD_YXYC_21: //0x21 遥信遥测 0x21帧
{
return;
}
case MODULE_CMD_SETTING_ACK: //0x81 //定值设置应答
{
return;
}
case MODULE_CMD_GETTING_ACK: //0x83 //定值查询应答
{
#if( MDU_PARA_READ_EN == 1) //模块参数读取使能
// 01 02 08 00 00 04 60 11 ; 02 00 80 10 27 36 01
if(rxMsg->Data[0] == 1){ //首包
memset(&s_mdu_data.u8_recv_most_pack[0] , 0 , 20); //清空多包解析缓存区
memcpy(&s_mdu_data.u8_recv_most_pack[0] , &rxMsg->Data[1] , 7); //将数据包存入缓存区
}
else if(rxMsg->Data[0] == 2){
memcpy(&s_mdu_data.u8_recv_most_pack[7] , &rxMsg->Data[1] , 7); //将数据包存入缓存区
if(s_mdu_data.u8_recv_most_pack[0] == 0x02 //报文总帧数
&& s_mdu_data.u8_recv_most_pack[1] == 0x08 //报文数量
&& s_mdu_data.u8_recv_most_pack[8] == 0x80) //解析成功标志
{
if(u16_crc_checksum(&s_mdu_data.u8_recv_most_pack[0] , 11) == \
(s_mdu_data.u8_recv_most_pack[11] + (s_mdu_data.u8_recv_most_pack[12] <<8)))
{
u16_data = s_mdu_data.u8_recv_most_pack[9] + (s_mdu_data.u8_recv_most_pack[10] <<8);
if(s_mdu_data.u8_recv_most_pack[6] == 17) //最大输出电压 0.1V
{
s_mdu_data.u16_mduPara_MaxOutVol = u16_data;
}
else if(s_mdu_data.u8_recv_most_pack[6] == 18) //最小输出电压 0.1V
{
s_mdu_data.u16_mduPara_MinOutVol = u16_data;
}
else if(s_mdu_data.u8_recv_most_pack[6] == 19) //最大输出电流 0.01A
{
s_mdu_data.u16_mduPara_MaxOutCur = u16_data / 10;
}
else if(s_mdu_data.u8_recv_most_pack[6] == 20) //最小输出电流 0.01A
{
s_mdu_data.u16_mduPara_MinOutCur = u16_data / 10;
}
}
}
}
#endif
return;
}
case MODULE_CMD_TEMP: //0xE6 模块温度查询解帧
{
u16_data = GetU16Data(rxMsg->Data[1],rxMsg->Data[0]);
s_mdu_state->s8_mdutemp_1 = (S8_T)(u16_data - MODULE_TEMP_OFFSET); //进风口温度,报文解析数据减去偏移量为模块温度
u16_data = GetU16Data(rxMsg->Data[3],rxMsg->Data[2]);
s_mdu_state->s8_mduPara_2 = (S8_T)(u16_data - MODULE_TEMP_OFFSET); //模块PFC温度;
return;
}
default:
return;
}
}
/**
* ************************************************************************
* @brief -模块通信接收解包函数
*
*
*
* @author jiankalka
* @date 2025-07-03
* ************************************************************************
*/
void v_mdu_comm_recv_unpack()
{
U8_T i, canRcvCnt = 0; //接收can报文数目
CAN_DATA rx_can_data[CAN_RECV_BUF_SIZE] = {0};
canRcvCnt= u8_MduCanMsg_recv(&rx_can_data[0]);
//DEBUG_LOG("fdcan1 recv num = %d\n",ret);
for (i = 0; i < canRcvCnt; i++)
{
v_mdu_rx_unpack(&rx_can_data[i]);
test_cnt++;
}
}
#endif
/**
* ************************************************************************
* @brief - 清空模块接收数据内容
*
* @param[in] u8_id - 模块id 0-N ,当为0xFF时 清空所有模块接收数据--除去非接收数据 例如超时计数值\模块状态
*
*
* @author jiankalka
* @date 2025-09-17
* ************************************************************************
*/
void v_mdu_clear_recv_data(U8_T u8_id)
{
U8_T i,u8_mdu_num = s_mdu_data.u8_mdu_num; //模块数量
S_MDU_STATE *s_mdu_state = NULL;
for(i=0;i<u8_mdu_num;i++)
{
s_mdu_state = &s_mdu_data.s_mdu[i].s_state; //获取模块状态
if(u8_id == MODULE_ALL || //清空所有模块故障内容
u8_id == i)
{
s_mdu_state->e_work_state = E_MDU_IDLE; //模块工作状态 空闲、工作
s_mdu_state->u8_groupNo = 0; //模块组号
s_mdu_state->u8_GrpMode = 0; //分组模式:【遥测分组模式:0固定分组,1动态分组】
s_mdu_state->u16_outVol = 0; //输出电压 精度0.1
s_mdu_state->u16_outCur = 0; //输出电流 精度0.1
s_mdu_state->u_alarm_data.u8_mdu_alarm = 0; //故障告警数据 0x20 遥信遥测帧上送
//模块温度读取使能
#if( MDU_TEMP_READ_EN == 1)
s_mdu_state->s8_mdutemp_1 = 0; //模块温度1 进风口温度 单位摄氏度 注意有正负号 范围是 -127 ~ 127
s_mdu_state->s8_mduPara_2 = 0; //模块温度2 模块PFC温度 单位摄氏度 注意有正负号 范围是 -127 ~ 127
#endif
}
}
}
/**
* ************************************************************************
* @brief -模块控制 报文接收超时检查
*
*
*
* @author jiankalka
* @date 2025-07-03
* ************************************************************************
*/
void v_mdu_comm_outtime_cheak(U16_T u16_sleepTime)
{
U8_T i,u8_mdu_num = s_mdu_data.u8_mdu_num; //模块数量
U8_T u8_mdu_comm_err_num = 0; //通信超时模块数量
S_MDU_STATE *s_mdu_state = NULL;
for(i=0;i<u8_mdu_num;i++)
{
s_mdu_state = &s_mdu_data.s_mdu[i].s_state; //获取模块状态
if(s_mdu_state->e_state == E_MDU_STATE_NONE) //模块未通信 判断通信
{
u8_mdu_comm_err_num ++;
if(s_mdu_state->u16_outtimecnt < 10*NUM_1000) //10秒超时
{
s_mdu_state->e_state = E_MDU_STATE_NORMAL; //通信正常
Mdu_Comm_LOG("(%d)号充电模块通讯正常\n",i);
}
v_mdu_set_comm_fault_info(i,1); //故障动作触发
}
else{ //模块已通信 判断超时
s_mdu_state->u16_outtimecnt += u16_sleepTime; //超时计数递增
if(s_mdu_state->u16_outtimecnt > 20*NUM_1000) //10秒超时
{
s_mdu_state->e_state = E_MDU_STATE_NONE;
v_mdu_clear_recv_data(i);
Mdu_Comm_LOG("(%d)号充电模块通讯超时\n",i);
}
else
{
}
v_mdu_set_comm_fault_info(i,0); //故障恢复触发
}
}
if(u8_mdu_comm_err_num == u8_mdu_num) //所有模块通信故障
{
v_mdu_set_comm_fault_info(MODULE_ALL,1); //故障恢复触发
}
else
{
v_mdu_set_comm_fault_info(MODULE_ALL,0); //故障恢复触发
}
}
static void v_mdu_clear_outtime()
{
U8_T i,u8_mdu_num = s_mdu_data.u8_mdu_num; //模块数量
for(i=0;i<u8_mdu_num;i++)
{
v_mdu_set_comm_fault_info(i,0); //故障恢复触发
}
v_mdu_set_comm_fault_info(MODULE_ALL,0); //故障恢复触发
}
/**
* ************************************************************************
* @brief - 国网三统一协议控制动作
*
*
*
* @author jiankalka
* @date 2025-11-12
* ************************************************************************
*/
static void v_mdu_comm_gw_action(U16_T u16_leep_time)
{
U16_T u16_runing_flag;
static U8_T u8_spican_init_flag = 0;
v_mdu_comm_recv_unpack(); //报文接收解包;
//获取模块任务运行标志 0模块任务不运行并清空模块数据 1模块任务运行-执行报文收发和超时判断
u16_runing_flag = u16_mdu_get_charge_need(0, E_MDU_GET_DATA_RUNING_FLAG);
if(u16_runing_flag == 1)
{
v_mdu_comm_send_ctrl(u16_leep_time); //报文发送控制
v_mdu_comm_outtime_cheak(u16_leep_time); //报文接收超时检查
if(u8_spican_init_flag == 0) //上电第一次运行到此处,且模块任务运行标志为1,说明模块任务启动了,但SPICAN未必初始化成功,此时强制初始化一次SPICAN,避免因SPICAN初始化失败导致的通信问题;后续如果SPICAN初始化成功了,这个标志就不会再被置0了
{
// CANSPI_HealthCheckAndRecover(1U);
u8_spican_init_flag = 1;
}
}
else
{
u8_spican_init_flag = 0; //模块任务不运行,SPICAN初始化标志复位,等待下次模块任务启动时再次强制初始化SPICAN
s_mdu_data.u32_runing_time = get_current_seconds();
v_mdu_clear_recv_data(MODULE_ALL); //清空所有模块接收数据
v_mdu_clear_outtime(); //清空所有模块故障告警
}
if(s_mdu_data.u16_timer < 0xFF00) //因为在
s_mdu_data.u16_timer += u16_leep_time; //计数周期累加
else
s_mdu_data.u16_timer = 0;
/* 辅源控制 CAN 帧:利用 s_mdu_data.u16_timer,每 1000ms 发送一次 */
#if (GUN_LINK_COMM_EN)
if (u8_stm_gb_enable() && (s_mdu_data.u16_timer % NUM_1000 == 0))
{
v_stm_status_can_send_aux_frame();
}
#endif
/* 周期性 SPI-CAN 健康检查:独立于模块通信超时运行 */
// if (s_mdu_data.u16_timer % NUM_1000 == 0)
// {
// (void)CANSPI_HealthCheckAndRecover(0U);
// }
}
void v_Mdu_Comm_task_init()
{
U8_T i;
memset(&s_mdu_data, 0 , sizeof(S_MDU_DATA)); //清空 模块结构体
s_mdu_data.u8_mdu_num = u16_mdu_get_charge_need(0,E_MDU_GET_DATA_MDU_NUM); //获取模块数量
s_mdu_data.u8_mdu_group_num = u16_mdu_get_charge_need(0,E_MDU_GET_DATA_GUN_NUM); //获取枪数量
s_mdu_data.u8_mdu_type = u16_mdu_get_charge_need(0,E_MDU_GET_DATA_MDU_TYPE); //模块类型 0 三统一 1优优绿能
#if( MDU_PARA_READ_EN == 1) //模块参数读取使能
s_mdu_data.u16_mduPara_MaxOutVol = 0xFF; //默认值为0xFF 便于后续参数获取识别
s_mdu_data.u16_mduPara_MaxOutCur = 0xFF; //默认值为0xFF 便于后续参数获取识别
s_mdu_data.u16_mduPara_MinOutVol = 0xFF; //默认值为0xFF 便于后续参数获取识别
s_mdu_data.u16_mduPara_MinOutCur = 0xFF; //默认值为0xFF 便于后续参数获取识别
#endif
for (i = 0; i < s_mdu_data.u8_mdu_num; i++) //初始化所有模块地址 从0x60开始
{
s_mdu_data.s_mdu[i].u8_mdu_addr = MODULE_MDU_FIRST_ADDR + i; //模块地址范围 0x20 0x9E,0x9F作为广播地址使用
s_mdu_data.s_mdu[i].s_state.u16_outtimecnt = 0xFFFF; //模块默认通信超时
}
}
/**
* ************************************************************************
* @brief -模块通信任务
*
* @param[in] p -线程参数
*
* @author jiankalka
*
* @date 2025-07-02
* ************************************************************************
*/
void v_Mdu_Comm_task(void *arg)
{
uint16_t sleep_time_ms;
uint32_t last_send_time;
uint32_t current_time;
(void)arg;
(void)MDUCOMM_LOCK_INIT();
sleep_time_ms = MDUCOMM_SLEEP_TIME_MS();
last_send_time = get_current_seconds();
v_Mdu_Comm_task_init();
for (;;) {
MDUCOMM_FEED_DOG();
current_time = get_current_seconds();
if ((TASK_RUN_PRINT_TIME != 0U) && (u32_safe_seconds_since(last_send_time) >= TASK_RUN_PRINT_TIME)) {
if (MDUCOMM_LOCK_TAKE() == 1U) {
MDUCOMM_LOG("mdu comm task is runing, sleep time is %ums", sleep_time_ms);
(void)MDUCOMM_LOCK_GIVE();
}
last_send_time = current_time;
}
if(u16_flow_get_sys_data(0, E_FLOW_GET_DATA_PILE_TYPE, 0U) < 2)
{
if(s_mdu_data.u8_mdu_type == 0)
{
v_mdu_comm_gw_action(sleep_time_ms); //国网三统一协议控制
}
else
{
#if MDU_UULN_EN
v_mdu_comm_uuln_action(sleep_time_ms); //优优绿能协议
#endif
}
}
else if(s_mdu_data.u8_mdu_type == 0x02)
{
v_pcm_comm_gw_action(sleep_time_ms); //PCM终端UDP通信协议处理函数(分桩角色)
}
//任务周期延时函数 报文发送时自动延时
if(s_mdu_data.u8_can_send_cnt*MDUCOMM_TASK_ID < sleep_time_ms)
mSleep(sleep_time_ms - s_mdu_data.u8_can_send_cnt*MDUCOMM_TASK_ID);
else
mSleep(sleep_time_ms);
s_mdu_data.u8_can_send_cnt = 0;
}
}