无论是大厂的STM32,还是咱们国产的MCU,对于GPIO输出电平控制都是有两种方法。两种方法相得益彰。下面我们就来认识一下这两种方法吧!
端口输出数据寄存器
GPIO port output data register (GPIOx_ODR),端口输出数据寄存器,对于该寄存器,其为GPIO输出控制的核心寄存器。输出寄存器可读可写,其数值对应GPIO Port口相应引脚的高低电平。
我们对其bit0写1置位时,则GPIO0引脚输出高电平。同理,对其bit0写0清零时,则GPIO0引脚输出低电平——就是这么简单!
所以,我们在一些代码中,常常可以看到对于LED灯的翻转实现多为:
GPIOx->ODR ^= 0x01; /* GPIO0 toggle */
其工作原理是先回读ODR寄存器的值,再将bit0(对应GPIO引脚)异或。之后,再写回ODR寄存器以达到仅翻转LED灯GPIO引脚,而其它引脚的输出值不变的原理。
还有一种典型的应用:并行数据接口式写入。即当我们按字节,半字或者字的方式写入ODR寄存器后,在Port口的GPIO引脚同时输出对应的数值。比如,我把GPIO7:0引脚按对应连接到并口芯片上,如数据位或地址位。这时,当我写入ODR=val时,则GPIO7:0引脚将同时输出数据,而不再需要按位变化,单次写入操作完成最多32个引脚的电平输出。
端口输出置位清零寄存器
GPIO port bit set/reset register (GPIOx_BSRR),端口输出置位清零寄存器。这个寄存器与刚刚提到的ODR寄存器大不相同。BS和BR两部分的bit位只有置位时才有效。而对写“0”的bit位无感。换句话说,BS和BR位对“1”感兴趣,自然忽略“0”。这样,对于Port口不需要改变电平状态的bit位,我们只要不对其写“1”,其原值则并不受影响。
当我们明确操作1个或多个GPIO引脚为高电平时,仅需要操作寄存器BS部分为“1”,而为低电平时,仅需要操作寄存器BR部分为“1”。再强调一遍,对于该寄存器的清零与置位均为写“1”哟!
__STATIC_INLINE void LL_GPIO_SetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask)
{
WRITE_REG(GPIOx->BSRR, PinMask);
}
__STATIC_INLINE void LL_GPIO_ResetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask)
{
WRITE_REG(GPIOx->BSRR, (PinMask << 16));
}上面的源代码就是演示的操作GPIO电平为高和低的两个API实现。
总结
通过上面的代码可以看出,设计端口输出置位清零寄存器的主要目的应该是对于GPIO的输出控制可以做到原子操作。这一点应该是工业控制里面必须要做到的吧!
我要赚赏金
