如何更改我的当前代码以直接从IDR寄存器中读取

时间:2019-05-28 23:01:47

标签: c embedded stm32 gpio

修改 ReadJoystick()的代码,以直接为关联的端口读取 IDR寄存器 与操纵杆输入。目的是最大程度地减少对寄存器的读取次数。中的代码 模板会为每个输入引脚进行单独调用,即使某些引脚是 在相同的端口上。 您可以参考HAL代码以获得灵感。使用HAL中的定义值进行寻址 注册,而不是创建新的。

提供给我的示例代码

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
    GPIO_PinState bitstatus;
     /* Check the parameters */
    assert_param(IS_GPIO_PIN(GPIO_Pin));
if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
{
    bitstatus = GPIO_PIN_SET;
}
else
{
    bitstatus = GPIO_PIN_RESET;
}
return bitstatus;

}


我需要更改的代码

//用您的解决方案替换以下代码

uint8_t
ReadJoystick ()
{
  uint8_t JoystickPosition = 0;

  // Get current joystick value
  if (HAL_GPIO_ReadPin (JOY_A_GPIO_Port, JOY_A_Pin) == GPIO_PIN_RESET)
  {
    JoystickPosition = 'L';
  }
  else if (HAL_GPIO_ReadPin (JOY_B_GPIO_Port, JOY_B_Pin) == 
GPIO_PIN_RESET)
  {
JoystickPosition = 'U';
  }
  else if (HAL_GPIO_ReadPin (JOY_C_GPIO_Port, JOY_C_Pin) == 
 GPIO_PIN_RESET)
   {
     JoystickPosition = 'D';
   }
   else if (HAL_GPIO_ReadPin (JOY_D_GPIO_Port, JOY_D_Pin) == 
 GPIO_PIN_RESET)
    {
      JoystickPosition = 'R';
    }
   else if (HAL_GPIO_ReadPin (JOY_CTR_GPIO_Port, JOY_CTR_Pin) == 
GPIO_PIN_RESET)
  {
    JoystickPosition = 'C';
  }

  return JoystickPosition;
 }

所以我理解我的当前代码正在读取每个引脚,尽管有人要求我更改此引脚以直接从IDR寄存器读取。我真的是嵌入式系统编程的新手,只是想找人指导我修改这段代码

1 个答案:

答案 0 :(得分:1)

在发布解决方案之前,我需要建议不要直接从寄存器中读取。谁在给您执行此任务,谁都想成为一个聪明的人,并认为调用HAL_GPIO_ReadPin函数会导致某种难以忍受的开销,这绝对是不正确的。实际上,如果从JOY_A_GPIO_Port到JOY_CTR_GPIO_Port的所有端口定义都不相同并且优化已打开,则编译器很可能会生成最佳代码。此外,将函数调用替换为直接寄存器读取会降低应用程序代码的重用能力。

无论如何,让我们进行一些更改...

让我们从使用直接寄存器访问的1:1转换开始:

uint8_t ReadJoystick() 
{
  uint8_t JoystickPosition = 0u;

  // Get current joystick value
  if ((JOY_A_GPIO_Port->IDR & JOY_A_Pin) == GPIO_PIN_RESET)
    JoystickPosition = 'L';
  else if ((JOY_B_GPIO_Port->IDR & JOY_B_Pin) == GPIO_PIN_RESET)
    JoystickPosition = 'U';
  else if ((JOY_C_GPIO_Port->IDR & JOY_C_Pin) == GPIO_PIN_RESET)
    JoystickPosition = 'D';
  else if ((JOY_D_GPIO_Port->IDR & JOY_D_Pin) == GPIO_PIN_RESET)
    JoystickPosition = 'R';
  else if ((JOY_CTR_GPIO_Port->IDR & JOY_CTR_Pin) == GPIO_PIN_RESET)
    JoystickPosition = 'C';

  return JoystickPosition;
}

如果您还没有完全理解代码:

  • xxx_Port-> IDR读取整个端口的输入数据寄存器
  • 按位&屏蔽输入,仅给我们提供特定的引脚 寻找

正如我之前提到的,这不会带来任何性能上的改善。

但是,如果某些端口定义相等并且指向相同的内存地址,我们可能会稍微改善代码。在实践中,这很常见,因为嵌入式设计人员通常热衷于在单个端口上连接外部设备的IO引脚。例如。让我们假设JOY_A_GPIO_Port == JOY_B_GPIO_Port,那么我们可以一次将这个端口的输入数据寄存器读入本地变量,如下所示:

uint8_t ReadJoystick() 
{
  uint8_t JoystickPosition = 0;

  // Read input data register for AB once
  uint32_t ab_port = JOY_AB_GPIO_Port->IDR;

  // Get current joystick value
  if ((ab_port & JOY_A_Pin) == GPIO_PIN_RESET)
    JoystickPosition = 'L';
  else if ((ab_port & JOY_B_Pin) == GPIO_PIN_RESET)
    JoystickPosition = 'U';
  else if ((JOY_C_GPIO_Port->IDR & JOY_C_Pin) == GPIO_PIN_RESET)
    JoystickPosition = 'D';
  else if ((JOY_D_GPIO_Port->IDR & JOY_D_Pin) == GPIO_PIN_RESET)
    JoystickPosition = 'R';
  else if ((JOY_CTR_GPIO_Port->IDR & JOY_CTR_Pin) == GPIO_PIN_RESET)
    JoystickPosition = 'C';

  return JoystickPosition;
}

这实际上为我们节省了一个寄存器读取。当然,单个端口上的操纵杆引脚越多越好。

/编辑 ST提供了另一种功能来读取其“ LL”库中的整个端口:

__STATIC_INLINE uint32_t LL_GPIO_ReadInputPort(GPIO_TypeDef *GPIOx)
{
  return (uint32_t)(READ_REG(GPIOx->IDR));
}