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

用stm32 的配置GPIO 来控制LED 显示状态,可用ODR,BSRR,BRR 直接来控制引脚输出状态.

ODR寄存器可读可写:既能控制管脚为高电平,也能控制管脚为低电平。

管脚对于位写1 gpio 管脚为高电平,写 0 为低电平

BSRR 只写寄存器:[color=Red]既能控制管脚为高电平,也能控制管脚为低电平。
对寄存器高 16bit 写1 对应管脚为低电平,对寄存器低16bit写1对应管脚为高电平。写 0 ,无动作

BRR 只写寄存器:只能改变管脚状态为低电平,对寄存器 管脚对于位写 1 相应管脚会为低电平。写 0 无动作。

刚开始或许你跟我一样有以下疑惑:

1.既然ODR 能控制管脚高低电平为什么还需要BSRR和SRR寄存器?
2.既然BSRR能实现BRR的全部功能,为什么还需要SRR寄存器?

对于问题 1 ------ 意法半导体给的答案是---

“This way, there is no risk that an IRQ occurs between the read and the modify access.”
什么意思呢?就就是你用BSRR和BRR去改变管脚状态的时候,没有被中断打断的风险。也就不需要关闭中断。

用ODR操作GPIO的伪代码如下:

disable_irq()
save_gpio_pin_sate = read_gpio_pin_state();
save_gpio_pin_sate = xxxx;
chang_gpio_pin_state(save_gpio_pin_sate);
enable_irq();

关闭中断明显会延迟或丢失一事件的捕获,所以控制GPIO的状态最好还是用SBRR和BRR

对于问题 2 ------- 个人经验判断意法半导体仅仅是为了程序员操作方便估计做么做的。

因为BSRR的 低 16bsts 恰好是set操作,而高16bit是 reset 操作 而BRR 低 16bits 是reset 操作。

简单地说GPIOx_BSRR的高16位称作清除寄存器,而GPIOx_BSRR的低16位称作设置寄存器。

另一个寄存器GPIOx_BRR只有低16位有效,与GPIOx_BSRR的高16位具有相同功能。

举个例子说明如何使用这两个寄存器和所体现的优势。

例如GPIOE的16个IO都被设置成输出,而每次操作仅需要

改变低8位的数据而保持高8位不变,假设新的8位数据在变量Newdata中,

这个要求可以通过操作这两个寄存器实现,STM32的固件库中有两个函数

GPIO_SetBits()和GPIO_ResetBits()使用了这两个寄存器操作端口。

上述要求可以这样实现:

GPIO_SetBits(GPIOE, Newdata & 0xff);
GPIO_ResetBits(GPIOE, (~Newdata & 0xff));

也可以直接操作这两个寄存器:

GPIOE->BSRR = Newdata & 0xff;
GPIOE->BRR = ~Newdata & 0xff;

当然还可以一次完成对8位的操作:

GPIOE->BSRR = (Newdata & 0xff) | ( (~Newdata & 0xff)<<16 );

当然还可以一次完成对16位的操作:

GPIOE->BSRR = (Newdata & 0xffff) | ( (~Newdata )<<16 );

从最后这个操作可以看出使用BSRR寄存器,可以实现8个端口位的同时修改操作。

有人问是否BSRR的高16位是多余的,请看下面这个例子:

假如你想在一个操作中对GPIOE的位7置'1',位6置'0',则使用BSRR非常方便: 
  GPIOE->BSRR = 0x400080;

如果没有BSRR的高16位,则要分2次操作,结果造成位7和位6的变化不同步! 
  GPIOE->BSRR = 0x80; 
  GPIOE->BRR = 0x40;

BSRR还有一个特点,就是Set比Reset的级别高,

就是说同一个bit又做Set又做Reset,最后结果是Set

要同步变化只要简单的 GPIOx->BSRR = 0xFFFF0000 | PATTEN;

即可,不用考虑哪些需要置1,哪些需要清零

从最后这个操作可以看出使用BSRR寄存器,可以实现8个端口位的同时修改操作。

STM32 GPIO 配置之ODR, BSRR, BRR 详解的更多相关文章

  1. GPIO 配置之ODR, BSRR, BRR 详解

    STM32 GPIO 配置之ODR, BSRR, BRR 详解 用stm32 的配置GPIO 来控制LED 显示状态,可用ODR,BSRR,BRR 直接来控制引脚输出状态. ODR寄存器可读可写:既能 ...

  2. STM32 GPIO寄存器 IDR ODR BSRR BRR

    IDR是查看引脚电平状态用的寄存器,ODR是引脚电平输出的寄存器 下面内容的原文:http://m646208823.blog.163.com/blog/static/1669029532012931 ...

  3. centos7.2环境nginx+mysql+php-fpm+svn配置walle自动化部署系统详解

    centos7.2环境nginx+mysql+php-fpm+svn配置walle自动化部署系统详解 操作系统:centos 7.2 x86_64 安装walle系统服务端 1.以下安装,均在宿主机( ...

  4. Nginx安全相关配置和nginx.conf中文详解

    一.centos下redis安全相关 1.背景 在使用云服务器时,如果我们的redis关闭了protected-mode模式,被病毒攻击的可能会大大增加,因此我们使用redis时候,最好更改默认端口, ...

  5. keepalived原理(主从配置+haproxy)及配置文件详解

    下图描述了使用keepalived+Haproxy主从配置来达到能够针对前段流量进行负载均衡到多台后端web1.web2.web3.img1.img2.但是由于haproxy会存在单点故障问题,因此使 ...

  6. Flume中的flume-env.sh和log4j.properties配置调整建议(图文详解)

    GC是内存的回收的意思. Flume中的flume-env.sh配置调整建议 [hadoop@master conf_HostInterceptor]$ pwd /home/hadoop/app/fl ...

  7. SpringBoot自动化配置之四:@Conditional注解详解

    前言 之前在分析spring boot 源码时导出可见@ConditionalOnBean 之类的注解,那么它到底是如何使用的以及其工作流程如何,我们这里就围绕以下几点来分析: @Conditiona ...

  8. 【必知必会】手把手教你配置MySQL环境变量——图文详解

    一.先决条件 假设我们已经成功安装MySQL数据库.如果还有小伙伴不知道如何安装MySQL数据库,可以在本文下留言,留言数超20,则出一期"手把手教你安装MySQL数据库--图文详解&quo ...

  9. IIS8 使用FastCGI配置PHP环境支持 过程详解

    平时帮朋友们配置过一些PHP环境的服务器,但是一直使用的都是Apache HTTP+PHP,今天呢,我吧IIS+PHP配置方式给大家发一下下~呵呵. 在这里,我使用的是FastCGI模块映射的方式配置 ...

随机推荐

  1. c++刷题(30/100)

    题目一:合并两个排序的链表 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 思路:利用两个指针cur1,cur2来指分别向两个链表中当前较小的和当前较大的 ...

  2. 【SSH异常】InvalidDataAccessApiUsageException异常

    今天在整合SSH的时候,一开始我再测试的时候service层添加了注解事务调用DAO可以正常的保存,在环境中我在XML中采用了spring的OpenSessionInViewFilter解决hiber ...

  3. hibernate介绍及环境搭建

    1.前言 hibernate与mybatis的位置一样,都是属于DAO层的框架,代替我们原来的JDBC操作数据库,属于ORM(object relationg mapping. 对象关系映射)框架.O ...

  4. ubuntu16.04 caffe(GPU模式)安装

    历时5天终于完成了,配置中出现了各种各样的Error,这里记录一下,希望能为正在安装的人提供一点帮助. 配置中主要参考博客:http://blog.csdn.net/yhaolpz/article/d ...

  5. Linux DRM KMS 驱动简介【转】

    转自:https://blog.csdn.net/yangkuanqaz85988/article/details/48689521 Whoops,上次写完<Linux DRM Graphic ...

  6. 常用SQL函数(字符串分隔转表、自增长转编号)

    字符串分隔转表 -- ============================================= -- Author: -- Create date: -- Description: ...

  7. Robotium_断言方法assert、is、search

    下面的这些方法都主要用来判断测试结果是否与预期结果相符,一般把is和search方法放在assert里面判断.assert最常用的还是assertThat方法,是Junit的判断,这里就不多说了.断言 ...

  8. js如何判断一个对象是不是Array?

    在开发中,我们经常需要判断某个对象是否为数组类型,在Js中检测对象类型的常见方法都有哪些呢? typeof 操作符 对于Function, String, Number ,Undefined 等几种类 ...

  9. mysql子查询 exists,not exists,all和any

    (1)实现让结果集A - 结果集B:--利用not exists,合并则可用union . exists,not exists:用于判断且获取结果集A是否存在地结果集B中! ==========结果集 ...

  10. c++中的类(class)

    c++的class(类)使用方法 这几天一直在调splay之类的东西,突然想转指针...qwq 于是,我就在沙华大佬的帮助下,学了下一顿乱指( $ -> $ ),也就是class(类) 首先:c ...