修改 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寄存器读取。我真的是嵌入式系统编程的新手,只是想找人指导我修改这段代码
答案 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;
}
如果您还没有完全理解代码:
正如我之前提到的,这不会带来任何性能上的改善。
但是,如果某些端口定义相等并且指向相同的内存地址,我们可能会稍微改善代码。在实践中,这很常见,因为嵌入式设计人员通常热衷于在单个端口上连接外部设备的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));
}