2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @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
|
|
|
|
|
|
|
2026-02-02 02:12:14 +08:00
|
|
|
|
#include <cstdint>
|
2025-09-23 00:27:51 +08:00
|
|
|
|
#include "gd32c10x_can.h"
|
2026-03-15 02:38:50 +08:00
|
|
|
|
#include "config.h"
|
2025-09-23 00:27:51 +08:00
|
|
|
|
|
2026-03-15 02:38:50 +08:00
|
|
|
|
// 定义一个联合体类型用于 float 和 byte 数组之间的转换
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 匿名联合体 联合体定义
|
|
|
|
|
|
*/
|
2025-09-23 00:27:51 +08:00
|
|
|
|
typedef union {
|
|
|
|
|
|
float f;
|
|
|
|
|
|
u8 b[4];
|
|
|
|
|
|
} float_union_t;
|
|
|
|
|
|
|
2026-03-15 02:38:50 +08:00
|
|
|
|
// 添加辅助函数用于将 u16 类型数据打包到 u8 数组中
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @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
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-16 02:13:37 +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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-15 02:38:50 +08:00
|
|
|
|
// 添加辅助函数用于将 float 类型数据打包到 u8 数组中
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @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
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-15 02:38:50 +08:00
|
|
|
|
// 添加辅助函数用于从 u8 数组中解包 short 类型数据
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @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
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-15 02:38:50 +08:00
|
|
|
|
// 添加辅助函数用于从 u8 数组中解包 u16 类型数据
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @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
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-15 02:38:50 +08:00
|
|
|
|
// 添加辅助函数用于从 u8 数组中解包 float 类型数据
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 初始化 CAN 引脚
|
|
|
|
|
|
* @return u8 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u8 can_gpio_init(void); // CAN 引脚初始化
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 配置 CAN FD 外设
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
void canfd_config(void); // CANFD 初始化
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 初始化 CAN DMA 通道
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
void can_dma_init(void); // CAN DMA 初始化
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief CAN0 发送中断处理函数
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
2026-05-15 23:04:04 +08:00
|
|
|
|
void CAN0_TX_IRQHandler(void); // CAN 发送中断处理函数
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief CAN0 接收中断处理函数
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
void CAN0_RX0_IRQHandler(void); // CAN 接收中断处理函数
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief DMA0 通道 4 中断处理函数
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
void DMA0_Channel4_IRQHandler(void); // DMA 通道 4 中断处理函数 (CAN 接收)
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief DMA0 通道 5 中断处理函数
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
void DMA0_Channel5_IRQHandler(void); // DMA 通道 5 中断处理函数 (CAN 发送)
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief jumpToBOOT 函数
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
2026-01-04 22:26:22 +08:00
|
|
|
|
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
|
|
|
|
/*!
|
2026-03-15 02:38:50 +08:00
|
|
|
|
\brief CAN 通信类
|
|
|
|
|
|
\note 封装 CAN 发送和接收功能,支持多电机节点 ID 隔离
|
2025-09-23 00:27:51 +08:00
|
|
|
|
*/
|
|
|
|
|
|
class CAN_transmiter {
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
2026-03-15 02:38:50 +08:00
|
|
|
|
static const uint8_t CAN_RX_BUFFER_SIZE = 8; // CAN 接收缓冲区大小
|
2026-03-19 23:49:08 +08:00
|
|
|
|
static const u32 CAN_SILENT_DURATION_MS = 10000; // CAN 静默时长 10 秒
|
2026-03-09 01:35:26 +08:00
|
|
|
|
|
2025-12-20 19:53:52 +08:00
|
|
|
|
bool is_sleep = false; // 是否休眠
|
2026-03-19 23:49:08 +08:00
|
|
|
|
bool is_silent = false; // 是否静默(收到 base_id=0x0000 后进入静默)
|
|
|
|
|
|
u32 silent_start_time = 0; // 静默开始时间(ms)
|
2025-12-20 19:53:52 +08:00
|
|
|
|
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u16 node_id; // 本节点 ID(0-254),使用 CAN ID 高 8 位存储 (在 init() 中初始化为 DEFAULT_NODE_ID)
|
2026-02-02 02:12:14 +08:00
|
|
|
|
u8 Target_Control_Mode = 0; // 目标控制模式
|
|
|
|
|
|
u8 controller_Mode = 0; // 当前模式
|
2026-03-15 02:38:50 +08:00
|
|
|
|
short mcu_temp = 0; // MCU 温度
|
2026-02-02 02:12:14 +08:00
|
|
|
|
short motor_temp = 0; // 电机温度
|
|
|
|
|
|
u16 Power_Voltage = 0; // 电源电压
|
|
|
|
|
|
|
|
|
|
|
|
u16 limit_voltage = 0; // 限制电压
|
2026-05-17 23:40:53 +08:00
|
|
|
|
u8 cpu_usage = 0; // CPU 使用率(%)
|
2026-02-02 02:12:14 +08:00
|
|
|
|
|
|
|
|
|
|
float_union_t rt_angle_union = {0}; // 实时角度
|
|
|
|
|
|
float_union_t rt_velocity_union = {0}; // 实时速度
|
|
|
|
|
|
float_union_t rt_current_union = {0}; // 实时电流
|
|
|
|
|
|
|
2025-12-20 19:53:52 +08:00
|
|
|
|
float_union_t target_angle_union = {0}; // 目标角度
|
|
|
|
|
|
float_union_t target_velocity_union = {0}; // 目标速度
|
2026-02-02 02:12:14 +08:00
|
|
|
|
float_union_t target_current_union = {0}; // 目标电流
|
|
|
|
|
|
|
2026-03-15 02:38:50 +08:00
|
|
|
|
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
|
|
|
|
|
2026-02-02 02:12:14 +08:00
|
|
|
|
bool MotorStatus = 0; // 电机状态码
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u8 EEPROMStatus = 0; // EEPROM 状态码
|
2026-02-02 02:12:14 +08:00
|
|
|
|
|
2025-10-14 00:49:58 +08:00
|
|
|
|
can_trasnmit_message_struct transmit_message; // 发送消息结构体
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u8 transmit_mailbox = CAN_NOMAILBOX; // 初始化为无 mailbox 状态
|
|
|
|
|
|
u8 transmit_data[64]; // CANFD 最大 64 字节
|
2025-09-23 00:27:51 +08:00
|
|
|
|
|
2026-03-15 02:38:50 +08:00
|
|
|
|
// CAN 接收消息队列
|
2026-03-09 01:35:26 +08:00
|
|
|
|
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;
|
|
|
|
|
|
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 更新对象内部状态或采样数据
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
2026-01-05 00:55:00 +08:00
|
|
|
|
void update(); // 更新数据
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief CAN_Receive 函数
|
|
|
|
|
|
* @return u8 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u8 CAN_Receive(); // CAN 接收
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief CANFD_Receive 函数
|
|
|
|
|
|
* @return u8 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u8 CANFD_Receive(); // CANFD 接收
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief is_rx_buffer_full 函数
|
|
|
|
|
|
* @return bool 返回值
|
|
|
|
|
|
*/
|
2026-03-09 01:35:26 +08:00
|
|
|
|
bool is_rx_buffer_full();
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief is_rx_buffer_empty 函数
|
|
|
|
|
|
* @return bool 返回值
|
|
|
|
|
|
*/
|
2026-03-09 01:35:26 +08:00
|
|
|
|
bool is_rx_buffer_empty();
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief dequeue_rx_message 函数
|
|
|
|
|
|
* @param[in] message 参数
|
|
|
|
|
|
* @return bool 返回值
|
|
|
|
|
|
*/
|
2026-03-09 01:35:26 +08:00
|
|
|
|
bool dequeue_rx_message(can_receive_message_struct& message);
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief check_silent_mode 函数
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
2026-03-19 23:49:08 +08:00
|
|
|
|
void check_silent_mode(); // 检查静默模式是否结束
|
2026-05-24 01:21:41 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @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 ¤t_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 ¤t_message);
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 处理已经确认发给本节点的普通协议消息
|
|
|
|
|
|
* @param[in,out] current_message 当前 CAN 消息
|
|
|
|
|
|
* @param[in] base_id 低 16 位基础 ID
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
|
|
|
|
|
void handle_node_message(can_receive_message_struct ¤t_message,
|
|
|
|
|
|
u32 base_id);
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 解析控制命令并更新 FOC 目标值和 PID 参数
|
|
|
|
|
|
* @param[in,out] current_message 当前 CAN 消息
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
|
|
|
|
|
void handle_control_command(can_receive_message_struct ¤t_message);
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 解析复位命令各 bit 位并执行对应动作
|
|
|
|
|
|
* @param[in,out] current_message 当前 CAN 消息
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
|
|
|
|
|
void handle_reset_command(can_receive_message_struct ¤t_message);
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 处理 OTA ACK 查询,APP 有效时回发确认帧
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
|
|
|
|
|
void handle_ota_ack_message();
|
2026-03-15 02:38:50 +08:00
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
// 节点 ID 相关辅助函数 (使用高 16 位存储节点 ID)
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief build_can_id 函数
|
|
|
|
|
|
* @param[in] base_id 参数
|
|
|
|
|
|
* @return u32 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u32 build_can_id(u32 base_id); // 根据节点 ID 构建 CAN ID,格式:[节点 ID(16 位)][基础 ID(16 位)]
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief is_message_for_me 函数
|
|
|
|
|
|
* @param[in] received_id 参数
|
|
|
|
|
|
* @return bool 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
bool is_message_for_me(u32 received_id); // 判断消息是否发给本节点
|
2025-09-23 00:27:51 +08:00
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
// 添加构造函数声明
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 初始化对象或模块
|
|
|
|
|
|
* @return u8 返回值
|
|
|
|
|
|
*/
|
2025-12-08 02:48:59 +08:00
|
|
|
|
u8 init(void);
|
2025-10-14 00:49:58 +08:00
|
|
|
|
|
2025-12-20 19:53:52 +08:00
|
|
|
|
can_receive_message_struct receive_message; // 接收消息结构体
|
2026-03-15 02:38:50 +08:00
|
|
|
|
FlagStatus can0_send_flag; // CAN0 发送标志
|
2025-12-20 19:53:52 +08:00
|
|
|
|
float_union_t testfloat_union = {0}; // 测试用
|
2026-02-02 02:12:14 +08:00
|
|
|
|
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; // 热能状态码
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief communication_check 函数
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
2026-01-05 00:55:00 +08:00
|
|
|
|
void communication_check(); // 通信检查
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief CAN_Sleep 函数
|
|
|
|
|
|
* @return u8 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u8 CAN_Sleep(); // CAN 进入睡眠
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief CAN_Wakeup 函数
|
|
|
|
|
|
* @return u8 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u8 CAN_Wakeup(); // CAN 唤醒
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief CAN_AsyncSend 函数
|
|
|
|
|
|
* @param[in] ID 参数
|
|
|
|
|
|
* @param[in] length 参数
|
|
|
|
|
|
* @param[in] data 参数
|
|
|
|
|
|
* @return u8 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u8 CAN_AsyncSend(u32 ID, u8 length, u8 *data); // CAN 异步发送 (使用 DMA)
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief CANFD_AsyncSend 函数
|
|
|
|
|
|
* @param[in] ID 参数
|
|
|
|
|
|
* @param[in] length 参数
|
|
|
|
|
|
* @param[in] data 参数
|
|
|
|
|
|
* @return u8 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u8 CANFD_AsyncSend(u32 ID, u8 length, u8 *data); // CANFD 异步发送 (使用 DMA)
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief CAN_all_Send 函数
|
|
|
|
|
|
* @return u8 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u8 CAN_all_Send(); // CAN 发送
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief CANFD_all_Send 函数
|
|
|
|
|
|
* @return u8 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u8 CANFD_all_Send(); // CANFD 发送
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief enter_silent_mode 函数
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
2026-03-19 23:49:08 +08:00
|
|
|
|
void enter_silent_mode(); // 进入静默模式(停发 10 秒)
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief is_in_silent_mode 函数
|
|
|
|
|
|
* @return bool 返回值
|
|
|
|
|
|
*/
|
2026-03-19 23:49:08 +08:00
|
|
|
|
bool is_in_silent_mode(); // 检查是否在静默模式中
|
2026-03-15 02:38:50 +08:00
|
|
|
|
|
|
|
|
|
|
// 节点 ID 管理接口
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取 get_node_id 对应的数据或状态
|
|
|
|
|
|
* @return u16 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u16 get_node_id(); // 获取当前节点 ID
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 设置 set_node_id 对应的参数或状态
|
|
|
|
|
|
* @param[in] new_id 参数
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
void set_node_id(u16 new_id); // 设置节点 ID
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief load_node_id_from_flash 函数
|
|
|
|
|
|
* @return u8 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u8 load_node_id_from_flash(); // 从 Flash 加载节点 ID
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief save_node_id_to_flash 函数
|
|
|
|
|
|
* @param[in] new_id 参数
|
|
|
|
|
|
* @return u8 返回值
|
|
|
|
|
|
*/
|
2026-03-15 02:38:50 +08:00
|
|
|
|
u8 save_node_id_to_flash(u16 new_id); // 保存节点 ID 到 Flash
|
2026-03-09 01:35:26 +08:00
|
|
|
|
|
|
|
|
|
|
// 中断处理函数需要访问的公共接口
|
2026-05-23 22:46:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief enqueue_rx_message_from_isr 函数
|
|
|
|
|
|
* @param[in] message 参数
|
|
|
|
|
|
* @return void
|
|
|
|
|
|
*/
|
2026-03-09 01:35:26 +08:00
|
|
|
|
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
|
|
|
|
|
|
|
2025-11-01 20:29:11 +08:00
|
|
|
|
#endif
|