上一节课我们已经完成了对GPIO端口复位和置位寄存器的初始化,这节课我们来对他进行一个完善的工作。完善工作很有必要,为什么呢?注意看如下代码段
(资料图片仅供参考)
前三行可以很清楚地看见我们操作的是GPIOB的CRL与CRH,以及RCC的APB2ENR寄存器,但是这些16进制数对于基础知识不好的同学容易看不明白。于是我希望可以把他们封装的更加简洁一点。
拿CRL这个GPIOx->CRL这个寄存器举例,我们来看一下技术手册中它的说明
可以看到如果想要操作这些寄存器的状态,我们要用两位二进制数代表(程序里面一般是用16进制操作)它的四种状态,操作起来麻烦,读者看起来也很抽象,尤其没有技术手册的时候更是不可能看明白的了。那我们能不能把这些需要16进制数进行|=和&=~操作的状态也如同上节课那样封装起来呢?答案是肯定的。
我们还是用到C语言的结构体进行封装,代码的思路如下,首先我们要确定具体是哪一个端口,接着要确定这个GPIO端口的工作速度,最后再设置它的工作模式。结构体代码如下图
之前的文章里我写到没有看见16位的结构体内定义的情况,这里就是了,对之前的疑问可以说是有了答案。之前定义的GPIO_Pin是16位的,因此这里也写的是16位。根据技术手册,可以看到输出模式有八种,输出速度只有有三种,16位的二进制数有65536种情况,为了防止编程时犯错误,我们希望把这些值限定在某个范围内。C语言里有一个叫做枚举的工具帮助我们完成这项工作,枚举的关键字叫做enum。
枚举的结果如下图所示
这里补充一些C语言的知识,大家看到枚举会感觉它和结构体很相似,但是注意枚举里面每一行结束是逗号,而结构体是分号。如果枚举的第一个对象赋值为1,那么第二个对象的赋值为1+1=2,后面是以此类推加1的,如上图工作速度枚举。如果对象的枚举值不是自加1的值,那么我们就要给每一个枚举值分别定义,如上图定义工作模式的枚举所示,它的对象每一个值都是根据技术手册来定义的。
这一部分因为理解起来较为困难,我单独拎出来着重讲解。首先我们看看技术手册里面关于工作模式的各种值的定义如下图:
可以发现都是00到11的二进制数,和枚举里写的不一样呀,而且输入输出怎么会是一样的值呢?答案我们只能去官方的固件库手册里面寻找。火哥已经把问题的答案总结为一张表格:
首先我们看,这张表格的16进制就对应的我们枚举里面的值,然后我们把它转化为2进制之后,既可以和右侧的配置一一对应了。
最右侧最低的两位都是0,其实这两个位对应的是工作速度,但是工作速度我们已经拿出来单独配置了,因此在确定工作模式的时候就把它们全部置为0,最后我们加上单独配置好的工作速度对应的值即可,加起来的值最终会写入控制寄存器。
还剩下的六位我们来看看它是如何配置的
位于第三位和第四位bit2和bit3,它们的值刚好对应图六中输入/输出模式的值,因此这两位就是控制GPIO引脚的输入模式和输出模式分别有四种,不过上拉和下拉输入有点特殊,下面会讲到。再看第五位bit4,它的作用就是区分输入还是输出,0为输入1为输出就是那么简单。把目光转到第六位和第七位上来,输入模式中有上拉和下拉输入,根据技术手册截图图六可以看到这两个都是10,在图七里的三四位都是写成了00,所以说三四位不好直接定义是上拉还是下拉,于是就在第六位和第七位下文章了,01代表下拉,10代表上拉。最后最高位都为0。
总结一下其实这相当于一个算法了,确实挺有难度的。
这节课的内容先到这里,下节课我们来讲,这么复杂的算法怎么用C语言,写到配置GPIO的C文件stm32f10x_gpio.c里面去。
Copyright 2015-2022 欧洲日报网 版权所有 备案号:沪ICP备2022005074号-23 联系邮箱: 58 55 97 3@qq.com