ISR无法更改嵌入C中的外部结构场



nucleo上的STM32F091RCT有问题,我用于控制步进电动机驱动器DRV8825。

下面的代码部分的主要目标是使用霍尔开关和磁铁中的中断旋转时停止步进电机。我还在使用STM32的HAL库,当然还有C语言。

我已经有这些文件:

电动机:

typedef struct{
   volatile uint8_t STOP_FLAG
} Motor;

电动机:

#include "motor.h"
void ClearStopFlag(Motor *motor)
{
  motor->STOP_FLAG = 0;
}
void SetStopFlag(Motor *motor)
{
  motor->STOP_FLAG = 1;
}
uint8_t GetStopFlag(Motor *motor)
{
  return motor->STOP_FLAG;
}
void Init(Motor *motor)
{
  ClearStopFlag(motor); 
}
void Rotate(Motor *motor)
{
  int i;
  for(i = 0; i < 50; i++)      // every iteration is a motor step
  {
    if(GetStopFlag(motor)) break;
    // irrelevant code switching the output used for driver step input ----
  }
}
void Disable(Motor *motor)
{
  // Code that sets the GPIO pin responsible for ENABLE pin in the driver ----
}

Hall.C:

#include "motor.h"
#include "exec.h"
extern Motor m;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  SetStopFlag(&m);
}

exec.c:

#include "hall.h"
#include "motor.h"
Motor m;
void SomeFunction(void)
{
  Init(&m);
  Rotate(&m); // here GPIO ISR in hall.c doesn't set the STOP_FLAG while Rotate() is executing
}

main.c:

#include "exec.h"
int main(void)
{
  SomeFunction();
  return 0;
}

首先,原始代码要复杂得多,我在这里还没有包括一些用于功能原型,其他电动机结构字段,其他功能等的标头。我现在无法访问该代码这样也更加干净。

我已经进行了很多测试,问题是GPIO中断回调函数无法更改stop_flag变量。这就是它的行为:

  • 中断效果很好 - 当我尝试打开中断部分中的二极管时,它可以打开;当我尝试使用Motor.c的disable((函数禁用驱动程序时,它可以工作并设置正确的GPIO端口
  • 当我尝试在isr whitout中设置stop_flag时,使用 m->STOP_FLAG = 1;,它不起作用
  • 当我调用exec.c的setStopflag((函数时(例如,在rotate((行之前的somefunction((中(,它可以正常工作

有人知道为什么hall.c在访问结构字段时遇到问题吗?

问题在其他地方。

与您提供的代码不可重现。

我为发现板的最小CUBEMX项目创建了两个LED(PB7上的LD3(,PB6上的LD4(和一个pushbutton(B1上的CC_6(,然后添加您的代码。

>

motor.c:将循环更改为无尽的循环,因为我不相信自己能够按几微秒来按下按钮,并测量差异

void Rotate(Motor *motor)
{
  while(1)      // every iteration is a motor step
  {
    if(GetStopFlag(motor))
        break;
    // irrelevant code switching the output used for driver step input ----
  }
}

main.c:添加了初始化和反馈。

#include "main.h"
#include "stm32l1xx_hal.h"
void EXTI0_IRQHandler(void) {
    HAL_GPIO_EXTI_IRQHandler(B1_Pin);
}
void EXTILine0_Config(void) {
    GPIO_InitTypeDef GPIO_InitStructure = { 0 };
    GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;
    GPIO_InitStructure.Pull = GPIO_NOPULL;
    GPIO_InitStructure.Pin = B1_Pin;
    HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStructure);
    HAL_NVIC_SetPriority(EXTI0_IRQn, 3, 0);
    HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}
int main(void) {
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  EXTILine0_Config();
  SomeFunction();
  HAL_GPIO_WritePin(LD4_GPIO_Port, LD4_Pin, GPIO_PIN_SET);
  while(1)
      ;
}

其余的都是相同的。

与此编译器一起编译: arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 7-2017-q4-major) 7.2.1 20170904 (release) [ARM/embedded-7-branch revision 255204]和这些选项:-mcpu=cortex-m3 -mthumb -O3 -fmessage-length=0 -ffunction-sections -fdata-sections -flto -Wall -Wextra -g3 -std=gnu11

它可以按预期工作。按下按钮会触发Exti中断,设置结构中的标志,循环停止,LD4点亮。