Files
tronone-h7-scaffold/User_Code/module/periph/power_meters/xiditech/xidipwmeter.c
2026-03-09 02:35:08 +08:00

180 lines
5.0 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 "bsp_dwt.h"
#include "bsp_fdcan.h"
#include "xidipwmeter.h"
#include <stdlib.h>
#include <string.h>
#include "daemon.h"
static XidiPowerMeterInstance *power_meter_instance = NULL;
/**
* @brief 功率计数据解码函数
* @param _instance FDCAN实例指针
*
* @note 数据格式:
* DATA[0]: 电流数值低8位
* DATA[1]: 电流数值高8位
* DATA[2]: 电压数值低8位
* DATA[3]: 电压数值高8位
* DATA[4]-DATA[7]: 保留
*
* 电压电流数值均为放大100倍后的整数需要除以100.0得到实际值
*/
void XidiPowerMeterDecode(FDCANInstance *_instance)
{
if (power_meter_instance == NULL)
return;
uint8_t *rxbuff = _instance->rx_buff;
XidiPowerMeter_Msg_s *measure = &power_meter_instance->powermeter_msg;
// 重载守护进程
if (power_meter_instance->daemon != NULL)
{
DaemonReload(power_meter_instance->daemon);
}
// 计算时间间隔
measure->dt = DWT_GetDeltaT(&power_meter_instance->feed_cnt);
// 解析电流数据 (放大100倍需要除以100)
auto current_raw = (int16_t) ((rxbuff[1] << 8) | rxbuff[0]);
measure->current = (float) current_raw / 100.0f;
// 解析电压数据 (放大100倍需要除以100)
auto voltage_raw = (int16_t) ((rxbuff[3] << 8) | rxbuff[2]);
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 功率计实例指针
*/
void XidiPowerMeterLostCallback(void *power_meter_ptr)
{
XidiPowerMeterInstance *power_meter = (XidiPowerMeterInstance *) power_meter_ptr;
}
/**
* @brief 功率计初始化
* @param XidiPowerMeter_config 功率计初始化配置结构体指针 (必须确保其生命周期是全局或静态的)
* @return XidiPowerMeterInstance* 功率计实例指针
*/
XidiPowerMeterInstance *XidiPowerMeterInit(XidiPowerMeter_Init_Config_s *XidiPowerMeter_config)
{
// 1. 检查是否已经初始化
if (power_meter_instance != NULL)
{
return power_meter_instance;
}
// 2. 分配内存并清零
power_meter_instance = (XidiPowerMeterInstance *)malloc(sizeof(XidiPowerMeterInstance));
if (power_meter_instance == NULL)
{
return NULL;
}
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)
{
free(power_meter_instance);
power_meter_instance = NULL;
return NULL;
}
// 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);
return power_meter_instance;
}
/**
* @brief 获取电压值
* @param power_meter 功率计实例指针
* @return float 电压值 (V)
*/
float XidiPowerMeterGetVoltage(XidiPowerMeterInstance *power_meter)
{
if (power_meter == NULL)
return 0.0f;
return power_meter->powermeter_msg.voltage;
}
/**
* @brief 获取电流值
* @param power_meter 功率计实例指针
* @return float 电流值 (A)
*/
float XidiPowerMeterGetCurrent(XidiPowerMeterInstance *power_meter)
{
if (power_meter == NULL)
return 0.0f;
return power_meter->powermeter_msg.current;
}
/**
* @brief 获取功率值
* @param power_meter 功率计实例指针
* @return float 功率值 (W)
*/
float XidiPowerMeterGetPower(XidiPowerMeterInstance *power_meter)
{
if (power_meter == NULL)
return 0.0f;
return power_meter->powermeter_msg.power;
}
/**
* @brief 获取累计能量
* @param power_meter 功率计实例指针
* @return float 累计能量 (J)
*/
float XidiPowerMeterGetEnergy(XidiPowerMeterInstance *power_meter)
{
if (power_meter == NULL)
return 0.0f;
return power_meter->powermeter_msg.energy;
}
/**
* @brief 重置累计能量
* @param power_meter 功率计实例指针
*/
void XidiPowerMeterResetEnergy(XidiPowerMeterInstance *power_meter)
{
if (power_meter != NULL)
{
power_meter->powermeter_msg.energy = 0.0f;
}
}
/**
* @brief 获取功率计实例(用于外部访问)
* @return PowerMeterInstance* 功率计实例指针
*/
XidiPowerMeterInstance *GetXidiPowerMeterInstance(void)
{
return power_meter_instance;
}