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:
+59
-27
@@ -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 时刻 */
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
/**
|
||||
* @file device/Timer.cpp
|
||||
* @brief 底层设备驱动与外设封装源文件
|
||||
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
|
||||
*/
|
||||
|
||||
#include "Timer.h"
|
||||
#include "Can.h"
|
||||
#include "FOC.h"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 传输完成标志
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
/**
|
||||
* @file device/motor.cpp
|
||||
* @brief 底层设备驱动与外设封装源文件
|
||||
* @note 本文件仅补充 Doxygen 文档注释,不改变代码逻辑。
|
||||
*/
|
||||
|
||||
#include "motor.h"
|
||||
#include "Timer.h"
|
||||
#include "gd32c10x_eval.h"
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user