块模式下的读取中断
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,它执行它在里面的操作,然后return回到它之前的位置。
- 如果程序在另一个程序中时发生中断,则可能会发生两种情况。如果当前中断的优先级大于传入中断,则首先执行完当前中断,然后跳转到传入中断。如果传入的优先级大于实际的,则跳转到传入的,然后return到第一个。
考虑到这些概念,我不知道该怎么做。
在 ISR 中将全局变量设置为标志并在主程序中读取它们对我没有帮助,因为我想要的是在按下机械继电器时停止步进电机,并且根据之前的两个概念,如果我设置标志,首先我的程序将完成步进电机的移动,然后它会停止它,但我希望它直接停止。
- 我想要的是自己处理每一个继电器,但是我只有 3 个中断,我不确定我是否能够做到。
- 解码器用于为其他东西节省一些引脚,以便能够仅用 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 函数中管理标志是最好的解决方案,因为它实际上停止移动步进电机。
我开发了一个系统,可以读取来自 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,它执行它在里面的操作,然后return回到它之前的位置。
- 如果程序在另一个程序中时发生中断,则可能会发生两种情况。如果当前中断的优先级大于传入中断,则首先执行完当前中断,然后跳转到传入中断。如果传入的优先级大于实际的,则跳转到传入的,然后return到第一个。
考虑到这些概念,我不知道该怎么做。
在 ISR 中将全局变量设置为标志并在主程序中读取它们对我没有帮助,因为我想要的是在按下机械继电器时停止步进电机,并且根据之前的两个概念,如果我设置标志,首先我的程序将完成步进电机的移动,然后它会停止它,但我希望它直接停止。
- 我想要的是自己处理每一个继电器,但是我只有 3 个中断,我不确定我是否能够做到。
- 解码器用于为其他东西节省一些引脚,以便能够仅用 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 函数中管理标志是最好的解决方案,因为它实际上停止移动步进电机。