mirror of
https://gitee.com/dlmu-cone/tronone-h7-scaffold
synced 2026-07-24 03:27:45 +08:00
xidipower test
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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=[]
|
||||
TableHeader="TargetExceptionDialog", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Address";"Description"], ColWidths=[26;26;26;26]
|
||||
Reference in New Issue
Block a user