From 8d88556f5f77a6848d70a8e57f5293e9dbd79ebc Mon Sep 17 00:00:00 2001 From: TuxMonkey <8196772+tuxmonkey@user.noreply.gitee.com> Date: Thu, 20 Nov 2025 19:11:56 +0800 Subject: [PATCH] powermeter --- .../power_meters/xiditech/xidipowermeter.md | 21 ++ .../power_meters/xiditech/xidipwmeter.c | 186 +++++++++++++++++- .../power_meters/xiditech/xidipwmeter.h | 45 ++++- 3 files changed, 247 insertions(+), 5 deletions(-) diff --git a/User_Code/module/periph/power_meters/xiditech/xidipowermeter.md b/User_Code/module/periph/power_meters/xiditech/xidipowermeter.md index e69de29..db2aeca 100644 --- a/User_Code/module/periph/power_meters/xiditech/xidipowermeter.md +++ b/User_Code/module/periph/power_meters/xiditech/xidipowermeter.md @@ -0,0 +1,21 @@ +# 溪地创新功率计驱动 + +使用示例: + +```c +// 在适当的地方初始化功率计(如main.c中) +PowerMeterInstance *power_meter = PowerMeterInit(&hfdcan1); // 使用FDCAN1 + +// 在任务循环中获取功率数据 +void PowerMonitorTask(void) +{ + float voltage = PowerMeterGetVoltage(power_meter); + float current = PowerMeterGetCurrent(power_meter); + float power = PowerMeterGetPower(power_meter); + float energy = PowerMeterGetEnergy(power_meter); + + // 打印或使用这些数据 + printf("V: %.1fV, I: %.1fA, P: %.1fW, E: %.1fJ\n", + voltage, current, power, energy); +} +``` \ No newline at end of file diff --git a/User_Code/module/periph/power_meters/xiditech/xidipwmeter.c b/User_Code/module/periph/power_meters/xiditech/xidipwmeter.c index e3b54f4..43409be 100644 --- a/User_Code/module/periph/power_meters/xiditech/xidipwmeter.c +++ b/User_Code/module/periph/power_meters/xiditech/xidipwmeter.c @@ -1,5 +1,183 @@ -// -// Created by ASUS on 2025/11/17. -// +#include "bsp_dwt.h" +#include "bsp_fdcan.h" +#include "xidipwmeter.h" -#include "xidipwmeter.h" \ No newline at end of file +#include +#include + +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) + int16_t current_raw = (int16_t) ((rxbuff[1] << 8) | rxbuff[0]); + measure->current = (float) current_raw / 100.0f; + + // 解析电压数据 (放大100倍,需要除以100) + int16_t 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; +} diff --git a/User_Code/module/periph/power_meters/xiditech/xidipwmeter.h b/User_Code/module/periph/power_meters/xiditech/xidipwmeter.h index b40234f..b0bfaeb 100644 --- a/User_Code/module/periph/power_meters/xiditech/xidipwmeter.h +++ b/User_Code/module/periph/power_meters/xiditech/xidipwmeter.h @@ -5,4 +5,47 @@ #ifndef TRONONEH7_SCAFFOLD_XIDIPWMETER_H #define TRONONEH7_SCAFFOLD_XIDIPWMETER_H -#endif //TRONONEH7_SCAFFOLD_XIDIPWMETER_H \ No newline at end of file +#include "general_def.h" +#include "bsp_dwt.h" +#include "bsp_fdcan.h" + +/* 功率计测量数据结构 */ +typedef struct +{ + float voltage; // 电压 (V) + float current; // 电流 (A) + float power; // 功率 (W) + float energy; // 累计能量 (J) + uint32_t update_cnt; // 更新计数器 + float dt; // 更新时间间隔 +} PowerMeter_Measure_s; + +/* 功率计实例结构 */ +typedef struct +{ + FDCANInstance *can_instance; // FDCAN实例指针 + PowerMeter_Measure_s measure; // 测量数据 + // DaemonInstance *daemon; // 守护进程 + uint32_t feed_cnt; // 喂狗计数器 +} PowerMeterInstance; + +/* 函数声明 */ +PowerMeterInstance *PowerMeterInit(FDCAN_HandleTypeDef *can_handle); + +void PowerMeterDecode(FDCANInstance *instance); + +void PowerMeterLostCallback(void *power_meter_ptr); + +float PowerMeterGetVoltage(PowerMeterInstance *power_meter); + +float PowerMeterGetCurrent(PowerMeterInstance *power_meter); + +float PowerMeterGetPower(PowerMeterInstance *power_meter); + +float PowerMeterGetEnergy(PowerMeterInstance *power_meter); + +void PowerMeterResetEnergy(PowerMeterInstance *power_meter); + +PowerMeterInstance *GetPowerMeterInstance(void); + +#endif //TRONONEH7_SCAFFOLD_XIDIPWMETER_H