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

STM32寄存器控制引脚高低电平

一. 引子

        最近在学习32代码的过程当中,虽然在学习IMX6ULL开发板的过程中接触过很多寄存器,最近在返回去看32的时候,在研究代码的时候发现自己对于寄存器的有些特性理解的不够深刻,所以下来的时候去查了资料,以及问了一下自己的学霸朋友楚灵魈,然后对有些寄存器还是有了一些新的认识

二. STM32F10xx部分寄存器

       1. 端口输出数据寄存器(GPIOx_ODR)(x=A..E)

        首先是GPIOx_ODR,官方解释是端口输出数据寄存器,从图示可以看出,bit[31:16]是保留位实际有效位只有bit[15:0],还有一个的点,就是图示下面有一个rw,表示这是一个读写寄存器,这里先解释具体作用,后面在介绍了其他寄存器再描述

        然后就是官方文档中的bit[15:0]的作用我们应该如何去理解。其中0-15位都对应GPIO端口的一个引脚,例如我们使用的是GPIOA_ODR0,那么对应的GPIO端口就是PA0,以此类推GPIOB_ODR1,GPIO端口就是PB1

        下一段的信息是,端口输出数据,也就是ODR寄存器中的每一位值,决定了相应引脚的输出电平。如果某一位为1,则输出为高电平,如果某一位为0,则输出为低电平。 
        如果我把GPIOA_ODR0设置为1,那么这个引脚就是高电平,反之如果设置为0就是低电平
        关于(y=0......15)对应的就是端口号,也就是0到15这个没什么好说的

        "这些位可读可写并只能以字(16位)的形式操作"首先这里再次强调这是一个16位的寄存器,在这段话中它也提到了是可读可写的
        只能以字(16位)的形式操作,意味着只能一次性读取或者写入整个16位的ODR寄存器,不能单独的读取或者写入ODR寄存器的某一位

        GPIOx_BSRR(x = A..E),可以分别对各个ODR位进行独立的设置/清除。x也就是可以对应选择GPIOA或则和GPIOB
        分别对各个ODE进行独立的设置/清除,这个点留到之后讲解因为会和其他的寄存器产生关联

        总而言之,ODR寄存器是一个16位的寄存器,可以用于控制GPIO端口的输出电平,设置为1为高点平,设置为0为低电平,目前主要的作用就是这样

        2. 端口位设置/清除寄存器(GPIOx_BSRR)(x=A..E)

        此寄存器是端口位设置/清除寄存器,如下图[31:0]都是有效位,但是所有的位下面都是w,表示这是一个只写寄存器,没有被读取功能
        

        简单来讲BSRR一个32位的寄存器,用于控制GPIO端口的输出,分别分为bit[31:16]和bit[15:0],按照简单理解就是,这个寄存器既可以控制端口输出高电平,也可以控制端口输出低电平


        这里讲解到BSRR的时候就要引出到之前没有了解到的一个概念,向BSRR寄存器写入值(例如0x003)后,硬件会立即更具掩码更新ODR寄存器,意思就是BSRR会将参数直接传输给ODR寄存器。
        也就是说为什么BSRR是只写寄存器,因为它本身不存储任何值,写入操作完成后BSSR内部的值会恢复为0(即使尝试读取此寄存器也会得到未定义的值或者0),下面我们具体讲解

        位31:16(BRy),这些位只能写入并只能以字(16位)的形式操作,这些16位是用于清除ODR寄存器中相应位为0(低电平)
        如果向BRy某一位写入0,ODR寄存器的相应位保持不变,如果向BRy的某一位写入1,则ODR寄存器的相应位被设置为0(低电平),但是如果同时向BSRR寄存器的低16位和高16位 ,则以低16位(BSy)的设置优先

        而15:0(BSy),用于设置ODR寄存器中相应位为1(高电平),和上面的类似,如果向BSy的某一位写入0,则0DR寄存器的相应位保持不变,如果向BSy的某一位写入1,则ODR寄存器的相应位被设置为1

        3. 端口位清除寄存器(GPIOx_BRR)(x=A...E)


        这个寄存器的功能如上图,那么从如上信息就可以看出,这个端口位清除寄存器,用于设置某个端口为低电平
        但是本质上还是在操作ODR寄存器,因为此寄存器也只有写入的功能,没有读取的功能,在写入值后还是把数据传输给ODR寄存器

        但是这个寄存器在之后很多的芯片中都被优化掉了,所以如果要对某个位进行单独的设置,所以还是可以使用BSRR

三. 实验验证

        借助博主最近正在学习的一段代码,首先接上Stlink后,给板子通电进入,然后点击上面的Start/Stop Debug Session,进入调试模式

       

        那么我们如何查阅寄存器的值,进入调试模式后,点击左上角的View

        然后进入System_Viewer,然后点击自己想要查考的寄存器,比如这里博主想要查找GPIOB_ODR寄存器,那么就在这里选择GPIOB

        点击后如下图,右栏可出现,和GPIOx相关的寄存器,其中就包含上面我们讲解过的ODR、BSRR、以及BRR寄存器
        和我们上面讲解的一致,BSRR和BRR等特殊的寄存器,并不具备被读的功能,所以它们的值都是0的状态

        如上图我们可以看到ODR寄存器的值是0X00000010,按道理来说刚开始我们并没有设置任何引脚的电平为高,寄存器这里为什么会显示值
        有些引脚可能是特殊位,所以刚开始的时候可能就被设置了值,例如这里的GPIOB_ ODR寄存器,就可以看出是PB4引脚被设置为了高电平,我们可以去看一下原理图

        

        是引脚PB4,JNTRST引脚,JNTRST引脚在默认状态下是高电平,所以在上面我们看到的ODR寄存器中ODR的值并不是全部为0
        所以在程序开始的时候,寄存器的值并不一定全部都是0,因为有些特殊的引脚比如上面JNTRST,以及SWDIO、SWCLK等引脚,也是全部置为1的,因为必须保持为高电平

        那么就根据博主的代码开始调试,刚开始的时候GPIOB->ODR寄存器的值是0X00000010, 

      
  
        在进行到如上这一步的时候,我们发现ODR寄存器的值产生了改变,变成了0x00000013,那么看一下,代码fLED_L中发生了什么


         这里进行了一个宏定义,然后操作了GPIO_Pin_0和GPIO_Pin_1,进行了位运算,那么我们要计算出结果,还是要去看GPIO_Pin_0和GPIO_Pin_1的参数
        

        代码执行的是fLED_L,那么我们计算一下0001和0011相或,得到的结果就是0x11,转换为十六进制就是3,因为结果是0X11但是前面讲解过,BSRR的值被写入后,会将数据直接传递给ODR寄存器,因为是低16位,所以是将引脚设置为1,所以ODR的0位和1位,也被设置为1,高电平
        那么这个宏定义的作用就是,控制PB0和PB1的引脚为高电平
        通过调试的方式我们读取到了寄存器的值,验证了我们的猜想,操作寄存器的值确实会让人觉得设计的非常的巧妙
        

        所以以上博客是博主在学习寄存器的过程中,学习到的一些知识点。如果有阅读者看到我的博客能够将寄存器理解的更好,那也是这篇博客的价值所在了


http://www.kler.cn/a/569564.html

相关文章:

  • Redis数据结构详解
  • linux-docker及docker-compose相关命令
  • 基于Springboot高校社团管理系统【附源码+文档】
  • 鸿蒙5.0实战案例:基于WaterFlow的页面滑动加载
  • InterHand26M(handposeX-json 格式)数据集-release >> DataBall
  • 【算法】3302. 表达式求值
  • nginx+keepalived负载均衡及高可用
  • react原理面试题
  • 大语言模型学习
  • 科技赋能筑未来 中建海龙MiC建筑技术打造保障房建设新标杆
  • 【Maven】入门介绍 与 安装、配置
  • Spring 源码硬核解析系列专题(十二):Spring Integration 的消息驱动源码解析
  • nio使用
  • 在 ASP.NET Core 中压缩并减少图像的文件大小
  • SQL命令详解之数据的查询操作
  • SpringBoot Maven快速上手
  • 量子关联特性的多维度探索:五量子比特星型系统与两量子比特系统的对比分析
  • Nodejs-逐行读取文件【简易版】
  • 【第十节】C++设计模式(结构型模式)-Flyweight( 享元)模式
  • Python爬虫:WebAssembly案例分析与爬取实战