文章目录
- 前言
- 一、LED的模块化
- 二、GPIO初始化详细解析
- 三、LED代码封装
- 总结
前言
本篇文章将带大家深入了解GPIO的配置,并带大家实现LED模块化编程。
一、LED的模块化
什么叫模块化编程?我的理解就是每一个模块都分别写成对应的.c和.h文件,有的人可能会问道为什么要这样写呢?这样写不是增加文件数量吗?其实模块化编程主要的好处就是代码看起来更加整洁,不会显得凌乱,而且方便移植。
在工程目录下新建Driver文件夹存放.h和.c文件。
在Driver目录下新建.c和.h文件
将driver_led.c和driver_led.h文件加入工程
把Driver的路径添加进来。
二、GPIO初始化详细解析
打开stm32f1xx_hal_gpio.c这个文件。
这里告诉了我们如何去初始化GPIO模块。
1.GPIO时钟初始化
看到下面这个注释就可以知道使能GPIO的时钟就使用下面这个函数
__HAL_RCC_GPIOx_CLK_ENABLE().
GPIOx就代表的是哪一组GPIO引脚,比如初始化的是GPIOB这一组引脚,那么这个函数就应该写成:__HAL_RCC_GPIOB_CLK_ENABLE().其他的也是一样。
Enable the GPIO APB2 clock using the following function : __HAL_RCC_GPIOx_CLK_ENABLE().
2.GPIO引脚选择,模式设置,速度设置,上下拉电阻设置。
HAL库中提供了GPIO_InitTypeDef这个结构体。
这个结构体一共包含了Pin,Mode,Pull,Speed。这四个参数。
typedef struct
{uint32_t Pin; /*!< Specifies the GPIO pins to be configured.This parameter can be any value of @ref GPIO_pins_define */uint32_t Mode; /*!< Specifies the operating mode for the selected pins.This parameter can be a value of @ref GPIO_mode_define */uint32_t Pull; /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.This parameter can be a value of @ref GPIO_pull_define */uint32_t Speed; /*!< Specifies the speed for the selected pins.This parameter can be a value of @ref GPIO_speed_define */
} GPIO_InitTypeDef;
pin:第几个引脚
Mode:
模式有下面这些模式可供选择,这里我们选择GPIO_MODE_OUTPUT_PP,推挽输出模式。
#define GPIO_MODE_INPUT 0x00000000u /*!< Input Floating Mode */
#define GPIO_MODE_OUTPUT_PP 0x00000001u /*!< Output Push Pull Mode */
#define GPIO_MODE_OUTPUT_OD 0x00000011u /*!< Output Open Drain Mode */
#define GPIO_MODE_AF_PP 0x00000002u /*!< Alternate Function Push Pull Mode */
#define GPIO_MODE_AF_OD 0x00000012u /*!< Alternate Function Open Drain Mode */
#define GPIO_MODE_AF_INPUT GPIO_MODE_INPUT /*!< Alternate Function Input Mode */
Pull:
上拉,下拉设置。
#define GPIO_NOPULL 0x00000000u /*!< No Pull-up or Pull-down activation */
#define GPIO_PULLUP 0x00000001u /*!< Pull-up activation */
#define GPIO_PULLDOWN 0x00000002u /*!< Pull-down activation */
Speed:
GPIO输出速度设置,这里我们只是点亮LED灯对GPIO的输出速度并没有很高的要求,这里选择低速即可。
像涉及到IIC协议等这些协议的时候对GPIO的输出速度会有一定的要求。
#define GPIO_SPEED_FREQ_LOW (GPIO_CRL_MODE0_1) /*!< Low speed */
#define GPIO_SPEED_FREQ_MEDIUM (GPIO_CRL_MODE0_0) /*!< Medium speed */
#define GPIO_SPEED_FREQ_HIGH (GPIO_CRL_MODE0) /*!< High speed */
使用HAL_GPIO_Init().这个函数将设置好的参数设置进GPIO对应寄存器,让这些设置生效。
Configure the GPIO pin(s) using HAL_GPIO_Init().
三、LED代码封装
这一部分代码还是很好理解的,而且都带有注释,这里就不作详细讲解了。
#include "driver_led.h"/** 函数名:void LedGpioInit(void)* 输入参数:无* 输出参数:无* 返回值:无* 函数作用:初始化LED的引脚,配置为上拉推挽输出
*/
void LedGpioInit(void)
{// 定义GPIO的结构体变量GPIO_InitTypeDef GPIO_InitStruct = {0};// 使能LED的GPIO对应的时钟LED0_GPIO_CLK_EN();LED1_GPIO_CLK_EN();GPIO_InitStruct.Pin = LED0_GPIO_PIN; // 选择LED0的引脚GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 设置为推挽输出模式GPIO_InitStruct.Pull = GPIO_PULLUP; // 默认上拉GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;// 引脚输出速度设置为慢// 初始化引脚配置HAL_GPIO_Init(LED0_GPIO_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin = LED1_GPIO_PIN; // 选择LED1的引脚GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 设置为推挽输出模式GPIO_InitStruct.Pull = GPIO_PULLUP; // 默认上拉GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;// 引脚输出速度设置为慢// 初始化引脚配置HAL_GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStruct);}
#ifndef __DRIVER_LED_H
#define __DRIVER_LED_H#include "stm32f1xx_hal.h"/********************** 引脚宏定义
**********************/
#define LED0_GPIO_PIN GPIO_PIN_5
#define LED0_GPIO_PORT GPIOB
#define LED0_GPIO_CLK_EN() __HAL_RCC_GPIOB_CLK_ENABLE()#define LED1_GPIO_PIN GPIO_PIN_5
#define LED1_GPIO_PORT GPIOE
#define LED1_GPIO_CLK_EN() __HAL_RCC_GPIOE_CLK_ENABLE()/********************** 函数宏定义
**********************/
/** LED亮灭函数宏定义
*/
#define ON GPIO_PIN_RESET
#define OFF GPIO_PIN_SET#define LED0(flag) HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, flag)
#define LED1(flag) HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, flag) /** 函数名:void LedGpioInit(void)* 输入参数:无* 输出参数:无* 返回值:无* 函数作用:初始化LED的引脚,配置为上拉推挽输出
*/
extern void LedGpioInit(void);#endif
总结
学会模块化编程是走像成功的必经之路。