GPIOx_BSRR ,GPIOx_BRR和ODR

📅 2026/7/29 5:01:28
GPIOx_BSRR ,GPIOx_BRR和ODR
目录GPIOx_BSRR 和 GPIOx_BRR 总结1.GPIOx_BSRRBit Set/Reset Register低16位Bit 0~15Set高16位Bit 16~31Reset2. GPIOx_BRRBit Reset RegisterBSRR 和 BRR 对比为什么不用 ODR最后记忆口诀GPIOx_BSRR 和 GPIOx_BRR 总结它们都是用来控制 GPIO 输出电平的寄存器目的都是让某个 GPIO 引脚输出高电平1让某个 GPIO 引脚输出低电平0区别是BSRR 一个寄存器完成置位和复位BRR 只负责复位。1.GPIOx_BSRRBit Set/Reset Register32位寄存器结构GPIOx_BSRR 31 16 15 0 -------------------------------- | Reset bits | Set bits | | 复位区域 | 置位区域 | --------------------------------低16位Bit 0~15Set作用写 1 → 对应 GPIO 输出高电平例如GPIOA-BSRR (1 5);表示PA5 1效果PA5 输出高电平高16位Bit 16~31Reset作用写 1 → 对应 GPIO 输出低电平例如GPIOA-BSRR (1 (516));表示PA5 0效果PA5 输出低电平2. GPIOx_BRRBit Reset Register部分 STM32 系列存在比如 STM32F116位寄存器结构GPIOx_BRR 15 0 --------------- | Reset bits | | 复位 | ---------------作用写 1 → 对应 GPIO 输出低电平例如GPIOA-BRR (1 5);效果PA5 0BSRR 和 BRR 对比寄存器位写1效果BSRR低16位0~15输出高BSRR高16位16~31输出低BRR0~15输出低为什么不用 ODR为什么两个地方都只是“改一个位”最后会互相影响先不要想中断先理解一个事实ODR | (15)不是“只改 PB5”而是“读整个 ODR → 改一个位 → 写回整个 ODR”。1. 假设 GPIO 有两个灯假设bit6 PB6灯 bit5 PB5灯现在两个灯都是灭的ODR 00000000对应PB6 0 PB5 02. 主程序想打开 PB5代码GPIOB-ODR | (15);CPU不是直接改 PB5。它做第一步读读取整个 ODR读到 00000000第二步改把 bit5 改成100000000 OR 00100000 00100000现在 CPU 心里已经算好了准备写入 00100000注意但是 GPIO 的 ODR 还没变此时真实硬件ODR 00000000CPU手里001000003. 这时候中断来了中断也想打开 PB6代码GPIOB-ODR | (16);它也不知道主程序正在操作。所以它也读ODR 00000000为什么还是 00000000因为主程序还没有最后写回。中断修改00000000 OR 01000000 01000000然后写回ODR 01000000现在真实硬件PB6 1 PB5 04. 中断结束回到主程序主程序继续自己的最后一步把刚才算好的00100000写回ODR 00100000结果PB6 0 PB5 1BSRR/BRR直接GPIOA-BSRR (15); // PA5 高 GPIOA-BSRR (1(516)); // PA5 低或者GPIOA-BRR (15); // PA5 低属于原子操作不需要读不影响其他引脚速度快更安全