Files
Motor_v2/Robot_V2/device/Timer.cpp
T
cbb a26dd1cc8e feat(can): 增强CAN通信缓冲区管理机制
- 实现循环缓冲区队列管理CAN消息接收
- 添加缓冲区满/空状态检查函数
- 实现消息出队列dequeue_rx_message功能
- 在中断处理程序中添加消息入队列机制
- 优化CAN消息处理流程,支持批量处理

refactor(motor): 优化电机控制类结构和安全机制
- 重命名PID控制器参数变量名以提高可读性
- 添加过热关机标志位thermal_shutdown和相关处理函数
- 实现过热关机shut_down_thermal和过热恢复resume_from_thermal功能
- 调整关机逻辑,添加drv_stop调用确保电机完全停止
- 修正电流环控制中的占空比设置,改为单相保持

feat(motor): 实现FOC控制算法改进和零点校准功能
- 实现电机零点校准函数calibrate_zero_position用于位置补偿
- 修正FOC控制器中的电气角度计算,集成KTH7823校准角度补偿
- 新增d轴电流计算功能
- 重构PID参数初始化方式,使用统一的电压限制配置
- 更新SVPWM相电压设置算法,改进角度归一化处理
- 修改缺省扇区输出占空比从0.0f改为0.5f以提高稳定性

fix(control): 修复控制回路方向和频率计算问题
- 修正角度控制回路中的误差计算方向
- 修正开环速度控制中的频率参数使用
- 修正速度环控制中的误差计算方向
- 修正MIT模式下多级PID控制器的参数设置和误差计算

refactor(filter): 修正编码器速度计算算法
- 移除速度计算中的冗余乘法因子2

feat(pid): 扩展PID控制器功能
- 添加reset方法用于重置PID内部状态

chore(build): 更新开发工具版本和ADC配置
- 更新csolution版本至2.13.0
- 调整ADC采样时间配置以优化性能
2026-03-09 01:35:26 +08:00

316 lines
11 KiB
C++
Raw 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.
#include "Timer.h"
#include "Can.h"
#include "FOC.h"
#include "Timer.h"
#include "gd32c10x.h"
#include "gd32c10x_gpio.h"
#include "gd32c10x_misc.h"
#include "gd32c10x_rcu.h"
#include "gd32c10x_timer.h"
#include "initial.h"
volatile u32 total_us100_counter = 0; // 总计数器,每 100 微秒增加 1
extern u16 adc_value[7];
extern FOC_Controller FOC;
extern TaskScheduler scheduler;
extern CAN_transmiter CAN0_transmiter;
// 添加系统运行时间计数器
extern u32 cnt_test;
// 任务调度查找表 - 每 100us 执行的任务 (1ms 周期内)
static const u32 task_schedule_100us[10] = {
(1u << TASK_MCU_TEMP_UPDATE), // 0: MCU 温度更新
(1u << TASK_DRV_TEMP_UPDATE), // 1: 驱动温度更新
(1u << TASK_VBUS_UPDATE), // 2: 电压更新
0, // 3: 空闲
0, // 4: 空闲
0, // 5: 空闲
0, // 6: 空闲
0, // 7: 空闲
0, // 8: 空闲
(1u << TASK_CAN_TRANSMIT) // 9: CAN 发送
};
// 任务调度查找表 - 每 1ms 执行的任务 (10ms 周期内)
static const u32 task_schedule_1ms[10] = {
(1u << TASK_THERMAL_CONTROL), // 0: 热量控制
(1u << TASK_MAGNETIC_CHECK), // 1: 磁感应强度检测
0, 0, 0, 0, 0, 0, 0, 0 // 空闲
};
// 任务调度查找表 - 每 10ms 执行的任务 (100ms 周期内)
static const u32 task_schedule_10ms[10] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 当前无任务,预留扩展
};
// 任务调度查找表 - 每 100ms 执行的任务 (1s 周期内)
static const u32 task_schedule_100ms[10] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 当前无任务,预留扩展
};
/**
* @brief 设置引脚中断优先级
* @return void
*
* 设置引脚中断优先级
*/
void nvic_config(void) {
/* 设置 NVIC 优先级分组,1 位抢占优先级,3 位响应优先级 */
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
/* 使能 TIMER2 中断,设置抢占优先级为 1,子优先级为 1 */
nvic_irq_enable(TIMER2_IRQn, 0, 1);
nvic_irq_enable(TIMER1_IRQn, 0, 2);
}
/**
* @brief 配置定时器 2-任务管理
* @return void
*
* 配置定时器 2,用于定时执行 FOC 控制、采样、CAN 发送等任务
*/
void TIMER2_config(void) {
/* ----------------------------------------------------------------------------
TIMER2 Configuration:
TIMER2CLK = SystemCoreClock/120 = 1MHz, the period is 100us(100/1000000 =
100us).
----------------------------------------------------------------------------
*/
timer_parameter_struct timer_struct;
/* 使能 TIMER2 时钟 */
rcu_periph_clock_enable(RCU_TIMER2);
/* 复位 TIMER2 外设到默认状态 */
timer_deinit(TIMER2);
/* 初始化 TIMER 初始化参数结构体 */
timer_struct_para_init(&timer_struct);
/* TIMER2 配置参数设置 */
timer_struct.prescaler =
TIMER2_PRESCALER; /* 预分频值:120 分频 (从 0 开始计数) */
timer_struct.alignedmode = TIMER_COUNTER_EDGE; /* 边沿对齐模式 */
timer_struct.counterdirection = TIMER_COUNTER_UP; /* 向上计数模式 */
timer_struct.period =
TIMER2_PERIOD; /* 自动重装载值:100 次计数 (从 0 开始计数) */
timer_struct.clockdivision = TIMER_CKDIV_DIV1; /* 时钟分频值:1 分频 */
timer_init(TIMER2, &timer_struct);
/* 清除更新中断标志位 */
timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP);
/* 使能更新中断 */
timer_interrupt_enable(TIMER2, TIMER_INT_UP);
/* 使能 TIMER2 */
timer_enable(TIMER2);
}
/**
* @brief 配置 TIMER2-任务管理中断
* @return void
*/
void User_timer_init(void) {
/* 配置 TIMER2 */
TIMER2_config();
/* 配置 TIMER2 中断 */
nvic_config();
}
/**
* @brief TIMER2-任务管理中断处理函数 (优化版)
* @return void
* @note 使用查找表替代多层 switch-case,减少代码复杂度和执行时间
* 中断周期:50us
* - 每 50us: 电机控制任务 (角度、速度更新)
* - 每 100us: 传感器采样、CAN 通信
* - 每 1ms: 热量控制、磁检
* - 每 10ms/100ms/1s: 预留扩展任务
*/
void TIMER2_IRQHandler(void) {
// 快速路径:检查并清除中断标志
if (timer_interrupt_flag_get(TIMER2, TIMER_INT_UP) == RESET) {
return;
}
timer_interrupt_flag_clear(TIMER2, TIMER_INT_UP);
// 固定任务:每 50us 执行电机控制
scheduler.taskFlags |= (1u << TASK_ANGLE_UPDATE) |
(1u << TASK_VELOCITY_UPDATE) |
(1u << TASK_MOTOR_CONTROL);
// 每 100us 执行一次的任务(使用位运算替代布尔变量)
static u32 call_counter = 0;
call_counter++;
if ((call_counter & 1u) == 0u) { // 偶数次调用(每 100us)
// 使用查找表设置 1ms 周期内的任务
scheduler.taskFlags |= task_schedule_100us[total_us100_counter];
total_us100_counter++;
if (total_us100_counter >= 10u) {
total_us100_counter = 0;
// 每 1ms 执行的任务
static u32 ms1_counter = 0;
ms1_counter++;
if (ms1_counter >= 10u) {
ms1_counter = 0;
// 每 10ms 执行的任务
static u32 ms10_counter = 0;
ms10_counter++;
if (ms10_counter >= 10u) {
ms10_counter = 0;
// 每 100ms 执行的任务
static u32 ms100_counter = 0;
ms100_counter++;
if (ms100_counter >= 10u) {
ms100_counter = 0;
// 每 1s 任务预留位置
}
scheduler.taskFlags |= task_schedule_100ms[ms100_counter];
}
scheduler.taskFlags |= task_schedule_10ms[ms10_counter];
}
scheduler.taskFlags |= task_schedule_1ms[ms1_counter];
}
}
}
/**
* @brief TIMER1-PWM GPIO 配置函数
*/
void timer1_gpio_config(void) {
// 时钟使能
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_AF);
rcu_periph_clock_enable(RCU_TIMER1);
// TIMER1 GPIO 初始化
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,
GPIO_PIN_0 | GPIO_PIN_12);
gpio_bit_set(GPIOB, GPIO_PIN_0);
gpio_bit_set(GPIOB, GPIO_PIN_12);
/* 配置 TIMER1 完全重映射*/
gpio_pin_remap_config(GPIO_TIMER1_FULL_REMAP, DISABLE);
}
/**
* @brief TIMER1-PWM 配置函数
*/
void timer1_pwm_config(void) {
timer_parameter_struct timer_initpara;
timer_oc_parameter_struct timer_ocinitpara;
// 使能 TIMER1 时钟
rcu_periph_clock_enable(RCU_TIMER1);
// 复位 TIMER1
timer_deinit(TIMER1);
// 配置 TIMER1 基本参数
timer_struct_para_init(&timer_initpara);
timer_initpara.prescaler = TIMER1_PRESCALER; // 预分频器
timer_initpara.counterdirection = TIMER_COUNTER_UP; // 向上计数
timer_initpara.period = TIMER1_PERIOD; // 计数周期
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_init(TIMER1, &timer_initpara);
// 配置通道输出参数
timer_channel_output_struct_para_init(&timer_ocinitpara);
timer_ocinitpara.outputstate = TIMER_CCX_ENABLE;
timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
// 配置三个通道为 PWM 模式
timer_channel_output_config(TIMER1, TIMER_CH_0, &timer_ocinitpara);
timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocinitpara);
timer_channel_output_config(TIMER1, TIMER_CH_2, &timer_ocinitpara);
// 配置第四个通道 (CH3) 用于在 PWM 周期 x% 位置触发中断
timer_ocinitpara.outputstate =
TIMER_CCX_DISABLE; // 不输出 PWM 波形,仅用于触发中断
timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_channel_output_config(TIMER1, TIMER_CH_3, &timer_ocinitpara);
// 设置 PWM 模式和占空比
timer_channel_output_mode_config(TIMER1, TIMER_CH_0, TIMER_OC_MODE_PWM0);
timer_channel_output_mode_config(TIMER1, TIMER_CH_1, TIMER_OC_MODE_PWM0);
timer_channel_output_mode_config(TIMER1, TIMER_CH_2, TIMER_OC_MODE_PWM0);
timer_channel_output_mode_config(TIMER1, TIMER_CH_3,
TIMER_OC_MODE_PWM0); // CH3 也设为 PWM 模式
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0,
TIMER1_DEFAULT_PULSE);
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1,
TIMER1_DEFAULT_PULSE);
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2,
TIMER1_DEFAULT_PULSE);
// 设置 CH3 比较值为 PWM 周期 x% 位置
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3,
TIMER1_CH3_COMPARE_VALUE);
// 使能主输出和自动重载
timer_primary_output_config(TIMER1, ENABLE);
timer_auto_reload_shadow_enable(TIMER1);
// 使能 CH3 比较中断
timer_interrupt_enable(TIMER1, TIMER_INT_CH3);
// 启动 TIMER1
timer_enable(TIMER1);
}
// 添加 TIMER1-PWM 中断处理函数
/**
* @brief TIMER1 中断处理函数
* @return void
*/
void TIMER1_IRQHandler(void) {
// 检查 CH3 比较中断标志并处理
if (timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_CH3) != RESET) {
// 清除 CH3 比较中断标志
timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH3);
scheduler.taskFlags |= (1 << TASK_CURRENT_UPDATE);
// 例如触发 ADC 采样或其他操作
}
}
/*!
\brief set PWM
\param[in] channel: TIMER_CH_0/TIMER_CH_1/TIMER_CH_2/TIMER_CH_3 (valid
values: 0, 1, 2, 3)
\param[in] pulse: PWM pulse value
\param[out] none
\retval none
\note The channel parameter must be between 0 and 3 inclusive.
*/
void Set_Pwm(u16 channel, float duty_cycle) {
float pulse = duty_cycle * TIMER1_PERIOD;
if (channel <= 3) {
timer_channel_output_pulse_value_config(TIMER1, channel, pulse);
} else {
} // Ensure channel is within valid range
}
/*!
\brief set PWM
\param[in] channel: TIMER_CH_0/TIMER_CH_1/TIMER_CH_2/TIMER_CH_3 (valid
values: 0, 1, 2, 3)
\param[in] pulse: PWM pulse value
\param[out] none
\retval none
\note The channel parameter must be between 0 and 3 inclusive.
*/
void Set_3Pwm(float duty_cycle0, float duty_cycle1, float duty_cycle2) {
// 直接写寄存器
TIMER_CH0CV(TIMER1) = (uint32_t)(duty_cycle0 * TIMER1_PERIOD);
TIMER_CH1CV(TIMER1) = (uint32_t)(duty_cycle1 * TIMER1_PERIOD);
TIMER_CH2CV(TIMER1) = (uint32_t)(duty_cycle2 * TIMER1_PERIOD);
}