关闭

STM32 BSRR BRR ODR 寄存器解析

标签: stm32函数
367人阅读 评论(2) 收藏 举报
分类:

一、用法

经常会看到类似如下的宏定义语句,用于对已经初始化后的 IO 口输出高、低电平。

#define SET_BL_HIGH()           GPIOA->BSRR=GPIO_Pin_0 
#define SET_BL_LOW()            GPIOA->BRR=GPIO_Pin_0

其作用类似于如下两个库函数,

void GPIO_SetBits(GPIO_Typedef* GPIOx, uint16_t GPIO_Pin)
void GPIO_ResetBits(GPIO_Typedef* GPIOx, uint16_t GPIO_Pin)  

而且实际上这两个库函数就是通过修改BSRR,BRR寄存器的值来实现对 IO 口设置的。如下便是输出高电平的函数体:

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));

  GPIOx->BSRR = GPIO_Pin;
}

因此,使用宏或者库函数本质上都是一样的。区别在于使用宏更快,而使用函数更灵活。

二、解释

BSRR 和 BRR 都是 STM32 系列 MCU 中 GPIO 的寄存器。 BSRR 称为端口位设置/清楚寄存器,BRR称为端口位清除寄存器。

BSRR 低 16 位用于设置 GPIO 口对应位输出高电平,高 16 位用于设置 GPIO 口对应位输出低电平。

BRR 低 16 位用于设置 GPIO 口对应位输出低电平。高 16 位为保留地址,读写无效。

所以理论上来讲,BRR 寄存器的功能和 BSRR 寄存器高 16 位的功能是一样的。也就是说,输出低电平的宏语句,可以有如下两种写法。

#define SET_BL_LOW()            GPIOA->BRR=GPIO_Pin_0
等价于
#define SET_BL_LOW()            GPIOA->BSRR=GPIO_Pin_0 << 16 

这么来看的话,其实 BRR 寄存器是比较多余的。而实际上,在最新的 STM32F4 系列 MCU 的 GPIO 寄存器中,已经找不到 BRR 寄存器了,仅保留了 BSRR 寄存器用于实现端口输出高低电平。因此,在 STM32F4 系列 MCU 的库函数中,对 GPIO 口输出高低电平的函数为如下形式:

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{
  /* Check the parameters */
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  assert_param(IS_GPIO_PIN_ACTION(PinState));

  if(PinState != GPIO_PIN_RESET)
  {
    GPIOx->BSRR = GPIO_Pin;
  }
  else
  {
    GPIOx->BSRR = (uint32_t)GPIO_Pin << 16U;
  }
}

可见,不管是输出高还是输出低,都是对 BSRR 寄存器的操作。

三、BSRR、BRR、 ODR 之间的关系

配置 BSRR , BRR 是为了对端口输出进行配置,而 ODR 寄存器也是用于输出数据的寄存器,一个 ODR 寄存器控制了一组(16位)的 GPIO 输出。因此,对 ODR 进行修改也可以到达对 IO 口输出进行配置。

但是,由于对 ODR 寄存器的读写操作必须以 16 位的形式进行。因此,如果使用 ODR 改写数据以控制输出时,须采用“读-改-写”的形式进行。

假设需要对 GPIOA_Pin_6 输出高电平。采用改写 ODR 寄存器的方式时,使用“读-改-写”操作,代码如下:

uint32_t temp;
temp = GPIOA->ODR;
temp = temp | GPIO_Pin_6;
GPIOA->ODR = temp;

而使用改写 BSRR 寄存器时,仅需要使用如下语句:

GPIOA->BSRR = GPIO_Pin_6;

这是因为在修改 ODR 时,为了确保对端口 6 的修改不会影响到其他端口的输出,需要对端口的原始数据进行保存,之后再对端口 6 的值进行修改,最后再写入寄存器。而对 BSRR 的操作,是写 1 有效,写 0 不改变原状态,因此可以对端口 6 置 1,其他位保持为 0。BSRR 为 1 的位,会修改相应的 ODR 位,从而控制输出电平。

对 BSRR 的操作可以实现原子操作。因此在设置单个 IO 口输出时,使用 BSRR 进行操作会更加方便。

但也有例外的时候,在需要对单个IO口进行 Toggle 操作时(即对当前输出取反输出,当前输出为高则输出低,当前输出低则输出高),官方的库函数就是直接对 ODR 寄存器进行操作的。代码如下:

void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  /* Check the parameters */
  assert_param(IS_GPIO_PIN(GPIO_Pin));

  GPIOx->ODR ^= GPIO_Pin;
}

这是因为,0 和 1 与 1 进行异或操作被取反,0 和 1 与 0 进行异或操作保持原值。如下:

0 ^ 1 = 1
1 ^ 1 = 0

0 ^ 0 = 0
1 ^ 0 = 1
0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

STM32 通用输入输出端口GPIO BRR、BSRR、ODR寄存器详解

详细页面:http://alanzjl.sinaapp.com/2015/02/gpio_brr_bsrr_odr/ BRR、BSRR、ODR都是用来控制16位针脚的。 其中,BRR和OD...
  • alanzjl
  • alanzjl
  • 2015-02-16 23:52
  • 5240

STM32学习笔记——GPIO之从库函数到寄存器

例子为单片机的“Hello World”级的流水灯实验——虽然只有一个,其中并不是将完整的代码给出,只是给出关键部分来说明“如何调用ST公司的的库来完成对硬件的控制,以及对库文件代码进行跟踪和分析至寄...
  • fovwin
  • fovwin
  • 2013-04-16 20:09
  • 24646

STM32F1学习-驱动led灯(寄存器版本)

驱动lled灯(寄存器版本)
  • u013355826
  • u013355826
  • 2016-07-17 16:14
  • 1416

STM32 通用输入输出端口GPIO BRR、BSRR、ODR寄存器详解

详细页面:http://alanzjl.sinaapp.com/2015/02/gpio_brr_bsrr_odr/ BRR、BSRR、ODR都是用来控制16位针脚的。 其中,BRR和OD...
  • alanzjl
  • alanzjl
  • 2015-02-16 23:52
  • 5240

STM32 GPIO 配置之ODR, BSRR, BRR 详解

用stm32 的配置GPIO 来控制LED 显示状态,可用ODR,BSRR,BRR 直接来控制引脚输出状态. ODR寄存器可读可写:既能控制管脚为高电平,也能控制管脚为低电平。 管脚对于位...
  • zhjmyx
  • zhjmyx
  • 2017-04-24 17:18
  • 347

STM32的CRH、CRL、ODR和IDR寄存器的使用总结

STM32的CRH、CRL、ODR和IDR寄存器的使用总结 一.CRH和CRL的使用: CRH和CRL的使用基本相同,CRH用于控制GPIOX(X表示A---G)的高8位(Pin15---Pin...
  • qq84395064
  • qq84395064
  • 2017-11-13 17:39
  • 212

GPIO的寄存器BSRR和BRR

【转】GPIO的寄存器BSRR和BRR 以写数据为例,提供的函数有 GPIO_SetBits  GPIO_ResetBits GPIO_WriteBit  GPIO_Write ...
  • xinleixinlei
  • xinleixinlei
  • 2013-03-25 14:51
  • 831

STM32定时器----TIMx->SR寄存器

在研究stm32定时器时发现,当进入定时器的中断时,定时器计数器以及中断接收时正常运行的,并没有因为进入中断而停止具体看以下分析:定时器初始化代码://TIM捕获通道开启宏定义,1:开启 0:关闭 ...
  • a3748622
  • a3748622
  • 3天前 15:58
  • 18

STM32学习笔记——GPIO之从库函数到寄存器 .

from:http://blog.csdn.net/fovwin/article/details/8810703 例子为单片机的“Hello World”级的流水灯实验——虽然只有一个,其中并不是将...
  • rensanshi
  • rensanshi
  • 2013-09-22 16:23
  • 1018

STM32F10x中的串口寄存器

USART 通用同步异步收发器(Universal Synchronous Asynchronous Receiver Transmitter)。 APB2ENR 高级外设总线(Andvaced Pe...
  • gaojinshan
  • gaojinshan
  • 2013-09-13 13:43
  • 6780
    个人资料
    • 访问:355735次
    • 积分:3708
    • 等级:
    • 排名:第10162名
    • 原创:96篇
    • 转载:3篇
    • 译文:2篇
    • 评论:84条
    文章分类
    最新评论