当前位置: 首页 > article >正文

[STM32]从零开始的STM32 BSRR、BRR、ODR寄存器讲解

一、前言

        学习STM32一阵子以后,相信大家对STM32 GPIO的控制也有一定的了解了。之前在STM32 LED的教程中也教了大家如何使用寄存器以及库函数控制STM32的引脚从而点亮一个LED,之前的寄存器只是作为一个引入,并没有深层次的讲解,在教程中,也没让大家有太多的了解。既然学习STM32有一段时间了,那我们能不能从现象推导到本质,去了解一下STM32 引脚控制的本质原理。那么本次教程,就来为大家讲解一下STM32引脚驱动的三个关键寄存器BSRR、BRR、ODR,相信看了本次教程以后,你对STM32会有更深层次的理解。如果你准备好了,那就让我们开始吧!

二、谁适合本次教程

        因为已经涉及到寄存器的操作与讲解了,所以请学习本次教程的小伙伴需要具备一定的STM32基础以及对十六进制转二进制比较熟悉。

三、资料的准备

        本次使用STM32F103C8T6进行演示,所以请大家自己准备一块STM32F103的开发板。本次教程中,我们需要去翻阅STM32F103的手册,所以大家准备一份STM32F103的数据手册,相信学习过一阵子STM32的小伙伴应该都有这个手册吧,这里我就不放了。

四、BSRR、BRR、ODR寄存器讲解

        在我们日常的代码或者一些模块的代码中,可能经常会看到下面这样的写法:

GPIOC->BSRR=0x00002000;

又或者是这种写法:

GPIOC->ODR=0x00002000;

我们可以很明显的看到,这些写法都是在控制GPIO的电平,那么这些写法之间都有什么区别呢?哪种写法更好呢?

1.BSRR

        这里我们首先来看BSRR,这里我们打开STM32F10的中文手册,找到BSRR寄存器处:

下面我们就来解释一下这个寄存器的作用,很明显的看到,这里寄存器的位下面只有一个W,表示这个寄存器只是可写的:

这里大家只需要记住这个寄存器只能写就可以了,后面会为大家讲解为什么。

我们再往下看,下面的寄存器详细描述中,将寄存器分为了两个部分来讲,分别是0-15位,以及16-31位,总的来说就是将这个寄存器分为了高十六位和低十六位:

这里我们先来看位16-31,这些位都被叫做BR位,这里的R即Reset,手册中的描述是这些位是用于清除端口0-15:

简单来说,16-31位就是用于将GPIO口拉低的。假如这里我想控制GPIOC,那么我就可以使用BSRR中的16-31位将GPIPC的0-16引脚全部拉低。

在下面也提到了,这些位只能写入并且只能一十六位的形式写入:

我们继续往下看,如果BSRR的16-31位写0不会对ODR产生影响,如果写1,则ODR的对应位就会为0,从而引脚电平被拉低。至于这里为什么我们写ODR的位就可以直接控制引脚我们后面讲解ODR寄存器的时候会讲。

然后我们来看BSRR的0-15位,这些位从手册中可以看到,是用于置位GPIO口的某一位的,0-15位被叫做BS位,这里的S即Set:

同样的,假如我还是控制GPIOC,那我就可以通过BSRR下的0-15位将GPIOC的0-15引脚都置高。同样的,下面也提到了,如果给0-15位的某一位置0,则ODR对应的位不产生影响。如果给0-15位置1那么对应的ODR位就会置1从而对应的引脚置1:

这里大家就可能有疑惑了,如果我将一个引脚对应BS位和BR位都置位,会怎么样?其实在手册中已经提到了,如果这样做的话,只有BR位会起作用:

看了上面的内容,相信大家对BSRR寄存器有一定的了解了,简单来说,它就是一个控制ODR寄存器对应位高低电平从而控制引脚的一个寄存器,在官方的库函数中,也使用到了BSRR寄存器来控制引脚电平:

这里大家可能又有疑问了,为什么我这里要通过BSRR来控制ODR从而来控制引脚的电平,我不能直接控制ODR吗?这个问题,同样也留到我们讲解ODR的时候再做讲解。

2.BRR

        BRR的功能和BSRR非常接近,以至于现在一些高端的芯片已经阉割了BRR寄存器,不过我们现在还是可以来看看,我们在手册中找到BRR对应的描述:

我们可以看到BRR寄存器的高十六位是没有作用的:

并且低十六位和BSRR一样,只能写:

这里我们直接看寄存器描述,这里提到了,0-15位主要用于清除端口的位,也就是为指定端口拉低。这里的用法其实和BSRR的高十六位一样,都是通过给对应的位置1从而给ORD对应的位置0从而控制引脚电平。如果你理解BSRR的话,理解BRR也不是什么难题,这里就不多说了:

3.ODR

        现在我们来讲解ODR,前面已经为大家留了许多问题在ODR这里了,现在我们一一来解决。

我们同样先在手册中找到ODR所在的位置:

这里我们可以看到,ODR的高十六位同样作为保留位。然后就是低十六位,这里的低十六位我们简单来说就是,对应了GPIO的十六个引脚。我们给ODR对应的位置高或者置低,那么对应的GPIO引脚就会被置对应的电平。假如我么就将ODR的第12位置1,那么对应的GPIO12就会被置1。在手册中也提到了,我们的BSRR寄存器可以对每个ODR位进行独立的设置和清除:

这就是为什么我们要通过BSRR来操作ODR从而来操作GPIO。因为BSRR可以对ODR的每一位进行操作并且不影响别的位。如果我们直接操作ODR的话,要实现不影响别的位的效果就需要将ODR的值先读出来然后再写入对应的值最后整体写入ODR,这也是我们常用的读-改-写的操作流程。那么大家可能又有疑问了,为什么我们的BSRR可以直接操作ODR。

这里我们在手册中,找到“8.1.8输出配置”,这里我们主要是需要下面的图:

我们将下面的图单独拿出来:

这里我们可以看到,我们的写入可以写到“位设置/清除寄存器”,这个“位设置/清除寄存器”是什么?这不就是BSRR吗?:

然后,我们写入BSRR以后,BSRR直接就写入了一个名为“输出数据寄存器”的地方,这个输出数据寄存器,不就是我们的ODR吗?:

相当于,BSRR一旦收到数据,就会发送给ODR,从而对ODR的位进行操作。BSRR发送完数据以后,就直接将内部存储的值扔掉了,本身就不保存值,所以读取BSRR本很就没有意义。这样也印证了为什么之前我们说BSRR不能读取。

最后,我们可以看到,我们的ODR上有一条单独的线,是用于读写ODR的,这些表示ODR可以被直接读写:

其实,总的来说,为什么我们不直接操作ODR呢?因为我们操作BSRR可以直接操作ODR的值从而不影响别的引脚。为什么我们操作BSRR可以直接操作ODR呢?因为它们在物理总线层面被链接在了一起,并且操作BSRR可以直接操作ODR的位。为什么BSRR不能读取呢?因为BSRR有了值以后直接就拿给ODR了,本身不存储值,没有读取的必要。

假如我们执行下面两段代码,在实际效果上应该是一样的:

#include "stm32f10x.h"                  
int main(void)
{RCC->APB2ENR=0x00000010;GPIOC->CRH=0x00300000;GPIOC->BSRR=0x00002000;while(1){}
}
#include "stm32f10x.h"                  
int main(void)
{RCC->APB2ENR=0x00000010;GPIOC->CRH=0x00300000;GPIOC->ODR=0x00002000;while(1){}
}

但是,最后的最后,仍然建议大家在操作引脚时不直接操作ODR,虽然我们可以通过读-改-写的方法保留原本的值并且写入新值,但是,这样会增加我们的代码量并且增加出错的概率。

五、结语

        以上就是我对GPIO相关的寄存器的一些见解,如果有讲得不对的地方,还请大家指正,最后感谢大家的观看!

相关文章:

[STM32]从零开始的STM32 BSRR、BRR、ODR寄存器讲解

一、前言 学习STM32一阵子以后,相信大家对STM32 GPIO的控制也有一定的了解了。之前在STM32 LED的教程中也教了大家如何使用寄存器以及库函数控制STM32的引脚从而点亮一个LED,之前的寄存器只是作为一个引入,并没有深层次的讲解,在教…...

DeepSeek-V3关键技术之一:DeepSeekMoE

DeepSeekMoE 是一种创新的大规模语言模型架构,旨在通过高效的计算流程和优化设计,在保持高性能的同时显著降低计算成本。 1. 架构设计 DeepSeekMoE 基于 Transformer 架构,融合了以下核心技术: 专家混合系统(Mixture…...

MySQL--DQL、DML、DDL、DCL概念与区别

在SQL中,根据功能和操作对象的不同,通常将语文分为四大类:DQL(数据查询语言)、DML(数据操作语言)、DDL(数据定义语言)、DCL(数据控制语言) 一、D…...

Android Activity启动流程详解

目录 Activity 启动流程详细解析 1. 应用层发起启动请求 1.1 调用 startActivity() 1.2 通过 Instrumentation 转发请求 2. 系统服务处理(AMS 阶段) 2.1 Binder IPC 通信 2.2 AMS 处理流程 2.3 跨进程回调 ApplicationThread 3. 目标进程初始化…...

夜天之书 #106 Apache 软件基金会如何投票选举?

近期若干开源组织进行换届选举。在此期间,拥有投票权的成员往往会热烈讨论,提名新成员候选人和治理团队的候选人。虽然讨论是容易进行的,但是实际的投票流程和运作方式,在一个成员众多的组织中,可能会有不少成员并不清…...

保姆级教程:用Chart.js实现柱状图与折线图联动

保姆级教程:用Chart.js实现柱状图与折线图联动 ▲ 最终实现的交互式组合图表效果 一、技术原理剖析 1.1 Chart.js渲染机制 Chart.js基于HTML5 Canvas实现图表绘制,其核心原理包括: 数据绑定:将数据对象映射为图形元素分层渲染:通过order属性控制图层叠加顺序坐标系计算:…...

初阶MySQL(两万字全面解析)

文章目录 1.初识MySQL1.1数据库1.2查看数据库1.3创建数据库1.4字符集编码和排序规则1.5修改数据库1.6删除数据库 2.MySQL常用数据类型和表的操作2.(一)常用数据类型1.数值类2.字符串类型3.二进制类型4.日期类型 2.(二)表的操作1查看指定库中所有表2.创建表 3.查看表结构和查看表…...

大模型应用:多轮对话(prompt工程)

概述 在与大型语言模型(如ChatGPT)交互的过程中,我们常常体验到与智能助手进行连贯多轮对话的便利性。那么,当我们开启一个新的聊天时,系统是如何管理聊天上下文的呢? 一、初始上下文的建立 1. 创建新会…...

4.3MISC流量分析练习-wireshark-https

流量分析题目的例题 1.了解wireshark的过滤方式 2.了解tls跟ssl协议基本还原 3.了解xor基本变换方式,获取flag 附件是一个流量包,打开之后有各种流量,但是分析无果,然后丢到kali中使用binwalk进行分析,发现有一个r…...

【AGI】DeepSeek开源周:The whale is making waves!

DeepSeek开源周:The whale is making waves! 思维火花引言一、DeepSeek模型体系的技术演进1. 通用语言模型:DeepSeek-V3系列2. 推理优化模型:DeepSeek-R1系列3. 多模态模型:Janus系列 二、开源周三大工具库的技术解析1…...

CSS Selectors

当然,理解纯CSS选择器(CSS Selectors)对于进行UI自动化测试非常重要。CSS选择器允许您通过元素的属性、层级关系、类名、ID等来精准定位页面上的元素。下面我将详细讲解CSS选择器的常见用法,并结合您的需求提供具体的示例。 1. 基…...

Java Junit框架

JUnit 是一个广泛使用的 Java 单元测试框架,用于编写和运行可重复的测试。它是 xUnit 家族的一部分,专门为 Java 语言设计。JUnit 的主要目标是帮助开发者编写可维护的测试代码,确保代码的正确性和稳定性。 JUnit 的主要特点 注解驱动&…...

3-3 WPS JS宏 遍历文件名获取函数(遍历指定文件夹下的所有工作)学习笔记

************************************************************************************************************** 点击进入 -我要自学网-国内领先的专业视频教程学习网站 *******************************************************************************************…...

STM32CubeMx DRV8833驱动

一、DRV8833驱动原理 ​ STBY口接单片机的IO口,STBY置0电机全部停止,置1才能工作。STBY置1后通过AIN1、AIN2、BIN1、BIN2 来控制正反转。 AIN1AIN2电机状态00停止1speed反转speed1正转11停止 其中A端(AIN1与AIN2)只能控制AO1与…...

用Python之requests库调用大型语言模型(LLM)API的流式输出与非流式输出比较

文章目录 1. 非流式输出与流式输出概述2. 非流式输出2.1 代码实例12.2 代码实例2 3. 流式输出3.1 流式输出的定义和作用3.2 流式输出适用的场景3.3 流式输出的实现方式与实现技术3.4 代码实例33.5 代码实例4 4. 小结 1. 非流式输出与流式输出概述 大模型收到输入后并不是一次性…...

【Qt】ffmpeg照片提取、视频播放▲

目录 一、图像的成像原理: RGB成像原理: YUV成像原理: 二、多线程 三、ffmpeg解码(照片提取) 1.准备工作 (1)在工程文件夹里面新建三个文件夹 (2)在main函数中加…...

Vue+Elementui 全局配置el-table表格列宽可拖拽

1、需求分析 如何让表格列宽可以拖动 elementui的el-table如果想要列宽可以拖动的话 有一个属性叫 border 在模板里添加这个属性即可实现 但是系统里面的表格我不可能一个一个去添加border太麻烦 如果能够全局配置岂不是非常省时间吗 我们在main.js里面通过全局混入的方式来…...

SQL命令详解之增删改数据

目录 简介 1 添加数据 1.1 基础语法 1.2 SQL 练习 2 修改数据 2.1 基础语法 2.2 SQL 练习 ​3 删除数据 3.1 基础语法 3.2 SQL 练习 总结 简介 在数据库操作中,增、删、改是最基础的操作,它们通常对应着SQL中的INSERT、DELETE和UPDATE命令。…...

鸿蒙开发第4篇__关于在鸿蒙应用中使用Java语言进行设计

本博文对于鸿蒙APP程序员来说,很重要 HarmonyOS从 API8 开始不再支持使用Java作为开发语言,未来的新功能将在ArkTS中实现. API 8对应的是HarmonyOS 3.0.0版本, 2022年7月27日, 华为发布了HarmonyOS 3.0。 请看下图: 因此&#…...

Linux三种网络方式

前言 发现运维啥都得会,这周就遇到了网络问题自己无法解决,因此痛定思痛学一下。 参考文献 你管这破玩意叫网络? 桥接模式、NAT模式、仅主机模式,原来是这样工作的 交换机 构成局域网,实现所有设备之间的通信。 …...

计算机网络之传输层(传输层提供的服务)

一、可靠的数据传输 传输层提供可靠的数据传输服务,确保数据在传输过程中不丢失、不重复、不乱序,并且能够被正确接收。这通常通过面向连接的协议(如TCP)来实现,TCP通过确认、重传、序号等机制来保证数据传输的可靠性…...

Ubuntu 防火墙iptables和 ufw

文章目录 iptables 和 ufw 的区别Ubuntu 上使用 ufw 配置 iptables 和 ufw 的区别 iptables 和 ufw 是 Linux 系统中用于管理防火墙的工具,但它们的设计目标和使用方式有所不同。 iptables:功能强大,适合高级用户和复杂场景,但配…...

11天 -- Redis 中跳表的实现原理是什么?Redis 的 hash 是什么?Redis Zset 的实现原理是什么?

Redis 中跳表的实现原理是什么? Redis 中的跳表(Skip List)是一种基于有序链表的高效数据结构,通过在链表上增加多级索引来提高数据的查找效率。以下是 Redis 中跳表的实现原理: 1. 基本概念 节点结构:跳…...

JavaWeb——HTML

一、什么是HTML HTML(HyperText Markup Language):超文本标记语言 超文本:超越了文本的限制,比普通文本更强大。除了文字信息还可以定义图片,音频,视频等。标记语言:由标签构成的语言 HTML语言都是预定义好…...

Spring DIIoC

一.IoC 1.简介 什么是IoC?IoC,全称 Inversion of Control,控制反转。IoC是Spring的核心思想,Spring是⼀个“控制反转”的容器。 如果我们需要一个对象,正常来说我们是通过new一个对象,这个时候我们依赖的…...

【前端基础】Day 2 CSS层叠样式表

目录 1.CSS简历 2.CSS 基础选择器 2.1标签选择器 2.2类选择器 2.3 id选择器 2.4通配符选择器 2.5总结 3.CSS字体属性 字体属性总结 4.CSS文本属性 4.1颜色 4.2对齐文本 4.3装饰文本 4.4文本缩进 4.5行间距 4.6文本属性总结 5.CSS的引入方式 5.1内部样式表 …...

建易WordPress

建易WordPress是一家专业的WordPress建站服务提供商,专注于为企业和个人提供一站式的WordPress网站建设、维护、托管、运营推广以及搜索引擎优化(SEO)服务。 服务内容 1. 网站建设 提供模板建站和定制开发两种服务,满足不同客户的需求。模板建站价格为…...

计算机毕业设计SpringBoot+Vue.js汽车资讯网站(源码+文档+PPT+讲解)

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...

nuxt常用组件库html-validator、@nuxtjs/i18n、@nuxt/image、@unocss/nuxt使用解析

html-validator 主要用于自动验证nuxt服务器呈现的HTML(SSR和SSG),以检测可能导致水合错误的HTML常见问题,有助于减少水合错误,检测常见的可访问性错误。 安装 npx nuxilatest module add html-validator配置 若自动更新nuxt.config.ts配置文…...

Leetcode-最大矩形(单调栈)

一、题目描述 给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。 输入:matrix [["1","0","1","0","0"],["1","0&…...