From 9c58a09eabbc648c26cbe4f827c08fd3b410f12f Mon Sep 17 00:00:00 2001 From: TuxMonkey Date: Mon, 9 Mar 2026 01:57:43 +0800 Subject: [PATCH] xidipower test --- .../power_meters/xiditech/xidipwmeter.c | 80 +++++++++---------- .../power_meters/xiditech/xidipwmeter.h | 32 +++++--- User_Code/user_task/dev_tasks/dev_cmd.c | 31 +++++-- ozonedeb/linuxdb2.jdebug.user | 21 ++--- 4 files changed, 92 insertions(+), 72 deletions(-) diff --git a/User_Code/module/periph/power_meters/xiditech/xidipwmeter.c b/User_Code/module/periph/power_meters/xiditech/xidipwmeter.c index 42098b8..5c51704 100644 --- a/User_Code/module/periph/power_meters/xiditech/xidipwmeter.c +++ b/User_Code/module/periph/power_meters/xiditech/xidipwmeter.c @@ -7,11 +7,11 @@ #include "daemon.h" -static PowerMeterInstance *power_meter_instance = NULL; +static XidiPowerMeterInstance *power_meter_instance = NULL; /** * @brief 功率计数据解码函数 - * @param instance FDCAN实例指针 + * @param _instance FDCAN实例指针 * * @note 数据格式: * DATA[0]: 电流数值低8位 @@ -22,13 +22,13 @@ static PowerMeterInstance *power_meter_instance = NULL; * * 电压电流数值均为放大100倍后的整数,需要除以100.0得到实际值 */ -void PowerMeterDecode(FDCANInstance *instance) +void XidiPowerMeterDecode(FDCANInstance *_instance) { if (power_meter_instance == NULL) return; - uint8_t *rxbuff = instance->rx_buff; - PowerMeter_Measure_s *measure = &power_meter_instance->measure; + uint8_t *rxbuff = _instance->rx_buff; + XidiPowerMeter_Msg_s *measure = &power_meter_instance->powermeter_msg; // 重载守护进程 // if (power_meter_instance->daemon != NULL) @@ -60,57 +60,51 @@ void PowerMeterDecode(FDCANInstance *instance) * @brief 功率计丢失回调函数 * @param power_meter_ptr 功率计实例指针 */ -void PowerMeterLostCallback(void *power_meter_ptr) +void XidiPowerMeterLostCallback(void *power_meter_ptr) { - PowerMeterInstance *power_meter = (PowerMeterInstance *) power_meter_ptr; + XidiPowerMeterInstance *power_meter = (XidiPowerMeterInstance *) power_meter_ptr; } /** * @brief 功率计初始化 - * @param can_handle FDCAN句柄指针 - * @return PowerMeterInstance* 功率计实例指针 + * @param XidiPowerMeter_config 功率计初始化配置结构体指针 (必须确保其生命周期是全局或静态的) + * @return XidiPowerMeterInstance* 功率计实例指针 */ -PowerMeterInstance *PowerMeterInit(FDCAN_HandleTypeDef *can_handle) +XidiPowerMeterInstance *XidiPowerMeterInit(XidiPowerMeter_Init_Config_s *XidiPowerMeter_config) { - // 检查是否已经初始化 + // 1. 检查是否已经初始化 if (power_meter_instance != NULL) { return power_meter_instance; } - // 分配内存 - power_meter_instance = (PowerMeterInstance *) malloc(sizeof(PowerMeterInstance)); + // 2. 分配内存并清零 + power_meter_instance = (XidiPowerMeterInstance *)malloc(sizeof(XidiPowerMeterInstance)); if (power_meter_instance == NULL) { return NULL; } - memset(power_meter_instance, 0, sizeof(PowerMeterInstance)); + memset(power_meter_instance, 0, sizeof(XidiPowerMeterInstance)); - // 配置功率计初始化参数 - 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传递 - }; + // 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; - // 注册FDCAN实例 - power_meter_instance->can_instance = CANRegister(&can_config); - if (power_meter_instance->can_instance == NULL) + 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; } - //注册守护进程 - 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); + // 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; } @@ -120,11 +114,11 @@ PowerMeterInstance *PowerMeterInit(FDCAN_HandleTypeDef *can_handle) * @param power_meter 功率计实例指针 * @return float 电压值 (V) */ -float PowerMeterGetVoltage(PowerMeterInstance *power_meter) +float XidiPowerMeterGetVoltage(XidiPowerMeterInstance *power_meter) { if (power_meter == NULL) return 0.0f; - return power_meter->measure.voltage; + return power_meter->powermeter_msg.voltage; } /** @@ -132,11 +126,11 @@ float PowerMeterGetVoltage(PowerMeterInstance *power_meter) * @param power_meter 功率计实例指针 * @return float 电流值 (A) */ -float PowerMeterGetCurrent(PowerMeterInstance *power_meter) +float XidiPowerMeterGetCurrent(XidiPowerMeterInstance *power_meter) { if (power_meter == NULL) return 0.0f; - return power_meter->measure.current; + return power_meter->powermeter_msg.current; } /** @@ -144,11 +138,11 @@ float PowerMeterGetCurrent(PowerMeterInstance *power_meter) * @param power_meter 功率计实例指针 * @return float 功率值 (W) */ -float PowerMeterGetPower(PowerMeterInstance *power_meter) +float XidiPowerMeterGetPower(XidiPowerMeterInstance *power_meter) { if (power_meter == NULL) return 0.0f; - return power_meter->measure.power; + return power_meter->powermeter_msg.power; } /** @@ -156,22 +150,22 @@ float PowerMeterGetPower(PowerMeterInstance *power_meter) * @param power_meter 功率计实例指针 * @return float 累计能量 (J) */ -float PowerMeterGetEnergy(PowerMeterInstance *power_meter) +float XidiPowerMeterGetEnergy(XidiPowerMeterInstance *power_meter) { if (power_meter == NULL) return 0.0f; - return power_meter->measure.energy; + return power_meter->powermeter_msg.energy; } /** * @brief 重置累计能量 * @param power_meter 功率计实例指针 */ -void PowerMeterResetEnergy(PowerMeterInstance *power_meter) +void XidiPowerMeterResetEnergy(XidiPowerMeterInstance *power_meter) { if (power_meter != NULL) { - power_meter->measure.energy = 0.0f; + power_meter->powermeter_msg.energy = 0.0f; } } @@ -179,7 +173,7 @@ void PowerMeterResetEnergy(PowerMeterInstance *power_meter) * @brief 获取功率计实例(用于外部访问) * @return PowerMeterInstance* 功率计实例指针 */ -PowerMeterInstance *GetPowerMeterInstance(void) +XidiPowerMeterInstance *GetXidiPowerMeterInstance(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 93f7ee0..1165168 100644 --- a/User_Code/module/periph/power_meters/xiditech/xidipwmeter.h +++ b/User_Code/module/periph/power_meters/xiditech/xidipwmeter.h @@ -19,34 +19,40 @@ typedef struct float energy; // 累计能量 (J) uint32_t update_cnt; // 更新计数器 float dt; // 更新时间间隔 -} PowerMeter_Measure_s; +} XidiPowerMeter_Msg_s; /* 功率计实例结构 */ typedef struct { - FDCANInstance *can_instance; // FDCAN实例指针 - PowerMeter_Measure_s measure; // 测量数据 + FDCANInstance *fdcan_ins; // FDCAN实例指针 + XidiPowerMeter_Msg_s powermeter_msg; // 测量数据 Daemon_Instance *daemon; // 守护进程 uint32_t feed_cnt; // 喂狗计数器 -} PowerMeterInstance; +} XidiPowerMeterInstance; + +/* 功率计初始化配置 */ +typedef struct { + FDCAN_Init_Config_s can_config; + Daemon_Init_Config_s daemon_config; +} XidiPowerMeter_Init_Config_s; /* 函数声明 */ -PowerMeterInstance *PowerMeterInit(FDCAN_HandleTypeDef *can_handle); +XidiPowerMeterInstance *XidiPowerMeterInit(XidiPowerMeter_Init_Config_s *XidiPowerMeter_config); -void PowerMeterDecode(FDCANInstance *instance); +void XidiPowerMeterDecode(FDCANInstance *_instance); -void PowerMeterLostCallback(void *power_meter_ptr); +void XidiPowerMeterLostCallback(void *power_meter_ptr); -float PowerMeterGetVoltage(PowerMeterInstance *power_meter); +float XidiPowerMeterGetVoltage(XidiPowerMeterInstance *power_meter); -float PowerMeterGetCurrent(PowerMeterInstance *power_meter); +float XidiPowerMeterGetCurrent(XidiPowerMeterInstance *power_meter); -float PowerMeterGetPower(PowerMeterInstance *power_meter); +float XidiPowerMeterGetPower(XidiPowerMeterInstance *power_meter); -float PowerMeterGetEnergy(PowerMeterInstance *power_meter); +float XidiPowerMeterGetEnergy(XidiPowerMeterInstance *power_meter); -void PowerMeterResetEnergy(PowerMeterInstance *power_meter); +void XidiPowerMeterResetEnergy(XidiPowerMeterInstance *power_meter); -PowerMeterInstance *GetPowerMeterInstance(void); +XidiPowerMeterInstance *GetPowerMeterInstance(void); #endif //TRONONEH7_SCAFFOLD_XIDIPWMETER_H diff --git a/User_Code/user_task/dev_tasks/dev_cmd.c b/User_Code/user_task/dev_tasks/dev_cmd.c index eda4775..f19c0c2 100644 --- a/User_Code/user_task/dev_tasks/dev_cmd.c +++ b/User_Code/user_task/dev_tasks/dev_cmd.c @@ -8,7 +8,7 @@ // ==================== 2. 定义局部指针 ==================== -static PowerMeterInstance *chassis_power_meter; // 功率计实例指针 +static XidiPowerMeterInstance *chassis_power_meter; // 功率计实例指针 // 存放读取到的功率数据(也可以直接放进发给底盘的结构体里) static float current_power_w = 0.0f; @@ -16,15 +16,34 @@ static float current_voltage_v = 0.0f; static float current_energy_j = 0.0f; // ==================== 3. 在初始化函数中注册 ==================== +// 1. 定义为静态变量(static),确保它的内存空间常驻,防止底层指针悬垂! +static XidiPowerMeter_Init_Config_s xidi_pm_config = { + .can_config = { + .can_handle = &hfdcan1, // 原来直接传的句柄,现在放进结构体里 + .rx_id = 0x213, // 接收 ID + .tx_id = 0x000, // 发送 ID (不发送填0) + }, + .daemon_config = { + .reload_count = 5, // 守护进程超时周期 (例如:5次没收到算离线) + } +}; + +// 2. 初始化任务 void RobotCMDInit() { - chassis_power_meter = PowerMeterInit(&hfdcan1); + // 传入配置结构体的地址,而不是直接传 hfdcan1 + chassis_power_meter = XidiPowerMeterInit(&xidi_pm_config); + if (chassis_power_meter == NULL) { LOGERROR("[CMD] Power Meter Init Failed!"); } + else + { + // 建议加一句成功日志,方便上机调试时确认 + LOGINFO("[CMD] Power Meter Init Success!"); + } } - // ==================== 4. 在控制任务中读取使用 ==================== void CmdTask() { @@ -33,9 +52,9 @@ void CmdTask() { if (chassis_power_meter != NULL) { - current_power_w = PowerMeterGetPower(chassis_power_meter); - current_voltage_v = PowerMeterGetVoltage(chassis_power_meter); - current_energy_j = PowerMeterGetEnergy(chassis_power_meter); + current_power_w = XidiPowerMeterGetPower(chassis_power_meter); + current_voltage_v = XidiPowerMeterGetVoltage(chassis_power_meter); + current_energy_j = XidiPowerMeterGetEnergy(chassis_power_meter); // 你可以将获取到的功率写入要发送给底盘的 cmd 中,例如限制最大速度 // chassis_cmd_send.real_power = current_power_w; diff --git a/ozonedeb/linuxdb2.jdebug.user b/ozonedeb/linuxdb2.jdebug.user index ce10059..33ced8e 100644 --- a/ozonedeb/linuxdb2.jdebug.user +++ b/ozonedeb/linuxdb2.jdebug.user @@ -3,25 +3,26 @@ OpenDocument="main.c", FilePath="/home/tuxmonkey/CLionProjects/tronone-h7-scaffold/Core/Src/main.c", Line=0 OpenToolbar="Debug", Floating=0, x=0, y=0 OpenWindow="Registers 1", DockArea=BOTTOM, x=5, y=0, w=492, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, FilteredItems=[], RefreshRate=1 -OpenWindow="Source Files", DockArea=LEFT, x=0, y=0, w=539, h=202, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 +OpenWindow="Source Files", DockArea=LEFT, x=0, y=0, w=539, h=203, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 OpenWindow="Disassembly", DockArea=BOTTOM, x=0, y=0, w=453, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 -OpenWindow="Break & Tracepoints", DockArea=LEFT, x=0, y=1, w=539, h=293, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, VectorCatchIndexMask=254 +OpenWindow="Break & Tracepoints", DockArea=LEFT, x=0, y=1, w=539, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, VectorCatchIndexMask=254 OpenWindow="Memory 1", DockArea=BOTTOM, x=4, y=0, w=438, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, EditorAddress=0x200003D8 -OpenWindow="Global Data", DockArea=RIGHT, x=0, y=1, w=561, h=330, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 -OpenWindow="Watched Data 1", DockArea=LEFT, x=0, y=2, w=539, h=146, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 +OpenWindow="Global Data", DockArea=RIGHT, x=0, y=1, w=561, h=329, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 +OpenWindow="Watched Data 1", DockArea=LEFT, x=0, y=2, w=539, h=153, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 OpenWindow="Functions", DockArea=BOTTOM, x=3, y=0, w=411, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 OpenWindow="Data Sampling", DockArea=BOTTOM, x=1, y=0, w=355, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, VisibleTab=0, UniformSampleSpacing=0 -OpenWindow="Timeline", DockArea=RIGHT, x=0, y=0, w=561, h=312, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=1, DataPaneShown=1, PowerPaneShown=1, CodePaneShown=1, PinCursor="Cursor Movable", TimePerDiv="1 ns / Div", TimeStampFormat="Time", DataGraphDrawAsPoints=0, DataGraphLegendShown=1, DataGraphUniformSampleSpacing=0, DataGraphLegendPosition="355;0", DataGraphShowNamesAtCursor=0, PowerGraphDrawAsPoints=0, PowerGraphLegendShown=1, PowerGraphAvgFilterTime=Off, PowerGraphAvgFilterLen=Off, PowerGraphUniformSampleSpacing=0, PowerGraphLegendPosition="360;-67", CodeGraphLegendShown=1, CodeGraphLegendPosition="369;0" +OpenWindow="Timeline", DockArea=RIGHT, x=0, y=0, w=561, h=313, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=1, DataPaneShown=1, PowerPaneShown=1, CodePaneShown=1, PinCursor="Cursor Movable", TimePerDiv="1 ns / Div", TimeStampFormat="Time", DataGraphDrawAsPoints=0, DataGraphLegendShown=1, DataGraphUniformSampleSpacing=0, DataGraphLegendPosition="355;-67", DataGraphShowNamesAtCursor=0, PowerGraphDrawAsPoints=0, PowerGraphLegendShown=1, PowerGraphAvgFilterTime=Off, PowerGraphAvgFilterLen=Off, PowerGraphUniformSampleSpacing=0, PowerGraphLegendPosition="360;-67", CodeGraphLegendShown=1, CodeGraphLegendPosition="309;0" OpenWindow="Console", DockArea=BOTTOM, x=2, y=0, w=406, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 SmartViewPlugin="", Page="", Toolbar="Hidden", Window="SmartView 1" -TableHeader="Global Data", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Location";"Size";"Type";"Scope"], ColWidths=[100;100;100;100;100;364] +TableHeader="Global Data", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Location";"Size";"Type";"Scope"], ColWidths=[100;100;100;100;100;100] TableHeader="Vector Catches", SortCol="", SortOrder="ASCENDING", VisibleCols=["";"Vector Catch";"Description"], ColWidths=[50;300;500] TableHeader="Break & Tracepoints", SortCol="None", SortOrder="ASCENDING", VisibleCols=["";"Type";"Location";"Extras"], ColWidths=[100;100;100;239] -TableHeader="Functions", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Address";"Size";"#Insts";"Source"], ColWidths=[1435;100;100;100;231] -TableHeader="Source Files", SortCol="File", SortOrder="ASCENDING", VisibleCols=["File";"Status";"Size";"#Insts";"Path"], ColWidths=[225;100;100;100;875] +TableHeader="Functions", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Address";"Size";"#Insts";"Source"], ColWidths=[1435;100;100;100;100] +TableHeader="Source Files", SortCol="File", SortOrder="ASCENDING", VisibleCols=["File";"Status";"Size";"#Insts";"Path"], ColWidths=[225;100;100;100;100] TableHeader="Data Sampling Table", SortCol="None", SortOrder="ASCENDING", VisibleCols=["Index";"Time"], ColWidths=[100;100] TableHeader="Data Sampling Setup", SortCol="Expression", SortOrder="ASCENDING", VisibleCols=["Expression";"Type";"Value";"Min";"Max";"Average";"# Changes";"Min. Change";"Max. Change"], ColWidths=[126;100;100;100;100;100;100;100;100] TableHeader="Power Sampling", SortCol="None", SortOrder="ASCENDING", VisibleCols=["Index";"Time";"Ch 0"], ColWidths=[100;100;100] -TableHeader="Registers 1", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Description"], ColWidths=[100;105;287] +TableHeader="Registers 1", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Description"], ColWidths=[100;105;271] TableHeader="Watched Data 1", SortCol="Expression", SortOrder="ASCENDING", VisibleCols=["Expression";"Value";"Location";"Refresh"], ColWidths=[170;100;100;169] -TableHeader="RegisterSelectionDialog", SortCol="None", SortOrder="ASCENDING", VisibleCols=[], ColWidths=[] \ No newline at end of file +TableHeader="RegisterSelectionDialog", SortCol="None", SortOrder="ASCENDING", VisibleCols=[], ColWidths=[] +TableHeader="TargetExceptionDialog", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Address";"Description"], ColWidths=[26;26;26;26] \ No newline at end of file