块模式下的读取中断

Read Interrupts in Block Mode

我开发了一个系统,可以读取来自 3:8 解码器的三行。该解码器将 7 条线路的机械继电器减少到 3 条线路。所以总结起来就是这样:

              m2        m1        m0        (decoder output)
             exti3    exti2     exti1
   RL01 on    0         0         1
   RL02 on    0         1         0
   RL03 on    0         1         1
   RL04 on    1         0         0
   RL05 on    1         0         1
   RL06 on    1         1         0
   RL07 on    1         1         1

只会同时激活一个继电器。

我试图找出一种读取中断的方法,并根据它的值做不同的事情。

我正在使用 STM32F4 micro,据我所知,它的调度程序是这样工作的:

考虑到这些概念,我不知道该怎么做。

在 ISR 中将全局变量设置为标志并在主程序中读取它们对我没有帮助,因为我想要的是在按下机械继电器时停止步进电机,并且根据之前的两个概念,如果我设置标志,首先我的程序将完成步进电机的移动,然后它会停止它,但我希望它直接停止。

  1. 我想要的是自己处理每一个继电器,但是我只有 3 个中断,我不确定我是否能够做到。
  2. 解码器用于为其他东西节省一些引脚,以便能够仅用 3 个引脚处理 7 个继电器。一开始我认为它会起作用,但现在我不太确定。我现在不能更改硬件。

这是我用来移动步进电机的函数,如果有帮助的话:

void moveMotorDegrees (uint8_t player, uint16_t degrees)
{
    double steps = 0;
    uint16_t cycles = 0;
    uint16_t i = 0;
    double oneLapSteps = 200;
    double oneLapDegrees = 360;


    steps = degrees * (oneLapSteps/oneLapDegrees);
    cycles = round(2 * steps);

    switch (player)
    {
    case 1:
        HAL_GPIO_WritePin(RESET_M1_GPIO_Port, RESET_M1_Pin, GPIO_PIN_SET);
        break;
    case 2:
        HAL_GPIO_WritePin(RESET_M2_GPIO_Port, RESET_M2_Pin, GPIO_PIN_SET);
        break;
    case 3:
        HAL_GPIO_WritePin(RESET_M3_GPIO_Port, RESET_M3_Pin, GPIO_PIN_SET);
        break;
    case 4:
        HAL_GPIO_WritePin(RESET_M4_GPIO_Port, RESET_M4_Pin, GPIO_PIN_SET);
        break;
    }


    for (i = 0; i < cycles; i++)
          {
              HAL_Delay(5);
              switch (player)
                {
                case 1:
                    HAL_GPIO_TogglePin(STEP_M1_GPIO_Port, STEP_M1_Pin);
                    break;
                case 2:
                    HAL_GPIO_TogglePin(STEP_M2_GPIO_Port, STEP_M2_Pin);
                    break;
                case 3:
                    HAL_GPIO_TogglePin(STEP_M3_GPIO_Port, STEP_M3_Pin);
                    break;
                case 4:
                    HAL_GPIO_TogglePin(STEP_M4_GPIO_Port, STEP_M4_Pin);
                    break;
                }
          }

    HAL_Delay(200);
    switch (player)
    {
    case 1:
        HAL_GPIO_WritePin(RESET_M1_GPIO_Port, RESET_M1_Pin, GPIO_PIN_RESET);
        break;
    case 2:
        HAL_GPIO_WritePin(RESET_M2_GPIO_Port, RESET_M2_Pin, GPIO_PIN_RESET);
        break;
    case 3:
        HAL_GPIO_WritePin(RESET_M3_GPIO_Port, RESET_M3_Pin, GPIO_PIN_RESET);
        break;
    case 4:
        HAL_GPIO_WritePin(RESET_M4_GPIO_Port, RESET_M4_Pin, GPIO_PIN_RESET);
        break;
    }
}

提前致谢。

根据之前与@serge 和@MartinNyolt 的对话,我认为这可行:

void moveMotorDegrees (uint8_t player, uint16_t degrees)
{
    double steps = 0;
    uint16_t cycles = 0;
    uint16_t i = 0;
    double oneLapSteps = 200;
    double oneLapDegrees = 360;


    steps = degrees * (oneLapSteps/oneLapDegrees);
    cycles = round(2 * steps);

    switch (player)
    {
    case 1:
        HAL_GPIO_WritePin(RESET_M1_GPIO_Port, RESET_M1_Pin, GPIO_PIN_SET);
        break;
    case 2:
        HAL_GPIO_WritePin(RESET_M2_GPIO_Port, RESET_M2_Pin, GPIO_PIN_SET);
        break;
    case 3:
        HAL_GPIO_WritePin(RESET_M3_GPIO_Port, RESET_M3_Pin, GPIO_PIN_SET);
        break;
    case 4:
        HAL_GPIO_WritePin(RESET_M4_GPIO_Port, RESET_M4_Pin, GPIO_PIN_SET);
        break;
    }


    for (i = 0; i < cycles; i++)
          {
              HAL_Delay(5);
              switch (player)
                {
                case 1:
                    if ((MA2_Flag != 1 && MA1_Flag != 1 && MA0_Flag != 1) || (MA2_Flag != 1 && MA1_Flag != 1 && MA0_Flag != 0))
                    {
                        HAL_GPIO_TogglePin(STEP_M1_GPIO_Port, STEP_M1_Pin);
                    }
                    break;
                case 2:
                    if ((MA2_Flag != 1 && MA1_Flag != 0 && MA0_Flag != 0) || (MA2_Flag != 1 && MA1_Flag != 0 && MA0_Flag != 1))
                    {
                        HAL_GPIO_TogglePin(STEP_M2_GPIO_Port, STEP_M2_Pin);
                    }
                    break;
                case 3:
                    if ((MA2_Flag != 0 && MA1_Flag != 1 && MA0_Flag != 0) || (MA2_Flag != 0 && MA1_Flag != 1 && MA0_Flag != 1))
                    {
                        HAL_GPIO_TogglePin(STEP_M3_GPIO_Port, STEP_M3_Pin);
                    }
                        break;
                case 4:
                    if ((MA2_Flag != 0 && MA1_Flag != 0 && MA0_Flag != 1) || (MAAux_Flag != 1))
                    {
                        HAL_GPIO_TogglePin(STEP_M4_GPIO_Port, STEP_M4_Pin);
                    }
                    break;
                }
          }

    MAAux_Flag = 0;
    MA2_Flag = 0;
    MA1_Flag = 0;
    MA0_Flag = 0;

    HAL_Delay(200);
    switch (player)
    {
    case 1:
        HAL_GPIO_WritePin(RESET_M1_GPIO_Port, RESET_M1_Pin, GPIO_PIN_RESET);
        break;
    case 2:
        HAL_GPIO_WritePin(RESET_M2_GPIO_Port, RESET_M2_Pin, GPIO_PIN_RESET);
        break;
    case 3:
        HAL_GPIO_WritePin(RESET_M3_GPIO_Port, RESET_M3_Pin, GPIO_PIN_RESET);
        break;
    case 4:
        HAL_GPIO_WritePin(RESET_M4_GPIO_Port, RESET_M4_Pin, GPIO_PIN_RESET);
        break;
    }
}

在每个 case 语句中,我都有两个 if 条件。每一个都根据一个不同的继电器(见下图)。在 ISR 中,我设置了标志。

也许执行了不止一步,但每一步都在 1.8 度,这不会有问题。

我想在主程序中做一个函数来根据标志停止一个或另一个电机,但是直接在 moveMotorsDistance 函数中管理标志是最好的解决方案,因为它实际上停止移动步进电机。