From 7f0ca1857bf6545cb002ed88c71489436c6e5ecf Mon Sep 17 00:00:00 2001 From: cbb <2625274797@qq.com> Date: Sun, 19 Oct 2025 23:20:28 +0800 Subject: [PATCH] =?UTF-8?q?feat(FOC):=20=E4=BC=98=E5=8C=96=E5=BC=80?= =?UTF-8?q?=E7=8E=AF=E9=80=9F=E5=BA=A6=E6=8E=A7=E5=88=B6=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E5=B9=B6=E6=8F=90=E5=8D=87=E6=80=A7=E8=83=BD=20refactor(ADC):?= =?UTF-8?q?=20=E9=87=8D=E6=9E=84=E9=87=87=E6=A0=B7=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E5=B9=B6=E5=B0=81=E8=A3=85=E4=B8=BA=20sampler=20=E7=B1=BB=20re?= =?UTF-8?q?factor(CAN):=20=E6=9B=B4=E6=96=B0=20CAN=20=E5=8F=91=E9=80=81?= =?UTF-8?q?=E5=99=A8=E4=BB=A5=E4=BD=BF=E7=94=A8=E6=96=B0=E7=9A=84sampler?= =?UTF-8?q?=20=E6=8E=A5=E5=8F=A3=20refactor(timer):=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E5=AE=9A=E6=97=B6=E5=99=A8=E4=B8=AD=E6=96=AD=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E4=BB=BB=E5=8A=A1=E8=B0=83=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Robot_V2/Algorithm/DengFOC.cpp | 45 +++-- .../RTE/_Release_GD32C103CB/RTE_Components.h | 50 +++++ Robot_V2/device/ADC.cpp | 134 +++++++++----- Robot_V2/device/Can.cpp | 13 +- Robot_V2/device/Timer.cpp | 171 ++++++++++-------- Robot_V2/device/adc.h | 28 ++- Robot_V2/device/test.cpp | 14 +- Robot_V2/main.cpp | 5 +- 8 files changed, 309 insertions(+), 151 deletions(-) create mode 100644 Robot_V2/RTE/_Release_GD32C103CB/RTE_Components.h diff --git a/Robot_V2/Algorithm/DengFOC.cpp b/Robot_V2/Algorithm/DengFOC.cpp index 6d55ef6..5b36b5d 100644 --- a/Robot_V2/Algorithm/DengFOC.cpp +++ b/Robot_V2/Algorithm/DengFOC.cpp @@ -8,13 +8,15 @@ constexpr double PI = 3.1415926535897932384626433832795f; constexpr float _3PI_2 = 4.71238898038f; constexpr u8 PP = 11, DIR = 1; +constexpr float sqrt3 = 1.73205080757f; // sqrt(3)的预计算值 // 初始变量及函数定义 #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; } + +inline float _electricalAngle(float shaft_angle) { return shaft_angle * PP; } /** * @brief 归一化角度 @@ -22,7 +24,7 @@ float _electricalAngle(float shaft_angle) { return shaft_angle * PP; } * @param angle * @return float */ -float _normalizeAngle(float angle) { +inline float _normalizeAngle(float angle) { float a = fmod(angle, 2 * PI); // 取余运算可以用于归一化,列出特殊值例子算便知 return a >= 0 ? a : (a + 2 * PI); @@ -78,18 +80,37 @@ void FOC_Controlroller::setPhaseVoltage(float Uq, float Ud, float angle_el) { * @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); + // 预计算常量 1e-4 = 100微秒控制周期 / 1秒 = 100e-6 + shaft_angle = _normalizeAngle(shaft_angle + target_velocity * 1e-4f); + + // 直接计算电气角度,避免函数调用开销 + float angle_el = shaft_angle * PP + zero_electric_angle; + angle_el = _normalizeAngle(angle_el); + + // 因为在开环控制中,Ud始终为0,只控制Uq + const float Uq = limit_voltage; + const float Ud = 0.0f; + + // 帕克逆变换 (直接计算,避免函数调用开销) + const float sin_el = sin(angle_el); + const float cos_el = cos(angle_el); + Ualpha = -Uq * sin_el; + Ubeta = Uq * cos_el; - float uq = limit_voltage; // 设定一个固定的q轴电压 - setPhaseVoltage(uq, 0, _electricalAngle(shaft_angle)); - last_time_us = now_us; - return uq; + // 克拉克逆变换 (预计算常量值) + const float v_half = voltage_power_supply * 0.5f; // 电源电压的一半 + Ua = Ualpha + v_half; + Ub = (sqrt3 * Ubeta - Ualpha) * 0.5f + v_half; + Uc = (-Ualpha - sqrt3 * Ubeta) * 0.5f + v_half; + + // 计算占空比 + const float dc_a = _constrain(Ua / voltage_power_supply, 0.0f, 1.0f); + const float dc_b = _constrain(Ub / voltage_power_supply, 0.0f, 1.0f); + const float dc_c = _constrain(Uc / voltage_power_supply, 0.0f, 1.0f); + Set_3Pwm(dc_a, dc_b, dc_c); + + return limit_voltage; } /** diff --git a/Robot_V2/RTE/_Release_GD32C103CB/RTE_Components.h b/Robot_V2/RTE/_Release_GD32C103CB/RTE_Components.h new file mode 100644 index 0000000..f92e443 --- /dev/null +++ b/Robot_V2/RTE/_Release_GD32C103CB/RTE_Components.h @@ -0,0 +1,50 @@ +/* + * CSOLUTION generated file: DO NOT EDIT! + * Generated by: csolution version 2.11.0 + * + * Project: 'Robot_V2.Release+GD32C103CB' + * Target: 'Release+GD32C103CB' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "gd32c10x.h" + +/* GigaDevice::Device:GD32C10x_StdPeripherals:ADC@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_ADC +/* GigaDevice::Device:GD32C10x_StdPeripherals:CAN@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_CAN +/* GigaDevice::Device:GD32C10x_StdPeripherals:DBG@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_DBG +/* GigaDevice::Device:GD32C10x_StdPeripherals:DMA@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_DMA +/* GigaDevice::Device:GD32C10x_StdPeripherals:EXTI@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_EXTI +/* GigaDevice::Device:GD32C10x_StdPeripherals:FMC@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_FMC +/* GigaDevice::Device:GD32C10x_StdPeripherals:FWDGT@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_FWDGT +/* GigaDevice::Device:GD32C10x_StdPeripherals:GPIO@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_GPIO +/* GigaDevice::Device:GD32C10x_StdPeripherals:MISC@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_MISC +/* GigaDevice::Device:GD32C10x_StdPeripherals:PMU@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_PMU +/* GigaDevice::Device:GD32C10x_StdPeripherals:RCU@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_RCU +/* GigaDevice::Device:GD32C10x_StdPeripherals:SPI_I2S@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_SPI +/* GigaDevice::Device:GD32C10x_StdPeripherals:TIMER@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_TIMER +/* GigaDevice::Device:GD32C10x_StdPeripherals:USART@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_USART +/* GigaDevice::Device:GD32C10x_StdPeripherals:WWDGT@1.0.0 */ +#define RTE_DEVICE_STDPERIPHERALS_WWDGT + + +#endif /* RTE_COMPONENTS_H */ diff --git a/Robot_V2/device/ADC.cpp b/Robot_V2/device/ADC.cpp index 98b0f11..406e3a7 100644 --- a/Robot_V2/device/ADC.cpp +++ b/Robot_V2/device/ADC.cpp @@ -1,39 +1,55 @@ #include "adc.h" +#include "Filter.h" +#include "math.h" +#include #include #include -#include "math.h" constexpr float ERROR_ADC_VAL = 255.0f; constexpr float ADC_SCALE = 3.3f / 4096.0f; constexpr float TEMP_FACTOR = 1000.0f / 4.3f; constexpr float VCC_FACTOR = 11.0f; -constexpr float CURRENT_FACTOR = 1.0f / 50.0f * 100.0f * 1000.0f; +constexpr float CURRENT_FACTOR = + 1.0f / 50.0f * 100.0f; // 50倍放大,100倍电流采样电阻, 单位mA constexpr float MAX_TEMP = 150.0f; constexpr float MIN_TEMP = -40.0f; -constexpr float MAX_CURRENT = 50.0f; +constexpr float MAX_CURRENT = 65.0f; constexpr float MIN_CURRENT = -0.1f; constexpr float MAX_VCC = 65.0f; constexpr float MIN_VCC = -0.1f; +u16 adc_value[7] = {0}; // 显式初始化数组元素为0 -u16 adc_value[7] = {0}; // 显式初始化数组元素为0 +/** + * @brief 采样类初始化 + */ +void sampler::init() { + for (int i = 0; i < 7; i++) { + mcu_temp_samples[i] = + (1.43f - adc_value[0] * ADC_SCALE) * TEMP_FACTOR + 35.0f; + currU_samples[i] = adc_value[2] * ADC_SCALE * CURRENT_FACTOR; + currV_samples[i] = adc_value[3] * ADC_SCALE * CURRENT_FACTOR; + currW_samples[i] = adc_value[4] * ADC_SCALE * CURRENT_FACTOR; + vbus_samples[i] = adc_value[5] * ADC_SCALE * VCC_FACTOR; + float R_now = (float)adc_value[1] / (4096 - (float)adc_value[1]) * 4700; + drv_temp_samples[i] = + 1.0f / (0.00335f + 0.00025f * log(R_now / 10000.0f)) - 273.15f; + } +} /** * @brief 获取MCU温度 * @return float * 温度值,单位为摄氏度,范围应在-40到145之间,如果读取失败则返回0.0f */ -float get_mcu_temp() { - float temp_latest = ERROR_ADC_VAL; - // 迭代采样5次,直到获得有效温度值 - for (int i = 0; i < 5; i++) { - temp_latest = (1.43f - adc_value[0] * ADC_SCALE) * TEMP_FACTOR + 35.0f; - - if (temp_latest < MIN_TEMP || temp_latest > MAX_TEMP) - return ERROR_ADC_VAL; +float sampler::get_mcu_temp() { + tempora_sample = medium_filter(mcu_temp_samples, 7); + // 检查温度读数是否在有效范围内 + if (tempora_sample < MIN_TEMP || tempora_sample > MAX_TEMP) { + return ERROR_ADC_VAL; } - return temp_latest; -} + return tempora_sample; +} /** * @brief 获取电机驱动温度 @@ -42,19 +58,13 @@ float get_mcu_temp() { * 通过热敏电阻分压电路计算温度值,使用Steinhart-Hart方程进行温度转换。 * 如果计算结果超出有效范围(-40到255摄氏度),则重新采样计算。 */ -float get_drv_temp() { - float temp_latest = ERROR_ADC_VAL; - for (int i = 0; i < 5; i++) { - float ana_val = adc_value[1]; - float R_now = ana_val / (4096 - ana_val) * 4700; - temp_latest = - 1.0f / (0.00335f + 0.00025f * log(R_now / 10000.0f)) - 273.15f; - - if (temp_latest < MIN_TEMP || temp_latest > MAX_TEMP) { - return ERROR_ADC_VAL; - } +float sampler::get_drv_temp() { + tempora_sample = medium_filter(drv_temp_samples, 7); + // 检查温度读数是否在有效范围内 + if (tempora_sample < MIN_TEMP || tempora_sample > MAX_TEMP) { + return ERROR_ADC_VAL; } - return temp_latest; + return tempora_sample; } /** @@ -64,31 +74,28 @@ float get_drv_temp() { * * 通过ADC采样计算各相电流值 */ -float get_current(char type) { - float current_latest = ERROR_ADC_VAL; +float sampler::get_current(char type) { switch (type) { case 'U': { - current_latest = adc_value[2] * ADC_SCALE * CURRENT_FACTOR; + tempora_sample = medium_filter(currU_samples, 7); break; } case 'V': { - current_latest = adc_value[3] * ADC_SCALE * CURRENT_FACTOR; + tempora_sample = medium_filter(currV_samples, 7); break; } case 'W': { - current_latest = adc_value[4] * ADC_SCALE * CURRENT_FACTOR; + tempora_sample = medium_filter(currW_samples, 7); break; } default: { return ERROR_ADC_VAL; } } - - // 检查电流读数是否在有效范围内 - if (current_latest < MIN_CURRENT || current_latest > MAX_CURRENT) { + if (tempora_sample < MIN_CURRENT || tempora_sample > MAX_CURRENT) { return ERROR_ADC_VAL; } - return current_latest; + return tempora_sample; } /** @@ -98,16 +105,51 @@ float get_current(char type) { * 通过ADC采样计算供电电压值,使用迭代方式确保获取有效的电压读数。 * 如果计算结果超出有效范围(-40到255伏特),则重新采样计算。 */ -float get_vbus_voltage() { - float vcc_latest = ERROR_ADC_VAL; - for (int i = 0; i < 5; i++) { - // 获取电压值 - vcc_latest = adc_value[5] * ADC_SCALE * VCC_FACTOR; - - // 检查电压读数是否在有效范围内 - if (vcc_latest > MAX_VCC || vcc_latest < MIN_VCC) { - return ERROR_ADC_VAL; - } +float sampler::get_vbus_voltage() { + // 检查电压读数是否在有效范围内 + if (vbus_samples[4] > MAX_VCC || vbus_samples[4] < MIN_VCC) { + return ERROR_ADC_VAL; } - return vcc_latest; + return vbus_samples[4]; } + +/** + * @brief 更新MCU温度 + * + * 通过ADC采样计算MCU温度值,使用Steinhart-Hart方程进行温度转换。 + * 如果计算结果超出有效范围(-40到255摄氏度),则重新采样计算。 + */ +void sampler::update_mcu_temp() { + memmove(mcu_temp_samples, mcu_temp_samples + 1, 6 * sizeof(float)); + mcu_temp_samples[6] = (1.43f - adc_value[0] * ADC_SCALE) * TEMP_FACTOR + 35.0f; +} + +/** + * @brief 更新MCU温度 + */ +void sampler::update_drv_temp() { + memmove(drv_temp_samples, drv_temp_samples + 1, 6 * sizeof(float)); + float R_now = (float)adc_value[1] / (4096 - (float)adc_value[1]) * 4700; + drv_temp_samples[6] = 1.0f / (0.00335f + 0.00025f * log(R_now / 10000.0f)) - 273.15f; +} + +/** + * @brief 更新相电流 + */ +void sampler::update_current() { + memmove(currU_samples, currU_samples + 1, 6 * sizeof(float)); + memmove(currV_samples, currV_samples + 1, 6 * sizeof(float)); + memmove(currW_samples, currW_samples + 1, 6 * sizeof(float)); + + currU_samples[6] = adc_value[2] * ADC_SCALE; + currV_samples[6] = adc_value[3] * ADC_SCALE; + currW_samples[6] = adc_value[4] * ADC_SCALE; +} + +/** + * @brief 更新供电电压 + */ +void sampler::update_vbus_voltage() { + memmove(vbus_samples, vbus_samples + 1, 6 * sizeof(float)); + vbus_samples[6] = adc_value[5] * ADC_SCALE; +} \ No newline at end of file diff --git a/Robot_V2/device/Can.cpp b/Robot_V2/device/Can.cpp index 81ba3be..3ec259f 100644 --- a/Robot_V2/device/Can.cpp +++ b/Robot_V2/device/Can.cpp @@ -19,6 +19,7 @@ extern CAN_transmiter CAN0_transmiter; extern FOC_Controlroller FOC; +extern sampler sampler; /*! \brief initialize CAN GPIO @@ -363,9 +364,9 @@ CAN_transmiter::CAN_transmiter() { void CAN_transmiter::update(void) { 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; + mcu_temp = sampler.get_mcu_temp() * 100; + motor_temp = sampler.get_drv_temp() * 100; + Power_Voltage = sampler.get_vbus_voltage() * 1000; 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; @@ -375,9 +376,9 @@ void CAN_transmiter::update(void) { 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; + u_current_union.f = sampler.get_current('U') * 1000; + w_current_union.f = sampler.get_current('W') * 1000; + v_current_union.f = sampler.get_current('V') * 1000; } /*! diff --git a/Robot_V2/device/Timer.cpp b/Robot_V2/device/Timer.cpp index 8e47a30..7c5bf8b 100644 --- a/Robot_V2/device/Timer.cpp +++ b/Robot_V2/device/Timer.cpp @@ -1,16 +1,16 @@ #include "Timer.h" #include "Can.h" +#include "DengFOC.h" +#include "Timer.h" #include "adc.h" #include "gd32c10x.h" #include "gd32c10x_gpio.h" #include "gd32c10x_rcu.h" #include "gd32c10x_timer.h" -#include "DengFOC.h" #include #include #include #include -#include "Timer.h" // 配置定时器每100微秒中断一次 // 系统时钟为120MHz,要得到100微秒的中断周期 @@ -19,8 +19,8 @@ constexpr int TIMER2_PRESCALER = 119; // 120MHz / 120 = 1MHz constexpr int TIMER2_PERIOD = 99; // 1MHz / 100 = 100us -constexpr int TIMER1_PRESCALER = 0; // 不分频,计数器时钟为120MHz -constexpr int TIMER1_PERIOD = 2999; // 120MHz / (0+1) / (5999+1) = 20kHz +constexpr int TIMER1_PRESCALER = 0; // 不分频,计数器时钟为120MHz +constexpr int TIMER1_PERIOD = 5999; // 120MHz / (0+1) / (5999+1) = 20kHz constexpr int TIMER1_CH0_PULSE = 0; constexpr int TIMER1_CH1_PULSE = 0; constexpr int TIMER1_CH2_PULSE = 0; @@ -33,6 +33,8 @@ static volatile std::u64 system_runtime_us = 0; // 声明外部FOC控制器对象 extern FOC_Controlroller FOC; +// 声明外部采样器对象 +extern sampler sampler; /** * @brief 设置引脚中断优先级 @@ -99,17 +101,13 @@ void User_timer_init(void) { nvic_config(); } - /*! - \brief 获取系统运行时间(毫秒) - \param[in] none - \param[out] none - \retval 系统运行时间,单位为毫秒 + \brief 获取系统运行时间(毫秒) + \param[in] none + \param[out] none + \retval 系统运行时间,单位为毫秒 */ -uint64_t get_system_runtime_us(void) -{ - return system_runtime_us; -} +uint64_t get_system_runtime_us(void) { return system_runtime_us; } /** * @brief TIMER2中断处理函数 @@ -120,30 +118,51 @@ void TIMER2_IRQHandler(void) { if (timer_interrupt_flag_get(TIMER2, TIMER_INT_UP) != RESET) { // 清除更新中断标志 timer_interrupt_flag_clear(TIMER2, TIMER_INT_UP); - // 增加总计数器 + + // 增加总计数器 (使用更高效的位运算代替取模运算) total_us100_counter++; system_runtime_us += 100; - // 每100us执行一次的操作可以放在这里 - - // 在定时器中断中执行FOC控制,确保控制频率稳定 + + // 在定时器中断中执行FOC控制,确保控制频率稳定 (最高频操作放在最前) FOC.velocity_open_loop(FOC.target_velocity); + + // 每100us执行一次的操作 + sampler.update_current(); - if (total_us100_counter % 10 == 0) { - // 每1ms执行的代码可以放在这里 - CAN0_transmiter.can0_send_flag = SET; - if (total_us100_counter % 100 == 0) { - // 每10ms执行的代码可以放在这里 - } + // 每1ms执行的代码 (100us * 10 = 1ms) + if (total_us100_counter >= 10) { + total_us100_counter = 0; // 重置计数器 - if (total_us100_counter % 1000 == 0) { - // 每100ms执行的代码可以放在这里 - } + // 设置CAN发送标志 + CAN0_transmiter.can0_send_flag = SET; + + // 更新各种传感器数据 + sampler.update_mcu_temp(); + sampler.update_drv_temp(); + sampler.update_vbus_voltage(); - if (total_us100_counter % 10000 == 0) { - // 每1s执行的代码可以放在这里 - - // 重置计数器避免溢出 - total_us100_counter = 0; + // 每10ms执行的代码 (1ms * 10 = 10ms) + static uint8_t ms10_counter = 0; + ms10_counter++; + if (ms10_counter >= 10) { + ms10_counter = 0; + // 可以添加每10ms执行的代码 + + // 每100ms执行的代码 (10ms * 10 = 100ms) + static uint8_t ms100_counter = 0; + ms100_counter++; + if (ms100_counter >= 10) { + ms100_counter = 0; + // 可以添加每100ms执行的代码 + + // 每1s执行的代码 (100ms * 10 = 1s) + static uint8_t sec_counter = 0; + sec_counter++; + if (sec_counter >= 10) { + sec_counter = 0; + // 可以添加每1s执行的代码 + } + } } } } @@ -164,7 +183,8 @@ void timer1_gpio_config(void) { 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_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); @@ -176,52 +196,53 @@ void timer1_gpio_config(void) { * @brief TIMER1 配置函数 */ void timer1_pwm_config(void) { - timer_parameter_struct timer_initpara; - timer_oc_parameter_struct timer_ocinitpara; + timer_parameter_struct timer_initpara; + timer_oc_parameter_struct timer_ocinitpara; - // 使能TIMER1时钟 - rcu_periph_clock_enable(RCU_TIMER1); + // 使能TIMER1时钟 + rcu_periph_clock_enable(RCU_TIMER1); - // 复位TIMER1 - timer_deinit(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); + // 配置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; + // 配置通道输出参数 + 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); + // 配置三个通道为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); - // 设置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); + // 设置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(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_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(TIMER1, ENABLE); - timer_auto_reload_shadow_enable(TIMER1); - - // 启动TIMER1 - timer_enable(TIMER1); + // 使能主输出和自动重载 + timer_primary_output_config(TIMER1, ENABLE); + timer_auto_reload_shadow_enable(TIMER1); + + // 启动TIMER1 + timer_enable(TIMER1); } - - /*! \brief set PWM \param[in] channel: TIMER_CH_0/TIMER_CH_1/TIMER_CH_2/TIMER_CH_3 (valid @@ -233,14 +254,13 @@ void timer1_pwm_config(void) { */ 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 @@ -250,8 +270,11 @@ void Set_Pwm(u16 channel, float duty_cycle) { \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); +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/adc.h b/Robot_V2/device/adc.h index c5b669b..c27027f 100644 --- a/Robot_V2/device/adc.h +++ b/Robot_V2/device/adc.h @@ -7,14 +7,32 @@ extern "C" { #include "stdint.h" -float get_mcu_temp(void); -float get_drv_temp(void); -float get_vbus_voltage(void); -float get_current(char); +class sampler { + private: + float vbus_samples[7]; + float currU_samples[7]; + float currV_samples[7]; + float currW_samples[7]; + float mcu_temp_samples[7]; + float drv_temp_samples[7]; + + float tempora_sample; + public: + void init(); + void update_mcu_temp(void); + void update_drv_temp(void); + void update_vbus_voltage(void); + void update_current(void); + + float get_mcu_temp(void); + float get_drv_temp(void); + float get_vbus_voltage(void); + float get_current(char); + +}; #ifdef __cplusplus } #endif - #endif diff --git a/Robot_V2/device/test.cpp b/Robot_V2/device/test.cpp index 8f1b6ec..22547a5 100644 --- a/Robot_V2/device/test.cpp +++ b/Robot_V2/device/test.cpp @@ -13,7 +13,7 @@ #include constexpr int status_print = 0; - +extern sampler sampler; void test_1111() { // 初始化CAN回环测试 // can_loopback_init(); @@ -21,13 +21,13 @@ void test_1111() { if (status_print) { /* value print */ printf(" the temperature data is %2.2f degrees Celsius\r\n", - get_mcu_temp()); + sampler.get_mcu_temp()); printf(" the drv_temperature data is %2.2f degrees Celsius\r\n", - get_drv_temp()); - printf(" the U current data is %2.2f mA\r\n", get_current('U')); - printf(" the V current data is %2.2f mA\r\n", get_current('V')); - printf(" the W current data is %2.2f mA\r\n", get_current('W')); - printf(" the VBUS is %2.2f V\r\n", get_vbus_voltage()); + sampler.get_drv_temp()); + printf(" the U current data is %2.2f mA\r\n", sampler.get_current('U')); + printf(" the V current data is %2.2f mA\r\n", sampler.get_current('V')); + printf(" the W current data is %2.2f mA\r\n", sampler.get_current('W')); + printf(" the VBUS is %2.2f V\r\n", sampler.get_vbus_voltage()); // printf(" the angle is %2.2f\r\n", tle5012b_read()); printf("\n----------------------------------------------------\n"); diff --git a/Robot_V2/main.cpp b/Robot_V2/main.cpp index 3762845..b900f21 100644 --- a/Robot_V2/main.cpp +++ b/Robot_V2/main.cpp @@ -18,6 +18,7 @@ CurrentKalman kalman(0.0f, 0.0026f, 4.8f, 0.0001f, 1e-6f, 0.02f); CAN_transmiter CAN0_transmiter; FOC_Controlroller FOC; +sampler sampler; int main(void) { systick_config(); // 系统时钟初始化 @@ -25,16 +26,18 @@ int main(void) { User_timer_init(); // Timer初始化 adc_config(); // ADC初始化 dma_config(); // DMA采样ADC初始化 + sampler.init(); // 采样器初始化 driver_init(); // 电机驱动初始化 tle5012b_gpio_init(); // TLI5012B初始化 tle5012b_spi_init(); watchdog_init(5000); + while (1) { /* clear the FWDGT reset flag */ + // std::printf("1\n"); fwdgt_counter_reload(); - printf("1\r\n"); CAN0_transmiter.communication_check(); } }