| @@ -107,6 +107,17 @@ typedef enum { | |||||
| PLSR_DIR_FORWARD = 0, // 正向 | PLSR_DIR_FORWARD = 0, // 正向 | ||||
| PLSR_DIR_REVERSE = 1 // 反向 | PLSR_DIR_REVERSE = 1 // 反向 | ||||
| } PLSR_Direction_t; | } PLSR_Direction_t; | ||||
| /** | |||||
| * @brief PLSR错误代码枚举 | |||||
| */ | |||||
| typedef enum { | |||||
| PLSR_ERROR_NONE = 0, ///< 无错误 | |||||
| PLSR_ERROR_FREQ_OUT_OF_RANGE = 1, ///< 频率超出范围 | |||||
| PLSR_ERROR_PARAM_CALC_FAILED = 2, ///< 参数计算失败 | |||||
| PLSR_ERROR_TIMER_CONFIG_FAILED = 3, ///< 定时器配置失败 | |||||
| PLSR_ERROR_HARDWARE_FAULT = 4 ///< 硬件故障 | |||||
| } PLSR_ErrorCode_t; | |||||
| /* USER CODE END Private defines */ | /* USER CODE END Private defines */ | ||||
| void MX_TIM2_Init(void); // TIM2恢复用于脉冲计数 | void MX_TIM2_Init(void); // TIM2恢复用于脉冲计数 | ||||
| @@ -168,7 +179,7 @@ typedef struct | |||||
| uint32_t freq_step; ///< 频率步长 | uint32_t freq_step; ///< 频率步长 | ||||
| uint32_t default_freq; ///< 脉冲默认速度 | uint32_t default_freq; ///< 脉冲默认速度 | ||||
| uint64_t pulse_count; ///< 当前脉冲计数 | |||||
| int64_t pulse_count; ///< 当前脉冲计数(支持正负值) | |||||
| int64_t prevPulseCount; ///< 上阶段目标脉冲 | int64_t prevPulseCount; ///< 上阶段目标脉冲 | ||||
| int64_t accel_pulse_count; ///< 第一部分脉冲数(可能是加速、减速或匀速) | int64_t accel_pulse_count; ///< 第一部分脉冲数(可能是加速、减速或匀速) | ||||
| int64_t const_pulse_count; ///< 第二部分脉冲数(匀速) | int64_t const_pulse_count; ///< 第二部分脉冲数(匀速) | ||||
| @@ -203,6 +214,7 @@ typedef struct | |||||
| uint8_t ext_port; ///< 外部事件端口选择 | uint8_t ext_port; ///< 外部事件端口选择 | ||||
| uint8_t dir_port; ///< 方向端口选择 | uint8_t dir_port; ///< 方向端口选择 | ||||
| uint8_t current_part; ///< 当前执行部分:1-第一部分,2-第二部分,3-第三部分 | uint8_t current_part; ///< 当前执行部分:1-第一部分,2-第二部分,3-第三部分 | ||||
| PLSR_ErrorCode_t error_code; ///< 错误代码 | |||||
| } PLSR_RouteConfig_t; | } PLSR_RouteConfig_t; | ||||
| // 三部分执行状态枚举 | // 三部分执行状态枚举 | ||||
| @@ -227,7 +239,7 @@ void PLSR_PWM_Init(void); | |||||
| void PLSR_PWM_Start(void); | void PLSR_PWM_Start(void); | ||||
| void PLSR_Section_PWM_Stop(void); | void PLSR_Section_PWM_Stop(void); | ||||
| void PLSR_Route_PWM_Stop(); | void PLSR_Route_PWM_Stop(); | ||||
| void PLSR_PWM_SetFrequency(uint32_t frequency); | |||||
| uint8_t PLSR_PWM_SetFrequency(uint32_t frequency); | |||||
| void PLSR_CalculateTimerParams(uint32_t frequency, uint16_t* prescaler, uint32_t* period); | void PLSR_CalculateTimerParams(uint32_t frequency, uint16_t* prescaler, uint32_t* period); | ||||
| void PLSR_Fix_Compensated(uint32_t frequency, uint32_t* ccr); | void PLSR_Fix_Compensated(uint32_t frequency, uint32_t* ccr); | ||||
| @@ -278,6 +290,8 @@ extern PLSR_RouteConfig_t PlsrRoute; // 全局PLSR路径控制结构体 | |||||
| extern uint8_t PlsrExtEventFlag; // 外部事件标志 | extern uint8_t PlsrExtEventFlag; // 外部事件标志 | ||||
| extern int64_t PlsrTotalPulseCount; // 全局累加脉冲计数器(程序运行期间持续累加,支持负数) | extern int64_t PlsrTotalPulseCount; // 全局累加脉冲计数器(程序运行期间持续累加,支持负数) | ||||
| extern int64_t PlsrLocation; | extern int64_t PlsrLocation; | ||||
| extern volatile uint8_t PlsrFreqUpdateRequest; // 频率更新请求标志(中断安全) | |||||
| extern volatile uint32_t PlsrPendingFreq; // 待更新的频率值(中断安全) | |||||
| /* USER CODE END Prototypes */ | /* USER CODE END Prototypes */ | ||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||
| @@ -708,25 +708,29 @@ void PLSR_Route_PWM_Stop() | |||||
| */ | */ | ||||
| void PLSR_PWM_SetFrequency(uint32_t frequency) | void PLSR_PWM_SetFrequency(uint32_t frequency) | ||||
| { | { | ||||
| uint16_t prescaler = 0; // 预分频器值 | |||||
| uint32_t period = 0; // 自动重载值(周期) | |||||
| uint32_t ccr = 0; | |||||
| uint16_t prescaler = 0; ///< 预分频器值 | |||||
| uint32_t period = 0; ///< 自动重载值(周期) | |||||
| uint32_t ccr = 0; ///< 比较寄存器值 | |||||
| // 频率范围检查 - 确保频率在1hz到100khz范围内 | |||||
| /* 频率范围检查 - 确保频率在有效范围内 */ | |||||
| if(frequency < PLSR_PWM_FREQ_MIN || frequency > PLSR_PWM_FREQ_MAX) | if(frequency < PLSR_PWM_FREQ_MIN || frequency > PLSR_PWM_FREQ_MAX) | ||||
| { | { | ||||
| return; // 频率超出范围,直接返回,不做任何修改 | |||||
| return; ///< 频率超出范围,直接返回,不做任何修改 | |||||
| } | } | ||||
| // 计算最佳定时器参数 - 根据目标频率计算预分频器和周期值 | |||||
| /* 计算最佳定时器参数 - 根据目标频率计算预分频器和周期值 */ | |||||
| PLSR_CalculateTimerParams(frequency, &prescaler, &period); | PLSR_CalculateTimerParams(frequency, &prescaler, &period); | ||||
| ccr = (period + 1) / 2; | |||||
| PLSR_Fix_Compensated(frequency,&ccr); | |||||
| // 参数有效性检查 - 防止period为0导致除零错误 | |||||
| /* 参数有效性检查 - 防止period为0导致除零错误 */ | |||||
| if(period == 0) | if(period == 0) | ||||
| { | { | ||||
| return; // period无效,直接返回,避免HardFault异常 | |||||
| return; ///< period无效,直接返回,避免HardFault异常 | |||||
| } | } | ||||
| /* 安全计算CCR值,使用64位避免溢出 */ | |||||
| uint64_t ccr_temp = ((uint64_t)period + 1ULL) / 2ULL; | |||||
| ccr = (uint32_t)ccr_temp; | |||||
| PLSR_Fix_Compensated(frequency, &ccr); | |||||
| // 根据output_port选择目标定时器并更新参数 | // 根据output_port选择目标定时器并更新参数 | ||||
| switch(PlsrRoute.output_port) | switch(PlsrRoute.output_port) | ||||
| { | { | ||||
| @@ -778,25 +782,32 @@ void PLSR_PWM_SetFrequency(uint32_t frequency) | |||||
| */ | */ | ||||
| void PLSR_TIM6_SetUpdateFreq(uint32_t freq_us) | void PLSR_TIM6_SetUpdateFreq(uint32_t freq_us) | ||||
| { | { | ||||
| // 保存新的频率设置 | |||||
| /* 参数有效性检查 */ | |||||
| if (freq_us == 0) freq_us = 1; ///< 防止除零错误 | |||||
| if (freq_us > 65535) freq_us = 65535; ///< 限制最大周期值 | |||||
| /* 保存新的频率设置 */ | |||||
| s_tim6_update_freq_us = freq_us; | s_tim6_update_freq_us = freq_us; | ||||
| // 定时器时钟参数 (基于STM32F4系列APB1时钟配置) | |||||
| // APB1时钟频率:42MHz 定时器二倍频 | |||||
| uint32_t target_period_us = freq_us; // 目标周期(微秒) | |||||
| /* 定时器时钟参数 (基于STM32F4系列APB1时钟配置) */ | |||||
| /* APB1时钟频率:42MHz 定时器二倍频到84MHz */ | |||||
| uint32_t target_period_us = freq_us; ///< 目标周期(微秒) | |||||
| /* 计算定时器参数 */ | |||||
| /* 预分频器设为83,使计数频率为84MHz/(83+1) = 1MHz,即1us/tick */ | |||||
| uint16_t prescaler = 83; ///< 预分频器值,产生1MHz计数频率 | |||||
| uint32_t period = target_period_us - 1; ///< 自动重载值,减1是因为从0开始计数 | |||||
| // 计算定时器参数 | |||||
| // 预分频器设为41,使计数频率为84MHz/(83+1) = 1MHz,即1us/tick | |||||
| uint16_t prescaler = 83; // 预分频器值,产生1MHz计数频率 | |||||
| uint32_t period = target_period_us - 1; // 自动重载值,减1是因为从0开始计数 | |||||
| /* 确保period在有效范围内 */ | |||||
| if (period > 65535) period = 65535; ///< 限制ARR最大值 | |||||
| // 停止TIM6中断 - 避免参数更新过程中的中断干扰 | |||||
| /* 停止TIM6中断 - 避免参数更新过程中的中断干扰 */ | |||||
| HAL_TIM_Base_Stop_IT(&htim6); | HAL_TIM_Base_Stop_IT(&htim6); | ||||
| // 更新TIM6核心参数 | |||||
| __HAL_TIM_SET_PRESCALER(&htim6, prescaler); // 设置预分频器 | |||||
| __HAL_TIM_SET_AUTORELOAD(&htim6, period); // 设置自动重载值(决定更新频率) | |||||
| __HAL_TIM_SET_COUNTER(&htim6, 0); // 重置计数器到初始状态 | |||||
| /* 更新TIM6核心参数 */ | |||||
| __HAL_TIM_SET_PRESCALER(&htim6, prescaler); ///< 设置预分频器 | |||||
| __HAL_TIM_SET_AUTORELOAD(&htim6, period); ///< 设置自动重载值(决定更新频率) | |||||
| __HAL_TIM_SET_COUNTER(&htim6, 0); ///< 重置计数器到初始状态 | |||||
| // 触发更新事件 - 立即将新参数加载到影子寄存器 | // 触发更新事件 - 立即将新参数加载到影子寄存器 | ||||
| HAL_TIM_GenerateEvent(&htim6, TIM_EVENTSOURCE_UPDATE); | HAL_TIM_GenerateEvent(&htim6, TIM_EVENTSOURCE_UPDATE); | ||||
| @@ -20,34 +20,44 @@ void PLSR_Fix_Compensated(uint32_t frequency, uint32_t* ccr) | |||||
| * @param prescaler: 预分频器值指针 | * @param prescaler: 预分频器值指针 | ||||
| * @param period: 周期值指针 | * @param period: 周期值指针 | ||||
| * @retval None | * @retval None | ||||
| * @note 根据目标频率计算TIM10的预分频器和周期值 | |||||
| * @note 根据目标频率计算定时器的预分频器和周期值,使用64位数据类型避免高频时溢出 | |||||
| */ | */ | ||||
| void PLSR_CalculateTimerParams(uint32_t frequency, uint16_t* prescaler, uint32_t* period) | void PLSR_CalculateTimerParams(uint32_t frequency, uint16_t* prescaler, uint32_t* period) | ||||
| { | { | ||||
| /* 参数有效性检查 */ | |||||
| if (frequency < PLSR_PWM_FREQ_MIN) frequency = PLSR_PWM_FREQ_MIN; | if (frequency < PLSR_PWM_FREQ_MIN) frequency = PLSR_PWM_FREQ_MIN; | ||||
| if (frequency > PLSR_PWM_FREQ_MAX) frequency = PLSR_PWM_FREQ_MAX; | if (frequency > PLSR_PWM_FREQ_MAX) frequency = PLSR_PWM_FREQ_MAX; | ||||
| uint32_t timer_clock = 0; | |||||
| /* 使用64位数据类型避免高频计算时的溢出 */ | |||||
| uint64_t timer_clock = 0; | |||||
| if(PlsrRoute.output_port == 0 || PlsrRoute.output_port == 1) | if(PlsrRoute.output_port == 0 || PlsrRoute.output_port == 1) | ||||
| { | { | ||||
| timer_clock = 168000000UL; // TIM10/TIM11时钟 (APB2 84MHz) | |||||
| timer_clock = 168000000ULL; ///< TIM10/TIM11时钟 (APB2 168MHz) | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| timer_clock = 84000000UL; // TIM13/TIM14时钟 (APB1 42MHz) | |||||
| timer_clock = 84000000ULL; ///< TIM13/TIM14时钟 (APB1 84MHz) | |||||
| } | } | ||||
| uint32_t divider = (timer_clock + frequency / 2) / frequency; // 四舍五入 | |||||
| if (divider < 2) divider = 2; // 至少 2 | |||||
| /* 防止除零错误 */ | |||||
| if (frequency == 0) frequency = 1; | |||||
| /* 使用64位计算避免溢出,四舍五入处理 */ | |||||
| uint64_t divider = (timer_clock + (uint64_t)frequency / 2) / (uint64_t)frequency; | |||||
| if (divider < 2) divider = 2; ///< 最小分频比为2 | |||||
| // 限制 ARR <= 65535 | |||||
| uint32_t psc = (divider + 65535) / 65536; // 向上取整 | |||||
| if (psc > 0xFFFF) psc = 0xFFFF; | |||||
| /* 计算预分频器,限制ARR <= 65535 */ | |||||
| uint64_t psc = (divider + 65535ULL) / 65536ULL; ///< 向上取整 | |||||
| if (psc > 0xFFFFULL) psc = 0xFFFFULL; ///< 限制预分频器最大值 | |||||
| uint32_t arr = (divider / psc) - 1; | |||||
| if (arr < 1) arr = 1; | |||||
| if (arr > 65535) arr = 65535; | |||||
| /* 计算自动重载值 */ | |||||
| uint64_t arr = (divider / psc) - 1; | |||||
| if (arr < 1) arr = 1; ///< 最小ARR值为1 | |||||
| if (arr > 65535ULL) arr = 65535ULL; ///< 限制ARR最大值 | |||||
| /* 安全转换为16位和32位数据类型 */ | |||||
| *prescaler = (uint16_t)(psc - 1); | *prescaler = (uint16_t)(psc - 1); | ||||
| *period = arr; | |||||
| *period = (uint32_t)arr; | |||||
| } | } | ||||
| // ==================== PLSR 路径计算函数实现 ==================== | // ==================== PLSR 路径计算函数实现 ==================== | ||||