[STM32F3] HAL_GPIO_TogglePin () 函数问题

[复制链接]
310|57
cemaj 发表于 2026-10-5 18:28 | 显示全部楼层
直接操作ODR寄存器              
deliahouse887 发表于 2026-10-6 14:00 | 显示全部楼层
static inline void GPIO_TogglePins(GPIO_TypeDef *GPIOx, uint16_t pins)
{
    uint32_t odr = GPIOx->ODR;                     /* 读一次 */
    GPIOx->BSRR = ((odr & pins) << 16) | (~odr & pins);
}
bartonalfred 发表于 2026-10-6 14:52 | 显示全部楼层
先读取当前电平,然后计算哪些引脚需要置位,哪些需要复位,最后通过一次写操作完成所有引脚的状态更新。
pixhw 发表于 2026-10-6 21:20 | 显示全部楼层
HAL_GPIO_TogglePin()的设计目标是单引脚操作,多引脚场景下需采用上述替代方案,而非认为是“BUG”。
phoenixwhite 发表于 2026-10-7 10:20 | 显示全部楼层
可以直接使用 BSRR 寄存器进行读-改-写,或者直接操作 ODR
wwppd 发表于 2026-10-7 12:20 | 显示全部楼层
如果只关心翻转,不关心其他引脚的并发状态,也可以直接操作 ODR 寄存器,但这并非原子操作,在多线程或中断环境下有风险。
biechedan 发表于 2026-10-7 17:46 | 显示全部楼层

GPIOx->ODR ^= GPIO_Pin;
iyoum 发表于 2026-10-8 16:22 | 显示全部楼层
HAL_GPIO_TogglePin() 的设计初衷是翻转单个引脚,其文档中“Toggles the specified GPIO pins”的表述确实容易引起误解
CarterERO 发表于 2026-10-9 15:19 | 显示全部楼层
改用BSRR寄存器操作,或者修改HAL_GPIO_TogglePin函数使其支持多引脚翻转。
wengh2016 发表于 2026-10-12 16:34 | 显示全部楼层
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
  uint32_t odr;

  /* Check the parameters */
  assert_param(IS_GPIO_PIN(GPIO_Pin));

  /* get current Output Data Register value */
  odr = GPIOx->ODR;

  /* Set selected pins that were at low level, and reset ones that were high */
  GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
}
DreamWanderer 发表于 2026-10-14 17:50 | 显示全部楼层
多引脚翻转确实容易出问题,我之前遇到过类似情况。解决方法是分别对每个引脚调用HAL_GPIO_TogglePin,或者改用BSRR寄存器直接翻转。
timfordlare 发表于 2026-10-14 18:53 | 显示全部楼层
为什么会出现“同步闪烁”现象?              
maqianqu 发表于 2026-10-14 20:02 | 显示全部楼层
HAL_GPIO_TogglePin, HAL_GPIO_WritePin, HAL_GPIO_ReadPin。这些函数针对单个引脚优化,且 TogglePin 依赖读取 ODR 寄存器来判断当前状态。
jonas222 发表于 2026-10-14 21:00 | 显示全部楼层
使用HAL_GPIO_TogglePin(),简单高效
AloneKaven 发表于 2026-10-15 12:37 | 显示全部楼层
用BSRR寄存器翻转,或者检查GPIOx-CR1的ODR位配置,确保没有误操作。
xiaoyaodz 发表于 2026-10-15 16:45 | 显示全部楼层
这个BUG是否会影响GPIO的输入输出功能?
fengm 发表于 2026-10-15 21:19 | 显示全部楼层
可以利用位带功能,将 ODR 寄存器的每一位映射到一个独立的地址上。
时光迷宫 发表于 2026-10-16 10:55 | 显示全部楼层
之前项目中也有遇到类似问题,建议改用 GPIOx->ODR ^= GPIO_Pin 来替代,它更符合多引脚切换需求。
cashrwood 发表于 2026-10-17 13:10 | 显示全部楼层
使用HAL_GPIO_WritePin()手动翻转
通过读取当前引脚状态,取反后写回,实现多引脚翻转
闪烁阴影 发表于 2026-10-17 16:55 | 显示全部楼层
用BSRR寄存器直接操作更稳妥,BSRR操作是原子的,避免了并发写ODR的问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部