赞
踩
(这里用两个定时器主要是为了学习配置多个定时器)
3.1各通道的配置 3.2 记得打开中断
1.motor.c文件
- #include "Motor.h"
- #include <math.h>
-
- X_speedRampData X_srd = {STOP,CW,0,0,0,0,0}; // X加减速曲线变量
- __IO int32_t X_step_position = 0; // X当前位置
- __IO uint8_t X_MotionStatus = 0; //X是否在运动?0:停止,1:运动
-
- Y_speedRampData Y_srd = {STOP,CW,0,0,0,0,0}; // Y加减速曲线变量
- __IO int32_t Y_step_position = 0; // Y当前位置
- __IO uint8_t Y_MotionStatus = 0; //Y是否在运动?0:停止,1:运动
-
- P_speedRampData P_srd = {STOP,CW,0,0,0,0,0}; // P加减速曲线变量
- __IO int32_t P_step_position = 0; // P当前位置
- __IO uint8_t P_MotionStatus = 0; //P是否在运动?0:停止,1:运动
-
- extern TIM_HandleTypeDef htim2;
- extern TIM_HandleTypeDef htim3;
-
- /**
- * 函数功能: 相对位置运动:运动给定的步数
- * 输入参数: step:移动的步数 (正数为顺时针,负数为逆时针).
- accel 加速度,实际值为accel*0.025*rad/sec^2
- decel 减速度,实际值为decel*0.025*rad/sec^2
- speed 最大速度,实际值为speed*0.05*rad/sec
- * 返 回 值: 无
- * 说 明: 以给定的步数移动步进电机,先加速到最大速度,然后在合适位置开始
- * 减速至停止,使得整个运动距离为指定的步数。如果加减速阶段很短并且
- * 速度很慢,那还没达到最大速度就要开始减速
- */
- /***X电机梯形加减速***/
- void X_STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed)
- {
- __IO uint16_t X_tim_count;
- // X达到最大速度时的步数
- __IO uint32_t X_max_s_lim;
- // X必须要开始减速的步数(如果加速没有达到最大速度)
- __IO uint32_t X_accel_lim;
-
- if(step < 0) // 步数为负数
- {
- X_srd.dir = CCW; // 逆时针方向旋转
- X_STEPMOTOR_DIR_REVERSAL();
- step =-step; // 获取步数绝对值
- }
- else
- {
- X_srd.dir = CW; // 顺时针方向旋转
- X_STEPMOTOR_DIR_FORWARD();
- }
-
- if(step == 1) // 步数为1
- {
- X_srd.accel_count = -1; // 只移动一步
- X_srd.run_state = DECEL; // 减速状态.
- X_srd.step_delay = 1000; // 短延时
- }
- else if(step != 0) // 如果目标运动步数不为0
- {
- // 我们的驱动器用户手册有详细的计算及推导过程
-
- // 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。
- // min_delay = (alpha / tt)/ w
- X_srd.min_delay = (int32_t)(A_T_x10/speed);
-
- // 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2
- // step_delay = 1/tt * sqrt(2*alpha/accel)
- // step_delay = ( tfreq*0.676/10 )*10 * sqrt( (2*alpha*100000) / (accel*10) )/100
- X_srd.step_delay = (int32_t)((T1_FREQ_148 * sqrt(A_SQ / accel))/10);
-
- // 计算多少步之后达到最大速度的限制
- // max_s_lim = speed^2 / (2*alpha*accel)
- X_max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));
- // 如果达到最大速度小于0.5步,我们将四舍五入为0
- // 但实际我们必须移动至少一步才能达到想要的速度
- if(X_max_s_lim == 0){
- X_max_s_lim = 1;
- }
-
- // 计算多少步之后我们必须开始减速
- // n1 = (n1+n2)decel / (accel + decel)
- X_accel_lim = (uint32_t)(step*decel/(accel+decel));
- // 我们必须加速至少1步才能才能开始减速.
- if(X_accel_lim == 0){
- X_accel_lim = 1;
- }
-
- // 使用限制条件我们可以计算出减速阶段步数
- if(X_accel_lim <= X_max_s_lim){
- X_srd.decel_val = X_accel_lim - step;
- }
- else{
- X_srd.decel_val = -(X_max_s_lim*accel/decel);
- }
- // 当只剩下一步我们必须减速
- if(X_srd.decel_val == 0){
- X_srd.decel_val = -1;
- }
-
- // 计算开始减速时的步数
- X_srd.decel_start = step + X_srd.decel_val;
-
- // 如果最大速度很慢,我们就不需要进行加速运动
- if(X_srd.step_delay <= X_srd.min_delay){
- X_srd.step_delay = X_srd.min_delay;
- X_srd.run_state = RUN;
- }
- else{
- X_srd.run_state = ACCEL;
- }
- // 复位加速度计数值
- X_srd.accel_count = 0;
- }
- X_MotionStatus = 1; // 电机为运动状态
- X_tim_count=__HAL_TIM_GET_COUNTER(&htim3);
- __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,X_tim_count+X_srd.step_delay); // 设置定时器比较值
- HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_1);
- TIM_CCxChannelCmd(TIM3,TIM_CHANNEL_1, TIM_CCx_ENABLE);// 使能定时器通道
- X_STEPMOTOR_OUTPUT_ENABLE();
- }
- /***Y电机梯形加减速***/
- void Y_STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed)
- {
- __IO uint16_t Y_tim_count;// X达到最大速度时的步数
- __IO uint32_t Y_max_s_lim;// X必须要开始减速的步数(如果加速没有达到最大速度)
- __IO uint32_t Y_accel_lim;
-
-
- if(step < 0) // 步数为负数
- {
- Y_srd.dir = CCW; // 逆时针方向旋转
- Y_STEPMOTOR_DIR_REVERSAL();
- step =-step; // 获取步数绝对值
- }
- else
- {
- Y_srd.dir = CW; // 顺时针方向旋转
- Y_STEPMOTOR_DIR_FORWARD();
- }
-
- if(step == 1) // 步数为1
- {
- Y_srd.accel_count = -1; // 只移动一步
- Y_srd.run_state = DECEL; // 减速状态.
- Y_srd.step_delay = 1000; // 短延时
- }
- else if(step != 0) // 如果目标运动步数不为0
- {
- // 我们的驱动器用户手册有详细的计算及推导过程
-
- // 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。
- // min_delay = (alpha / tt)/ w
- Y_srd.min_delay = (int32_t)(A_T_x10/speed);
-
- // 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2
- // step_delay = 1/tt * sqrt(2*alpha/accel)
- // step_delay = ( tfreq*0.676/10 )*10 * sqrt( (2*alpha*100000) / (accel*10) )/100
- Y_srd.step_delay = (int32_t)((T1_FREQ_148 * sqrt(A_SQ / accel))/10);
-
- // 计算多少步之后达到最大速度的限制
- // max_s_lim = speed^2 / (2*alpha*accel)
- Y_max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));
- // 如果达到最大速度小于0.5步,我们将四舍五入为0
- // 但实际我们必须移动至少一步才能达到想要的速度
- if(Y_max_s_lim == 0){
- Y_max_s_lim = 1;
- }
-
- // 计算多少步之后我们必须开始减速
- // n1 = (n1+n2)decel / (accel + decel)
- Y_accel_lim = (uint32_t)(step*decel/(accel+decel));
- // 我们必须加速至少1步才能才能开始减速.
- if(Y_accel_lim == 0){
- Y_accel_lim = 1;
- }
-
- // 使用限制条件我们可以计算出减速阶段步数
- if(Y_accel_lim <= Y_max_s_lim){
- Y_srd.decel_val = Y_accel_lim - step;
- }
- else{
- Y_srd.decel_val = -(Y_max_s_lim*accel/decel);
- }
- // 当只剩下一步我们必须减速
- if(Y_srd.decel_val == 0){
- Y_srd.decel_val = -1;
- }
-
- // 计算开始减速时的步数
- Y_srd.decel_start = step + Y_srd.decel_val;
-
- // 如果最大速度很慢,我们就不需要进行加速运动
- if(Y_srd.step_delay <= Y_srd.min_delay){
- Y_srd.step_delay = Y_srd.min_delay;
- Y_srd.run_state = RUN;
- }
- else{
- Y_srd.run_state = ACCEL;
- }
- // 复位加速度计数值
- Y_srd.accel_count = 0;
- }
- Y_MotionStatus = 1; // 电机为运动状态
- Y_tim_count=__HAL_TIM_GET_COUNTER(&htim3);
- __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,Y_tim_count+Y_srd.step_delay); // 设置定时器比较值
- HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_2);
- TIM_CCxChannelCmd(TIM3,TIM_CHANNEL_2, TIM_CCx_ENABLE);// 使能定时器通道
- Y_STEPMOTOR_OUTPUT_ENABLE();
- }
-
- /***P电机梯形加减速***/
- void P_STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed)
- {
- __IO uint16_t P_tim_count;
- // X达到最大速度时的步数
- __IO uint32_t P_max_s_lim;
- // X必须要开始减速的步数(如果加速没有达到最大速度)
- __IO uint32_t P_accel_lim;
-
- if(step < 0) // 步数为负数
- {
- P_srd.dir = CCW; // 逆时针方向旋转
- P_STEPMOTOR_DIR_REVERSAL();
- step =-step; // 获取步数绝对值
- }
- else
- {
- P_srd.dir = CW; // 顺时针方向旋转
- P_STEPMOTOR_DIR_FORWARD();
- }
-
- if(step == 1) // 步数为1
- {
- P_srd.accel_count = -1; // 只移动一步
- P_srd.run_state = DECEL; // 减速状态.
- P_srd.step_delay = 1000; // 短延时
- }
- else if(step != 0) // 如果目标运动步数不为0
- {
- // 我们的驱动器用户手册有详细的计算及推导过程
-
- // 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。
- // min_delay = (alpha / tt)/ w
- P_srd.min_delay = (int32_t)(A_T_x10/speed);
-
- // 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2
- // step_delay = 1/tt * sqrt(2*alpha/accel)
- // step_delay = ( tfreq*0.676/10 )*10 * sqrt( (2*alpha*100000) / (accel*10) )/100
- P_srd.step_delay = (int32_t)((T1_FREQ_148 * sqrt(A_SQ / accel))/10);
-
- // 计算多少步之后达到最大速度的限制
- // max_s_lim = speed^2 / (2*alpha*accel)
- P_max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));
- // 如果达到最大速度小于0.5步,我们将四舍五入为0
- // 但实际我们必须移动至少一步才能达到想要的速度
- if(P_max_s_lim == 0){
- P_max_s_lim = 1;
- }
-
- // 计算多少步之后我们必须开始减速
- // n1 = (n1+n2)decel / (accel + decel)
- P_accel_lim = (uint32_t)(step*decel/(accel+decel));
- // 我们必须加速至少1步才能才能开始减速.
- if(P_accel_lim == 0){
- P_accel_lim = 1;
- }
-
- // 使用限制条件我们可以计算出减速阶段步数
- if(P_accel_lim <= P_max_s_lim){
- P_srd.decel_val = P_accel_lim - step;
- }
- else{
- P_srd.decel_val = -(P_max_s_lim*accel/decel);
- }
- // 当只剩下一步我们必须减速
- if(P_srd.decel_val == 0){
- P_srd.decel_val = -1;
- }
-
- // 计算开始减速时的步数
- P_srd.decel_start = step + P_srd.decel_val;
-
- // 如果最大速度很慢,我们就不需要进行加速运动
- if(P_srd.step_delay <= P_srd.min_delay){
- P_srd.step_delay = P_srd.min_delay;
- P_srd.run_state = RUN;
- }
- else{
- P_srd.run_state = ACCEL;
- }
- // 复位加速度计数值
- P_srd.accel_count = 0;
- }
- P_MotionStatus = 1; // 电机为运动状态
- P_tim_count=__HAL_TIM_GET_COUNTER(&htim2);
- __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_3,P_tim_count+X_srd.step_delay); // 设置定时器比较值
- HAL_TIM_OC_Start_IT(&htim2,TIM_CHANNEL_3);
- TIM_CCxChannelCmd(TIM2,TIM_CHANNEL_3, TIM_CCx_ENABLE);// 使能定时器通道
- P_STEPMOTOR_OUTPUT_ENABLE();
- }
-
-
- /**
- * 函数功能: 定时器中断服务函数
- * 输入参数: 无
- * 返 回 值: 无
- * 说 明: 实现加减速过程
- */
- void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)//定时器中断处理
- {
- /*X电机*/
- __IO uint16_t X_tim_count=0;
- // X保存新(下)一个延时周期
- uint16_t X_new_step_delay=0;
- // X加速过程中最后一次延时(脉冲周期).
- __IO static uint16_t X_last_accel_delay=0;
- // X总移动步数计数器
- __IO static uint32_t X_step_count = 0;
- // X记录new_step_delay中的余数,提高下一步计算的精度
- __IO static int32_t X_rest = 0;
- //X定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲
- __IO static uint8_t X_i=0;
-
- /*Y电机*/
- __IO uint16_t Y_tim_count=0;
- // Y保存新(下)一个延时周期
- uint16_t Y_new_step_delay=0;
- // Y加速过程中最后一次延时(脉冲周期).
- __IO static uint16_t Y_last_accel_delay=0;
- // Y总移动步数计数器
- __IO static uint32_t Y_step_count = 0;
- // X记录new_step_delay中的余数,提高下一步计算的精度
- __IO static int32_t Y_rest = 0;
- //Y定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲
- __IO static uint8_t Y_i=0;
-
- /*P电机*/
- __IO uint16_t P_tim_count=0;
- // Y保存新(下)一个延时周期
- uint16_t P_new_step_delay=0;
- // Y加速过程中最后一次延时(脉冲周期).
- __IO static uint16_t P_last_accel_delay=0;
- // Y总移动步数计数器
- __IO static uint32_t P_step_count = 0;
- // X记录new_step_delay中的余数,提高下一步计算的精度
- __IO static int32_t P_rest = 0;
- //Y定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲
- __IO static uint8_t P_i=0;
-
- if(htim->Instance==TIM3)
- {
- /*X电机的定时器配置*/
- if(__HAL_TIM_GET_IT_SOURCE(&htim3, TIM_IT_CC1) !=RESET)
- {
- // 清楚定时器中断
- __HAL_TIM_CLEAR_IT(&htim3, TIM_IT_CC1);
-
- // 设置比较值
- X_tim_count=__HAL_TIM_GET_COUNTER(&htim3);
- __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,X_tim_count+X_srd.step_delay);
-
- X_i++; // 定时器中断次数计数值
- if(X_i==2) // 2次,说明已经输出一个完整脉冲
- {
- X_i=0; // 清零定时器中断次数计数值
- switch(X_srd.run_state) // 加减速曲线阶段
- {
- case STOP:
- X_step_count = 0; // 清零步数计数器
- X_rest = 0; // 清零余值
- // 关闭通道
- TIM_CCxChannelCmd(TIM3, TIM_CHANNEL_1, TIM_CCx_DISABLE);
- __HAL_TIM_CLEAR_FLAG(&htim3,TIM_FLAG_CC1);
- X_STEPMOTOR_OUTPUT_DISABLE();
- X_MotionStatus = 0; // 电机为停止状态
- break;
-
- case ACCEL:
- X_step_count++; // 步数加1
- if(X_srd.dir==CW)
- {
- X_step_position++; // 绝对位置加1
- }
- else
- {
- X_step_position--; // 绝对位置减1
- }
- X_srd.accel_count++; // 加速计数值加1
- X_new_step_delay = X_srd.step_delay - (((2 *X_srd.step_delay) + X_rest)/(4 * X_srd.accel_count + 1));//计算新(下)一步脉冲周期(时间间隔)
- X_rest = ((2 * X_srd.step_delay)+X_rest)%(4 * X_srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
- if(X_step_count >= X_srd.decel_start)// 检查是够应该开始减速
- {
- X_srd.accel_count = X_srd.decel_val; // 加速计数值为减速阶段计数值的初始值
- X_srd.run_state = DECEL; // 下个脉冲进入减速阶段
- }
- else if(X_new_step_delay <= X_srd.min_delay) // 检查是否到达期望的最大速度
- {
- X_last_accel_delay = X_new_step_delay; // 保存加速过程中最后一次延时(脉冲周期)
- X_new_step_delay = X_srd.min_delay; // 使用min_delay(对应最大速度speed)
- X_rest = 0; // 清零余值
- X_srd.run_state = RUN; // 设置为匀速运行状态
- }
- break;
-
- case RUN:
- X_step_count++; // 步数加1
- if(X_srd.dir==CW)
- {
- X_step_position++; // 绝对位置加1
- }
- else
- {
- X_step_position--; // 绝对位置减1
- }
- X_new_step_delay = X_srd.min_delay; // 使用min_delay(对应最大速度speed)
- if(X_step_count >= X_srd.decel_start) // 需要开始减速
- {
- X_srd.accel_count = X_srd.decel_val; // 减速步数做为加速计数值
- X_new_step_delay = X_last_accel_delay;// 加阶段最后的延时做为减速阶段的起始延时(脉冲周期)
- X_srd.run_state = DECEL; // 状态改变为减速
- }
- break;
-
- case DECEL:
- X_step_count++; // 步数加1
- if(X_srd.dir==CW)
- {
- X_step_position++; // 绝对位置加1
- }
- else
- {
- X_step_position--; // 绝对位置减1
- }
- X_srd.accel_count++;
- X_new_step_delay = X_srd.step_delay - (((2 * X_srd.step_delay) + X_rest)/(4 * X_srd.accel_count + 1)); //计算新(下)一步脉冲周期(时间间隔)
- X_rest = ((2 * X_srd.step_delay)+X_rest)%(4 * X_srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
-
- //检查是否为最后一步
- if(X_srd.accel_count >= 0)
- {
- X_srd.run_state = STOP;
- }
- break;
- }
- X_srd.step_delay = X_new_step_delay; // 为下个(新的)延时(脉冲周期)赋值
- }
- }
-
- /*Y电机的定时器配置*/
- if(__HAL_TIM_GET_IT_SOURCE(&htim3, TIM_IT_CC2) !=RESET)
- {
- // 清楚定时器中断
- __HAL_TIM_CLEAR_IT(&htim3, TIM_IT_CC2);
-
- // 设置比较值
- Y_tim_count=__HAL_TIM_GET_COUNTER(&htim3);
- __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,Y_tim_count+Y_srd.step_delay);
-
- Y_i++; // 定时器中断次数计数值
- if(Y_i==2) // 2次,说明已经输出一个完整脉冲
- {
- Y_i=0; // 清零定时器中断次数计数值
- switch(Y_srd.run_state) // 加减速曲线阶段
- {
- case STOP:
- Y_step_count = 0; // 清零步数计数器
- Y_rest = 0; // 清零余值
- // 关闭通道
- TIM_CCxChannelCmd(TIM3, TIM_CHANNEL_2, TIM_CCx_DISABLE);
- __HAL_TIM_CLEAR_FLAG(&htim3,TIM_FLAG_CC2);
- Y_STEPMOTOR_OUTPUT_DISABLE();
- Y_MotionStatus = 0; // 电机为停止状态
- break;
-
- case ACCEL:
- Y_step_count++; // 步数加1
- if(Y_srd.dir==CW)
- {
- Y_step_position++; // 绝对位置加1
- }
- else
- {
- Y_step_position--; // 绝对位置减1
- }
- Y_srd.accel_count++; // 加速计数值加1
- Y_new_step_delay = Y_srd.step_delay - (((2 *Y_srd.step_delay) + Y_rest)/(4 * Y_srd.accel_count + 1));//计算新(下)一步脉冲周期(时间间隔)
- Y_rest = ((2 * Y_srd.step_delay)+Y_rest)%(4 * Y_srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
- if(Y_step_count >= Y_srd.decel_start)// 检查是够应该开始减速
- {
- Y_srd.accel_count = Y_srd.decel_val; // 加速计数值为减速阶段计数值的初始值
- Y_srd.run_state = DECEL; // 下个脉冲进入减速阶段
- }
- else if(Y_new_step_delay <= Y_srd.min_delay) // 检查是否到达期望的最大速度
- {
- Y_last_accel_delay = Y_new_step_delay; // 保存加速过程中最后一次延时(脉冲周期)
- Y_new_step_delay = Y_srd.min_delay; // 使用min_delay(对应最大速度speed)
- Y_rest = 0; // 清零余值
- Y_srd.run_state = RUN; // 设置为匀速运行状态
- }
- break;
-
- case RUN:
- Y_step_count++; // 步数加1
- if(Y_srd.dir==CW)
- {
- Y_step_position++; // 绝对位置加1
- }
- else
- {
- Y_step_position--; // 绝对位置减1
- }
- Y_new_step_delay = Y_srd.min_delay; // 使用min_delay(对应最大速度speed)
- if(Y_step_count >= Y_srd.decel_start) // 需要开始减速
- {
- Y_srd.accel_count = Y_srd.decel_val; // 减速步数做为加速计数值
- Y_new_step_delay = Y_last_accel_delay;// 加阶段最后的延时做为减速阶段的起始延时(脉冲周期)
- Y_srd.run_state = DECEL; // 状态改变为减速
- }
- break;
-
- case DECEL:
- Y_step_count++; // 步数加1
- if(Y_srd.dir==CW)
- {
- Y_step_position++; // 绝对位置加1
- }
- else
- {
- Y_step_position--; // 绝对位置减1
- }
- Y_srd.accel_count++;
- Y_new_step_delay = Y_srd.step_delay - (((2 * Y_srd.step_delay) + Y_rest)/(4 * Y_srd.accel_count + 1)); //计算新(下)一步脉冲周期(时间间隔)
- Y_rest = ((2 * Y_srd.step_delay)+Y_rest)%(4 * Y_srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
-
- //检查是否为最后一步
- if(Y_srd.accel_count >= 0)
- {
- Y_srd.run_state = STOP;
- }
- break;
- }
- Y_srd.step_delay = Y_new_step_delay; // 为下个(新的)延时(脉冲周期)赋值
- }
- }
- }
- if(htim->Instance==TIM2)
- {
- /*P电机的定时器配置*/
- if(__HAL_TIM_GET_IT_SOURCE(&htim2, TIM_IT_CC3) !=RESET)
- {
- // 清楚定时器中断
- __HAL_TIM_CLEAR_IT(&htim2, TIM_IT_CC3);
-
- // 设置比较值
- P_tim_count=__HAL_TIM_GET_COUNTER(&htim2);
- __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_3,P_tim_count+P_srd.step_delay);
-
- P_i++; // 定时器中断次数计数值
- if(P_i==2) // 2次,说明已经输出一个完整脉冲
- {
- P_i=0; // 清零定时器中断次数计数值
- switch(P_srd.run_state) // 加减速曲线阶段
- {
- case STOP:
- P_step_count = 0; // 清零步数计数器
- P_rest = 0; // 清零余值
- // 关闭通道
- TIM_CCxChannelCmd(TIM2, TIM_CHANNEL_3, TIM_CCx_DISABLE);
- __HAL_TIM_CLEAR_FLAG(&htim2,TIM_FLAG_CC3);
- P_STEPMOTOR_OUTPUT_DISABLE();
- P_MotionStatus = 0; // 电机为停止状态
- break;
-
- case ACCEL:
- P_step_count++; // 步数加1
- if(P_srd.dir==CW)
- {
- P_step_position++; // 绝对位置加1
- }
- else
- {
- P_step_position--; // 绝对位置减1
- }
- P_srd.accel_count++; // 加速计数值加1
- P_new_step_delay = P_srd.step_delay - (((2 *P_srd.step_delay) + P_rest)/(4 * P_srd.accel_count + 1));//计算新(下)一步脉冲周期(时间间隔)
- P_rest = ((2 * P_srd.step_delay)+P_rest)%(4 *P_srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
- if(P_step_count >= P_srd.decel_start)// 检查是够应该开始减速
- {
- P_srd.accel_count = P_srd.decel_val; // 加速计数值为减速阶段计数值的初始值
- P_srd.run_state = DECEL; // 下个脉冲进入减速阶段
- }
- else if(P_new_step_delay <= P_srd.min_delay) // 检查是否到达期望的最大速度
- {
- P_last_accel_delay = P_new_step_delay; // 保存加速过程中最后一次延时(脉冲周期)
- P_new_step_delay = P_srd.min_delay; // 使用min_delay(对应最大速度speed)
- P_rest = 0; // 清零余值
- P_srd.run_state = RUN; // 设置为匀速运行状态
- }
- break;
-
- case RUN:
- P_step_count++; // 步数加1
- if(P_srd.dir==CW)
- {
- P_step_position++; // 绝对位置加1
- }
- else
- {
- P_step_position--; // 绝对位置减1
- }
- P_new_step_delay = P_srd.min_delay; // 使用min_delay(对应最大速度speed)
- if(P_step_count >= P_srd.decel_start) // 需要开始减速
- {
- P_srd.accel_count = P_srd.decel_val; // 减速步数做为加速计数值
- P_new_step_delay = P_last_accel_delay;// 加阶段最后的延时做为减速阶段的起始延时(脉冲周期)
- P_srd.run_state = DECEL; // 状态改变为减速
- }
- break;
-
- case DECEL:
- P_step_count++; // 步数加1
- if(P_srd.dir==CW)
- {
- P_step_position++; // 绝对位置加1
- }
- else
- {
- P_step_position--; // 绝对位置减1
- }
- P_srd.accel_count++;
- P_new_step_delay = P_srd.step_delay - (((2 * P_srd.step_delay) + P_rest)/(4 * P_srd.accel_count + 1)); //计算新(下)一步脉冲周期(时间间隔)
- P_rest = ((2 * P_srd.step_delay)+P_rest)%(4 * P_srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
-
- //检查是否为最后一步
- if(P_srd.accel_count >= 0)
- {
- P_srd.run_state = STOP;
- }
- break;
- }
- P_srd.step_delay = P_new_step_delay; // 为下个(新的)延时(脉冲周期)赋值
- }
- }
- }
- }
-
-
- //==================end【By_Gerhart】======================//
2.motor.h文件
- #ifndef __MOTOR_H__
- #define __MOTOR_H__
- /*引用库函数*/
- #include "main.h"
-
- #define X_Motor_OFF() HAL_TIM_OC_Stop_IT(&htim3,TIM_CHANNEL_1)
- #define Y_Motor_OFF() HAL_TIM_OC_Stop_IT(&htim3,TIM_CHANNEL_2)
- #define P_Motor_OFF() HAL_TIM_OC_Stop_IT(&htim2,TIM_CHANNEL_3)
- //#define Motor_EN() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET)
- //#define Motor_DIS() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET)
-
- /* 电机结构体宏定义 ------------------------------------------------------------------*/
- typedef struct {
- __IO uint8_t run_state ; // 电机旋转状态
- __IO uint8_t dir ; // 电机旋转方向
- __IO int32_t step_delay; // 下个脉冲周期(时间间隔),启动时为加速度
- __IO uint32_t decel_start; // 启动减速位置
- __IO int32_t decel_val; // 减速阶段步数
- __IO int32_t min_delay; // 最小脉冲周期(最大速度,即匀速段速度)
- __IO int32_t accel_count; // 加减速阶段计数值
- }X_speedRampData;
-
- typedef struct {
- __IO uint8_t run_state ; // 电机旋转状态
- __IO uint8_t dir ; // 电机旋转方向
- __IO int32_t step_delay; // 下个脉冲周期(时间间隔),启动时为加速度
- __IO uint32_t decel_start; // 启动减速位置
- __IO int32_t decel_val; // 减速阶段步数
- __IO int32_t min_delay; // 最小脉冲周期(最大速度,即匀速段速度)
- __IO int32_t accel_count; // 加减速阶段计数值
- }Y_speedRampData;
-
- typedef struct {
- __IO uint8_t run_state ; // 电机旋转状态
- __IO uint8_t dir ; // 电机旋转方向
- __IO int32_t step_delay; // 下个脉冲周期(时间间隔),启动时为加速度
- __IO uint32_t decel_start; // 启动减速位置
- __IO int32_t decel_val; // 减速阶段步数
- __IO int32_t min_delay; // 最小脉冲周期(最大速度,即匀速段速度)
- __IO int32_t accel_count; // 加减速阶段计数值
- }P_speedRampData;
-
- extern X_speedRampData X_srd;
- extern __IO int32_t X_step_position;
- extern __IO uint8_t X_MotionStatus;
- extern Y_speedRampData Y_srd;
- extern __IO int32_t Y_step_position;
- extern __IO uint8_t Y_MotionStatus;
- extern P_speedRampData P_srd;
- extern __IO int32_t P_step_position;
- extern __IO uint8_t P_MotionStatus;
-
- #define STEPMOTOR_TIM_PRESCALER 3 // 步进电机驱动器细分设置为: 32 细分
- // 定义定时器周期,输出比较模式周期设置为0xFFFF
- #define STEPMOTOR_TIM_PERIOD 0xFFFF
-
- #define FALSE 0
- #define TRUE 1
- #define CW 0 // 顺时针
- #define CCW 1 // 逆时针
-
- #define STOP 0 // 加减速曲线状态:停止
- #define ACCEL 1 // 加减速曲线状态:加速阶段
- #define DECEL 2 // 加减速曲线状态:减速阶段
- #define RUN 3 // 加减速曲线状态:匀速阶段
- #define T1_FREQ (SystemCoreClock/(STEPMOTOR_TIM_PRESCALER+1)) // 频率ft值
- #define FSPR 200 //步进电机单圈步数
- #define MICRO_STEP 32 // 步进电机驱动器细分数
- #define SPR (FSPR*MICRO_STEP) // 旋转一圈需要的脉冲数
-
- // 数学常数
- #define ALPHA ((float)(2*3.14159/SPR)) // α= 2*pi/spr
- #define A_T_x10 ((float)(10*ALPHA*T1_FREQ))
- #define T1_FREQ_148 ((float)((T1_FREQ*0.676)/10)) // 0.676为误差修正值
- #define A_SQ ((float)(2*100000*ALPHA))
- #define A_x200 ((float)(200*ALPHA))
-
- #define X_STEPMOTOR_DIR_FORWARD() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET)
- #define X_STEPMOTOR_DIR_REVERSAL() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET)
- #define Y_STEPMOTOR_DIR_FORWARD() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET)
- #define Y_STEPMOTOR_DIR_REVERSAL() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET)
- #define P_STEPMOTOR_DIR_FORWARD() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_SET)
- #define P_STEPMOTOR_DIR_REVERSAL() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET)
-
- #define X_STEPMOTOR_OUTPUT_ENABLE(); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET)
- #define X_STEPMOTOR_OUTPUT_DISABLE(); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET)
- #define Y_STEPMOTOR_OUTPUT_ENABLE(); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_SET)
- #define Y_STEPMOTOR_OUTPUT_DISABLE(); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET)
- #define P_STEPMOTOR_OUTPUT_ENABLE(); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET)
- #define P_STEPMOTOR_OUTPUT_DISABLE(); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET)
-
- /*可以被外部使用的函数声明*/
- void X_STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed);
- void Y_STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed);
- void P_STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed);
-
-
- #endif
3. tim.c中添加使能函数
- /* USER CODE BEGIN TIM2_Init 2 */
- HAL_TIM_OC_Stop_IT(&htim2,TIM_CHANNEL_3); /*停止定时器2 比较输出通道3*/
- TIM_CCxChannelCmd(TIM2,TIM_CHANNEL_3, TIM_CCx_DISABLE); /* 使能定时器2比较输出通道3 */
- __HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_CC3); /* 清除指定的TIM2中断标志3 */
- __HAL_TIM_ENABLE_IT(&htim2, TIM_IT_CC3); /* 使能定时器2比较输出3 */
- /* Enable the main output */
- __HAL_TIM_MOE_ENABLE(&htim2); /* 启用TIM2主输出 */
- HAL_TIM_Base_Start(&htim2); /* 使能定时器2 */
- /* USER CODE END TIM2_Init 2 */
-
-
-
-
-
- /* USER CODE BEGIN TIM3_Init 2 */
- HAL_TIM_OC_Stop_IT(&htim3,TIM_CHANNEL_1); /*停止定时器3 比较输出通道1*/
- HAL_TIM_OC_Stop_IT(&htim3,TIM_CHANNEL_2); /*停止定时器3 比较输出通道2*/
-
- TIM_CCxChannelCmd(TIM3,TIM_CHANNEL_1, TIM_CCx_DISABLE); /* 使能定时器3比较输出通道1 */
- TIM_CCxChannelCmd(TIM3,TIM_CHANNEL_2, TIM_CCx_DISABLE); /* 使能定时器3比较输出通道2 */
-
- __HAL_TIM_CLEAR_FLAG(&htim3, TIM_FLAG_CC1); /* 清除指定的TIM3中断标志1 */
- __HAL_TIM_CLEAR_FLAG(&htim3, TIM_FLAG_CC2); /* 清除指定的TIM3中断标志2 */
-
- __HAL_TIM_ENABLE_IT(&htim3, TIM_IT_CC1); /* 使能定时器3比较输出1 */
- __HAL_TIM_ENABLE_IT(&htim3, TIM_IT_CC2); /* 使能定时器3比较输出2 */
-
- /* Enable the main output */
- __HAL_TIM_MOE_ENABLE(&htim3); /* 启用TIM3主输出 */
- HAL_TIM_Base_Start(&htim3); /* 使能定时器3 */
-
- /* USER CODE END TIM3_Init 2 */
4. main函数配置
- /* USER CODE BEGIN Header */
- /**
- ******************************************************************************
- * @file : main.c
- * @brief : Main program body
- ******************************************************************************
- * @attention
- *
- * Copyright (c) 2022 STMicroelectronics.
- * All rights reserved.
- *
- * This software is licensed under terms that can be found in the LICENSE file
- * in the root directory of this software component.
- * If no LICENSE file comes with this software, it is provided AS-IS.
- * *串口连接:
- *******************孔板X轴移动の电机**********************************
- PUL--->PA6
- DIR--->PB8
- ENA--->PB9
- OPTO--->3.3V
- *******************加液针头Y轴移动の电机****************************************
- PUL--->PA7
- DIR--->PB7
- ENA--->PC7
- OPTO--->3.3V
- *******************蠕动泵の电机****************************************
- PUL+-->5V
- PUL--->PA2
- DIR--->PC6
- ENA--->PB12
- ******************************************************************************
- * 此行为测试VS2022与Keil能否同步开发
- */
- /* USER CODE END Header */
- /* Includes ------------------------------------------------------------------*/
- #include "main.h"
- #include "tim.h"
- #include "usart.h"
- #include "gpio.h"
-
- /* Private includes ----------------------------------------------------------*/
- /* USER CODE BEGIN Includes */
- #include "Motor.h"
- /* USER CODE END Includes */
-
- /* Private typedef -----------------------------------------------------------*/
- /* USER CODE BEGIN PTD */
-
- /* USER CODE END PTD */
-
- /* Private define ------------------------------------------------------------*/
- /* USER CODE BEGIN PD */
-
- /* USER CODE END PD */
-
- /* Private macro -------------------------------------------------------------*/
- /* USER CODE BEGIN PM */
-
- /* USER CODE END PM */
-
- /* Private variables ---------------------------------------------------------*/
-
- /* USER CODE BEGIN PV */
-
- /* USER CODE END PV */
-
- /* Private function prototypes -----------------------------------------------*/
- void SystemClock_Config(void);
- /* USER CODE BEGIN PFP */
-
- /* USER CODE END PFP */
-
- /* Private user code ---------------------------------------------------------*/
- /* USER CODE BEGIN 0 */
- uint8_t Tx_str1[] = "Wellcome_Gerhart!\r\n";
- uint8_t Tx_str2[] = "X1_Forward!\r\n";
- uint8_t Tx_str3[] = "X1_Reversal!\r\n";
- uint8_t Tx_str4[] = "Stop!\r\n";
- uint8_t Tx_str5[] = "Y1_Forward!\r\n";
- uint8_t Tx_str6[] = "Y1_Reversal!\r\n";
- uint8_t Tx_str7[] = "P1_Forward!\r\n";
- uint8_t Tx_str8[] = "P1_Reversal!\r\n";
- uint8_t Rx_dat = 0;
-
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart)
- {
- if (huart->Instance == USART1)//这部分作用是通过串口控制电机
- {
- if (Rx_dat == 0xa1)//发送A1电机X正转
- {
- X_STEPMOTOR_AxisMoveRel(1 * 16 * 200, 9, 9, 19);//设置X电机参数(转数,加速度,减速度,峰值速度)
- HAL_UART_Transmit(&huart1, Tx_str2, sizeof(Tx_str2), 500);
- HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
- }
- else if (Rx_dat == 0xa2)//发送A2电机X反转
- {
- X_STEPMOTOR_AxisMoveRel(1 * 16 * -200, 9, 9, 19);//设置X电机参数(转数,加速度,减速度,峰值速度)
- HAL_UART_Transmit(&huart1, Tx_str3, sizeof(Tx_str3), 500);
- HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
- }
- else if (Rx_dat == 0xa3)//发送A3电机X停止
- {
- X_Motor_OFF();
- HAL_UART_Transmit(&huart1, Tx_str4, sizeof(Tx_str4), 500);
- HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
- }
- else if (Rx_dat == 0xa4)//发送A4电机Y正转
- {
- Y_STEPMOTOR_AxisMoveRel(1 * 16 * 200, 9, 9, 19);//设置Y电机参数(转数,加速度,减速度,峰值速度)
- HAL_UART_Transmit(&huart1, Tx_str5, sizeof(Tx_str5), 500);
- HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
- }
- else if (Rx_dat == 0xa5)//发送A5电机Y反转
- {
- Y_STEPMOTOR_AxisMoveRel(1 * 16 * -200, 9, 9, 19);//设置Y电机参数(转数,加速度,减速度,峰值速度)
- HAL_UART_Transmit(&huart1, Tx_str6, sizeof(Tx_str6), 500);
- HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
- }
- else if (Rx_dat == 0xa6)//发送A6电机Y停止
- {
- Y_Motor_OFF();
- HAL_UART_Transmit(&huart1, Tx_str4, sizeof(Tx_str4), 500);
- HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
- }
- else if (Rx_dat == 0xa7)//发送A7电机P正转
- {
- P_STEPMOTOR_AxisMoveRel(1 * 16 * 200, 9, 9, 19);//设置P电机参数(转数,加速度,减速度,峰值速度)
- HAL_UART_Transmit(&huart1, Tx_str7, sizeof(Tx_str7), 500);
- HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
- }
- else if (Rx_dat == 0xa8)//发送A8电机P反转
- {
- P_STEPMOTOR_AxisMoveRel(1 * 16 * -200, 9, 9, 19);//设置P电机参数(转数,加速度,减速度,峰值速度)
- HAL_UART_Transmit(&huart1, Tx_str8, sizeof(Tx_str8), 500);
- HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
- }
- else if (Rx_dat == 0xa9)//发送A9电机P停止
- {
- P_Motor_OFF();
- HAL_UART_Transmit(&huart1, Tx_str4, sizeof(Tx_str4), 500);
- HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
- }
- }
- }
- /* USER CODE END 0 */
-
- /**
- * @brief The application entry point.
- * @retval int
- */
- int main(void)
- {
- /* USER CODE BEGIN 1 */
-
- /* USER CODE END 1 */
-
- /* MCU Configuration--------------------------------------------------------*/
-
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
- HAL_Init();
-
- /* USER CODE BEGIN Init */
-
- /* USER CODE END Init */
-
- /* Configure the system clock */
- SystemClock_Config();
-
- /* USER CODE BEGIN SysInit */
-
- /* USER CODE END SysInit */
-
- /* Initialize all configured peripherals */
- MX_GPIO_Init();
- MX_TIM3_Init();
- MX_USART1_UART_Init();
- MX_TIM2_Init();
- /* USER CODE BEGIN 2 */
- HAL_UART_Transmit(&huart1, Tx_str1, sizeof(Tx_str1), 10000);
- HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
- /* USER CODE END 2 */
-
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- // HAL_Delay(1000);
- // P_STEPMOTOR_AxisMoveRel(1*16*200, 9, 9 , 19);//设置X电机参数(转数,加速度,减速度,峰值速度)
- // HAL_Delay(5000);
- // P_STEPMOTOR_AxisMoveRel(1*16*-200, 9, 9 , 19);//设置X电机参数(转数,加速度,减速度,峰值速度)
- // HAL_Delay(5000);
- }
- /* USER CODE END WHILE */
-
- /* USER CODE BEGIN 3 */
-
- /* USER CODE END 3 */
- }
-
- /**
- * @brief System Clock Configuration
- * @retval None
- */
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
- RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
-
- /** Initializes the RCC Oscillators according to the specified parameters
- * in the RCC_OscInitTypeDef structure.
- */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
- RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
- RCC_OscInitStruct.HSIState = RCC_HSI_ON;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
- RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
- /** Initializes the CPU, AHB and APB buses clocks
- */
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
- | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
-
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
- {
- Error_Handler();
- }
- }
-
- /* USER CODE BEGIN 4 */
-
- /* USER CODE END 4 */
-
- /**
- * @brief This function is executed in case of error occurrence.
- * @retval None
- */
- void Error_Handler(void)
- {
- /* USER CODE BEGIN Error_Handler_Debug */
- /* User can add his own implementation to report the HAL error return state */
- __disable_irq();
- while (1)
- {
- }
- /* USER CODE END Error_Handler_Debug */
- }
-
- #ifdef USE_FULL_ASSERT
- /**
- * @brief Reports the name of the source file and the source line number
- * where the assert_param error has occurred.
- * @param file: pointer to the source file name
- * @param line: assert_param error line source number
- * @retval None
- */
- void assert_failed(uint8_t* file, uint32_t line)
- {
- /* USER CODE BEGIN 6 */
- /* User can add his own implementation to report the file name and line number,
- ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
- /* USER CODE END 6 */
- }
- #endif /* USE_FULL_ASSERT */
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。