gpt4 book ai didi

c - 如何更改当前代码以直接从 IDR 寄存器读取

转载 作者:行者123 更新时间:2023-11-30 20:57:47 24 4
gpt4 key购买 nike

修改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 寄存器读取。我对嵌入式系统编程非常陌生,只是想找人指导我更改此代码

最佳答案

在发布我的解决方案之前,我需要建议不要直接从寄存器读取。给你这个任务的人都想成为一个自作聪明的人,并认为调用 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));
}

关于c - 如何更改当前代码以直接从 IDR 寄存器读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56351072/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com