如何在阿里云自主建网站,优化大师是什么意思,门户网站建站注意事项,wordpress网关支付一、前言 学习STM32一阵子以后#xff0c;相信大家对STM32 GPIO的控制也有一定的了解了。之前在STM32 LED的教程中也教了大家如何使用寄存器以及库函数控制STM32的引脚从而点亮一个LED#xff0c;之前的寄存器只是作为一个引入#xff0c;并没有深层次的讲解#xff0c;在教…一、前言 学习STM32一阵子以后相信大家对STM32 GPIO的控制也有一定的了解了。之前在STM32 LED的教程中也教了大家如何使用寄存器以及库函数控制STM32的引脚从而点亮一个LED之前的寄存器只是作为一个引入并没有深层次的讲解在教程中也没让大家有太多的了解。既然学习STM32有一段时间了那我们能不能从现象推导到本质去了解一下STM32 引脚控制的本质原理。那么本次教程就来为大家讲解一下STM32引脚驱动的三个关键寄存器BSRR、BRR、ODR相信看了本次教程以后你对STM32会有更深层次的理解。如果你准备好了那就让我们开始吧
二、谁适合本次教程 因为已经涉及到寄存器的操作与讲解了所以请学习本次教程的小伙伴需要具备一定的STM32基础以及对十六进制转二进制比较熟悉。
三、资料的准备 本次使用STM32F103C8T6进行演示所以请大家自己准备一块STM32F103的开发板。本次教程中我们需要去翻阅STM32F103的手册所以大家准备一份STM32F103的数据手册相信学习过一阵子STM32的小伙伴应该都有这个手册吧这里我就不放了。
四、BSRR、BRR、ODR寄存器讲解 在我们日常的代码或者一些模块的代码中可能经常会看到下面这样的写法
GPIOC-BSRR0x00002000;
又或者是这种写法
GPIOC-ODR0x00002000;
我们可以很明显的看到这些写法都是在控制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-APB2ENR0x00000010;GPIOC-CRH0x00300000;GPIOC-BSRR0x00002000;while(1){}
}
#include stm32f10x.h
int main(void)
{RCC-APB2ENR0x00000010;GPIOC-CRH0x00300000;GPIOC-ODR0x00002000;while(1){}
}
但是最后的最后仍然建议大家在操作引脚时不直接操作ODR虽然我们可以通过读-改-写的方法保留原本的值并且写入新值但是这样会增加我们的代码量并且增加出错的概率。
五、结语 以上就是我对GPIO相关的寄存器的一些见解如果有讲得不对的地方还请大家指正最后感谢大家的观看