简体   繁体   English

STM32 - 步进电机应用程序中 timerUpdate 回调的 While 循环阻塞行为

[英]STM32 - While loop blocking behaviour of timerUpdate callback in stepper motor application

I am working on a 2-axis CNC machine using an STM32F103C8T6 and using the HAL libraries.我正在使用 STM32F103C8T6 和 HAL 库在 2 轴 CNC 机器上工作。 I've setup a seperate timer for each axis of the machine and have those configured in PWM mode.我已经为机器的每个轴设置了一个单独的计时器,并将它们配置为 PWM 模式。

I have a function called step_x(numberSteps, Direction) which takes in two parameters which are the number of steps to make and the direction to move in. The function sets the number of steps as the target number of steps in a global variable, sets the direction via GPIO write and then starts the PWM in interrupt mode using the HAL library:我有一个名为 step_x(numberSteps, Direction) 的函数,它接受两个参数,分别是要执行的步数和要移动的方向。该函数将步数设置为全局变量中的目标步数,设置通过 GPIO 写入的方向,然后使用 HAL 库在中断模式下启动 PWM:

void step_x(uint32_t numberSteps, uint16_t direction){
    RELEASE_X=0;
    steps_x_target = numberSteps;
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, direction_x);
    __HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);
    HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_1);
}

This then starts the PWM and I am counting the number of pulses via the timer update callback function:然后启动PWM,我通过定时器更新回调函数计算脉冲数:

void TIM1_UP_IRQHandler(void)
{
  if (__HAL_TIM_GET_FLAG(&htim1, TIM_FLAG_UPDATE))
  {
    if (__HAL_TIM_GET_IT_SOURCE(&htim1, TIM_IT_UPDATE))
    {
        step_update('X');
        __HAL_TIM_CLEAR_FLAG(&htim1, TIM_FLAG_UPDATE);
        __HAL_TIM_CLEAR_FLAG(&htim1,TIM_FLAG_CC1 );
      }
    }
  }

Inside this callback, step_update() is called taking as a parameter which axis I am working with.在这个回调中, step_update() 被调用,将我正在使用的轴作为参数。

The step_update function adds +1 to a count for the number of steps that have occured and stops the PWM when the number of steps is equal to the target number of steps that was set. step_update 函数将已发生的步数加 1,并在步数等于设置的目标步数时停止 PWM。 It also calls a function which keeps track of the position in mm rather than steps.它还调用一个函数,该函数以毫米而不是步长跟踪位置。 (Y and Z axis cases removed for the sake of brevity) (为简洁起见,删除了 Y 和 Z 轴案例)

void step_update(char axis){
    switch(axis){
        case 'X':
            steps_x++;
            updatePosition(axis);
            if(steps_x==(2*steps_x_target)){ //check if 2* because the update event happens twice every pulse
                HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
                steps_x_target=0;
                steps_x=0;
                RELEASE_X=1;
                if(limitSwitchX_Trigger==1){
                    positionX=0;
                    limitSwitchX_Trigger=0;
                    NVIC_EnableIRQ(EXTI0_IRQn);
                }
            }
            break;
        case 'Y':
 
            break;
 
        case 'Z':
 
            break;
 
        }
}

I'm sure this is not an entirely efficient way to do this however it works well enough except for the fact that I have no way to call the step_x() function and wait for it to finish before making the call to the next one.我确信这不是一种完全有效的方法,但是它工作得很好,除了我无法调用 step_x() 函数并在调用下一个函数之前等待它完成。 I added the volatile variables RELEASE_X which is set to 0 when step_x() is called and set to 1 when the step_update() function has stopped the PWM when the target steps are reached.我添加了 volatile 变量 RELEASE_X,它在 step_x() 被调用时设置为 0,当 step_update() 函数在达到目标步骤时停止 PWM 时设置为 1。 I thought using this that I may be able to do something like this which I would expect to step 800 pulses in one direction and then step 800 pulses in another direction:我认为使用这个我可以做这样的事情,我希望在一个方向上步进 800 个脉冲,然后在另一个方向上步进 800 个脉冲:

step_x(800,0);
while(RELEASE_X!=1);
step_x(800,1);

However what happens is that the while loop ends up blocking the Timer1_Update callback from occuring and the pulses don't get counted.然而,发生的情况是,while 循环最终阻止了 Timer1_Update 回调的发生,并且不会对脉冲进行计数。 I expected that because the pulse counting is done in an ISR callback that the MCU would just jump to the ISR from this while loop and update the steps until RELEASE_X is set to true and then advance to the next call of step_x()?我期望因为脉冲计数是在 ISR 回调中完成的,所以 MCU 会从这个 while 循环跳转到 ISR 并更新步骤直到 RELEASE_X 设置为 true 然后前进到 step_x() 的下一次调用? Why is this not so?为什么不是这样?

Could someone suggest a way that I can write code which will allow me to call a function which steps a certain amount of steps while waiting for them to finish before moving on to the next call?有人可以建议一种我可以编写代码的方法,它允许我调用一个函数,该函数在等待它们完成之前执行一定数量的步骤,然后再继续下一次调用吗? I am trying to implement Bresenhams line algorithm next and so I need to step a certain amount of steps and then only return from the call and advance to the next line of code when the steps are complete.我正在尝试接下来实现 Bresenhams 线算法,因此我需要执行一定数量的步骤,然后仅从调用返回并在步骤完成时前进到下一行代码。 (Essentially, how can I make this function blocking but without toggling GPIO pins/bit bashing) (本质上,我怎样才能使这个功能阻塞但不切换 GPIO 引脚/位攻击)

https://github.com/Blargian/EPR400 https://github.com/Blargian/EPR400

It's not really an answer as to why this happened but I solved the problem by disabling the timer update and global interrupts in CubeMX under the NVIC tab.这并不是为什么会发生这种情况的真正答案,但我通过在 NVIC 选项卡下禁用 CubeMX 中的计时器更新和全局中断解决了这个问题。 I removed the callback functions from my main.h and main.c and then I modified the step_x function to be:我从 main.h 和 main.c 中删除了回调函数,然后将 step_x 函数修改为:

void step_x(uint32_t numberSteps, uint16_t direction){
    RELEASE_X=0;
    steps_x_target = numberSteps;
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, direction_x);
    __HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);
    HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_1);
    while(RELEASE_X!=1){
         if (__HAL_TIM_GET_FLAG(&htim1, TIM_FLAG_UPDATE))
          {
            if (__HAL_TIM_GET_IT_SOURCE(&htim1, TIM_IT_UPDATE))
            {
                step_update('X');
                __HAL_TIM_CLEAR_FLAG(&htim1, TIM_FLAG_UPDATE);
                __HAL_TIM_CLEAR_FLAG(&htim1,TIM_FLAG_CC1 );
              }
    }
    }
}

Basically just moved the code that was in the callback function to within the while loop in the step_x function.基本上只是将回调函数中的代码移动到 step_x 函数中的 while 循环中。 The function is now a blocking function which is atually what I need anyway.该函数现在是一个阻塞函数,无论如何这正是我所需要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM