Files
tronone-h7-scaffold/User_Code/module/periph/power_meters/xiditech/xidipwmeter.c
2025-11-20 19:26:42 +08:00

184 lines
4.9 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>
static PowerMeterInstance *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 PowerMeterDecode(FDCANInstance *instance)
{
if (power_meter_instance == NULL)
return;
uint8_t *rxbuff = instance->rx_buff;
PowerMeter_Measure_s *measure = &power_meter_instance->measure;
// 重载守护进程
// 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 PowerMeterLostCallback(void *power_meter_ptr)
{
PowerMeterInstance *power_meter = (PowerMeterInstance *) power_meter_ptr;
}
/**
* @brief 功率计初始化
* @param can_handle FDCAN句柄指针
* @return PowerMeterInstance* 功率计实例指针
*/
PowerMeterInstance *PowerMeterInit(FDCAN_HandleTypeDef *can_handle)
{
// 检查是否已经初始化
if (power_meter_instance != NULL)
{
return power_meter_instance;
}
// 分配内存
power_meter_instance = (PowerMeterInstance *) malloc(sizeof(PowerMeterInstance));
if (power_meter_instance == NULL)
{
return NULL;
}
memset(power_meter_instance, 0, sizeof(PowerMeterInstance));
// 配置FDCAN初始化参数 - 完全适配您的FDCAN驱动
FDCAN_Init_Config_s can_config = {
.can_handle = can_handle,
.rx_id = 0x213, // 功率计反馈标识符
.tx_id = 0x000, // 不需要发送设为0
.can_module_callback = PowerMeterDecode,
.id = power_meter_instance, // 将实例指针作为ID传递
};
// 注册FDCAN实例 - 使用FDCANRegister函数
power_meter_instance->can_instance = FDCANRegister(&can_config);
if (power_meter_instance->can_instance == NULL)
{
free(power_meter_instance);
power_meter_instance = NULL;
return NULL;
}
// 注册守护进程
// Daemon_Init_Config_s daemon_config = {
// .callback = PowerMeterLostCallback,
// .owner_id = power_meter_instance,
// .reload_count = 5, // 50ms未收到数据则认为丢失 (1000Hz发送5个周期)
// };
// power_meter_instance->daemon = DaemonRegister(&daemon_config);
return power_meter_instance;
}
/**
* @brief 获取电压值
* @param power_meter 功率计实例指针
* @return float 电压值 (V)
*/
float PowerMeterGetVoltage(PowerMeterInstance *power_meter)
{
if (power_meter == NULL)
return 0.0f;
return power_meter->measure.voltage;
}
/**
* @brief 获取电流值
* @param power_meter 功率计实例指针
* @return float 电流值 (A)
*/
float PowerMeterGetCurrent(PowerMeterInstance *power_meter)
{
if (power_meter == NULL)
return 0.0f;
return power_meter->measure.current;
}
/**
* @brief 获取功率值
* @param power_meter 功率计实例指针
* @return float 功率值 (W)
*/
float PowerMeterGetPower(PowerMeterInstance *power_meter)
{
if (power_meter == NULL)
return 0.0f;
return power_meter->measure.power;
}
/**
* @brief 获取累计能量
* @param power_meter 功率计实例指针
* @return float 累计能量 (J)
*/
float PowerMeterGetEnergy(PowerMeterInstance *power_meter)
{
if (power_meter == NULL)
return 0.0f;
return power_meter->measure.energy;
}
/**
* @brief 重置累计能量
* @param power_meter 功率计实例指针
*/
void PowerMeterResetEnergy(PowerMeterInstance *power_meter)
{
if (power_meter != NULL)
{
power_meter->measure.energy = 0.0f;
}
}
/**
* @brief 获取功率计实例(用于外部访问)
* @return PowerMeterInstance* 功率计实例指针
*/
PowerMeterInstance *GetPowerMeterInstance(void)
{
return power_meter_instance;
}