From aaee40f36b82b07b23e68bc9fdad3ba0c350430f Mon Sep 17 00:00:00 2001 From: cbb <2625274797@qq.com> Date: Thu, 16 Oct 2025 21:43:34 +0800 Subject: [PATCH] =?UTF-8?q?FOC=E5=BC=80=E7=8E=AF=E8=B0=83=E8=AF=95?= =?UTF-8?q?=E6=88=90=E5=8A=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Robot_V2/Algorithm/DengFOC.cpp | 109 ++++++++++++++++ Robot_V2/Algorithm/DengFOC.h | 42 ++++++ Robot_V2/Robot_V2.cproject.yml | 2 + Robot_V2/device/Can.cpp | 46 ++++--- Robot_V2/device/Can.h | 28 +++- Robot_V2/device/Timer.cpp | 232 ++++++++++++++++++--------------- Robot_V2/device/Timer.h | 13 +- Robot_V2/main.cpp | 19 ++- Robot_V2/sys/initial.cpp | 8 ++ Robot_V2/sys/initial.h | 2 + Robot_V2/sys/systick.cpp | 3 +- Robot_V2/sys/systick.h | 8 +- 12 files changed, 365 insertions(+), 147 deletions(-) create mode 100644 Robot_V2/Algorithm/DengFOC.cpp create mode 100644 Robot_V2/Algorithm/DengFOC.h diff --git a/Robot_V2/Algorithm/DengFOC.cpp b/Robot_V2/Algorithm/DengFOC.cpp new file mode 100644 index 0000000..6d55ef6 --- /dev/null +++ b/Robot_V2/Algorithm/DengFOC.cpp @@ -0,0 +1,109 @@ +#include "DengFOC.h" +#include "Timer.h" +#include "systick.h" +#include +#include +#include + +constexpr double PI = 3.1415926535897932384626433832795f; +constexpr float _3PI_2 = 4.71238898038f; +constexpr u8 PP = 11, DIR = 1; +// 初始变量及函数定义 +#define _constrain(amt, low, high) \ + ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt))) +#define constrain(value, min, max, target_min, target_max) \ + ((value - min) / (max - min) * (target_max - target_min)) + +float _electricalAngle(float shaft_angle) { return shaft_angle * PP; } + +/** + * @brief 归一化角度 + * + * @param angle + * @return float + */ +float _normalizeAngle(float angle) { + float a = fmod(angle, 2 * PI); + // 取余运算可以用于归一化,列出特殊值例子算便知 + return a >= 0 ? a : (a + 2 * PI); +} +/** + * @brief 电机控制类构造函数 + * + */ +FOC_Controlroller::FOC_Controlroller() { ; } +/** + * @brief 获取电机 shaft_angle + * + * @return void + */ +void FOC_Controlroller::driver_output(float Ua, float Ub, float Uc) { + + // 计算占空比 + Ua = constrain(Ua, 0.0f, voltage_power_supply, 0.0f, limit_voltage); + Ub = constrain(Ub, 0.0f, voltage_power_supply, 0.0f, limit_voltage); + Uc = constrain(Uc, 0.0f, voltage_power_supply, 0.0f, limit_voltage); + float dc_a = _constrain(Ua / voltage_power_supply, 0.0f, 1.0f); + float dc_b = _constrain(Ub / voltage_power_supply, 0.0f, 1.0f); + float dc_c = _constrain(Uc / voltage_power_supply, 0.0f, 1.0f); + Set_3Pwm(dc_a, dc_b, dc_c); + // std::printf("PWM:%f,%f,%f\n", dc_a, dc_b, dc_c); +} + +/** + * @brief 设置电机输出 + * + * @param Uq: q轴电压 + * @param Ud: d轴电压 + * @param angle_el: 电机轴角度 + */ +void FOC_Controlroller::setPhaseVoltage(float Uq, float Ud, float angle_el) { + Uq = _constrain(Uq, -voltage_power_supply / 2, voltage_power_supply / 2); + angle_el = _normalizeAngle(angle_el + zero_electric_angle); + // 帕克逆变换 + Ualpha = -Uq * sin(angle_el); + Ubeta = Uq * cos(angle_el); + + // 克拉克逆变换 + Ua = Ualpha + voltage_power_supply / 2; + Ub = (sqrt(3) * Ubeta - Ualpha) / 2 + voltage_power_supply / 2; + Uc = (-Ualpha - sqrt(3) * Ubeta) / 2 + voltage_power_supply / 2; + driver_output(Ua, Ub, Uc); +} + +/** + * @brief 速度开环控制 + * + * @param target_velocity: 目标速度 + * @return float: q轴电压 + */ +float FOC_Controlroller::velocity_open_loop(float target_velocity) { + now_us = get_system_runtime_us(); + float dt = (now_us - last_time_us) * 1e-6f; + // 限制时间间隔 + if (dt <= 0.0f || dt > 0.5f) + dt = 1e-3f; + // 通过时间间隔和目标速度计算需要转动的机械角度,存储在shaft_angle中,在此之前,还需要对轴角度归一化 + shaft_angle = _normalizeAngle(shaft_angle + target_velocity * dt); + + float uq = limit_voltage; // 设定一个固定的q轴电压 + setPhaseVoltage(uq, 0, _electricalAngle(shaft_angle)); + last_time_us = now_us; + return uq; +} + +/** + * @brief 电机初始化 + * + * @param _PP: 电机极队数 + * @param _DIR: 电机极性 + */ +void FOC_Controlroller::DFOC_alignSensor(int _PP, int _DIR) { + u8 PP = _PP; + u8 DIR = _DIR; + setPhaseVoltage(3, 0, _3PI_2); + delay_1ms(3000); + zero_electric_angle = _electricalAngle(0); + setPhaseVoltage(0, 0, _3PI_2); + std::printf("0电角度:%f", zero_electric_angle); +} diff --git a/Robot_V2/Algorithm/DengFOC.h b/Robot_V2/Algorithm/DengFOC.h new file mode 100644 index 0000000..43f04ed --- /dev/null +++ b/Robot_V2/Algorithm/DengFOC.h @@ -0,0 +1,42 @@ +// 灯哥开源,遵循GNU协议,转载请著名版权! +// GNU开源协议(GNU General Public License, +// GPL)是一种自由软件许可协议,保障用户能够自由地使用、研究、分享和修改软件。 +// 该协议的主要特点是,要求任何修改或衍生的作品必须以相同的方式公开发布,即必须开源。此外,该协议也要求在使用或分发软件时,必须保留版权信息和许可协议。GNU开源协议是自由软件基金会(FSF)制定和维护的一种协议,常用于GNU计划的软件和其他自由软件中。 +// 仅在DengFOC官方硬件上测试过,欢迎硬件购买/支持作者,淘宝搜索店铺:灯哥开源 +// 你的支持将是接下来做视频和持续开源的经费,灯哥在这里先谢谢大家了 +// 函数声明 +#ifndef _DENGFOC_H +#define _DENGFOC_H +#include +class FOC_Controlroller { + public: + FOC_Controlroller(); + + float control_mode = 0; + float limit_voltage = 2.0f; + float limit_velocity = 0.0f; + float target_angle = 0.0f; + float target_velocity = 0.0f; + + float velocity_open_loop(float target_velocity); + void DFOC_alignSensor(int _PP, int _DIR); + + private: + std::u64 last_time_us = 0; + std::u64 now_us = 0; + float shaft_angle = 0; + float Ualpha, Ubeta = 0, Ua = 0, Ub = 0, Uc = 0; + float zero_electric_angle = 0; + float voltage_power_supply = 12.0f; // 电源电压 + + void driver_output(float Ua, float Ub, float Uc); + void setPhaseVoltage(float Uq, float Ud, float angle_el); +}; + +float _normalizeAngle(float angle); +void DFOC_Vbus(float power_supply); +float _electricalAngle(float shaft_angle); +float DFOC_M0_Angle(); +float serial_motor_target(); + +#endif diff --git a/Robot_V2/Robot_V2.cproject.yml b/Robot_V2/Robot_V2.cproject.yml index abb5113..3e94352 100644 --- a/Robot_V2/Robot_V2.cproject.yml +++ b/Robot_V2/Robot_V2.cproject.yml @@ -25,6 +25,8 @@ project: files: - file: Algorithm/Filter.cpp - file: Algorithm/Filter.h + - file: Algorithm/DengFOC.cpp + - file: Algorithm/DengFOC.h components: - component: ARM::CMSIS:CORE - component: Device:Startup diff --git a/Robot_V2/device/Can.cpp b/Robot_V2/device/Can.cpp index e5468c8..81ba3be 100644 --- a/Robot_V2/device/Can.cpp +++ b/Robot_V2/device/Can.cpp @@ -1,4 +1,5 @@ #include "Can.h" +#include "DengFOC.h" #include "gd32c10x.h" #include "gd32c10x_can.h" #include @@ -17,6 +18,7 @@ #define DEV_CAN_LOOPBACK_ID 0x0000 extern CAN_transmiter CAN0_transmiter; +extern FOC_Controlroller FOC; /*! \brief initialize CAN GPIO @@ -276,7 +278,6 @@ void canfd_loopback_test(void) { } } - /** \brief CAN0 回环测试 \param[in] none @@ -360,17 +361,20 @@ CAN_transmiter::CAN_transmiter() { \brief CAN 数据更新 */ void CAN_transmiter::update(void) { - limit_velocity_union.f = 0; - limit_voltage = 0 * 1000; + limit_velocity_union.f = FOC.limit_velocity; + limit_voltage = FOC.limit_voltage * 1000; mcu_temp = get_mcu_temp() * 100; motor_temp = get_drv_temp() * 100; Power_Voltage = get_vbus_voltage() * 1000; - rt_angle_union.f = 0; - rt_velocity_union.f = 0; - Status_code = (gpio_input_bit_get(GPIOB, GPIO_PIN_2) == SET) ? 1 : 0; - target_angle_union.f = 0; - Target_Control_Mode = 0; - target_velocity_union.f = 0; + rt_angle_union.f = 0.0f; + rt_velocity_union.f = 0.0f; + Status_code = (gpio_input_bit_get(GPIOB, GPIO_PIN_2) == SET) ? 0 : 1; + + Target_Control_Mode = FOC.control_mode; + controller_Mode = FOC.control_mode; + + target_angle_union.f = FOC.target_angle; + target_velocity_union.f = FOC.target_velocity; u_current_union.f = get_current('U') * 1000; w_current_union.f = get_current('W') * 1000; v_current_union.f = get_current('V') * 1000; @@ -522,13 +526,13 @@ u8 CAN_transmiter::CAN_all_Send() { // 打包Status_FEED transmit_data[0] = Status_code; transmit_data[1] = controller_Mode; - pack_short_to_bytes(transmit_data, 2, motor_temp); - pack_short_to_bytes(transmit_data, 4, mcu_temp); - pack_short_to_bytes(transmit_data, 6, Power_Voltage); + pack_u16_to_bytes(transmit_data, 2, motor_temp); + pack_u16_to_bytes(transmit_data, 4, mcu_temp); + pack_u16_to_bytes(transmit_data, 6, Power_Voltage); success_flag += CAN_Send(Status_FEED, 8, transmit_data); // 打包Limit_Vel_Vol_FEED pack_float_to_bytes(transmit_data, 0, limit_velocity_union); - pack_short_to_bytes(transmit_data, 4, limit_voltage); + pack_u16_to_bytes(transmit_data, 4, limit_voltage); success_flag += CAN_Send(Limit_Vel_Vol_FEED, 6, transmit_data); return success_flag; @@ -545,8 +549,8 @@ u8 CAN_transmiter::CANFD_all_Send() { constexpr u32 STATUS_ID = 0x18FF0100; constexpr u32 CONFIG_ID = 0x18FF0101; // 打包status数据 - pack_short_to_bytes(transmit_data, 0, mcu_temp); - pack_short_to_bytes(transmit_data, 2, motor_temp); + pack_u16_to_bytes(transmit_data, 0, mcu_temp); + pack_u16_to_bytes(transmit_data, 2, motor_temp); pack_u16_to_bytes(transmit_data, 4, u16(u_current_union.f)); pack_u16_to_bytes(transmit_data, 6, u16(w_current_union.f)); pack_u16_to_bytes(transmit_data, 8, u16(v_current_union.f)); @@ -589,11 +593,21 @@ void CAN_transmiter::communication_check() { // for (i = 0; i < receive_message.rx_dlen; i++) { // printf(" %02x", receive_message.rx_data[i]); // } + if (receive_message.rx_efid == 0x18ff0200) { + FOC.control_mode = receive_message.rx_data[0]; + FOC.limit_voltage = + float(unpack_bytes_to_u16(receive_message.rx_data, 1)) / 1000; + FOC.limit_velocity = + unpack_bytes_to_float(receive_message.rx_data, 3).f; + FOC.target_angle = + unpack_bytes_to_float(receive_message.rx_data, 7).f; + FOC.target_velocity = + unpack_bytes_to_float(receive_message.rx_data, 11).f; + } can0_receive_flag = RESET; } } - /** * @brief CAN0中断服务程序 * @retval 无 diff --git a/Robot_V2/device/Can.h b/Robot_V2/device/Can.h index 5d1264d..73ca165 100644 --- a/Robot_V2/device/Can.h +++ b/Robot_V2/device/Can.h @@ -17,12 +17,6 @@ typedef union { u8 b[4]; } float_union_t; -// 添加辅助函数用于将short类型数据打包到u8数组中 -static inline void pack_short_to_bytes(u8 *buffer, u16 offset, short value) { - buffer[offset] = (u8)(value & 0xFF); - buffer[offset + 1] = (u8)((value >> 8) & 0xFF); -} - // 添加辅助函数用于将u16类型数据打包到u8数组中 static inline void pack_u16_to_bytes(u8 *buffer, u16 offset, u16 value) { buffer[offset] = (u8)(value & 0xFF); @@ -38,6 +32,28 @@ static inline void pack_float_to_bytes(u8 *buffer, u16 offset, buffer[offset + 3] = float_union.b[3]; } +// 添加辅助函数用于从u8数组中解包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类型数据 +static inline u16 unpack_bytes_to_u16(u8 *buffer, u16 offset) { + u16 value = (u16)(buffer[offset] | (buffer[offset + 1] << 8)); + return value; +} + +// 添加辅助函数用于从u8数组中解包float类型数据 +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]; + return float_union; +} + u8 can_gpio_init(void); // CAN引脚初始化 void can_config(void); // CAN初始化 void canfd_config(void);// CANFD初始化 diff --git a/Robot_V2/device/Timer.cpp b/Robot_V2/device/Timer.cpp index ced3cad..8e47a30 100644 --- a/Robot_V2/device/Timer.cpp +++ b/Robot_V2/device/Timer.cpp @@ -3,29 +3,36 @@ #include "adc.h" #include "gd32c10x.h" #include "gd32c10x_gpio.h" +#include "gd32c10x_rcu.h" #include "gd32c10x_timer.h" -#include "initial.h" +#include "DengFOC.h" #include #include #include #include +#include "Timer.h" // 配置定时器每100微秒中断一次 // 系统时钟为120MHz,要得到100微秒的中断周期 // 可以使用预分频器119,定时器时钟为120MHz/(119+1) = 1MHz // 然后设置周期为99,即计数100次,1MHz/100 = 10kHz = 100微秒 -constexpr int TIMER1_PRESCALER = 119; // 120MHz / 120 = 1MHz -constexpr int TIMER1_PERIOD = 99; // 1MHz / 100 = 100us +constexpr int TIMER2_PRESCALER = 119; // 120MHz / 120 = 1MHz +constexpr int TIMER2_PERIOD = 99; // 1MHz / 100 = 100us -constexpr int TIMER0_PRESCALER = 5999; -constexpr int TIMER0_PERIOD = 15999; -constexpr int TIMER0_CH0_PULSE = 4000; -constexpr int TIMER0_CH1_PULSE = 6000; -constexpr int TIMER0_CH2_PULSE = 8000; +constexpr int TIMER1_PRESCALER = 0; // 不分频,计数器时钟为120MHz +constexpr int TIMER1_PERIOD = 2999; // 120MHz / (0+1) / (5999+1) = 20kHz +constexpr int TIMER1_CH0_PULSE = 0; +constexpr int TIMER1_CH1_PULSE = 0; +constexpr int TIMER1_CH2_PULSE = 0; static u32 total_us100_counter = 0; // 总计数器,每100微秒增加1 extern u16 adc_value[7]; extern CAN_transmiter CAN0_transmiter; +// 添加系统运行时间计数器 +static volatile std::u64 system_runtime_us = 0; + +// 声明外部FOC控制器对象 +extern FOC_Controlroller FOC; /** * @brief 设置引脚中断优先级 @@ -36,8 +43,8 @@ extern CAN_transmiter CAN0_transmiter; void nvic_config(void) { /* 设置NVIC优先级分组,1位抢占优先级,3位响应优先级 */ nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); - /* 使能TIMER1中断,设置抢占优先级为1,子优先级为1 */ - nvic_irq_enable(TIMER1_IRQn, 1, 1); + /* 使能TIMER2中断,设置抢占优先级为1,子优先级为1 */ + nvic_irq_enable(TIMER2_IRQn, 1, 1); } /** @@ -46,73 +53,88 @@ void nvic_config(void) { * *配置定时器1 */ -void timer1_config(void) { +void TIMER2_config(void) { /* ---------------------------------------------------------------------------- - TIMER1 Configuration: - TIMER1CLK = SystemCoreClock/120 = 1MHz, the period is 100us(100/1000000 = + TIMER2 Configuration: + TIMER2CLK = SystemCoreClock/120 = 1MHz, the period is 100us(100/1000000 = 100us). ---------------------------------------------------------------------------- */ timer_parameter_struct timer_struct; - /* 使能TIMER1时钟 */ - rcu_periph_clock_enable(RCU_TIMER1); + /* 使能TIMER2时钟 */ + rcu_periph_clock_enable(RCU_TIMER2); - /* 复位TIMER1外设到默认状态 */ - timer_deinit(TIMER1); + /* 复位TIMER2外设到默认状态 */ + timer_deinit(TIMER2); /* 初始化TIMER初始化参数结构体 */ timer_struct_para_init(&timer_struct); - /* TIMER1配置参数设置 */ + /* TIMER2配置参数设置 */ timer_struct.prescaler = - TIMER1_PRESCALER; /* 预分频值:120分频(从0开始计数) */ + TIMER2_PRESCALER; /* 预分频值:120分频(从0开始计数) */ timer_struct.alignedmode = TIMER_COUNTER_EDGE; /* 边沿对齐模式 */ timer_struct.counterdirection = TIMER_COUNTER_UP; /* 向上计数模式 */ timer_struct.period = - TIMER1_PERIOD; /* 自动重装载值:100次计数(从0开始计数) */ + TIMER2_PERIOD; /* 自动重装载值:100次计数(从0开始计数) */ timer_struct.clockdivision = TIMER_CKDIV_DIV1; /* 时钟分频值:1分频 */ - timer_init(TIMER1, &timer_struct); + timer_init(TIMER2, &timer_struct); /* 清除更新中断标志位 */ - timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_UP); + timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP); /* 使能更新中断 */ - timer_interrupt_enable(TIMER1, TIMER_INT_UP); + timer_interrupt_enable(TIMER2, TIMER_INT_UP); - /* 使能TIMER1 */ - timer_enable(TIMER1); + /* 使能TIMER2 */ + timer_enable(TIMER2); } /** - * @brief 配置TIMER1中断 + * @brief 配置TIMER2中断 * @return void */ void User_timer_init(void) { - /* 配置TIMER1 */ - timer1_config(); - /* 配置TIMER1中断 */ + /* 配置TIMER2 */ + TIMER2_config(); + /* 配置TIMER2中断 */ nvic_config(); } + +/*! + \brief 获取系统运行时间(毫秒) + \param[in] none + \param[out] none + \retval 系统运行时间,单位为毫秒 +*/ +uint64_t get_system_runtime_us(void) +{ + return system_runtime_us; +} + /** - * @brief TIMER1中断处理函数 + * @brief TIMER2中断处理函数 * @return void */ -void TIMER1_IRQHandler(void) { +void TIMER2_IRQHandler(void) { // 检查更新中断标志并处理 - if (timer_interrupt_flag_get(TIMER1, TIMER_INT_UP) != RESET) { + if (timer_interrupt_flag_get(TIMER2, TIMER_INT_UP) != RESET) { // 清除更新中断标志 - timer_interrupt_flag_clear(TIMER1, TIMER_INT_UP); + timer_interrupt_flag_clear(TIMER2, TIMER_INT_UP); // 增加总计数器 total_us100_counter++; - + system_runtime_us += 100; // 每100us执行一次的操作可以放在这里 + // 在定时器中断中执行FOC控制,确保控制频率稳定 + FOC.velocity_open_loop(FOC.target_velocity); + if (total_us100_counter % 10 == 0) { // 每1ms执行的代码可以放在这里 CAN0_transmiter.can0_send_flag = SET; if (total_us100_counter % 100 == 0) { // 每10ms执行的代码可以放在这里 } - + if (total_us100_counter % 1000 == 0) { // 每100ms执行的代码可以放在这里 } @@ -128,99 +150,77 @@ void TIMER1_IRQHandler(void) { } /** - * @brief TIMER0 GPIO配置函数 + * @brief TIMER1 GPIO配置函数 */ -void timer0_gpio_config(void) { +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); - // TIMER0 GPIO初始化 + // 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); - /* 配置TIMER0完全重映射 */ - gpio_pin_remap_config(GPIO_TIMER0_FULL_REMAP, ENABLE); + 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完全重映射 - 应该使用DISABLE,因为我们使用的是默认引脚 */ + gpio_pin_remap_config(GPIO_TIMER1_FULL_REMAP, DISABLE); } /** - * @brief TIMER0 配置函数 + * @brief TIMER1 配置函数 */ -void timer0_config(void) { - /* ----------------------------------------------------------------------- - TIMER0配置: - 生成3路具有不同占空比的互补PWM信号: - TIMER0CLK固定为systemcoreclock,TIMER0预分频器设置为6000,因此 - TIMER0计数器时钟为20KHz。 - 三个占空比的计算如下: - 通道0的占空比设置为25%,因此通道1N设置为75%。 - 通道1的占空比设置为50%,因此通道2N设置为50%。 - 通道2的占空比设置为75%,因此通道3N设置为25%。 - ----------------------------------------------------------------------- */ - timer_oc_parameter_struct timer_ocinitpara; - timer_parameter_struct timer_initpara; +void timer1_pwm_config(void) { + timer_parameter_struct timer_initpara; + timer_oc_parameter_struct timer_ocinitpara; - rcu_periph_clock_enable(RCU_TIMER0); + // 使能TIMER1时钟 + rcu_periph_clock_enable(RCU_TIMER1); - timer_deinit(TIMER0); - /* initialize TIMER init parameter struct */ - timer_struct_para_init(&timer_initpara); - /* TIMER0 configuration */ - timer_initpara.prescaler = TIMER0_PRESCALER; - timer_initpara.alignedmode = TIMER_COUNTER_EDGE; - timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = TIMER0_PERIOD; - timer_initpara.clockdivision = TIMER_CKDIV_DIV1; - timer_initpara.repetitioncounter = 0; - timer_init(TIMER0, &timer_initpara); + // 复位TIMER1 + timer_deinit(TIMER1); - /* initialize TIMER channel output parameter struct */ - timer_channel_output_struct_para_init(&timer_ocinitpara); - /* CH0, CH1 and CH2 configuration in PWM mode */ - timer_ocinitpara.outputstate = TIMER_CCX_ENABLE; - timer_ocinitpara.outputnstate = TIMER_CCXN_DISABLE; - timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH; - timer_ocinitpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; - timer_ocinitpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; - timer_ocinitpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; + // 配置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_config(TIMER0, TIMER_CH_0, &timer_ocinitpara); - timer_channel_output_config(TIMER0, TIMER_CH_1, &timer_ocinitpara); - timer_channel_output_config(TIMER0, TIMER_CH_2, &timer_ocinitpara); + // 配置通道输出参数 + timer_channel_output_struct_para_init(&timer_ocinitpara); + timer_ocinitpara.outputstate = TIMER_CCX_ENABLE; + timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH; - timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, - TIMER0_CH0_PULSE); - timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM0); - timer_channel_output_shadow_config(TIMER0, TIMER_CH_0, - TIMER_OC_SHADOW_DISABLE); + // 配置三个通道为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); - timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_1, - TIMER0_CH1_PULSE); - timer_channel_output_mode_config(TIMER0, TIMER_CH_1, TIMER_OC_MODE_PWM0); - timer_channel_output_shadow_config(TIMER0, TIMER_CH_1, - TIMER_OC_SHADOW_DISABLE); + // 设置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_pulse_value_config(TIMER0, TIMER_CH_2, - TIMER0_CH2_PULSE); - timer_channel_output_mode_config(TIMER0, TIMER_CH_2, TIMER_OC_MODE_PWM0); - timer_channel_output_shadow_config(TIMER0, TIMER_CH_2, - TIMER_OC_SHADOW_DISABLE); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, TIMER1_CH0_PULSE); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, TIMER1_CH1_PULSE); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2, TIMER1_CH2_PULSE); - timer_primary_output_config(TIMER0, ENABLE); - - // 自动重载模式使能和启动TIMER0 - timer_auto_reload_shadow_enable(TIMER0); - timer_enable(TIMER0); + // 使能主输出和自动重载 + timer_primary_output_config(TIMER1, ENABLE); + timer_auto_reload_shadow_enable(TIMER1); + + // 启动TIMER1 + timer_enable(TIMER1); } -/** - * @brief TIMER0 GPIO config - */ -void Timer0_init(void) { - timer0_gpio_config(); - timer0_config(); -} + /*! \brief set PWM @@ -231,9 +231,27 @@ void Timer0_init(void) { \retval none \note The channel parameter must be between 0 and 3 inclusive. */ -void Set_Pwm(u16 channel, u32 palse) { +void Set_Pwm(u16 channel, float duty_cycle) { + float pulse = duty_cycle * TIMER1_PERIOD; + if (channel <= 3) { - timer_channel_output_pulse_value_config(TIMER0, channel, palse); + 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_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, duty_cycle0 * TIMER1_PERIOD); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, duty_cycle1 * TIMER1_PERIOD); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2, duty_cycle2 * TIMER1_PERIOD); +} diff --git a/Robot_V2/device/Timer.h b/Robot_V2/device/Timer.h index 7aa2416..5cf00ef 100644 --- a/Robot_V2/device/Timer.h +++ b/Robot_V2/device/Timer.h @@ -8,9 +8,16 @@ extern "C" { #include void User_timer_init(void); -void Timer0_init(void); -void Set_Pwm(u16 channel,u32 pulse); -void TIMER1_IRQHandler(void); +void Set_Pwm(uint16_t channel, float duty_cycle); +void Set_3Pwm(float duty_cycle0, float duty_cycle1,float duty_cycle2); +void TIMER2_IRQHandler(void); + +void timer1_pwm_config(void); +void timer1_gpio_config(void); +/* 获取系统运行时间 */ +uint64_t get_system_runtime_us(void); + + #ifdef __cplusplus } #endif diff --git a/Robot_V2/main.cpp b/Robot_V2/main.cpp index e2026eb..22735b2 100644 --- a/Robot_V2/main.cpp +++ b/Robot_V2/main.cpp @@ -1,40 +1,39 @@ #include "main.h" #include "Can.h" +#include "DengFOC.h" #include "Filter.h" #include "Timer.h" #include "adc.h" #include "core_cm4.h" #include "device/tle5012b.h" +#include "gd32c10x_gpio.h" #include "initial.h" #include "sys/initial.h" #include "systick.h" #include "tle5012b.h" -#include #include - // 全局变量定义 CurrentKalman kalman(0.0f, 0.0026f, 4.8f, 0.0001f, 1e-6f, 0.02f); CAN_transmiter CAN0_transmiter; +FOC_Controlroller FOC; + int main(void) { systick_config(); // 系统时钟初始化 USART0_init(); // 调试串口初始化 User_timer_init(); // Timer初始化 adc_config(); // ADC初始化 dma_config(); // DMA采样ADC初始化 - + driver_init(); // 电机驱动初始化 + tle5012b_gpio_init(); // TLI5012B初始化 tle5012b_spi_init(); - // cdd_TLI5012_Init(); // 初始化TLE5012B传感器 - + watchdog_init(5000); while (1) { /* clear the FWDGT reset flag */ fwdgt_counter_reload(); - + printf("1\r\n"); CAN0_transmiter.communication_check(); - // delay_1ms(2); - - Set_Pwm(0, 1500); } -} +} \ No newline at end of file diff --git a/Robot_V2/sys/initial.cpp b/Robot_V2/sys/initial.cpp index 9476285..cd28de7 100644 --- a/Robot_V2/sys/initial.cpp +++ b/Robot_V2/sys/initial.cpp @@ -1,6 +1,7 @@ #include "initial.h" #include "systick.h" #include +#include "Timer.h" extern u16 adc_value[7]; @@ -117,6 +118,13 @@ u8 watchdog_init(u32 time) { fwdgt_enable(); return status; } +/** + * @brief driver输出初始化 + */ +void driver_init(void) { + timer1_gpio_config(); + timer1_pwm_config(); +} int fputc(int ch, FILE *f) throw() { usart_data_transmit(EVAL_COM0, (uint8_t)ch); diff --git a/Robot_V2/sys/initial.h b/Robot_V2/sys/initial.h index 32c22ec..e5d4687 100644 --- a/Robot_V2/sys/initial.h +++ b/Robot_V2/sys/initial.h @@ -19,6 +19,8 @@ int fputc(int ch, FILE *f); // 声明fputc函数以重载标准库实现 u8 tle5210b_init(void); u8 USART0_init(void); u8 watchdog_init(u32 time); +void driver_init(void); + #ifdef __cplusplus } diff --git a/Robot_V2/sys/systick.cpp b/Robot_V2/sys/systick.cpp index e427419..baeebda 100644 --- a/Robot_V2/sys/systick.cpp +++ b/Robot_V2/sys/systick.cpp @@ -34,8 +34,6 @@ OF SUCH DAMAGE. #include "gd32c10x.h" #include "systick.h" -#include "initial.h" -#include volatile static uint32_t delay; @@ -69,6 +67,7 @@ void delay_1s(uint32_t count) delay_1ms(1000); } } + /*! \brief delay a time in milliseconds \param[in] count: count in milliseconds diff --git a/Robot_V2/sys/systick.h b/Robot_V2/sys/systick.h index ebc8ee8..2c0f4e3 100644 --- a/Robot_V2/sys/systick.h +++ b/Robot_V2/sys/systick.h @@ -48,11 +48,13 @@ void delay_1ms(uint32_t count); void delay_1s(uint32_t count); /* delay decrement */ void delay_decrement(void); - -void timer_delay_ms(uint32_t ms); +/* 空闲任务计数 */ +void idle_task_count(void); +/* 获取CPU使用率 */ +uint8_t get_cpu_usage(void); #ifdef __cplusplus } #endif -#endif /* SYSTICK_H */ +#endif /* SYSTICK_H */ \ No newline at end of file