Files
ASER-NAV/App/Can/snc_can_app.h

184 lines
6.0 KiB
C
Raw Permalink 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.
#ifndef __SNC_CAN_APP_H
#define __SNC_CAN_APP_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include "fdcan.h"
#define SNC_ODOM_TIMEOUT_MS 300U
/* ========================= 协议 CAN ID ========================= */
#define SNC_CAN_ID_HEARTBEAT 0x080U
#define SNC_CAN_ID_CMD_VEL 0x100U
#define SNC_CAN_ID_STATUS 0x181U
#define SNC_CAN_ID_ACTUAL_RPM 0x182U
#define SNC_CAN_ID_TARGET_RPM 0x183U
#define SNC_CAN_ID_COMM_DIAG 0x184U
#define SNC_CAN_ID_ODOM 0x200U
/* ========================= 系统状态定义 ========================= */
typedef enum
{
SNC_SYSTEM_BOOTING = 0,
SNC_SYSTEM_OPERATIONAL = 1,
SNC_SYSTEM_SAFE_FAULT = 2
} SNC_SystemState_t;
typedef enum
{
SNC_SYSTEM_HEALTH_OK = 0,
SNC_SYSTEM_HEALTH_WARNING = 1,
SNC_SYSTEM_HEALTH_FAULT = 2
} SNC_SystemHealth_t;
/* ========================= 诊断位定义 ========================= */
typedef enum
{
SNC_DIAG_COMM_TIMEOUT = (1UL << 0),
SNC_DIAG_CAN_BUS_OFF = (1UL << 1),
SNC_DIAG_CMD_CRC_STORM = (1UL << 2),
SNC_DIAG_CMD_CNT_STORM = (1UL << 3),
SNC_DIAG_MOTOR_FL_STALL = (1UL << 4),
SNC_DIAG_MOTOR_RL_STALL = (1UL << 5),
SNC_DIAG_MOTOR_FR_STALL = (1UL << 6),
SNC_DIAG_MOTOR_RR_STALL = (1UL << 7),
SNC_DIAG_CONTROL_SATURATION = (1UL << 8)
} SNC_DiagBits_t;
/* ========================= 下位机状态快照 ========================= */
typedef struct
{
uint8_t state;
uint8_t health;
uint32_t diag_bits;
uint8_t cmd_age_10ms;
uint8_t status_counter;
uint32_t last_update_ms;
bool online;
} SNC_ChassisStatus_t;
/* ========================= 轮速数据 ========================= */
typedef struct
{
int16_t fl;
int16_t rl;
int16_t fr;
int16_t rr;
uint32_t last_update_ms;
} SNC_WheelRpmFrame_t;
/* ========================= 里程增量 ========================= */
typedef struct
{
int16_t fl_delta;
int16_t rl_delta;
int16_t fr_delta;
int16_t rr_delta;
uint32_t last_update_ms;
} SNC_OdomDeltaFrame_t;
/**
* @brief 里程增量累加器
*
* 解决 0x200 增量帧的"漏积分/重复积分"问题:
* - ISR 收到每帧 0x200 时,将增量**累加**到此结构体(不覆盖)
* - 消费者调用 SNC_CAN_ConsumeOdomDelta() 原子取走累计值并清零
*
* 这样即使消费者频率 (100ms) 低于帧到达频率 (~60ms)
* 也不会丢失任何增量;也不会重复消费同一份增量。
*/
typedef struct
{
int32_t fl_accum; /**< 左前轮累计增量 ticks (int32 防溢出) */
int32_t rl_accum; /**< 左后轮累计增量 ticks */
int32_t fr_accum; /**< 右前轮累计增量 ticks */
int32_t rr_accum; /**< 右后轮累计增量 ticks */
uint32_t first_frame_ms; /**< 本次累加窗口内第一帧的时间戳 [ms] */
uint32_t last_frame_ms; /**< 本次累加窗口内最后一帧的时间戳 [ms] */
uint32_t span_ms; /**< 本次累计增量实际覆盖的时间窗 [ms] */
uint8_t frame_count; /**< 本次累加窗口内收到的帧数 */
} SNC_OdomDeltaAccum_t;
/* ========================= 通信诊断 ========================= */
typedef struct
{
uint8_t valid_cmd_total_lsb;
uint8_t crc_error_total_lsb;
uint8_t counter_reject_total_lsb;
uint8_t can_tx_drop_total_lsb;
uint8_t busoff_total_lsb;
uint8_t rx_overrun_total_lsb;
uint8_t last_accepted_counter;
uint8_t consecutive_counter_errors;
uint8_t consecutive_crc_errors;
uint32_t last_update_ms;
} SNC_CommDiagFrame_t;
/* ========================= 上位机应用层总状态 ========================= */
typedef struct
{
SNC_ChassisStatus_t status;
SNC_WheelRpmFrame_t actual_rpm;
SNC_WheelRpmFrame_t target_rpm;
SNC_OdomDeltaFrame_t odom_delta; /**< 最近一帧快照 (保留兼容性, 勿用于积分) */
SNC_OdomDeltaAccum_t odom_accum; /**< 里程增量累加器 (正确消费入口) */
SNC_CommDiagFrame_t comm_diag;
uint8_t tx_counter;
uint8_t tx_ctrl_flags;
uint32_t tx_total;
uint32_t tx_fail_total;
uint32_t rx_total;
} SNC_CAN_AppContext_t;
/* ========================= 全局上下文 ========================= */
extern SNC_CAN_AppContext_t g_snc_can_app;
/* ========================= 初始化与任务 ========================= */
void SNC_CAN_AppInit(void);
void SNC_CAN_20msTask(void);
void SNC_CAN_100msTask(void);
void SNC_CAN_PollOnlineState(uint32_t now_ms);
/* ========================= 发送接口 ========================= */
HAL_StatusTypeDef SNC_CAN_SendHeartbeat(void);
HAL_StatusTypeDef SNC_CAN_SendCmdVel(float vx_mps, float wz_radps, uint8_t ctrl_flags);
/* ========================= 接收回调 ========================= */
void SNC_CAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t rxFifo0ITs);
/* ========================= 数据读取接口 ========================= */
const SNC_CAN_AppContext_t *SNC_CAN_GetContext(void);
/**
* @brief 原子取走并清零里程增量累加器
*
* 消费者monitorTask每周期调用一次取走自上次消费以来
* ISR 累积的全部增量帧总和。返回后累加器归零,等待下一批帧。
*
* @param[out] fl 左前轮累计增量 ticks (截断为 int16)
* @param[out] rl 左后轮累计增量 ticks
* @param[out] fr 右前轮累计增量 ticks
* @param[out] rr 右后轮累计增量 ticks
* @param[out] dt_ms 累加增量实际覆盖的时间窗 [ms]
* 若无法可靠计算(如系统首帧)则为 0可用默认帧间隔替代
* @return 本次取走的帧数0 表示期间没有新帧到达
*/
uint8_t SNC_CAN_ConsumeOdomDelta(int16_t *fl, int16_t *rl,
int16_t *fr, int16_t *rr,
uint32_t *dt_ms);
/* ========================= 工具接口 ========================= */
uint8_t SNC_CAN_Crc8J1850(const uint8_t *data, uint16_t len);
#ifdef __cplusplus
}
#endif
#endif /* __SNC_CAN_APP_H */