首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >步进电机应用中timerUpdate回调的STM32 - While循环阻塞行为

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

Stack Overflow用户
提问于 2020-10-17 21:06:43
回答 1查看 280关注 0票数 1

我正在使用STM32F103C8T6和HAL库在一台2轴数控机床上工作。我已经为机器的每个轴设置了一个单独的计时器,并将其配置为PWM模式。

我有一个叫做step_x(numberSteps,Direction)的函数,它有两个参数,一个是要走的步数,另一个是前进的方向。该函数将步数设置为全局变量中的目标步数,通过GPIO写入设置方向,然后使用HAL库在中断模式下启动PWM:

代码语言:javascript
复制
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);
}

然后启动PWM,我通过定时器更新回调函数计算脉冲数:

代码语言:javascript
复制
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 );
      }
    }
  }

在这个回调函数中,step_update()被调用,将我正在处理的轴作为参数。

step_update函数将已发生步数的计数加+1,并在步数等于设定的目标步数时停止脉宽调制。它还调用一个函数,该函数跟踪以mm为单位的位置而不是步数。(为简洁起见,删除了Y轴和Z轴的情况)

代码语言:javascript
复制
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;
 
        }
}

我确信这不是一种完全有效的方法,但是它工作得很好,除了我无法调用step_x()函数并等待它完成后再调用下一个函数。我添加了易失性变量RELEASE_X,它在调用step_x()时设置为0,当step_update()函数在达到目标步数时停止脉宽调制时设置为1。我想使用这个我可以做一些类似的事情,我希望在一个方向上阶跃800个脉冲,然后在另一个方向上阶跃800个脉冲:

代码语言:javascript
复制
step_x(800,0);
while(RELEASE_X!=1);
step_x(800,1);

但是,while循环最终阻止了Timer1_Update回调的发生,脉冲也不会被计算在内。我以为因为脉冲计数是在ISR回调中完成的,所以MCU会从这个while循环跳到ISR,并更新步骤,直到RELEASE_X设置为true,然后前进到下一次调用step_x()?为何不是这样呢?

有没有人能推荐一种方法,让我可以编写代码,允许我调用一个函数,该函数将执行一定数量的步骤,同时等待它们完成,然后继续下一次调用?接下来我将尝试实现Bresenhams行算法,因此我需要执行一定数量的步骤,然后仅从调用返回,并在步骤完成时前进到下一行代码。(本质上,我如何才能在不切换GPIO引脚/位绑定的情况下阻止此功能)

https://github.com/Blargian/EPR400

EN

回答 1

Stack Overflow用户

发布于 2020-10-18 00:10:07

这并不能真正解释为什么会发生这种情况,但我通过在NVIC选项卡下禁用CubeMX中的计时器更新和全局中断解决了这个问题。我从main.h和main.c中删除了回调函数,然后将step_x函数修改为:

代码语言:javascript
复制
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 );
              }
    }
    }
}

基本上,只是将回调函数中的代码移动到step_x函数的while循环中。这个函数现在是一个阻塞函数,这是我无论如何都需要的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64402807

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档