修复了吗?没有,很难的啦111

This commit is contained in:
TuxMonkey
2026-03-09 21:43:44 +08:00
parent e3f5951881
commit 0ccdd0a0d5
5 changed files with 73 additions and 74 deletions

View File

@@ -78,24 +78,26 @@ static void CANAddFilter(FDCANInstance *_instance)
fdcan_filter_conf.IsCalibrationMsg = 0;
//fdcan_filter_conf.RxBufferIndex=0;
// ================== 【核心修复区】 ==================@todo有问题 我要验牌
// 1. 强制让 FDCAN 进入 INIT 模式,否则无法写入 Message RAM
HAL_FDCAN_Stop(_instance->can_handle);
// // ================== 【核心修复区】 ==================@todo有问题 我要验牌
// // 1. 强制让 FDCAN 进入 INIT 模式,否则无法写入 Message RAM
// HAL_FDCAN_Stop(_instance->can_handle);
//
// // 2. 写入过滤器配置
// HAL_FDCAN_ConfigFilter(_instance->can_handle, &fdcan_filter_conf);
//
// // 3. 重新启动 FDCAN
// HAL_FDCAN_Start(_instance->can_handle);
//
// // 4. 【救命稻草】HAL_FDCAN_Stop 关闭了所有中断,必须在这里重新激活!
// uint32_t FDCAN_RXActiveITs = FDCAN_IT_RX_FIFO0_NEW_MESSAGE | FDCAN_IT_RX_FIFO0_FULL |
// FDCAN_IT_RX_FIFO0_WATERMARK | FDCAN_IT_RX_FIFO0_MESSAGE_LOST |
// FDCAN_IT_RX_FIFO1_NEW_MESSAGE | FDCAN_IT_RX_FIFO1_FULL |
// FDCAN_IT_RX_FIFO1_WATERMARK | FDCAN_IT_RX_FIFO1_MESSAGE_LOST;
// HAL_FDCAN_ActivateNotification(_instance->can_handle, FDCAN_RXActiveITs, 0);
// // ====================================================
// 2. 写入过滤器配置
HAL_FDCAN_ConfigFilter(_instance->can_handle, &fdcan_filter_conf);
// 3. 重新启动 FDCAN
HAL_FDCAN_Start(_instance->can_handle);
// 4. 【救命稻草】HAL_FDCAN_Stop 关闭了所有中断,必须在这里重新激活!
uint32_t FDCAN_RXActiveITs = FDCAN_IT_RX_FIFO0_NEW_MESSAGE | FDCAN_IT_RX_FIFO0_FULL |
FDCAN_IT_RX_FIFO0_WATERMARK | FDCAN_IT_RX_FIFO0_MESSAGE_LOST |
FDCAN_IT_RX_FIFO1_NEW_MESSAGE | FDCAN_IT_RX_FIFO1_FULL |
FDCAN_IT_RX_FIFO1_WATERMARK | FDCAN_IT_RX_FIFO1_MESSAGE_LOST;
HAL_FDCAN_ActivateNotification(_instance->can_handle, FDCAN_RXActiveITs, 0);
// ====================================================
#else
CAN_FilterTypeDef can_filter_conf;
static uint8_t can1_filter_idx = 0, can2_filter_idx = 14; // 0-13给can1用,14-27给can2用

View File

@@ -13,14 +13,15 @@ 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得到实际值
* @note 新版数据格式 (大端模式):
* DATA[0]: 电压高8位
* DATA[1]: 电压低8位
* DATA[2]: 电流高8位
* DATA[3]: 电流低8位
* DATA[4]: 功率高8位
* DATA[5]: 功率低8位
* DATA[6]: 标识符
* DATA[7]: 校验和
*/
void XidiPowerMeterDecode(FDCANInstance *_instance)
{
@@ -39,18 +40,20 @@ void XidiPowerMeterDecode(FDCANInstance *_instance)
// 计算时间间隔
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]);
// 1. 解析电压 (高8位在前低8位在后)
uint16_t voltage_raw = (rxbuff[0] << 8) | rxbuff[1];
measure->voltage = (float) voltage_raw / 100.0f;
// 计算功率
measure->power = measure->voltage * measure->current;
// 2. 解析电流 (高8位在前低8位在后)
uint16_t current_raw = (rxbuff[2] << 8) | rxbuff[3];
measure->current = (float) current_raw / 100.0f;
// 计算累计能量 (功率 × 时间)
// 3. 解析功率 (高8位在前低8位在后)
// 既然协议里直接发了功率,我们就直接读硬件算好的,比自己用 U*I 算更准
uint16_t power_raw = (rxbuff[4] << 8) | rxbuff[5];
measure->power = (float) power_raw / 100.0f;
// 4. 计算累计能量 (功率 × 时间)
measure->energy += measure->power * measure->dt * 0.001f; // dt单位是ms转换为秒
measure->update_cnt++;
@@ -79,7 +82,7 @@ XidiPowerMeterInstance *XidiPowerMeterInit(XidiPowerMeter_Init_Config_s *XidiPow
}
// 2. 分配内存并清零
power_meter_instance = (XidiPowerMeterInstance *)malloc(sizeof(XidiPowerMeterInstance));
power_meter_instance = (XidiPowerMeterInstance *) malloc(sizeof(XidiPowerMeterInstance));
if (power_meter_instance == NULL)
{
return NULL;

View File

@@ -19,7 +19,7 @@ static float current_energy_j = 0.0f;
// 1. 定义为静态变量static确保它的内存空间常驻防止底层指针悬垂
static XidiPowerMeter_Init_Config_s xidi_pm_config = {
.can_config = {
.can_handle = &hfdcan1, // 原来直接传的句柄,现在放进结构体里
.can_handle = &hfdcan2, // 原来直接传的句柄,现在放进结构体里
.rx_id = 0x213, // 接收 ID
.tx_id = 0x000, // 发送 ID (不发送填0)
},
@@ -52,16 +52,7 @@ void CmdTask(void *argument)
DaemonReload(chassis_power_meter->daemon);
while (1)
{
if (chassis_power_meter != NULL)
{
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;
}
DaemonReload(chassis_power_meter->daemon);
osDelay(10); // 根据实际需要调整读取频率
}
}