refactor(FOC): 添加Doxygen文档注释并优化SVPWM算法性能

添加了完整的Doxygen文档注释到FOC算法模块的所有函数、类和变量,提升了代码可读性和维护性。同时优化了SVPWM算法实现,将atan2f替换为符号法扇区判断,显著提升计算效率(约15周期vs atan2f 300周期),并改进了arm_sin_cos_f32替代sqrtf提高性能。

feat(FOC): 统一电气角度计算避免重复运算

重构代码以统一电气角度计算,在各个控制循环中只计算一次电气角度并传递给需要的函数,避免了多次重复的fmodf运算和角度归一化操作,提升了实时控制性能。

refactor(Filter): 改进α-β观测器角度处理精度

修改角度卡尔曼滤波器在归一化角度空间[0,360)内工作,避免大累积角度的浮点精度损失问题,确保静止状态下不会产生虚假速度,同时保持与下游代码的兼容性。

refactor: 为算法模块添加完整文档注释

为所有算法模块(FOC、Filter、pid、thermal)添加了详细的Doxygen文档注释,包括函数说明、参数描述、返回值说明等,便于代码理解和API文档生成。
This commit is contained in:
cbb
2026-05-23 22:46:32 +08:00
parent bec7c11b87
commit 4c4e47e9e3
62 changed files with 10367 additions and 126 deletions
+59 -27
View File
@@ -1,3 +1,9 @@
/**
* @file device/ADC.cpp
* @brief 底层设备驱动与外设封装源文件
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
*/
#include "adc.h"
#include "Can.h"
#include "FOC.h"
@@ -10,9 +16,13 @@
#include <cstring>
#include <gd32c10x_dma.h>
/** @brief ADC_SCALE 常量定义 */
constexpr float ADC_SCALE = 3.3f / 4096.0f;
/** @brief TEMP_FACTOR 常量定义 */
constexpr float TEMP_FACTOR = 1000.0f / 4.3f;
/** @brief VCC_FACTOR 常量定义 */
constexpr float VCC_FACTOR = 11.0f;
/** @brief CURRENT_FACTOR 常量定义 */
constexpr float CURRENT_FACTOR =
1.0f / 50.0f * 100.0f; // 50倍放大,100倍电流采样电阻, 单位mA
extern CAN_transmiter CAN0_transmiter;
@@ -22,6 +32,11 @@ u16 adc_value[3] = {0}; // regular DMA: MCU温度 / DRV温度 / VBUS
static volatile u16 adc_current_value[3] = {0}; // injected 同步采样: U / V / W
static volatile u8 adc_current_frame_ready = 0;
/**
* @brief 将电流 ADC 原始值换算为毫安值
* @param[in] raw_adc 参数
* @return float 返回值
*/
static inline float current_adc_to_ma(u16 raw_adc) {
return (raw_adc * ADC_SCALE + CURRENT_OFFSET) * CURRENT_FACTOR;
}
@@ -155,12 +170,7 @@ u8 sampler::init() {
* 温度值,单位为摄氏度,范围应在-40到145之间,如果读取失败则返回0.0f
*/
float sampler::get_mcu_temp() {
tempora_sample = medium_filter(mcu_temp_samples, ADC_FILTER_SIZE);
// 检查温度读数是否在有效范围内
if (tempora_sample < MIN_TEMP or tempora_sample > MAX_TEMP) {
return ERROR_ADC_VAL;
}
return tempora_sample;
return cached_mcu_temp;
}
/**
@@ -171,12 +181,7 @@ float sampler::get_mcu_temp() {
* 如果计算结果超出有效范围(-40到255摄氏度),则重新采样计算。
*/
float sampler::get_drv_temp() {
tempora_sample = medium_filter(drv_temp_samples, ADC_FILTER_SIZE);
// 检查温度读数是否在有效范围内
if (tempora_sample < MIN_TEMP || tempora_sample > MAX_TEMP) {
return ERROR_ADC_VAL;
}
return tempora_sample;
return cached_drv_temp;
}
/**
@@ -221,13 +226,7 @@ float sampler::get_current(char type) {
* 如果计算结果超出有效范围(-40到255伏特),则重新采样计算。
*/
float sampler::get_vbus_voltage() {
tempora_sample = medium_filter(vbus_samples, ADC_FILTER_SIZE);
// 检查电压读数是否在有效范围内
const u8 mid = ADC_FILTER_SIZE / 2;
if (vbus_samples[mid] > MAX_VCC or vbus_samples[mid] < MIN_VCC) {
return ERROR_ADC_VAL;
}
return tempora_sample;
return cached_vbus;
}
/**
@@ -237,21 +236,39 @@ float sampler::get_vbus_voltage() {
* 如果计算结果超出有效范围(-40到255摄氏度),则重新采样计算。
*/
void sampler::update_mcu_temp() {
memmove(mcu_temp_samples, mcu_temp_samples + 1,
(ADC_FILTER_SIZE - 1) * sizeof(float));
mcu_temp_samples[ADC_FILTER_SIZE - 1] =
// 环形缓冲区写入,替代 memmove
mcu_temp_samples[mcu_temp_head] =
(1.43f - adc_value[0] * ADC_SCALE) * TEMP_FACTOR + 35.0f;
mcu_temp_head++;
if (mcu_temp_head >= ADC_FILTER_SIZE) mcu_temp_head = 0;
// 更新缓存:中值滤波
tempora_sample = medium_filter(mcu_temp_samples, ADC_FILTER_SIZE);
if (tempora_sample < MIN_TEMP || tempora_sample > MAX_TEMP) {
cached_mcu_temp = ERROR_ADC_VAL;
} else {
cached_mcu_temp = tempora_sample;
}
}
/**
* @brief 更新MCU温度
*/
void sampler::update_drv_temp() {
memmove(drv_temp_samples, drv_temp_samples + 1,
(ADC_FILTER_SIZE - 1) * sizeof(float));
// 环形缓冲区写入,替代 memmove
float R_now = (float)adc_value[1] / (4096 - (float)adc_value[1]) * 4700;
drv_temp_samples[ADC_FILTER_SIZE - 1] =
drv_temp_samples[drv_temp_head] =
1.0f / (0.00335f + 0.00025f * log(R_now / 10000.0f)) - 273.15f;
drv_temp_head++;
if (drv_temp_head >= ADC_FILTER_SIZE) drv_temp_head = 0;
// 更新缓存:中值滤波
tempora_sample = medium_filter(drv_temp_samples, ADC_FILTER_SIZE);
if (tempora_sample < MIN_TEMP || tempora_sample > MAX_TEMP) {
cached_drv_temp = ERROR_ADC_VAL;
} else {
cached_drv_temp = tempora_sample;
}
}
/**
@@ -278,10 +295,25 @@ void sampler::update_current() {
* @brief 更新供电电压
*/
void sampler::update_vbus_voltage() {
memmove(vbus_samples, vbus_samples + 1, (ADC_FILTER_SIZE - 1) * sizeof(float));
vbus_samples[ADC_FILTER_SIZE - 1] = adc_value[2] * ADC_SCALE * VCC_FACTOR;
// 环形缓冲区写入,替代 memmove
vbus_samples[temp_vbus_head] = adc_value[2] * ADC_SCALE * VCC_FACTOR;
temp_vbus_head++;
if (temp_vbus_head >= ADC_FILTER_SIZE) temp_vbus_head = 0;
// 更新缓存:中值滤波 + 范围检查
tempora_sample = medium_filter(vbus_samples, ADC_FILTER_SIZE);
const u8 mid = ADC_FILTER_SIZE / 2;
if (vbus_samples[mid] > MAX_VCC || vbus_samples[mid] < MIN_VCC) {
cached_vbus = ERROR_ADC_VAL;
} else {
cached_vbus = tempora_sample;
}
}
/**
* @brief ADC0_1_IRQHandler 中断处理函数
* @return void
*/
extern "C" void ADC0_1_IRQHandler(void) {
if (adc_interrupt_flag_get(ADC0, ADC_INT_FLAG_EOIC) != RESET) {
/* 丢弃 rank0 dummy,真实样本使用 rank1/2/3,对应 U/V/W 同一 PWM 时刻 */
+108
View File
@@ -1,3 +1,9 @@
/**
* @file device/Can.cpp
* @brief 底层设备驱动与外设封装源文件
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
*/
#include "Can.h"
#include "FOC.h"
#include "Filter.h"
@@ -20,11 +26,14 @@
// CAN 调试宏定义
#if CAN_DEBUG
/** @brief CAN_DEBUG_PRINT 宏定义 */
#define CAN_DEBUG_PRINT(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
/** @brief CAN_DEBUG_PRINT 宏定义 */
#define CAN_DEBUG_PRINT(fmt, ...) ((void)0)
#endif
/** @brief CANX 常量定义 */
constexpr u16 CANX = CAN0;
extern FOC_Controller FOC;
extern sampler sampler;
@@ -43,7 +52,9 @@ static volatile bool can_rx_dma_busy = false;
static can_receive_message_struct can_rx_dma_message;
// CAN接收/发送队列结构
/** @brief CAN_RX_QUEUE_SIZE 宏定义 */
#define CAN_RX_QUEUE_SIZE 32
/** @brief CAN_TX_QUEUE_SIZE 宏定义 */
#define CAN_TX_QUEUE_SIZE 32
typedef struct {
@@ -233,6 +244,10 @@ bool CAN_transmiter::dequeue_rx_message(can_receive_message_struct &message) {
// 静默模式相关函数实现
// 使用 systick 获取系统时间(ms)
/**
* @brief 获取系统毫秒计数
* @return extern u32 返回值
*/
extern u32 get_systick_ms(void);
/*!
@@ -523,6 +538,10 @@ void canfd_loopback_test(void) {
uint8_t transmit_mailbox = 0;
std::mt19937 gen;
/**
* @brief dis 函数
* @return std::uniform_int_distribution<int> 返回值
*/
std::uniform_int_distribution<int> dis(0, 255);
can_struct_para_init(CAN_FD_FRAME_STRUCT, &transmit_message);
@@ -581,7 +600,17 @@ void can_loopback_test(void) {
uint32_t timeout = 0xFF;
uint8_t transmit_mailbox = 0;
/**
* @brief gen 函数
* @param[in] rand 参数
* @return std::mt19937 返回值
*/
std::mt19937 gen(rand()); // 使用随机设备生成的种子
/**
* @brief dis 函数
* @param[in] xff 参数
* @return std::uniform_int_distribution<int> 返回值
*/
std::uniform_int_distribution<int> dis(0, 0xff);
can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &transmit_message);
@@ -671,19 +700,38 @@ u8 CAN_transmiter::init() {
return 0;
}
/**
* @brief CAN_EnterCritical 函数
* @return uint32_t 返回值
*/
static uint32_t CAN_EnterCritical(void) {
uint32_t primask = __get_PRIMASK();
__disable_irq();
return primask;
}
/**
* @brief CAN_ExitCritical 函数
* @param[in] primask 参数
* @return void
*/
static void CAN_ExitCritical(uint32_t primask) { __set_PRIMASK(primask); }
/**
* @brief CANFD_DlcToLength 函数
* @param[in] dlc 参数
* @return u8 返回值
*/
static u8 CANFD_DlcToLength(u8 dlc) {
return (dlc <= 8U) ? dlc
: ((dlc <= 15U) ? CANFD_DLC_LENGTH_TABLE[dlc - 9U] : 0U);
}
/**
* @brief CANFD_NormalizeLength 函数
* @param[in] length 参数
* @return u8 返回值
*/
static u8 CANFD_NormalizeLength(u8 length) {
if (length <= 8U)
return length;
@@ -695,8 +743,18 @@ static u8 CANFD_NormalizeLength(u8 length) {
return 0U;
}
/**
* @brief CANFD_WordCount 函数
* @param[in] length 参数
* @return u8 返回值
*/
static u8 CANFD_WordCount(u8 length) { return (length + 3U) / 4U; }
/**
* @brief CAN_RX_QueuePushFromIsr 函数
* @param[in] message 参数
* @return void
*/
static void CAN_RX_QueuePushFromIsr(const can_receive_message_struct &message) {
if (rx_queue_count < CAN_RX_QUEUE_SIZE) {
rx_queue[rx_queue_tail].id = message.rx_efid;
@@ -716,16 +774,29 @@ static void CAN_RX_QueuePushFromIsr(const can_receive_message_struct &message) {
static void CAN_RX_ReleaseFifo0(void) { CAN_RFIFO0(CAN0) |= CAN_RFIFO0_RFD0; }
/**
* @brief CAN_RX_Fifo0PendingCount 函数
* @return u8 返回值
*/
static u8 CAN_RX_Fifo0PendingCount(void) {
return can_receive_message_length_get(CAN0, CAN_FIFO0);
}
/**
* @brief CAN_TX_HasEmptyMailbox 函数
* @return bool 返回值
*/
static bool CAN_TX_HasEmptyMailbox(void) {
return (can_flag_get(CAN0, CAN_FLAG_TME0) != RESET) ||
(can_flag_get(CAN0, CAN_FLAG_TME1) != RESET) ||
(can_flag_get(CAN0, CAN_FLAG_TME2) != RESET);
}
/**
* @brief CAN_RX_ReadMetadata 函数
* @param[in] message 参数
* @return void
*/
static void CAN_RX_ReadMetadata(can_receive_message_struct *message) {
uint8_t dlc;
uint32_t rfifomi = CAN_RFIFOMI(CAN0, CAN_FIFO0);
@@ -752,6 +823,11 @@ static void CAN_RX_ReadMetadata(can_receive_message_struct *message) {
}
}
/**
* @brief CAN_RX_StartPayloadDma 函数
* @param[in] metadata 参数
* @return void
*/
static void CAN_RX_StartPayloadDma(const can_receive_message_struct &metadata) {
can_rx_dma_message = metadata;
if (can_rx_dma_message.rx_dlen > 64) {
@@ -775,6 +851,10 @@ static void CAN_RX_StartPayloadDma(const can_receive_message_struct &metadata) {
dma_channel_enable(DMA0, DMA_CH4);
}
/**
* @brief CAN_RX_PumpFifo0 函数
* @return void
*/
static void CAN_RX_PumpFifo0(void) {
while (!can_rx_dma_busy) {
if (CAN_RX_Fifo0PendingCount() == 0U) {
@@ -794,6 +874,11 @@ static void CAN_RX_PumpFifo0(void) {
}
}
/**
* @brief CAN_RX_QueuePop 函数
* @param[in] item 参数
* @return u8 返回值
*/
static u8 CAN_RX_QueuePop(can_rx_queue_item_t *item) {
u8 popped = 0U;
uint32_t primask = CAN_EnterCritical();
@@ -810,6 +895,11 @@ static u8 CAN_RX_QueuePop(can_rx_queue_item_t *item) {
return popped;
}
/**
* @brief CAN_TX_QueuePush 函数
* @param[in] message 参数
* @return u8 返回值
*/
static u8 CAN_TX_QueuePush(const can_trasnmit_message_struct &message) {
u8 queued = 0U;
uint32_t primask = CAN_EnterCritical();
@@ -831,6 +921,11 @@ static u8 CAN_TX_QueuePush(const can_trasnmit_message_struct &message) {
return 0U;
}
/**
* @brief CAN_TX_QueuePeek 函数
* @param[in] message 参数
* @return u8 返回值
*/
static u8 CAN_TX_QueuePeek(can_trasnmit_message_struct *message) {
u8 has_message = 0U;
uint32_t primask = CAN_EnterCritical();
@@ -842,6 +937,11 @@ static u8 CAN_TX_QueuePeek(can_trasnmit_message_struct *message) {
return has_message;
}
/**
* @brief CAN_TX_QueuePop 函数
* @param[in] message 参数
* @return u8 返回值
*/
static u8 CAN_TX_QueuePop(can_trasnmit_message_struct *message) {
u8 popped = 0U;
uint32_t primask = CAN_EnterCritical();
@@ -856,6 +956,10 @@ static u8 CAN_TX_QueuePop(can_trasnmit_message_struct *message) {
return popped;
}
/**
* @brief CAN_TX_DisableTmeIfQueueEmpty 函数
* @return void
*/
static void CAN_TX_DisableTmeIfQueueEmpty(void) {
uint32_t primask = CAN_EnterCritical();
if (tx_queue_count == 0U) {
@@ -864,6 +968,10 @@ static void CAN_TX_DisableTmeIfQueueEmpty(void) {
CAN_ExitCritical(primask);
}
/**
* @brief CAN_TX_ServiceQueue 函数
* @return void
*/
static void CAN_TX_ServiceQueue(void) {
can_trasnmit_message_struct queued_message;
while (CAN_TX_HasEmptyMailbox()) {
+193
View File
@@ -1,3 +1,9 @@
/**
* @file device/Can.h
* @brief 底层设备驱动与外设封装源文件
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
*/
#ifndef _CAN_H
#define _CAN_H
@@ -11,18 +17,35 @@ extern "C" {
#include "config.h"
// 定义一个联合体类型用于 float 和 byte 数组之间的转换
/**
* @brief 匿名联合体 联合体定义
*/
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
*/
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);
}
// 添加辅助函数用于将 float 类型数据打包到 u8 数组中
/**
* @brief pack_float_to_bytes 函数
* @param[in] buffer 参数
* @param[in] offset 参数
* @param[in] float_union 参数
* @return void
*/
static inline void pack_float_to_bytes(u8 *buffer, u16 offset,
float_union_t &float_union) {
buffer[offset] = float_union.b[0];
@@ -32,18 +55,36 @@ static inline void pack_float_to_bytes(u8 *buffer, u16 offset,
}
// 添加辅助函数用于从 u8 数组中解包 short 类型数据
/**
* @brief unpack_bytes_to_short 函数
* @param[in] buffer 参数
* @param[in] offset 参数
* @return short 返回值
*/
static inline short unpack_bytes_to_short(u8 *buffer, u16 offset) {
short value = (short)(buffer[offset] | (buffer[offset + 1] << 8));
return value;
}
// 添加辅助函数用于从 u8 数组中解包 u16 类型数据
/**
* @brief unpack_bytes_to_u16 函数
* @param[in] buffer 参数
* @param[in] offset 参数
* @return u16 返回值
*/
static inline u16 unpack_bytes_to_u16(u8 *buffer, u16 offset) {
u16 value = (u16)(buffer[offset] | (buffer[offset + 1] << 8));
return value;
}
// 添加辅助函数用于从 u8 数组中解包 float 类型数据
/**
* @brief unpack_bytes_to_float 函数
* @param[in] buffer 参数
* @param[in] offset 参数
* @return float_union_t 返回值
*/
static inline float_union_t unpack_bytes_to_float(u8 *buffer, u16 offset) {
float_union_t float_union;
float_union.b[0] = buffer[offset];
@@ -53,17 +94,61 @@ static inline float_union_t unpack_bytes_to_float(u8 *buffer, u16 offset) {
return float_union;
}
/**
* @brief 初始化 CAN 引脚
* @return u8 返回值
*/
u8 can_gpio_init(void); // CAN 引脚初始化
/**
* @brief 配置 CAN 外设
* @return void
*/
void can_config(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
*/
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();
/**
* @brief can_loopback_init 函数
* @return void
*/
void can_loopback_init(void);
/**
* @brief can_loopback_test 函数
* @return void
*/
void can_loopback_test(void);
/*!
@@ -114,21 +199,64 @@ class CAN_transmiter {
volatile uint8_t rx_buffer_head = 0;
volatile uint8_t rx_buffer_tail = 0;
/**
* @brief 更新对象内部状态或采样数据
* @return void
*/
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(); // 检查静默模式是否结束
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); // 判断消息是否发给本节点
public:
// 添加构造函数声明
/**
* @brief 初始化对象或模块
* @return u8 返回值
*/
u8 init(void);
can_receive_message_struct receive_message; // 接收消息结构体
@@ -138,23 +266,88 @@ class CAN_transmiter {
bool MagStatus = 0; // 磁状态码
bool ThermalStatus = 0; // 热能状态码
/**
* @brief communication_check 函数
* @return void
*/
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;
+6
View File
@@ -1,3 +1,9 @@
/**
* @file device/Timer.cpp
* @brief 底层设备驱动与外设封装源文件
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
*/
#include "Timer.h"
#include "Can.h"
#include "FOC.h"
+39
View File
@@ -1,3 +1,9 @@
/**
* @file device/Timer.h
* @brief 底层设备驱动与外设封装源文件
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
*/
#ifndef _TIMER_H
#define _TIMER_H
@@ -7,13 +13,46 @@ extern "C" {
#include <cstdint>
/**
* @brief User_timer_init 函数
* @return void
*/
void User_timer_init(void);
/**
* @brief Set_Pwm 函数
* @param[in] channel 参数
* @param[in] duty_cycle 参数
* @return void
*/
void Set_Pwm(u16 channel, float duty_cycle);
/**
* @brief Set_3Pwm 函数
* @param[in] duty_cycle0 参数
* @param[in] duty_cycle1 参数
* @param[in] duty_cycle2 参数
* @return void
*/
void Set_3Pwm(float duty_cycle0, float duty_cycle1,float duty_cycle2);
/**
* @brief TIMER2 中断处理函数
* @return void
*/
void TIMER2_IRQHandler(void);
/**
* @brief timer1_pwm_config 函数
* @return void
*/
void timer1_pwm_config(void);
/**
* @brief timer1_gpio_config 函数
* @return void
*/
void timer1_gpio_config(void);
/**
* @brief TIMER1 中断处理函数
* @return void
*/
void TIMER1_IRQHandler(void); // 添加TIMER1中断处理函数声明
#ifdef __cplusplus
+56
View File
@@ -1,3 +1,9 @@
/**
* @file device/adc.h
* @brief 底层设备驱动与外设封装源文件
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
*/
#ifndef _ADC_H
#define _ADC_H
@@ -7,6 +13,9 @@ extern "C" {
#include "config.h"
/**
* @brief sampler 类或结构体
*/
class sampler {
private:
float vbus_samples[ADC_FILTER_SIZE];
@@ -16,22 +25,69 @@ class sampler {
float mcu_temp_samples[ADC_FILTER_SIZE];
float drv_temp_samples[ADC_FILTER_SIZE];
u8 current_sample_head;
u8 temp_vbus_head; // 环形缓冲区 head
u8 mcu_temp_head;
u8 drv_temp_head;
float tempora_sample;
float cached_mcu_temp; // getter 缓存
float cached_drv_temp;
float cached_vbus;
public:
/**
* @brief 初始化对象或模块
* @return u8 返回值
*/
u8 init(void);
/**
* @brief 更新 mcu_temp 相关状态
* @return void
*/
void update_mcu_temp(void);
/**
* @brief 更新 drv_temp 相关状态
* @return void
*/
void update_drv_temp(void);
/**
* @brief 更新 vbus_voltage 相关状态
* @return void
*/
void update_vbus_voltage(void);
/**
* @brief 更新 current 相关状态
* @return void
*/
void update_current(void);
/**
* @brief 获取 get_mcu_temp 对应的数据或状态
* @return float 返回值
*/
float get_mcu_temp(void);
/**
* @brief 获取 get_drv_temp 对应的数据或状态
* @return float 返回值
*/
float get_drv_temp(void);
/**
* @brief 获取 get_vbus_voltage 对应的数据或状态
* @return float 返回值
*/
float get_vbus_voltage(void);
/**
* @brief 获取 get_current 对应的数据或状态
* @param[in] char 参数
* @return float 返回值
*/
float get_current(char);
};
/**
* @brief ADC0_1_IRQHandler 中断处理函数
* @return void
*/
void ADC0_1_IRQHandler(void);
#ifdef __cplusplus
+12
View File
@@ -1,3 +1,9 @@
/**
* @file device/ang_sensor.cpp
* @brief 底层设备驱动与外设封装源文件
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
*/
#include "ang_sensor.h"
#include "Can.h"
#include "Filter.h"
@@ -12,14 +18,20 @@
// ANG_SENS 调试宏定义
#if ANG_SENS_DEBUG
/** @brief ANG_SENS_DEBUG_PRINT 宏定义 */
#define ANG_SENS_DEBUG_PRINT(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
/** @brief ANG_SENS_DEBUG_PRINT 宏定义 */
#define ANG_SENS_DEBUG_PRINT(fmt, ...) ((void)0)
#endif
/** @brief ANG_SPI_CS_ENABLE 宏定义 */
#define ANG_SPI_CS_ENABLE() gpio_bit_reset(GPIOA, GPIO_PIN_15)
/** @brief ANG_SPI_CS_DISABLE 宏定义 */
#define ANG_SPI_CS_DISABLE() gpio_bit_set(GPIOA, GPIO_PIN_15)
/** @brief DRV_SPI_CS_ENABLE 宏定义 */
#define DRV_SPI_CS_ENABLE() gpio_bit_reset(GPIOB, GPIO_PIN_14)
/** @brief DRV_SPI_CS_DISABLE 宏定义 */
#define DRV_SPI_CS_DISABLE() gpio_bit_set(GPIOB, GPIO_PIN_14)
// DMA 传输完成标志
+70 -1
View File
@@ -1,3 +1,9 @@
/**
* @file device/ang_sensor.h
* @brief 底层设备驱动与外设封装源文件
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
*/
#ifndef _angsensor_H
#define _angsensor_H
#ifdef __cplusplus
@@ -7,22 +13,76 @@ extern "C" {
#include <cstring>
#include "config.h"
/**
* @brief spi_rw_half_word 函数
* @param[in] spi_periph 参数
* @param[in] i_HalfWord 参数
* @return u16 返回值
*/
u16 spi_rw_half_word(u32 spi_periph, const u16 i_HalfWord);
/**
* @brief spi_rw_half_word_dma 函数
* @param[in] spi_periph 参数
* @param[in] tx_data 参数
* @param[in] rx_data 参数
* @return int 返回值
*/
int spi_rw_half_word_dma(uint32_t spi_periph, uint16_t tx_data,
uint16_t *rx_data);
/**
* @brief angle_sensor 类或结构体
*/
class angle_sensor {
public:
float calibration_angle = ANGLESENS_CALIBRATION_ANGLE;
/**
* @brief 初始化对象或模块
* @return u8 返回值
*/
u8 init(void);
/**
* @brief 读取 read_sensorAngle 相关数据
* @return float 返回值
*/
float read_sensorAngle(void);
/**
* @brief 更新对象内部状态或采样数据
* @return float 返回值
*/
float update(void);
/**
* @brief 复位对象内部状态
* @return void
*/
void reset(void);
/**
* @brief 获取 getAngle 对应的数据或状态
* @return float 返回值
*/
float getAngle(void) const;
/**
* @brief 获取 getRawAngle 对应的数据或状态
* @return float 返回值
*/
float getRawAngle(void) const;
/**
* @brief 获取 getcurrent_sensorangle 对应的数据或状态
* @return float 返回值
*/
float getcurrent_sensorangle(void) const;
/**
* @brief angle_set 函数
* @param[in] angle 参数
* @return u8 返回值
*/
u8 angle_set(float angle);
/**
* @brief 设置 set_calibration 对应的参数或状态
* @param[in] angle 参数
* @return u8 返回值
*/
u8 set_calibration(float angle);
protected:
@@ -34,7 +94,16 @@ class angle_sensor {
float m_lastcumulativeAngle;
float velocity[VEL_FILTER_SIZE] = {0.0f};
};
/**
* @brief 快速角度归一化到 [0, 360)
* 用 while 减法替代 fmodf,在角度变化量很小时(电机控制场景)
* 通常只需 0~1 次减法,远快于 fmodf 的 ~30-50 周期开销。
*/
inline float normalizeAngle360(float angle) {
while (angle >= 360.0f) angle -= 360.0f;
while (angle < 0.0f) angle += 360.0f;
return angle;
}
#ifdef __cplusplus
}
#endif
+6
View File
@@ -1,3 +1,9 @@
/**
* @file device/motor.cpp
* @brief 底层设备驱动与外设封装源文件
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
*/
#include "motor.h"
#include "Timer.h"
#include "gd32c10x_eval.h"
+25
View File
@@ -1,14 +1,39 @@
/**
* @file device/motor.h
* @brief 底层设备驱动与外设封装源文件
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
*/
#ifndef _MOTOR_H
#define _MOTOR_H
// 定义电机驱动使能引脚
/** @brief MOTOR_EN_GPIO_PORT 宏定义 */
#define MOTOR_EN_GPIO_PORT GPIOC
/** @brief MOTOR_EN_GPIO_PIN 宏定义 */
#define MOTOR_EN_GPIO_PIN GPIO_PIN_13
/** @brief RCU_MOTOR_EN_GPIO 宏定义 */
#define RCU_MOTOR_EN_GPIO RCU_GPIOC
/**
* @brief 初始化电机驱动输出
* @return void
*/
void motor_init(void);
/**
* @brief 复位电机驱动
* @return void
*/
void motor_reset(void);
/**
* @brief 唤醒电机驱动
* @return void
*/
void motor_resume(void);
/**
* @brief 使电机驱动进入休眠
* @return void
*/
void motor_sleep(void);
#endif