Files
Motor_v2/Robot_V2/device/Can.h
T

431 lines
12 KiB
C++
Raw Normal View History

/**
* @file device/Can.h
* @brief 底层设备驱动与外设封装源文件
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
*/
2025-09-23 00:27:51 +08:00
#ifndef _CAN_H
#define _CAN_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <cstdint>
2025-09-23 00:27:51 +08:00
#include "gd32c10x_can.h"
#include "config.h"
2025-09-23 00:27:51 +08:00
// 定义一个联合体类型用于 float 和 byte 数组之间的转换
/**
* @brief 匿名联合体 联合体定义
*/
2025-09-23 00:27:51 +08:00
typedef union {
float f;
u8 b[4];
} float_union_t;
// 添加辅助函数用于将 u16 类型数据打包到 u8 数组中
/**
* @brief pack_u16_to_bytes 函数
* @param[in] buffer 参数
* @param[in] offset 参数
* @param[in] value 参数
* @return void
*/
2025-11-23 18:31:47 +08:00
static inline void pack_u16_to_bytes(u8 *buffer, u16 offset, u16 value) {
buffer[offset] = (u8)(value & 0xFF);
buffer[offset + 1] = (u8)((value >> 8) & 0xFF);
2025-10-02 02:52:07 +08:00
}
// 将 mA 电流值饱和转换为 int16 后按小端打包。
// DBC 中 U/V/W current 定义为 signed int16([-32768,32767] mA);
// 相电流有正有负,此前用 u16() 打包负值被削成 0,上位机波形下半周丢失。
/**
* @brief pack_current_s16_to_bytes 函数
* @param[in] buffer 参数
* @param[in] offset 参数
* @param[in] value_mA 参数
* @return void
*/
static inline void pack_current_s16_to_bytes(u8 *buffer, u16 offset,
float value_mA) {
short value;
if (value_mA > 32767.0f) {
value = 32767; // 饱和,避免 float→int 超范围截断环绕
} else if (value_mA < -32768.0f) {
value = -32768;
} else {
value = (short)value_mA;
}
pack_u16_to_bytes(buffer, offset, (u16)value);
}
// 添加辅助函数用于将 float 类型数据打包到 u8 数组中
/**
* @brief pack_float_to_bytes 函数
* @param[in] buffer 参数
* @param[in] offset 参数
* @param[in] float_union 参数
* @return void
*/
2025-11-23 18:31:47 +08:00
static inline void pack_float_to_bytes(u8 *buffer, u16 offset,
float_union_t &float_union) {
buffer[offset] = float_union.b[0];
buffer[offset + 1] = float_union.b[1];
buffer[offset + 2] = float_union.b[2];
buffer[offset + 3] = float_union.b[3];
2025-10-02 02:52:07 +08:00
}
// 添加辅助函数用于从 u8 数组中解包 short 类型数据
/**
* @brief unpack_bytes_to_short 函数
* @param[in] buffer 参数
* @param[in] offset 参数
* @return short 返回值
*/
2025-11-23 18:31:47 +08:00
static inline short unpack_bytes_to_short(u8 *buffer, u16 offset) {
short value = (short)(buffer[offset] | (buffer[offset + 1] << 8));
return value;
2025-10-16 21:43:34 +08:00
}
// 添加辅助函数用于从 u8 数组中解包 u16 类型数据
/**
* @brief unpack_bytes_to_u16 函数
* @param[in] buffer 参数
* @param[in] offset 参数
* @return u16 返回值
*/
2025-11-23 18:31:47 +08:00
static inline u16 unpack_bytes_to_u16(u8 *buffer, u16 offset) {
u16 value = (u16)(buffer[offset] | (buffer[offset + 1] << 8));
return value;
2025-10-16 21:43:34 +08:00
}
// 添加辅助函数用于从 u8 数组中解包 float 类型数据
/**
* @brief unpack_bytes_to_float 函数
* @param[in] buffer 参数
* @param[in] offset 参数
* @return float_union_t 返回值
*/
2025-11-23 18:31:47 +08:00
static inline float_union_t unpack_bytes_to_float(u8 *buffer, u16 offset) {
float_union_t float_union;
float_union.b[0] = buffer[offset];
float_union.b[1] = buffer[offset + 1];
float_union.b[2] = buffer[offset + 2];
float_union.b[3] = buffer[offset + 3];
2025-10-16 21:43:34 +08:00
return float_union;
}
/**
* @brief 初始化 CAN 引脚
* @return u8 返回值
*/
u8 can_gpio_init(void); // CAN 引脚初始化
/**
* @brief 配置 CAN FD 外设
* @return void
*/
void canfd_config(void); // CANFD 初始化
/**
* @brief 初始化 CAN DMA 通道
* @return void
*/
void can_dma_init(void); // CAN DMA 初始化
/**
* @brief CAN0 发送中断处理函数
* @return void
*/
2026-05-15 23:04:04 +08:00
void CAN0_TX_IRQHandler(void); // CAN 发送中断处理函数
/**
* @brief CAN0 接收中断处理函数
* @return void
*/
void CAN0_RX0_IRQHandler(void); // CAN 接收中断处理函数
/**
* @brief DMA0 通道 4 中断处理函数
* @return void
*/
void DMA0_Channel4_IRQHandler(void); // DMA 通道 4 中断处理函数 (CAN 接收)
/**
* @brief DMA0 通道 5 中断处理函数
* @return void
*/
void DMA0_Channel5_IRQHandler(void); // DMA 通道 5 中断处理函数 (CAN 发送)
/**
* @brief jumpToBOOT 函数
* @return void
*/
void jumpToBOOT();
2025-10-14 00:49:58 +08:00
2025-10-02 02:52:07 +08:00
2025-09-23 00:27:51 +08:00
/*!
\brief CAN 通信类
\note 封装 CAN 发送和接收功能,支持多电机节点 ID 隔离
2025-09-23 00:27:51 +08:00
*/
class CAN_transmiter {
private:
static const uint8_t CAN_RX_BUFFER_SIZE = 8; // CAN 接收缓冲区大小
static const u32 CAN_SILENT_DURATION_MS = 10000; // CAN 静默时长 10 秒
bool is_sleep = false; // 是否休眠
bool is_silent = false; // 是否静默(收到 base_id=0x0000 后进入静默)
u32 silent_start_time = 0; // 静默开始时间(ms)
u16 node_id; // 本节点 ID(0-254),使用 CAN ID 高 8 位存储 (在 init() 中初始化为 DEFAULT_NODE_ID)
u8 Target_Control_Mode = 0; // 目标控制模式
u8 controller_Mode = 0; // 当前模式
short mcu_temp = 0; // MCU 温度
short motor_temp = 0; // 电机温度
u16 Power_Voltage = 0; // 电源电压
u16 limit_voltage = 0; // 限制电压
u8 cpu_usage = 0; // CPU 使用率(%)
float_union_t rt_angle_union = {0}; // 实时角度
float_union_t rt_velocity_union = {0}; // 实时速度
float_union_t rt_current_union = {0}; // 实时电流
float_union_t target_angle_union = {0}; // 目标角度
float_union_t target_velocity_union = {0}; // 目标速度
float_union_t target_current_union = {0}; // 目标电流
float_union_t u_current_union = {0}; // U 相电流
float_union_t w_current_union = {0}; // W 相电流
float_union_t v_current_union = {0}; // V 相电流
2025-09-23 00:27:51 +08:00
bool MotorStatus = 0; // 电机状态码
u8 EEPROMStatus = 0; // EEPROM 状态码
2025-10-14 00:49:58 +08:00
can_trasnmit_message_struct transmit_message; // 发送消息结构体
u8 transmit_mailbox = CAN_NOMAILBOX; // 初始化为无 mailbox 状态
u8 transmit_data[64]; // CANFD 最大 64 字节
2025-09-23 00:27:51 +08:00
// CAN 接收消息队列
can_receive_message_struct rx_message_buffer[CAN_RX_BUFFER_SIZE];
volatile uint8_t rx_buffer_head = 0;
volatile uint8_t rx_buffer_tail = 0;
/**
* @brief 更新对象内部状态或采样数据
* @return void
*/
2026-01-05 00:55:00 +08:00
void update(); // 更新数据
/**
* @brief CAN_Receive 函数
* @return u8 返回值
*/
u8 CAN_Receive(); // CAN 接收
/**
* @brief CANFD_Receive 函数
* @return u8 返回值
*/
u8 CANFD_Receive(); // CANFD 接收
/**
* @brief is_rx_buffer_full 函数
* @return bool 返回值
*/
bool is_rx_buffer_full();
/**
* @brief is_rx_buffer_empty 函数
* @return bool 返回值
*/
bool is_rx_buffer_empty();
/**
* @brief dequeue_rx_message 函数
* @param[in] message 参数
* @return bool 返回值
*/
bool dequeue_rx_message(can_receive_message_struct& message);
/**
* @brief check_silent_mode 函数
* @return void
*/
void check_silent_mode(); // 检查静默模式是否结束
/**
* @brief 处理周期性发送请求,静默模式下只检查是否退出静默
* @return void
*/
void handle_periodic_send_tick();
/**
* @brief 将底层接收队列项转换为 CAN 消息并按协议分发
* @param[in] id 接收到的扩展 CAN ID
* @param[in] length 接收数据长度
* @param[in] data 接收数据指针
* @return void
*/
void handle_received_queue_item(u32 id, u8 length, const u8 *data);
/**
* @brief 处理不受本节点过滤限制的特殊消息
* @param[in,out] current_message 当前 CAN 消息
* @param[in] base_id 低 16 位基础 ID
* @param[in] sender_node_id 发送方节点 ID
* @return bool true 表示消息已处理,false 表示继续按普通节点消息处理
*/
bool handle_special_message(can_receive_message_struct &current_message,
u32 base_id, u16 sender_node_id);
/**
* @brief 处理 BOOT 命令或其他节点 BOOT 广播导致的静默逻辑
* @param[in] sender_node_id 发送方节点 ID
* @return void
*/
void handle_boot_message(u16 sender_node_id);
/**
* @brief 处理节点 ID 设置命令,发送应答并保存新 ID 到 Flash
* @param[in,out] current_message 当前 CAN 消息
* @return void
*/
void handle_set_node_id_message(can_receive_message_struct &current_message);
/**
* @brief 处理已经确认发给本节点的普通协议消息
* @param[in,out] current_message 当前 CAN 消息
* @param[in] base_id 低 16 位基础 ID
* @return void
*/
void handle_node_message(can_receive_message_struct &current_message,
u32 base_id);
/**
* @brief 解析控制命令并更新 FOC 目标值和 PID 参数
* @param[in,out] current_message 当前 CAN 消息
* @return void
*/
void handle_control_command(can_receive_message_struct &current_message);
/**
* @brief 解析复位命令各 bit 位并执行对应动作
* @param[in,out] current_message 当前 CAN 消息
* @return void
*/
void handle_reset_command(can_receive_message_struct &current_message);
/**
* @brief 处理 OTA ACK 查询,APP 有效时回发确认帧
* @return void
*/
void handle_ota_ack_message();
public:
// 节点 ID 相关辅助函数 (使用高 16 位存储节点 ID)
/**
* @brief build_can_id 函数
* @param[in] base_id 参数
* @return u32 返回值
*/
u32 build_can_id(u32 base_id); // 根据节点 ID 构建 CAN ID,格式:[节点 ID(16 位)][基础 ID(16 位)]
/**
* @brief is_message_for_me 函数
* @param[in] received_id 参数
* @return bool 返回值
*/
bool is_message_for_me(u32 received_id); // 判断消息是否发给本节点
2025-09-23 00:27:51 +08:00
public:
// 添加构造函数声明
/**
* @brief 初始化对象或模块
* @return u8 返回值
*/
2025-12-08 02:48:59 +08:00
u8 init(void);
2025-10-14 00:49:58 +08:00
can_receive_message_struct receive_message; // 接收消息结构体
FlagStatus can0_send_flag; // CAN0 发送标志
float_union_t testfloat_union = {0}; // 测试用
u16 test_u16 = 0;
2025-10-14 00:49:58 +08:00
2026-01-05 00:55:00 +08:00
bool MagStatus = 0; // 磁状态码
bool ThermalStatus = 0; // 热能状态码
/**
* @brief communication_check 函数
* @return void
*/
2026-01-05 00:55:00 +08:00
void communication_check(); // 通信检查
/**
* @brief CAN_Sleep 函数
* @return u8 返回值
*/
u8 CAN_Sleep(); // CAN 进入睡眠
/**
* @brief CAN_Wakeup 函数
* @return u8 返回值
*/
u8 CAN_Wakeup(); // CAN 唤醒
/**
* @brief CAN_AsyncSend 函数
* @param[in] ID 参数
* @param[in] length 参数
* @param[in] data 参数
* @return u8 返回值
*/
u8 CAN_AsyncSend(u32 ID, u8 length, u8 *data); // CAN 异步发送 (使用 DMA)
/**
* @brief CANFD_AsyncSend 函数
* @param[in] ID 参数
* @param[in] length 参数
* @param[in] data 参数
* @return u8 返回值
*/
u8 CANFD_AsyncSend(u32 ID, u8 length, u8 *data); // CANFD 异步发送 (使用 DMA)
/**
* @brief CAN_all_Send 函数
* @return u8 返回值
*/
u8 CAN_all_Send(); // CAN 发送
/**
* @brief CANFD_all_Send 函数
* @return u8 返回值
*/
u8 CANFD_all_Send(); // CANFD 发送
/**
* @brief enter_silent_mode 函数
* @return void
*/
void enter_silent_mode(); // 进入静默模式(停发 10 秒)
/**
* @brief is_in_silent_mode 函数
* @return bool 返回值
*/
bool is_in_silent_mode(); // 检查是否在静默模式中
// 节点 ID 管理接口
/**
* @brief 获取 get_node_id 对应的数据或状态
* @return u16 返回值
*/
u16 get_node_id(); // 获取当前节点 ID
/**
* @brief 设置 set_node_id 对应的参数或状态
* @param[in] new_id 参数
* @return void
*/
void set_node_id(u16 new_id); // 设置节点 ID
/**
* @brief load_node_id_from_flash 函数
* @return u8 返回值
*/
u8 load_node_id_from_flash(); // 从 Flash 加载节点 ID
/**
* @brief save_node_id_to_flash 函数
* @param[in] new_id 参数
* @return u8 返回值
*/
u8 save_node_id_to_flash(u16 new_id); // 保存节点 ID 到 Flash
// 中断处理函数需要访问的公共接口
/**
* @brief enqueue_rx_message_from_isr 函数
* @param[in] message 参数
* @return void
*/
void enqueue_rx_message_from_isr(const can_receive_message_struct& message) {
if (!is_rx_buffer_full()) {
rx_message_buffer[rx_buffer_head] = message;
rx_buffer_head = (rx_buffer_head + 1) % CAN_RX_BUFFER_SIZE;
}
// 如果缓冲区满,丢弃新消息
}
2025-09-23 00:27:51 +08:00
};
#ifdef __cplusplus
}
#endif
#endif