[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相关的寄存器的一些见解,如果有讲得不对的地方,还请大家指正,最后感谢大家的观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/26341.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Truffle、Ganache、MetaMask、Vue+Web3完成的一个简单区块链项目

文章目录 概要初始化Truffle项目创建编写合约编译合约配置Ganache修改truffle-config.js文件编写迁移文件部署合约使用Truffle 控制台使用MetaMask和VueWeb3与链交互 概要 使用Truffle、Ganache、MetaMask、VueWeb3完成的一个简单区块链项目。 初始化Truffle项目 安装好truf…

在线会议时, 笔记本电脑的麦克风收音效果差是为什么

背景 最近在线面试. 使用腾讯会议或者飞书, 戴耳机参加在线面试, 遇到好几个面试官说我的音质不好. 一直没在意, 后来反思, 应该是电脑哪里出了问题. 排查 先买了一副品牌有线耳机, 测试后本地录制的声音仍然品质很差去掉耳机延长线后, 麦克风品质仍然很差最终找到答案, 原…

通过百度构建一个智能体

通过百度构建一个智能体 直接可用,我不吝啬算力 首先部署一个模型,我们选用deepseek14 构建智能体思考步骤,甚至多智能体; from openai import OpenAIclass Agent:def __init__(self, api_key, base_url, model

解决“request returned Internal Server Error for API route and version xxx”错误

一、问题描述 ragflow/README_zh.md at main infiniflow/ragflowhttps://github.com/infiniflow/ragflow/blob/main/README_zh.md 当我们使用Docker部署ragflow,确认服务器状态时,提示“request returned Internal Server Error for API route and version http://%2F%2F.%…

OpenFlexure记录

https://openflexure.org/projects/microscope/build

游戏引擎学习第131天

仓库:https://gitee.com/mrxiao_com/2d_game_3 运行游戏并识别我们的小问题 今天的工作重点是对游戏引擎进行架构优化,特别是针对渲染和多线程的部分。目前,我们的目标是让地面块在独立线程上进行渲染,以提高性能。在此过程中,我…

Hbase伪分布安装教程,详细版

注意Hbase版本与Hadoop版本的兼容,还有与JDK版本的兼容 本次用到的Hbase为2.4.6版本,Hadoop为3.1.3版本,JDK为JDK8 打开下面的网址查看兼容问题 Apache HBase Reference Guidehttps://hbase.apache.org/book.html#configuration 点击基础先…

使用Hydra进行AI项目的动态配置管理

引言:机器学习中的超参数调优挑战 在机器学习领域,超参数调优是决定模型性能的关键环节。不同的模型架构,如神经网络中的层数、节点数,决策树中的最大深度、最小样本分割数等;以及各种训练相关的超参数,像学习率、优化器类型、批量大小等,其取值的选择对最终模型的效果…

基于Kerberos认证对接华为云Elasticsearch

可以通过华为官方提供的Elasticsearch Java客户端(基于Elasticsearch官方版本改造),实现基于Kerberos认证访问和操作华为云Elasticsearch;亦可以使用更加通用的开源Elasticsearch Java客户端bboss,实现基于Kerberos认证…

Rocky Linux 8.5 6G内存 静默模式(没图形界面)安装Oracle 19C

Oracle19c 下载地址 Database Software Downloads | Oraclehttps://www.oracle.com/database/technologies/oracle-database-software-downloads.html#db_ee 目录 一、准备服务器 1、服务器可以克隆、自己装 2、修改主机名 3、重启 4、关闭selinux 5、关闭防火墙 5.1、…

6.6.6 嵌入式SQL

文章目录 2个核心问题识别SQL语句主语言和SQL通信完整导图 2个核心问题 SQL语句嵌入高级语言需要解决的2个核心问题是:如何识别嵌入语句?如何让主语言(比如C,C语言)和SQL通信? 识别SQL语句 为了识别主语言中嵌入的SQL…

农作物叶子病害检测数据集VOC+YOLO格式5169张29类别

数据集有部分增强 数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):5169 标注数量(xml文件个数):5169 标注数量(txt文件个数)…

hfs for windows linux apple

HFS(HTTP File Server)是一款轻量级的文件共享工具,专门用于通过 HTTP 协议快速共享文件。它非常适合在局域网或互联网上临时共享文件,操作简单,无需复杂的配置。 HFS 的主要特点 简单易用: 界面直观&#…

塑造网络安全的关键事件

注:本文为 “网络安全” 相关文章合辑。 机翻,未校。 Timeline of Cyber Security: Key Events that Shaped the Field 网络安全时间表:塑造该领域的关键事件 October 29, 2023 Cyberattacks are an everyday threat, always changing. T…

本地部署deepseek大模型后使用c# winform调用(可离线)

介于最近deepseek的大火,我就在想能不能用winform也玩一玩本地部署,于是经过查阅资料,然后了解到ollama部署deepseek,最后用ollama sharp NUGet包来实现winform调用ollama 部署的deepseek。 本项目使用Vs2022和.net 8.0开发,ollam…

Python 绘制迷宫游戏,自带最优解路线

1、需要安装pygame 2、上下左右移动,空格实现物体所在位置到终点的路线,会有虚线绘制。 import pygame import random import math# 迷宫单元格类 class Cell:def __init__(self, x, y):self.x xself.y yself.walls {top: True, right: True, botto…

2025-03-01 学习记录--C/C++-PTA 7-35 有理数均值

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 二、代码&#xff08;C语言&#xff09;⭐️ #include <stdio.h>// 【关键】计算最大公约数&#xff…

入门基础项目(SpringBoot+Vue)

文章目录 1. css布局相关2. JS3. Vue 脚手架搭建4. ElementUI4.1 引入ElementUI4.2 首页4.2.1 整体框架4.2.2 Aside-logo4.2.3 Aside-菜单4.2.4 Header-左侧4.2.5 Header-右侧4.2.6 iconfont 自定义图标4.2.7 完整代码 4.3 封装前后端交互工具 axios4.3.1 安装 axios4.3.2 /src…

CAM350_安装

版本&#xff1a;V14.5 一、安装 打开.exe文件 选择不重启&#xff0c;然后再打开这个.exe 再来一次类似的操作 二、配置 复制patch文件夹中的这三个 &#xff0c;粘贴到掉安装目录中 设置ACT_INC_LICENSE_FILE用户环境变量来设置license管理 打开电脑的环境变量 破解完毕&am…

STM32定时器超声波测距实验手册

1. 实验目标 使用STM32 HAL库和定时器实现超声波测距功能。 当超声波模块前方障碍物距离 < 10cm 时&#xff0c;点亮板载LED。 2. 硬件准备 硬件模块说明STM32开发板STM32F103C8T6HC-SR04模块超声波测距模块杜邦线若干连接模块与开发板 3. 硬件连接 HC-SR04引脚STM32引脚…