我正在使用STM32F103C8T6和HAL库在双轴数控机床上工作。我为机器的每个轴设置了一个单独的定时器,并将其配置为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,并在步数等于设定的目标步数时停止PWM。它还调用了一个函数,该函数以毫米而不是步数来跟踪位置。(为简洁起见,删除了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((函数停止PWM时将其设为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,然后前进到步骤X((的下一个调用?为什么不是这样?
有人能提出一种我可以编写代码的方法吗?该方法允许我调用一个函数,该函数在等待它们完成后再进行下一次调用?接下来我将尝试实现Bresenhams行算法,因此我需要逐步执行一定数量的步骤,然后只有在步骤完成后才能从调用返回并前进到下一行代码。(本质上,我如何在不切换GPIO引脚/位抨击的情况下阻止此功能(
https://github.com/Blargian/EPR400
这并不是真正的答案,但我通过在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循环中。这个函数现在是一个阻塞函数,这正是我所需要的。