在块模式下读取中断

时间:2016-08-30 15:37:39

标签: c block interrupt handle

我开发了一个系统,它读取来自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,它会完成它所在的内容,并返回到之前的状态。
  • 如果程序在另一个程序中发生中断,则可能发生两件事。如果当前中断的优先级大于传入中断的优先级,则首先它将完成当前中断的执行,然后它将跳转到传入的中断。如果传入的优先级大于实际的优先级,那么它将跳转到传入的优先级,然后它将返回到第一个优先级。

考虑到这个概念,我不知道如何做我想做的事。

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

  1. 我想要的是自己处理每一个继电器,但我只有3个中断,我不确定我能做到。
  2. 解码器用于保存一些引脚用于其他东西,只需3个引脚即可处理7个继电器。一开始我觉得它会起作用,但现在我不太确定。此时我无法更改硬件。
  3. 这是我用来移动步进电机的功能,如果有帮助的话:

    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;
        }
    }
    

    提前致谢。

1 个答案:

答案 0 :(得分:0)

根据之前与@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内部,我设置了标志。

Truth Table of encoder 8:3

可能执行了多个步骤但是每个步骤都是1.8度,这不会成为问题。

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