我正在使用STM32F103C8T6和HAL库在一台2轴数控机床上工作。我已经为机器的每个轴设置了一个单独的计时器,并将其配置为PWM模式。
我有一个叫做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);
}然后启动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 );
}
}
}在这个回调函数中,step_update()被调用,将我正在处理的轴作为参数。
step_update函数将已发生步数的计数加+1,并在步数等于设定的目标步数时停止脉宽调制。它还调用一个函数,该函数跟踪以mm为单位的位置而不是步数。(为简洁起见,删除了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;
}
}我确信这不是一种完全有效的方法,但是它工作得很好,除了我无法调用step_x()函数并等待它完成后再调用下一个函数。我添加了易失性变量RELEASE_X,它在调用step_x()时设置为0,当step_update()函数在达到目标步数时停止脉宽调制时设置为1。我想使用这个我可以做一些类似的事情,我希望在一个方向上阶跃800个脉冲,然后在另一个方向上阶跃800个脉冲:
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引脚/位绑定的情况下阻止此功能)
发布于 2020-10-18 00:10:07
这并不能真正解释为什么会发生这种情况,但我通过在NVIC选项卡下禁用CubeMX中的计时器更新和全局中断解决了这个问题。我从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 );
}
}
}
}基本上,只是将回调函数中的代码移动到step_x函数的while循环中。这个函数现在是一个阻塞函数,这是我无论如何都需要的。
https://stackoverflow.com/questions/64402807
复制相似问题