STM32总结一 STM32三种点亮LED灯方式的不同之处(寄存器点亮,模板点亮和位带操作)_寄存器点亮led灯区别在哪-程序员宅基地

技术标签: STM32  

      STM32点亮LED灯有很多种方法。第一种是操作寄存器来点亮LED灯,(以GPIOC的第一个LED为例)操作的方法是首先在中文手册,首先要声明的是,手册里面看到的地址,都是字节,表示第多少多少个字节,然后这个数字对应一个字节位,所以每一个32位的寄存器占四个字节,找到block2(这个是外设区,所有的外设地址都在这个区)的基地址,然后加上第一段偏移地址,就越过APB1总线的内存区,到达了APB2总线这个区的基地址。然后再加上相对于APB2的偏移地址就可以定位出某个特定外设的基地址,这里所指的是GPIOC端口的基地址,然后再在这个端口外设基地址的基础上,加上相应的偏移地址,就可以定义出这个端口的寄存器地址,这些寄存器是紧紧的挨着的,一个接一个的,每个寄存器占四个字节。然后就参考手册的寄存器介绍图来编程,从而操作寄存器相应的位来实现引脚输入输出的不同,也就是配置寄存器实现相关的功能。(要注意的是:其实这里我们所定义的宏(也就是定义的地址)其实就是相关的寄存器的基地址,这个寄存器的全程还包括这个基地址以后的四个字节,其实这里定义的这个宏代表的就是这个寄存器,虽然它只用了每个寄存器的基地址来表示),其实都是一样的,每个数字对应着一个位。要让GPIOC的引脚0输出低电平的意思就是配置BSRR寄存器的BS0位为1。当然在配置这个之前,我们还需要了解GPIOC的基本结构(其实每个GPIO的结构都是一样的,这里用GPIOC引脚来举例子)和它的八种工作模式。这里需要着重说一下的是,除了模拟输入和模拟输出这两种工作模式用的是模拟量以外,其他的工作模式,如果是输入则从引脚处进去模拟量通过施密特触发器以后变成数字0和1,如果是输出则通过一个模拟量输出然后经过MOS管的处理变成了输出量为高电平和低电平,这里本质上就是把控制引脚输出高低电平的寄存器位设置为0或者1,然后会让相应的引脚输出高低电平。当然在配置寄存器让引脚输出高低电平之前,还需要配置其他的寄存器,让这个引脚位置有相应的工作模式和工作速度。这样就实现了LED点亮(本质上就是引脚位置输出了一个低电平接在LED灯的一端,LED灯的另一端接了一个VDD正电源,然后灯就亮了)。所有的点亮LED灯的操作说白了都是这个最基本原理,配置寄存器,输出低电平,点亮灯。在GPIO每个端口的某个引脚输出电平时,其实可以在输入端测出到底输出的是高电平还是低电平(测的原理就和输入原理一样)。
     第二种方式用的是固件库模板点亮LED。这种方法的本质和第一种是一样的都是操作寄存器的位从而实现对应引脚输出不同的电平。使用这种方法首先需要创建一个模板,创建方式可以参考中文参考手册和开发攻略。然后再自己新定义一个函数,将用到的函数从已经定义好的库文件中调用出来即可。再在main.c函数中调用新定义的函数初始化寄存器即可。虽然与第一种方式不同,但实际上达到的效果是一样的(也就是说最后实现的配置结构是一样的,只是配置的方式并不相同)。

        第三种方法是位带操作。

STM32所基于的ARM Cortex-M3内核引入了一种新颖的“位带”技术(英文称为Bit
Band),这种“位带”技术将部分其片内的部分称为“位带区”的存储区域和另外一部分称为“位带别名区”的区域映射起来。一个比较完整的描述是:Cortex-M3的内部存储空间有2个“位带区”,分别称为“SRAM位带区”和“外设存储位带区”,各自位于SRAM区和外设存储区各自最低的1MBit空间;并有对应的2个“位带别名区”,分别称为“SRAM位带别名区”和“外设存储位带别名区”,每个别名区大小为32MBit。“位带”技术将两个“位带区”的每一位分别映射带对应的“位带别名区”的一个“字”(即32位)的最低位上。图1展示了这种关系:


图1


       图1中,左边的0x40000000表示“外设存储位带区”的起始地址,而右边的0x42000000则表示“外设存储位带别名区”的存储地址,0th Bit、1th Bit等表示从地址0x40000000依次往后的第0位,第1位等。右边的0x42000000表示STM32内部的“外设存储位带别名区”起始地址,而下面的0x42000000 – 0x420000010、0x42000010 – 0x420000020等则表示从地址0x42000000依次往后的第1个、第二个“字”空间。在此要注意到的是,STM32作为一款32位控制器,其数据总线当然是32位的,但其内部存储空间不仅支持32位存取,同时也支持8位(字节)、16位(半字)存取方式,因此其内部存储空间是按照最小存取长度(8位)来对齐的,以图1中的0x42000000 – 0x420000010为例,其存储空间的排列情况如下图2所示。假设想这段空间内写入数据0x12345678,则实际内容(假设是小端存储格式)如图3所示。



图2                                                                                                                                图3


        8位长度的对齐方式决定了用户通过应用程序操作存储空间的最小长度为8位,亦即1个字节。因此如果要单独对某一“位”进行操作,则必须使用上文中所讲述的办法。
但通过这种“位带”技术进行存储空间的映射后,可以很轻易快捷的实现位操作。当对“位带别名区”的某一个“字”空间的最低位进行清除操作时,则对应的“位带区”所对应的“位”即会被清除,反之当对“位带别名区”的某一个“字”空间的最低位进行置位操作时,,则对应的“位带区”所对应的“位”也会被置位。这样一来,前文所讲述的“读出——修改——写入”就变成了只有“写入”的过程,这是一种非常典型的空间换时间的做法。也许有读者会疑问,这样岂不是损失掉了2个32MBit的存储空间?答案是这部分存储空间是通过映射技术“虚拟”出来的,STM32片内的这部分地址空间并没有物理存储介质存在。
         下面通过一个简单的例子讲述如何实现STM32微控制器平台上的“位带”技术实现一个简单的点亮发光二极管的操作。其中发光二极管使用STM32的PA4引脚的输出高电平点亮,则只要在PA4引脚输出一个高电平,即可点亮该发光二极管。
         通过查阅STM32的开发手册可以知道,要在PA4引脚输出高电平,则只需要在初始化完毕GPIOA设备之后对GPIOA的ODR寄存器的第4位写入一个“1”即可。这个目的很简单,重点是如何计算ODR寄存器的第4位在“位带别名区”中所对应的“字”空间地址。获取该地址的过程如下图4所示。

图4


                事实上有了前文的描述,相信图4是比较容易理解的。图中自上往下最终推算出了GPIOA的ODR各个位的“位带别名区”的地址,可以看到ODR寄存器的第4位所对应的“字”空间地址为0x42210190。从STM32的开发手册上也可以获取“位带别名区”的字空间所对应的“位”:
bit_word_addr = bit_band_base + (byte_offset×32) + (bit_number×4)
上述公式中,bit_word_addr表示“位带别名区”字空间,bit_band_base表示对应的“位带区别名区”起始地址,byte_offset表示“位”在“位带区”中的字节偏移地址,bit_number则表示“位”在对应“位带区”字节中的位置。
         以对GPIOA的ODR寄存器的第4位写入一个“1”为例,首先要找到ODR寄存器的第4位的“位带区”起始地址,字节偏移地址和在字节中的位置。其中“位带区”起始地址已知为0x42000000,而字节偏移地址由在图4找出为0x0001080C(注意是此处偏移地址,不是图中的绝对地址),同时位置为第4位,因此可以套用上述公式计算对应的“字空间”
bit_word_addr = 0x42000000 + (0x0001080C × 32) + (4 × 4) = 0x42210190
可知可图中推算的结果一致。因此,只要向地址为0x42210190的空间写入“1”即可点亮发光二极管。



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wise18146705004/article/details/79991539

智能推荐

vue自定义组件,ElementUi表单校验v-model不能即时生效的解决方法_elmentui为什么不能使用validatefield-程序员宅基地

文章浏览阅读5.6k次,点赞4次,收藏7次。vue自定义组件,ElementUi表单校验v-model不能即时生效的解决方法前言核心解决代码完整代码父组件子组件前言上篇文字我们介绍了vue自定义组件并使用v-mode实现双向绑定,当我们做form组件的时候经常要使用表单校验,但在使用ElementUi表单校验时,有时候校验v-model不能即时生效,如下图:其中子组件为一个输入框,父组件使用ElementUi校验子组件输入的值,我们..._elmentui为什么不能使用validatefield

php 运行方式 cgi,fastcgi,php-fpm的区别与联系_php-cgi 方式 和 php-fpm 方式差别在哪里-程序员宅基地

文章浏览阅读645次,点赞3次,收藏2次。刚开始对这个问题我也挺纠结的,看了《HTTP权威指南》后,感觉清晰了不少。首先,CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者。web server(比如说nginx)只是内容的分发者。比如,如果请求/index.html,那么web server会去文件系统中找到这个文件,发送给浏览器,这里分发的是静态数据。好了,如果现_php-cgi 方式 和 php-fpm 方式差别在哪里

Http failure response for (unknown url): 401 From Simple Intercept-程序员宅基地

文章浏览阅读6.6k次。1、问题现象及背景和后台配合做一个验证码功能,前端直接以一个get请求获取验证码数据。报该错误Http failure response for (unknown url): 401 From Simple Intercept -->http://ng-alain.com/docs/auth"name2、原因前后台没有对齐,后台返回的直接是一个图片,不是数据。..._http failure response for

Android webview记住账号密码_webview记住密码-程序员宅基地

文章浏览阅读7.2k次。好累,不想说话。private void syncCookie(String url) { try{ CookieSyncManager.createInstance(this); CookieManager cookieManager = CookieManager.getInstance();_webview记住密码

项目 | Java+PhantomJs爬虫实战——半次元 下载高清原图_半次元原图提取-程序员宅基地

文章浏览阅读2k次,点赞2次,收藏8次。写在前面前段时间实习结束回来休息,某日闲逛无意间又打开了半次元,突然看见几个好漂亮的coser小姐姐,就想存个图片当壁纸(づ ̄3 ̄)づ╭~然而又发现,很多小姐姐都设置了作品禁止保存或者是右下角带水印身为一个重度强迫症患者,默默打开浏览器,看看能不能偷鸡扒到原图。。。开始之前本文旨在学习交流,希望所有阅读的小伙伴们清楚以下几点:\color{#FF0000}{本文旨在学习交流,希望所..._半次元原图提取

C++ unordered_map-程序员宅基地

文章浏览阅读2.1w次,点赞10次,收藏31次。转载自这里目录查找元素迭代器容量修改操作通接口哈希策略观察器std::swap(std::unordered_map)std::erase_if(std::unordered_map)简介本篇博客介绍C++常用的无序关联容器unordered_map。unordered_map是C++11正式加入的对hash_map的官方实现(之前标准C++没有hash_map的官方实现,我们使用的STL的hash_map并不是官方的)。从名字可以看出这个结构是无序的,底.._c++ unordered_map

随便推点

【nexus】nexus : mac 安装 nexus_nexus4 mac-程序员宅基地

文章浏览阅读1.1k次。1.美图2.概述2.1 原理nexus的私服原理就不多说了,直接上一幅网图吧。2.安装2.1 下载安装在保证安装jdk 1.7+,去nexus官网下载nexus(http://www.sonatype.com/download-oss-sonatype) 最新版本解压zip文件,配置nexus下bin目录全局变量 打开.bash_profile添加如下export NEXUS_..._nexus4 mac

OpenJPA (7)-程序员宅基地

文章浏览阅读323次。10 Miscellaneous Features10.1 Restoring State JPA规范要求不应该使用rolled back objects,但是这些对象在OpenJPA中是有效的。可以通过配置openjpa.RestoreState 属性来控制是否将对象的状态回滚到事务前的状态。它有以下可选值:none: 不回滚对象状态,但是对象变成hollow,在下次访问的时..._openjpapersistence.cast转换异常

Spring Boot 使用 Spring Security 后无法 POST 提交数据解决方法_springsecurity将表单提交改成json的post提交-程序员宅基地

文章浏览阅读1.6w次,点赞3次,收藏18次。【问题描述】项目使用的是 spring-boot + spring-security,页面用了 thymeleaf 模板页面代码如下: username: password: Submit登录操作代码:/** * 登录操作; * * @param userName 用户名; * @param password 密码;_springsecurity将表单提交改成json的post提交

基于InnoDB索引主键策略_innodb 字符串做主键-程序员宅基地

文章浏览阅读699次。1、建议采用自增长int型为主键,主键的数据应该与应用无关,不建议采用字符串作为主键。因为采用数字作为主键可以保证数据行是按照顺序写入,但是采用字符串为主键可能导致随机写入,进而导致数据的频繁移动,甚至导致页分裂影响性能。InnoDB页分裂的最大填充因为为15/16。 2、使用字符串作为主键的缺点: 2.1、由于字符串作为主键是随机写入,所以可能写入的目标页已经刷新到了磁盘中并从缓存_innodb 字符串做主键

Tensorflow报错“Could not find ‘cudart64_6.dll”_tensorflow报错cuda sm86-程序员宅基地

文章浏览阅读2.2w次。声明:我使用的版本tensorflow-gpu==1.4.0CUDA (release 8.0, V8.0.60) 8.0版cudnn(6.0)但是最近在使用tensorflow时,突然报错 OSError: [WinError 126] 找不到指定的模块/Could not find ‘cudart64_6.dll’ 原因:在tensorflow调用NVIDIA时缺..._tensorflow报错cuda sm86

Linux下载安装mysql5.7版本教程最全详解_linux mariadb5.7安装包-程序员宅基地

文章浏览阅读5.7k次,点赞8次,收藏48次。linux下安装mysql服务_linux mariadb5.7安装包

推荐文章

热门文章

相关标签