打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
为你的STM32芯片手写一个外设库

为你的STM32芯片手写一个外设库,开始!

STM32库开发实战指南 PDF+源码,你也可以看看这里的东西。

寄存器来讲是绝对的地址,在这个大的地址段里面如果操作这个地址,就是这个寄存器。后面的偏移我觉得是一种相对的地址,基址+变址,就好像是数组一样,只要找到首元素就行。

x是一个占位符号,后面是可以填入的值,这个值也说明,GPIO的每一个都有这样的寄存器。

注意的是有一个地址叫偏移地址,是相对于GPIO这个外设的基地址的偏移量

在28页

这就是位表

紧接着的是本寄存器的位表,表中列出它的0-31 位的名称及权限。表上方的数字为位编号,中间为位名称,最下方为读写权限,其中w 表示只写,r 表示只读,rw 表示可读写。本寄存器中的位权限都是w,所以只能写,如果读本寄存器,是无法保证读取到它真正内容的。而有的寄存器位只读,一般是用于表示STM32外设的某种工作状态的,由STM32 硬件自动更改,程序通过读取那些寄存器位来判断外设的工作状态。

这也好理解,你一个复位的寄存器,你想读说明东西出来。

具体的定义在这里

32个位,每一位是什么意思,位功能说明很重要了。

位功能是寄存器说明中最重要的部分,它详细介绍了寄存器每一个位的功能。

例如本寄存器中有两种寄存器位,分别为BRy 及BSy,其中的y 数值可以是0-15,这里的0-15 表示端口的引脚号,如BR0、BS0 用于控制GPIOx 的第0 个引脚,若x 表示GPIOA,那就是控制GPIOA 的第0 引脚,而BR1、BS1 就是控制GPIOA第1 个引脚。

其中BRy 引脚的说明是“0:不会对相应的ODRx 位执行任何操作;1:对相应

ODRx 位进行复位”。这里的“复位”是将该位设置为0 的意思,而“置位”表示将该位设置为1;说明中的ODRx 是另一个寄存器的寄存器位,我们只需要知道ODRx 位为1 的时候,对应的引脚x 输出高电平,为0 的时候对应的引脚输出低电平即可。

所以,如果对BR0 写入“1”的话,那么GPIOx 的第0 个引脚就会输出“低电平”,但是对BR0 写入“0”的话,却不会影响ODR0 位,所以引脚电平不会改变。要想该引脚输出“高电平”,就需要对“BS0”位写入“1”,寄存器位BSy 与BRy 是相反的操作。

这种东西一次肯定你也学不懂,反正就知道这个东西是开关就行,开关就是控制的作用,只不过就是写的方式而已了。

其实就点灯什么的,可以不用标准库,我们知道,操作GPIO就是在地址线的地址上面用指针进行取指,所以我们一开始可以自己进行一个封装。

基地址就是开始,然后APB就是+基址,然后AHB也是一样的,就是地址变了。

GPIO其实是一种低速的设备,在APB上面挂着,也就是APB+基址就到了GPIOB的地址上面。

GPIOB的基址上面+偏移就是这个GPIO组上面的对应的寄存器的操作。单纯的看是一个地址,然后就要用个指针强转嘛。接着*再让它方便的使用,接着加个好看的名字,CRL,封装好啦!

来操作一下我们的寄存器好不好~

#define GPIOB_BSRR    *(unsigned int*)(GPIOB_BASE+0x10)

具体操作的时候,继续转指针。

BSRR是对一个位的操作

因为如果对寄存器的操作,就是要不停的看各种定义。

GPIO的寄存器就这么多

很多时候要操作GPIO前要先看看状态是什么?

直接把这个地址转出来,取指针就好了,然后把他和temp联系在一起。

目前为止,我们已经完成了GPIO的单个封装,但是你说100多个IO,每个都写一次?不现实~~~我们要想办法就写一个。

使用结构体进行一次封装是不是比较好?不过不是是不是的问题,除了结构体还有啥???

先把我们的数据类型改个名字

因为每次寄存器的功能位是固定的,那就可以写一起unsigned int。

这段代码用typedef 关键字声明了名为GPIO_TypeDef 的结构体类型,结构体内有7 个成员变量,变量名正好对应寄存器的名字。C 语言的语法规定,结构体内变量的存储空间是连续的,其中32位的变量占用4 个字节,16 位的变量占用2 个字节,具体见图GPIO_TypeDef 结构体成员的地址偏移。

就是这样的

也就是说,我们定义的这个GPIO_TypeDef ,假如这个结构体的首地址为0x4001 0C00(这也是第一个成员变量CRL 的地址),那么结构体中第二个成员变量CRH 的地址即为0x4001 0C00 +0x04,加上的这个0x04,正是代表CRL 所占用的4 个字节地址的偏移量,其它成员变量相对于结构体首地址的偏移。

这样的地址偏移与STM32 GPIO 外设定义的寄存器地址偏移一一对应,只要给结构体设置好首地址,就能把结构体内成员的地址确定下来,然后就能以结构体的形式访问寄存器。

#define  GPIOB_CRL              *(unsigned int*)(GPIOB_BASE + 0x00)#define  GPIOB_CRH              *(unsigned int*)(GPIOB_BASE + 0x04)#define  GPIOB_IDR              *(unsigned int*)(GPIOB_BASE + 0x08)#define  GPIOB_ODR              *(unsigned int*)(GPIOB_BASE + 0x0C)#define  GPIOB_BSRR             *(unsigned int*)(GPIOB_BASE + 0x10)#define  GPIOB_BRR              *(unsigned int*)(GPIOB_BASE + 0x14)#define  GPIOB_LCKR             *(unsigned int*)(GPIOB_BASE + 0x18)

来看看我们的工作好不好!!!,这个是封装前。

这是我们的改写的东西。现在就好像是一个,我想想怎么形容,就好像是我们定下了规律,但是还没有使用。

接下来就是用了:

先创建一个GPIO的结构体,给个名字。

这段代码先用GPIO_TypeDef 类型定义一个结构体指针GPIOx, 并让指针指向地址GPIOB_BASE(0x4001 0C00),使用地址确定下来,然后根据C语言访问结构体的语法,用GPIOx->ODR 及GPIOx->IDR 等方式读写寄存器。

最后,我们更进一步,直接使用宏定义好GPIO_TypeDef 类型的指针,而且指针指向各个GPIO端口的首地址,使用时我们直接用该宏访问寄存器即可。就是后面的BASE地址这些通过前面的GPIO的类型来重构,没这样写以前是一堆连续的地址,但是这样被结构体转换后,就赋予了独特的意思。

我们把这写GPIO组都这样写一下,就算把GPIO封装完了

接着就是操作了,我们知道,寄存器彼此之间有32位。要写32个不同的01.现在就是这样的操作。

那我们就知道就行了,ST给我们搞好啦!ADC,DAC也是这样的。

在操作寄存器的时候,一次是32位,我们大多数时候也不是都变,就改几位,这个时候就位操作了。

比如我们的某位清零。先左移2位,接着取反,接着与运算就改了一位。

把几个连续的位清0.

然后就是写入了。

这样就写入了

还有对位取反的操作。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
STM32学习笔记——GPIO之从库函数到寄存器
stm32标准库对寄存器地址的封装
STM32笔记:什么是寄存器
STM32 GPIO
STM32寄存器深入分析
STM32单片机中C语言操作寄存器的原理
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服