新建的led.c文件用于驱动GPIO引脚来点亮或者熄灭LED。按照GPIO使用的步骤,必须先初始化GPIO。初始化步骤如图3-22所示。
图3-22 GPIO初始化步骤
因为使用了固件库,初始化的大部分代码已经由ST完成,用户无须再编写复杂的驱动代码,只需调用固件库中的函数。使用固件库函数的方法有两种:一种方法是查看固件库代码,另一种方法是使用固件库帮助文件。
1.查看固件库代码
读者通过查看固件库代码,可以很清楚地知道固件库是如何封装各个结构体、如何构成函数的,但其缺点是阅读量比较大。作为初学者,应该学会查看代码,在分析代码的过程中结合帮助文件进行学习。
固件库包含了STM32的外设驱动,比如GPIO、ADC、SPI、I2C等。这些驱动都放到了工程模板的STM32F4xx_StdPeriph_Driver组中。需要使用外设时,在组中找到相应的“*.c”文件,即可查看外设的驱动函数。
以点亮LED为例,要使PF6输出低电平,确定要使用外设GPIO,因此在外设驱动组里找到stm32f4xx_gpio.c,如图3-23所示。将其打开,可以查看代码。如果要使用AD转换器转换模拟电压,这时就要使用外设ADC,意味着要使用ADC的驱动,于是打开stm32f4xx_adc.c进行查看,以此类推。
图3-23 查看stm32f4xx_gpio.c代码
每一个驱动文件的开头都有帮助说明。查阅这些帮助说明,可以快速地了解该驱动的作用,快速索引到相关函数的作用。
(1)打开总线时钟。
按GPIO初始化步骤,首先打开相应总线的时钟RCC,从帮助说明How to use的第一行可看到使能GPIO AHB Clock。使用函数RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx,ENABLE)进行设置。要找到这个函数可以用鼠标选择函数名,然后单击右键,在弹出的快捷菜单中选择“Go To Definition Of‘RCC_AHB1PeriphClockCmd’”,如图3-24所示。单引号内为需要寻找的函数名,单击之后,系统会跳转到该函数所在位置。查找函数都可以使用这个方法,如图3-25所示。
图3-24 查找RCC_AHB1PeriphClock Cmd函数
图3-25 RCC_AHB1PeriphClock Cmd函数
跳转到RCC_AHB1PeriphClockCmd函数,读者会发现该函数在stm32f4xx_rcc.c文件内,在函数前有函数的说明,包括用途brief、注意note、形参param和返回值retval。通过阅读,从@brief可以得知该函数用于开启和关闭AHB1外设时钟,@note提示复位后时钟默认是关闭的,要使用AHB1外设必须先打开时钟。要重点掌握@param形参和@retval返回值。该函数有两个形参,无返回值。第一个形参是外设的RCC寄存器地址,固件库不需要用户去记忆寄存器地址,因固件库已经将地址与寄存器名字映射完毕,用户只需填写寄存器名字即可。用户在@arg中可查看参数说明。固件库把所有的AHB1外设的RCC寄存器名字都罗列出来了,比如GPIOF的RCC寄存器名称是RCC_AHB1Periph_GPIOF。第二个形参可取ENABLE和DISABLE两个值,顾名思义,打开时钟时填写参数ENABLE,关闭时钟时填写参数DISABLE。
要打开GPIOF时钟,则编写函数如下:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
(2)定义GPIO初始化结构体。
继续回到帮助说明的第二项,可看到GPIO配置的说明:
(#)Configure the GPIO pin(s)using GPIO_Init()
即使用GPIO_Init()函数配置GPIO。用前面所述的方法可以找到GPIO_Init()函数,并查看其说明,如图3-26所示。
图3-26 GPIO_Init()函数
由说明可知,GPIO_Init()函数有两个形参:结构体类型的GPIOx与结构体类型的GPIO_InitStruct。这两个形参都是地址的形式。这两个结构体定义分别是GPIO_TypeDef与GPIO_InitTypeDef。用前面的方法通过右键找到这两个结构体定义,它们分别在stm32f4xx.h与stm32f4xx_gpio.h文件内,如图3-27所示。
(www.xing528.com)
图3-27 GPIO_TypeDef与GPIO_InitTypeDef结构体
GPIO_TypeDef在项目二中已经使用过,该结构体的作用是将GPIO的几个寄存器组织起来。在stm32f4xx.h文件中,使用查找功能,按【Ctrl】+【F】键,可查找到GPIO_TypeDef。可以找到对GPIOF基地址的映射,GPIOF已经是PF口寄存器结构体的首地址了,这一步骤固件库已经做好了,用户只需填入对应的外设名。图3-28列出的就是#define的外设名称,第一个形参只需填入GPIOx,x代表的是A,B,C,…,F,H。
图3-28 固件库使用GPIO_TypeDef对外设地址映射
GPIO_InitTypeDef结构体成员分别对应引脚、工作模式、速度、输出类型与上、下拉这些设置。这些设置用的结构体成员需要用户赋值,因此下面对使用的GPIO进行结构体定义:
GPIO_InitTypeDef GPIO_InitStruct;
此时结构体GPIO_InitStruct定义完成,成员有GPIO_Pin、GPIO_Mode、GPIO_Speed、GPIO_OType、GPIO_PuPd,这几个成员就是在项目二中介绍的GPIO的寄存器设置。
(3)配置GPIO结构体成员。
对结构体成员赋值完毕就完成了对GPIO的工作模式的设置:
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed=GPIO_Low_Speed;
GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
为了更好地编写程序,赋值时并不需要使用二进制数或者十六进制数,因为固件库已经将二进制数宏定义成英文单词了,这样使用起来非常方便。具体这些英文单词的定义在stm32f4xx_gpio.h文件内。比如GPIO_Mode_OUT,使用查找功能可搜索到“GPIO_Mode_OUT=0x01;”这条语句(图3-29)。根据图2-5的描述,01正是通用输出模式。其他英文单词的含义都以类似的方法进行定义或者赋值,与数据手册的二进制配置含义一致。
图3-29 GPIO_Mode_OUT的赋值
(4)初始化GPIO。
固件库处理GPIO初始化的函数是GPIO_Init()函数,在stm32f4xx_gpio.c文件中可以查找到,如图3-30所示。
图3-30 GPIO_Init()函数
从函数说明可以看出,该函数用于GPIO初始化。它有两个形参:第一个形参是GPIOx,x可以是A,B,…,K;第二个形参是GPIO_InitStruct结构体的首地址。具体函数的实现与项目二类似,这里不再阐述。
由于LED接在PF6引脚,结构体已经定义好,因此编写初始化函数如下:
GPIO_Init(GPIOF,& GPIO_InitStruct);至此,GPIO初始化完毕。
2.完成led.c文件
led.c文件完成的任务是做好GPIO初始化。最后的文件如下:
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。