精华内容
下载资源
问答
  • 这是因为如果操作ODR寄存器,需要先读出ODR寄存器,然后修改相应的位的值,再写回ODR,分为3步。而BSRR寄存器设置位,只需要对相应的设置或复位的位直接写1,其他位写0(BSRR只对写1有效,写0无意义,不影响原先位的...

    这是因为如果操作ODR寄存器,需要先读出ODR寄存器,然后修改相应的位的值,再写回ODR,分为3步。而BSRR寄存器设置位,只需要对相应的设置或复位的位直接写1,其他位写0(BSRR只对写1有效,写0无意义,不影响原先位的电平),可以直接一步到位。这个在实时操作系统和中断会有比较大的意义,如果使用ODR寄存器,可能在读取ODR的值后,被其他优先级更高的操作打断(该高优先级的操作可能也操作了相应ODR),等到高优先级操作完成后再返回接着设置ODR,可能这个过程中ODR的值已经改变,若我们重新写入ODR,会覆盖更高优先级配置的值。

     

    展开全文
  • 高手带你解析STM32 BSRR BRR ODR 寄存器

    千次阅读 2017-10-19 23:52:08
    高手带你解析STM32 BSRR BRR ODR 寄存器http://www.21ic.com/jichuzhishi/mcu/memory/2017-09-28/739785.html 一、用法 经常会看到类似如下的宏定义语句,用于对已经初始化后的 IO 口输出高、低电平。 ...

    高手带你解析STM32 BSRR BRR ODR 寄存器http://www.21ic.com/jichuzhishi/mcu/memory/2017-09-28/739785.html

    一、用法

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

    #define SET_BL_HIGH() GPIOA->BSRR=GPIO_Pin_0

    #define SET_BL_LOW() GPIOA->BRR=GPIO_Pin_012

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

    void GPIO_SetBits(GPIO_Typedef* GPIOx, uint16_t GPIO_Pin)

    void GPIO_ResetBits(GPIO_Typedef* GPIOx, uint16_t GPIO_Pin) 12

    而且实际上这两个库函数就是通过修改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;

    }12345678

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

    二、解释

    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 123

    这么来看的话,其实 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;

    }

    }123456789101112131415

    可见,不管是输出高还是输出低,都是对 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;1234

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

    GPIOA->BSRR = GPIO_Pin_6;1

    这是因为在修改 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;

    }1234567

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

    0 ^ 1 = 1

    1 ^ 1 = 0

    0 ^ 0 = 0

    1 ^ 0 = 1


    展开全文
  • STM32中的IDR和ODR寄存器

    万次阅读 多人点赞 2018-06-15 15:06:52
    #define WARM_KEY_PIN (GPIOC-&gt;IDR&amp;(1&lt;&lt;5))#define Speak(tmp) GPIOA-&gt;ODR=tmp?...12)))(1)IDR是查看引脚电平状态用的寄存器ODR是引脚电平输出的寄存器。...
    #define WARM_KEY_PIN     (GPIOC->IDR&(1<<5))
    
    #define Speak(tmp)       GPIOA->ODR=tmp?(GPIOA->ODR|1<<12):(GPIOA->ODR&(~(1<<12)))

    (1)IDR是查看引脚电平状态用的寄存器,ODR是引脚电平输出的寄存器。

    (2)1<<5表示:1左移5位(0000 0001---->0010 0000)


    1、->在C语言中称为间接引用运算符,是二目运算符,优先级同成员运算符“.”。
    2、用法:
    p->a,其中p是指向一个结构体的指针,a是这个结构体类型的一个成员。表达式p->a引用了指针p指向的结构体的成员a。
    3、例如:
    struct T
    {
     int a;
     char b;
    }s;
    struct T* p=&s;
    那么,p->a相当于s.a。显然,有个等价写法:(*p).a,和p->a完全等效。
    展开全文
  • STM32 BSRR BRR ODR 寄存器解析

    千次阅读 2017-08-01 11:54:09
    配置 BSRR , BRR 是为了对端口输出进行配置,而 ODR 寄存器也是用于输出数据的寄存器,一个 ODR 寄存器控制了一组(16位)的 GPIO 输出。因此,对 ODR 进行修改也可以到达对 IO 口输出进行配置。 但是,由于对 ODR...

    一、用法

    经常会看到类似如下的宏定义语句,用于对已经初始化后的 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 的 HAL 库函数中,对 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;
      }
    }
    

    而早期 ST 的标准库 std 中,关于 GPIO 口输出高低电平的函数为如下形式,里面通过两个16位的指针分别指向 BSRR 的高16位和低16位。

    typedef struct
    {
      __IO uint32_t MODER;    /*!< GPIO port mode register,               Address offset: 0x00      */
      __IO uint32_t OTYPER;   /*!< GPIO port output type register,        Address offset: 0x04      */
      __IO uint32_t OSPEEDR;  /*!< GPIO port output speed register,       Address offset: 0x08      */
      __IO uint32_t PUPDR;    /*!< GPIO port pull-up/pull-down register,  Address offset: 0x0C      */
      __IO uint32_t IDR;      /*!< GPIO port input data register,         Address offset: 0x10      */
      __IO uint32_t ODR;      /*!< GPIO port output data register,        Address offset: 0x14      */
      __IO uint16_t BSRRL;    /*!< GPIO port bit set/reset low register,  Address offset: 0x18      */
      __IO uint16_t BSRRH;    /*!< GPIO port bit set/reset high register, Address offset: 0x1A      */
      __IO uint32_t LCKR;     /*!< GPIO port configuration lock register, Address offset: 0x1C      */
      __IO uint32_t AFR[2];   /*!< GPIO alternate function registers,     Address offset: 0x20-0x24 */
    } GPIO_TypeDef;
    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->BSRRL = GPIO_Pin;
    }
    void GPIO_ResetBits(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->BSRRH = GPIO_Pin;
    }
    

    可见,不管是输出高还是输出低,都是对 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
    
    展开全文
  • STM32 通用输入输出端口GPIO BRR、BSRR、ODR寄存器详解

    万次阅读 多人点赞 2015-02-16 23:52:55
    详细页面:...其中,BRR和ODR高16位都不可用(Reserved),使用低16位控制针脚,而BSRR高16位和低16位皆可用,都用来控制16位针脚。 BRR与BSRR使用方法 BRR和BSRR的最显著用处就是可以只改
  • STM32寄存器ODR,BSRR和BRR

    千次阅读 2019-07-25 19:13:28
    ODR寄存器可读可写:既能控制管脚为高电平,也能控制管脚为低电平。管脚对于位写1 gpio 管脚为高电平,写 0 为低电平 ·缺点:会因中断而打断,关闭中断明显会延迟或丢失一事件的捕获,所以控制GPIO的状态最好还是用...
  • ODR寄存器, 控制管脚的高/低电平, 只有低16位, 置1 为高电平,置0为低电平; BSRR寄存器, 控制管脚的高/低电平, 低16位:写入1为高电平, 高16位:写入1为低电平; BRR寄存器, 只能控制管脚的低电平, 只有低16位, 写入1...
  • ...用stm32 的配置GPIO 来控制LED 显示状态,可用... ODR寄存器可读可写:既能控制管脚为高电平,也能控制管脚为低电平。管脚对于位写1 gpio 管脚为高电平,写 0 为低电平 BSRR 只写寄存器:[color=Re...
  •  关于CRH、CRL、ODR和IDR寄存器的使用总结   一.CRH和CRL的使用: CRH和CRL的使用基本相同,CRH用于控制GPIOX(X表示A---G)的高8位(Pin15---Pin8),而CRL用于控制GPIOX(X表示A---G)的低8位(Pin7----Pin0...
  • STM32的CRH、CRL、ODR和IDR寄存器的使用总结

    万次阅读 多人点赞 2017-11-13 17:39:26
    STM32的CRH、CRL、ODR和IDR寄存器的使用总结 一.CRH和CRL的使用: CRH和CRL的使用基本相同,CRH用于控制GPIOX(X表示A---G)的高8位(Pin15---Pin8),而CRL用于控制GPIOX(X表示A---G)的低8位(Pin7----Pin0)...
  • 51单片机寄存器地址映射使用sfr关键字...STM32寄存器地址映射当我们想ODR寄存器赋值0时,MCU是如何知道ODR寄存器的地址呢?GPIOA->ODR = 0x00000000; 在STM32中, 寄存器地址 = (外设基地址+偏移量1) + (总线基地址
  • STM32 GPIO寄存器ODR BSRR BRR

    千次阅读 2017-04-11 19:25:57
    STM32 GPIO寄存器ODR BSRR BRR 使用BRR和BSRR寄存器可以方便地快速地实现对端口某些特定位的操作,而不影响其它位的状态。 比如希望快速地对GPIOE的位7进行翻转,则可以: GPIOE->BSRR = 0x80; // ...
  • stm32通用IO寄存器详解

    2021-08-01 00:07:11
    CRH、CRL1、MODE2、CNF二、数据寄存器 ODR、IDR1、ODR2、IDR三、置位/复位寄存器 BSRR1、BSRR四、复位寄存器 BRR1、BRR五、锁存寄存器 LCKR1、LCKR六、ODR、BSRR、BRR之间的联系与区别**既然ODR寄存器既可以输出高电...
  • Stm32 寄存器直接控制

    2019-12-08 21:56:32
    直接控制IO口 地址不能直接控制 要把地址转成指针 *(unsigned int *)...只控制地址不行 修改ODR寄存器 寄存器有输入输出 默认是输入的话 要在对寄存器设置为推挽输出 设置时钟 始终默认关闭 要打开时钟 RCC控制 ...
  • STM32通过寄存器实现IO口取反

    千次阅读 2020-12-02 10:54:40
    通过按位异或,写ODR寄存器,如: GPIOB->ODR ^= GPIO_Pin_5; //对PB5 IO口取反 在官方给的固件库中,有 #define GPIO_Pin_5 ((uint16_t)0x0020) /*!< Pin 5 selected */ 这样的宏定义,所以这样的异或操作...
  • IDR是查看引脚电平状态用的寄存器ODR是引脚电平输出的寄存器 下面内容的原文:http://m646208823.blog.163.com/blog/static/166902953201293132522237/ 使用BRR和BSRR寄存器可以方便地快速地实现对端口某些特...
  • Author:DriverMonkey ...QQ:196568501 Phone:18575593141 欢迎交流!   用stm32 的配置GPIO 来控制LED 显示状态,可用ODR,BSRR,BRR 直接来控制引脚输出状态. ODR寄存器可读可写:既能控制管脚为高电...
  • STM32-用寄存器点亮LED

    2021-03-30 23:40:33
    STM32-用寄存器点亮LED 目录一 GPIO知识1 推挽输出2 开漏输出3 GPIO初始化顺序 ...ODR寄存器控制输出数据 1 推挽输出 以下这个灌电流和拉电流反了 2 开漏输出 开漏输出只能输出低电平 3 GPIO初始化顺序 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,332
精华内容 1,732
关键字:

odr寄存器