2025-11-20 19:11:56 +08:00
|
|
|
|
#include "bsp_dwt.h"
|
|
|
|
|
|
#include "bsp_fdcan.h"
|
|
|
|
|
|
#include "xidipwmeter.h"
|
2025-11-17 16:27:19 +08:00
|
|
|
|
|
2025-11-20 19:11:56 +08:00
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
2026-02-24 23:47:15 +08:00
|
|
|
|
#include "daemon.h"
|
|
|
|
|
|
|
2026-03-09 01:57:43 +08:00
|
|
|
|
static XidiPowerMeterInstance *power_meter_instance = NULL;
|
2025-11-20 19:11:56 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 功率计数据解码函数
|
2026-03-09 01:57:43 +08:00
|
|
|
|
* @param _instance FDCAN实例指针
|
2025-11-20 19:11:56 +08:00
|
|
|
|
*
|
|
|
|
|
|
* @note 数据格式:
|
|
|
|
|
|
* DATA[0]: 电流数值低8位
|
|
|
|
|
|
* DATA[1]: 电流数值高8位
|
|
|
|
|
|
* DATA[2]: 电压数值低8位
|
|
|
|
|
|
* DATA[3]: 电压数值高8位
|
|
|
|
|
|
* DATA[4]-DATA[7]: 保留
|
|
|
|
|
|
*
|
|
|
|
|
|
* 电压电流数值均为放大100倍后的整数,需要除以100.0得到实际值
|
|
|
|
|
|
*/
|
2026-03-09 01:57:43 +08:00
|
|
|
|
void XidiPowerMeterDecode(FDCANInstance *_instance)
|
2025-11-20 19:11:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (power_meter_instance == NULL)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2026-03-09 01:57:43 +08:00
|
|
|
|
uint8_t *rxbuff = _instance->rx_buff;
|
|
|
|
|
|
XidiPowerMeter_Msg_s *measure = &power_meter_instance->powermeter_msg;
|
2025-11-20 19:11:56 +08:00
|
|
|
|
|
|
|
|
|
|
// 重载守护进程
|
|
|
|
|
|
// if (power_meter_instance->daemon != NULL)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// DaemonReload(power_meter_instance->daemon);
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// 计算时间间隔
|
|
|
|
|
|
measure->dt = DWT_GetDeltaT(&power_meter_instance->feed_cnt);
|
|
|
|
|
|
|
|
|
|
|
|
// 解析电流数据 (放大100倍,需要除以100)
|
2025-11-20 19:26:42 +08:00
|
|
|
|
auto current_raw = (int16_t) ((rxbuff[1] << 8) | rxbuff[0]);
|
2025-11-20 19:11:56 +08:00
|
|
|
|
measure->current = (float) current_raw / 100.0f;
|
|
|
|
|
|
|
|
|
|
|
|
// 解析电压数据 (放大100倍,需要除以100)
|
2025-11-20 19:26:42 +08:00
|
|
|
|
auto voltage_raw = (int16_t) ((rxbuff[3] << 8) | rxbuff[2]);
|
2025-11-20 19:11:56 +08:00
|
|
|
|
measure->voltage = (float) voltage_raw / 100.0f;
|
|
|
|
|
|
|
|
|
|
|
|
// 计算功率
|
|
|
|
|
|
measure->power = measure->voltage * measure->current;
|
|
|
|
|
|
|
|
|
|
|
|
// 计算累计能量 (功率 × 时间)
|
|
|
|
|
|
measure->energy += measure->power * measure->dt * 0.001f; // dt单位是ms,转换为秒
|
|
|
|
|
|
|
|
|
|
|
|
measure->update_cnt++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 功率计丢失回调函数
|
|
|
|
|
|
* @param power_meter_ptr 功率计实例指针
|
|
|
|
|
|
*/
|
2026-03-09 01:57:43 +08:00
|
|
|
|
void XidiPowerMeterLostCallback(void *power_meter_ptr)
|
2025-11-20 19:11:56 +08:00
|
|
|
|
{
|
2026-03-09 01:57:43 +08:00
|
|
|
|
XidiPowerMeterInstance *power_meter = (XidiPowerMeterInstance *) power_meter_ptr;
|
2025-11-20 19:11:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 功率计初始化
|
2026-03-09 01:57:43 +08:00
|
|
|
|
* @param XidiPowerMeter_config 功率计初始化配置结构体指针 (必须确保其生命周期是全局或静态的)
|
|
|
|
|
|
* @return XidiPowerMeterInstance* 功率计实例指针
|
2025-11-20 19:11:56 +08:00
|
|
|
|
*/
|
2026-03-09 01:57:43 +08:00
|
|
|
|
XidiPowerMeterInstance *XidiPowerMeterInit(XidiPowerMeter_Init_Config_s *XidiPowerMeter_config)
|
2025-11-20 19:11:56 +08:00
|
|
|
|
{
|
2026-03-09 01:57:43 +08:00
|
|
|
|
// 1. 检查是否已经初始化
|
2025-11-20 19:11:56 +08:00
|
|
|
|
if (power_meter_instance != NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
return power_meter_instance;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-09 01:57:43 +08:00
|
|
|
|
// 2. 分配内存并清零
|
|
|
|
|
|
power_meter_instance = (XidiPowerMeterInstance *)malloc(sizeof(XidiPowerMeterInstance));
|
2025-11-20 19:11:56 +08:00
|
|
|
|
if (power_meter_instance == NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
2026-03-09 01:57:43 +08:00
|
|
|
|
memset(power_meter_instance, 0, sizeof(XidiPowerMeterInstance));
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 配置并注册 FDCAN 实例
|
|
|
|
|
|
// (rx_id, tx_id, can_handle 等参数由外部 config 提供,这里只绑定回调和私有指针)
|
|
|
|
|
|
XidiPowerMeter_config->can_config.can_module_callback = XidiPowerMeterDecode;
|
|
|
|
|
|
XidiPowerMeter_config->can_config.id = power_meter_instance;
|
|
|
|
|
|
|
|
|
|
|
|
power_meter_instance->fdcan_ins = CANRegister(&XidiPowerMeter_config->can_config);
|
|
|
|
|
|
if (power_meter_instance->fdcan_ins == NULL)
|
2025-11-20 19:11:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
free(power_meter_instance);
|
|
|
|
|
|
power_meter_instance = NULL;
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-09 01:57:43 +08:00
|
|
|
|
// 4. 配置并注册 守护进程
|
|
|
|
|
|
// (reload_count 等参数由外部 config 提供,这里只绑定回调和私有指针)
|
|
|
|
|
|
XidiPowerMeter_config->daemon_config.callback = XidiPowerMeterLostCallback;
|
|
|
|
|
|
XidiPowerMeter_config->daemon_config.owner_id = power_meter_instance;
|
|
|
|
|
|
|
|
|
|
|
|
power_meter_instance->daemon = DaemonRegister(&XidiPowerMeter_config->daemon_config);
|
2025-11-20 19:11:56 +08:00
|
|
|
|
|
|
|
|
|
|
return power_meter_instance;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取电压值
|
|
|
|
|
|
* @param power_meter 功率计实例指针
|
|
|
|
|
|
* @return float 电压值 (V)
|
|
|
|
|
|
*/
|
2026-03-09 01:57:43 +08:00
|
|
|
|
float XidiPowerMeterGetVoltage(XidiPowerMeterInstance *power_meter)
|
2025-11-20 19:11:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (power_meter == NULL)
|
|
|
|
|
|
return 0.0f;
|
2026-03-09 01:57:43 +08:00
|
|
|
|
return power_meter->powermeter_msg.voltage;
|
2025-11-20 19:11:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取电流值
|
|
|
|
|
|
* @param power_meter 功率计实例指针
|
|
|
|
|
|
* @return float 电流值 (A)
|
|
|
|
|
|
*/
|
2026-03-09 01:57:43 +08:00
|
|
|
|
float XidiPowerMeterGetCurrent(XidiPowerMeterInstance *power_meter)
|
2025-11-20 19:11:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (power_meter == NULL)
|
|
|
|
|
|
return 0.0f;
|
2026-03-09 01:57:43 +08:00
|
|
|
|
return power_meter->powermeter_msg.current;
|
2025-11-20 19:11:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取功率值
|
|
|
|
|
|
* @param power_meter 功率计实例指针
|
|
|
|
|
|
* @return float 功率值 (W)
|
|
|
|
|
|
*/
|
2026-03-09 01:57:43 +08:00
|
|
|
|
float XidiPowerMeterGetPower(XidiPowerMeterInstance *power_meter)
|
2025-11-20 19:11:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (power_meter == NULL)
|
|
|
|
|
|
return 0.0f;
|
2026-03-09 01:57:43 +08:00
|
|
|
|
return power_meter->powermeter_msg.power;
|
2025-11-20 19:11:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取累计能量
|
|
|
|
|
|
* @param power_meter 功率计实例指针
|
|
|
|
|
|
* @return float 累计能量 (J)
|
|
|
|
|
|
*/
|
2026-03-09 01:57:43 +08:00
|
|
|
|
float XidiPowerMeterGetEnergy(XidiPowerMeterInstance *power_meter)
|
2025-11-20 19:11:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (power_meter == NULL)
|
|
|
|
|
|
return 0.0f;
|
2026-03-09 01:57:43 +08:00
|
|
|
|
return power_meter->powermeter_msg.energy;
|
2025-11-20 19:11:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 重置累计能量
|
|
|
|
|
|
* @param power_meter 功率计实例指针
|
|
|
|
|
|
*/
|
2026-03-09 01:57:43 +08:00
|
|
|
|
void XidiPowerMeterResetEnergy(XidiPowerMeterInstance *power_meter)
|
2025-11-20 19:11:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (power_meter != NULL)
|
|
|
|
|
|
{
|
2026-03-09 01:57:43 +08:00
|
|
|
|
power_meter->powermeter_msg.energy = 0.0f;
|
2025-11-20 19:11:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取功率计实例(用于外部访问)
|
|
|
|
|
|
* @return PowerMeterInstance* 功率计实例指针
|
|
|
|
|
|
*/
|
2026-03-09 01:57:43 +08:00
|
|
|
|
XidiPowerMeterInstance *GetXidiPowerMeterInstance(void)
|
2025-11-20 19:11:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
return power_meter_instance;
|
|
|
|
|
|
}
|