欢迎光临散文网 会员登陆 & 注册

野火STM32学习笔记(构建库函数模型第四节课)

2023-06-25 16:55 作者:是晃晃叔叔  | 我要投稿

紧接着第三节课的内容

        上一节课我们已经在函数的头文件里,描述了GPIO端口是如何通过结构体和枚举来定义和配置它的工作模式,工作速度以及端口号的。尤其对工作模式枚举方式的讲解做了具体的说明。知道了决定GPIO口的四种输入与输出模式的16进制数是如何得来的。这一切都是为了在stm32f10x_gpio.c中编写GPIO的初始化函数做准备的。

GPIO初始化函数的编写

这段代码非常的长,我就直接复制官方库里的函数,来慢慢讲解它。这段代码先截图给大家

这个图这节课要来回翻看

将近100多行的代码。。。。。没关系这里面有注释,只要大家认真耐心看一定可以看明白。

初始化的时候,相当于配置main.c函数里面的这俩行(控制端口配置低寄存器CRL),如图:

画红色圈圈的两行的工作,就可以由第一张图那个一大段程序来完成。我们想要使用这个函数,就要在头文件里面定义一下,每一个新写的函数都要这样做!!!!如图:

火哥在这里翻车了两三分钟hhhhh

目光转移到stm32f10x_gpio.c这个C文件里的函数上,首先它有两个形式参数:GPIO_TypeDef* GPIOx和GPIO_InitTypeDef* GPIO_InitStruct。大家看到这个可能会云里雾里,这两个参数干啥用的?请看下面。

对于GPIO初始化函数的形参1讲解

        第一个形式参数就是决定我们对哪一个GPIO口进行初始化的,那个GPIOx是一个很明显的特征,这个语句的意思是定义一个指针变量,指针的首地址是名字叫GPIO_TypeDef这个结构体下面我们将会看到它在哪)的首地址,这个参数我们只需要填入如GPIOA,GPIOB,GPIOC等等这些指针就可以。为什么说GPIOA,GPIOB,GPIOC是指针,答案可以在官方标准库函数的头文件stm32f10x.h里找到答案,如图:已经都是宏定义封装好的指针(这些指针干啥用的不懂的,看我第一篇文章


对于GPIO初始化函数的形参2(GPIO_InitTypeDef* GPIO_InitStruct)讲解

第二个参数GPIO_InitTypeDef* GPIO_InitStruct,我们不妨来看一下他们在main.c文件里面是如何使用的,先把这俩行代码删除。

我们先定义一个GPIO初始化结构体变量GPIO_InitStructure如图所示

这个语句有两点非常需要我们重视,第一点它是怎么定义一个GPIO初始化结构体的:这个GPIO_InitTypeDef ,存在于stm32f10x_gpio.h这个头文件之中,位于封装GPIO工作状态的结构体的末尾,如图所示:

GPIO_InitTypeDef,这在C语言当中相当于这个结构体的名字。而在main函数中,它的后面加上GPIO_InitStructure的作用就是声明一个结构体,名字是GPIO_InitStructure。结构体原型由名字叫GPIO_InitTypeDef的结构体 确定。在之前的stm32f10x_gpio.h头文件里设置完了GPIO_InitStructure里面的内容是GPIO_InitTypeDef的 )里面的内容后
在初始化函数GPIO_Init (GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_InitStruct)里面调用,比如初始化pa口,就是GPIO_Init (GPIOA, &GPIO_InitStructure)。

       因为形式参数GPIO_InitTypeDef* GPIO_InitStruct(下面我简称形参2)也是一个指针变量,所以它只能是有效的指针和地址。由于第一个形式参数填入的GPIOA/B/C.......是已经封装好的地址,因此看起来不像一个正常的地址(上文已经解释)。因此,形参2要正常地进行取结构体(GPIO_InitStructureGPIO_InitTypeDef)地址的操作,才会写成GPIO_Init (GPIOx, &GPIO_InitStructure)看到最后大家就能知道在哪应用的了。

       第二点,这个是C99版本C语言的一个默认的规定,即定义的变量必须在第一个大括号之后,因此刚才定义的GPIO_InitTypeDef GPIO_InitStructure必须放在开头第一个大括号以后,前面不能以其他语句


        因为前面的的语句(之前几节课的内容)用#if 0.......#else语句相当于注释了,我们只执行#else......#endif之间的语句,因此GPIO_InitTypeDef GPIO_InitStructure实际上是跟在第一个大括号后面。不过听说后来的C语言标准没那么严格了,有些版本的Keil 编译器不会报错。

配置结构体成员

我们在main.c中配置结构体GPIO_InitStructure的成员,输入GPIO_InitStructure.(最后面有一个点千万别忘了)如下图:

配置的三个选项就出来了,可以看到它们本是结构体GPIO_InitTypeDef的成员,我们选择GPIO_Pin,再接上= GPIO_Pin_0;分号结束一个C语言语句,如图


再配置速度和工作模式,它们的值可以在stm32f10x_gpio.h里面找到


我们配置为推挽输出模式和50MHZ的工作速度(目的还是为了点亮LED绿灯)就在main.c里面这样写:

该结构体配置完成以后,我们要将这些值写入寄存器CRL(端口配置低寄存器)中,这时就调用GPIO_Init这个函数了,我们要配置GPIOB就这样写:GPIO_Init(GPIOB, &GPIO_InitStructure);

这样我们配置CRL寄存器的工作就完成了,非常直观明了。配置的哪一个口,什么模式,速度。比之前那两行代码容易理解多了。

直接配置寄存器的话非常晦涩

这一节课的上下两部分内容就结束了,可以看到我们正在由寄存器编程向固件库编程推进。

端午假期摸了几天🐟,不好意思哈。

下一节课,我会把GPIO_Init()函数(100多行那个)里面的内容简单讲解一下。

野火STM32学习笔记(构建库函数模型第四节课)的评论 (共 条)

分享到微博请遵守国家法律