以下文章来源于:公_众_号开源电子网 读取更多技术文章,请扫码关注
如何从HAL库中找到寄存器的蛛丝马迹 对于初学者来说,有时候知其然而不知其所以然,换句话来讲,知道这个东西是这样子操作,但是不知道为啥这么做。虽然老话有讲,不管黑猫白猫,捉到老鼠就是好猫,但是某些时候我们还是得需要知道为啥这么干。 举个栗子,配置一个GPIO去控制一个LED灯。 寄存器版本的代码:
这里就涉及两个与GPIO相关的寄存器:GPIOx_CRL,GPIOx_ODR。通过注释我们也知道了这两个寄存器的功能。 为什么这么赋值呢?下面就先看一下这两个寄存器的详情。 首先是端口配置低寄存器(GPIOx_CRL),因为我们配置的GPIO口为PB5,所以是看端口配置低寄存器。假如是GPIO8~GPIO15,我们就需要查看GPIOx_CRH。 我们是用PB5来控制LED灯,所以说模式要设置为推挽输出模式,速度可以设置为50MHz。所以说我们对Bit[23:20]赋值0x3。
通过上面,已经把PB5设置好了,这里就相当于我们理解中的初始化成功。初始化成功后,那么就是对该GPIO口的控制了,让它输出高电平还是低电平,这里使用端口输出数据寄存器(GPIOx_ODR)去实现了。 对ODR5位置1或者清0就是控制GPIO输出高电平还是低电平了,具体根据原理图查看才知道,赋值0还是1能让LED亮。当然我们的LED灯设计是低电平点亮,高电平熄灭。初始化情况下,还是赋值1,让LED处于熄灭状态。
以上就是寄存器版本对GPIO口配置,我们可以很清晰的看到相对底层的操作。 我们再来看一下HAL库对GPIO的操作。
很明显,HAL库函数就是有封装了,标准库同样也是一样的。初始化一个外设,老掉牙的套路:定义一个外设结构体,并且对其成员进行赋值,然后调用HAL_XXX_Init函数完成。 GPIO初始化结构体哪里找呢?就在stm32f1xx_hal_gpio.h中已经定义好了,具体如下:
Pin就是引脚号,Mode就是模式设置,Pull就是上下拉设置(F1的话,输出模式不用设置),Speed就是速度设置。 我们是用PB5去控制灯,和寄存器版本一样的配置,模式是设置推挽输出,速度设置50MHz。 那么如何赋值?其实上面已经有图了,这里还是简单提一下吧。 gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; 怎么知道“GPIO_MODE_OUTPUT_PP”含义呢?如下图所示: 就是使用最为常用的操作“Go to Definition”去走到底查看这个宏代表的值,那么通过上图就可以知道“GPIO_MODE_OUTPUT_PP”为1。 同样的,查看“GPIO_SPEED_FREQ_HIGH”含义呢?如下图所示:
这个宏相对上一个宏再多跳转了一级,我们要以获得值为前提,所以说还没有见到我们熟悉的数字时,就需要一直“Go to Definition”,最终我们发现该宏是为3。 到这里还没有看到寄存器的操作,但是看到这个0x3的出现,我们现在已经有点底了。前面也说了对结构体成员赋值后,就可以调用初始化函数,这时候同样的Go to Definition。函数如下(经过处理):
解析过程如上图,经过漫长的兜兜转转,最终你会发现HAL库的实际依然是操作寄存器,对GPIOB_CRL进行0x3
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?