Files
ESP32_COMM/main/monitor/motor_state.h
T
小龙虾 e9cb7342f6 feat(motor): 支持多通道同节点号电机状态管理
支持同一节点号在多个CAN通道上的电机状态管理,采用node×channel双键存储机制。

- 修改motor_state.cpp中的槽位索引逻辑,从单节点索引改为(node-1)*MOTOR_CHANNELS+channel索引
- 增加MOTOR_CHANNELS和MOTOR_MAX_SLOTS宏定义,支持9节点×3通道共27个槽位
- 更新http_handlers.cpp中的二进制响应缓冲区为static类型,避免大缓冲区占用栈空间
- 调整循环遍历范围从MOTOR_MAX_NODES改为MOTOR_MAX_SLOTS
- 添加HTML页面的空favicon配置,避免浏览器404请求
- 新增CSS样式用于显示节点在其他通道在线的状态提示
2026-07-30 11:57:21 +08:00

78 lines
2.8 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.
/*
* motor_state.h - 被动接收 GD32 多电机状态推送(SPI TYPE 0xC5)
*
* 与 CAN 0xC1 / ADC 0xC4 同模型:GD32 250ms 主动按铃推送(独立任务位),ESP32 takeEvent 侧解析入库。
* 是否推送由 GD32 CONFIG_MOTOR_STATE_ENABLE 决定;ESP32 无本地开关,有帧即解析。
*
* payload 格式(每页):
* [0] page, [1] total_pages, [2] entry_count, [3] active_count
* [4..] 每个 entry 44B:
* [0] node_id, [1] channel, [2] online, [3] dlc,
* [4..7] rx_count (LE), [8..11] seq (LE),
* [12..43] data[32] (原始 STATUS payload)
*
* 同一节点号可能同时挂在多个 CAN 通道(两台电机同号异线),
* 缓存表与 GD32 端一致按 node×channel 双键存储(27 槽)。
*/
#ifndef MOTOR_STATE_H
#define MOTOR_STATE_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MOTOR_MAX_NODES 9
#define MOTOR_CHANNELS 3
#define MOTOR_MAX_SLOTS (MOTOR_MAX_NODES * MOTOR_CHANNELS)
#define MOTOR_STATUS_DLC 32
#define MOTOR_ENTRY_SIZE 44
#define MOTOR_PAGE_HEADER 4
#define MOTOR_TOTAL_PAGES 6
/** @brief 单电机状态快照。 */
typedef struct {
uint8_t node_id; ///< 1-9, 0=空槽
uint8_t channel; ///< CAN 通道 (0/1/2)
uint8_t online; ///< 1=在线, 0=离线
uint8_t dlc; ///< STATUS 帧 DLC (正常=32)
uint32_t rx_count; ///< 累计收到帧数
uint32_t seq; ///< GD32 侧更新序号
uint8_t data[MOTOR_STATUS_DLC]; ///< 原始 STATUS payload
} motor_slot_t;
/** @brief 全局电机状态表。 */
typedef struct {
motor_slot_t slots[MOTOR_MAX_SLOTS]; ///< 按 (node_id-1)*MOTOR_CHANNELS+channel 索引
uint8_t active_count; ///< 在线电机数
uint8_t boot_active; ///< 1=总线上有电机在 BOOT(0x103 心跳,来自 0xC5 头 bit7)
uint8_t valid_slots; ///< 有效槽位数(node_id!=0)
int64_t recv_ms; ///< ESP32 最近收到时 esp_timer ms
bool have_data; ///< 至少收到过一帧
} motor_state_table_t;
/**
* @brief 处理一帧 0xC5 EVENT payload(由 can_fb 任务 takeEvent 分发)。
* @return true 表示已接受并更新。
*/
bool onMotorStateEvent(const uint8_t *payload, size_t len);
/**
* @brief 拷贝最新电机状态表(线程安全)。
* @param[out] out 输出缓冲
* @return true 表示至少收到过一帧
*/
bool getLatestMotorState(motor_state_table_t *out);
/** @brief 距离上次收到的毫秒数;无数据返回 UINT32_MAX。 */
uint32_t motorStateAgeMs(void);
#ifdef __cplusplus
}
#endif
#endif /* MOTOR_STATE_H */