• STM32F407之GPIO


    因为有新人需要学习STM32的应用,一遍遍讲又感觉效率低,时间上大大的浪费了,遂打算写下一些笔记供其他人观看、学习和纠错,同时也巩固下基础。近期用到STM32F407VET6的开发板,所以用到的标准库都是F4系列的,不过没关系,不管是F4还是F103或者其他系列的,原理都是一样的。


    今天主要总结的是关于GPIO的配置,GPIO的定义是General Purpose Input Output (通用输入/输出),也是STM32最基础和最常用的配置。这里假设事先已经下载好STM32F4的标准库文件以及配置好STM32的开发环境了,如果还不会的可以先去百度一会。

    使能时钟

    要想使用GPIO,我们首先需要初始化GPIO的时钟。

    从芯片手册的截图中我们可以看到,所有GPIO的时钟都是由AHB1总线提供的,这里暂且不用管STM32的时钟分类,关于STM32时钟有时间会专门作介绍。所以这里GPIO时钟的初始化就一行代码带过

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    

    结构体声明

    在STM32F4标准库文件中有一个“stm32f4xx_gpio.h”的头文件,里面包含了GPIO配置的所有信息,我们可以一步一步来分析如何配置满足要求的GPIO。首先找到GPIO初始化结构体声明如下:

    /** 
      * @brief   GPIO Init structure definition  
      */ 
    typedef struct
    {
      uint32_t GPIO_Pin;              /*!< Specifies the GPIO pins to be configured.
                                           This parameter can be any value of @ref GPIO_pins_define */
    
      GPIOMode_TypeDef GPIO_Mode;     /*!< Specifies the operating mode for the selected pins.
                                           This parameter can be a value of @ref GPIOMode_TypeDef */
    
      GPIOSpeed_TypeDef GPIO_Speed;   /*!< Specifies the speed for the selected pins.
                                           This parameter can be a value of @ref GPIOSpeed_TypeDef */
    
      GPIOOType_TypeDef GPIO_OType;   /*!< Specifies the operating output type for the selected pins.
                                           This parameter can be a value of @ref GPIOOType_TypeDef */
    
      GPIOPuPd_TypeDef GPIO_PuPd;     /*!< Specifies the operating Pull-up/Pull down for the selected pins.
                                           This parameter can be a value of @ref GPIOPuPd_TypeDef */
    }GPIO_InitTypeDef;
    

    所以在初始化结构体中一共需要配置5个东西,我们先声明一个GPIO初始化结构体变量再来一步步配置。声明如下:

    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    

    需要注意,在keil的编译器中,变量声明要在使用之前,所以初始化变量的声明要在我们刚刚说的时钟初始化之前。

    1、GPIO_Pin

    第一个是选择你所需要用的的引脚,从“stm32f4xx_gpio.h”的头文件中可以看到由如下几个宏定义:

    /** @defgroup GPIO_pins_define 
      * @{
      */ 
    #define GPIO_Pin_0                 ((uint16_t)0x0001)  /* Pin 0 selected */
    #define GPIO_Pin_1                 ((uint16_t)0x0002)  /* Pin 1 selected */
    #define GPIO_Pin_2                 ((uint16_t)0x0004)  /* Pin 2 selected */
    #define GPIO_Pin_3                 ((uint16_t)0x0008)  /* Pin 3 selected */
    #define GPIO_Pin_4                 ((uint16_t)0x0010)  /* Pin 4 selected */
    #define GPIO_Pin_5                 ((uint16_t)0x0020)  /* Pin 5 selected */
    #define GPIO_Pin_6                 ((uint16_t)0x0040)  /* Pin 6 selected */
    #define GPIO_Pin_7                 ((uint16_t)0x0080)  /* Pin 7 selected */
    #define GPIO_Pin_8                 ((uint16_t)0x0100)  /* Pin 8 selected */
    #define GPIO_Pin_9                 ((uint16_t)0x0200)  /* Pin 9 selected */
    #define GPIO_Pin_10                ((uint16_t)0x0400)  /* Pin 10 selected */
    #define GPIO_Pin_11                ((uint16_t)0x0800)  /* Pin 11 selected */
    #define GPIO_Pin_12                ((uint16_t)0x1000)  /* Pin 12 selected */
    #define GPIO_Pin_13                ((uint16_t)0x2000)  /* Pin 13 selected */
    #define GPIO_Pin_14                ((uint16_t)0x4000)  /* Pin 14 selected */
    #define GPIO_Pin_15                ((uint16_t)0x8000)  /* Pin 15 selected */
    #define GPIO_Pin_All               ((uint16_t)0xFFFF)  /* All pins selected */
    

    也就是STM32F407VET6所有引出的引脚了,这里我们选择一个或多个引脚可以这么些:

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3;
    

    选择多个的时候可以用'|'隔开。

    2、GPIO_Mode

    第二个是选择所选择引脚的工作模式,从头文件中我们可以看到STM32引脚的工作模式一共有4种,分别是GPIO输入模式、GPIO输出模式、GPIO复用模和GPIO模拟模式。

    typedef enum
    { 
      GPIO_Mode_IN   = 0x00, /*!< GPIO Input Mode */
      GPIO_Mode_OUT  = 0x01, /*!< GPIO Output Mode */
      GPIO_Mode_AF   = 0x02, /*!< GPIO Alternate function Mode */
      GPIO_Mode_AN   = 0x03  /*!< GPIO Analog Mode */
    }GPIOMode_TypeDef;
    

    这几种模式的功能和应用这里不作介绍,我们这里选择最常用的输出模式,即GPIO_Mode_OUT,代码如下:

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    

    3、GPIO_Speed

    顾名思义,接下来要配置的是GPIO的频率或速度,事实上芯片为我们提供了4种速度模式

    typedef enum
    { 
      GPIO_Low_Speed     = 0x00, /*!< Low speed    */
      GPIO_Medium_Speed  = 0x01, /*!< Medium speed */
      GPIO_Fast_Speed    = 0x02, /*!< Fast speed   */
      GPIO_High_Speed    = 0x03  /*!< High speed   */
    }GPIOSpeed_TypeDef;
    
    /* Add legacy definition */
    #define  GPIO_Speed_2MHz    GPIO_Low_Speed    
    #define  GPIO_Speed_25MHz   GPIO_Medium_Speed 
    #define  GPIO_Speed_50MHz   GPIO_Fast_Speed 
    #define  GPIO_Speed_100MHz  GPIO_High_Speed  
    

    分别是2MHz、25MHz、50MHz、100MHz,关于这GPIO速度的选择可以去了解下“香农采样定理”,这里我们选择最高速100MHz。

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    

    4、GPIO_OType

    第四个是关于输出的形式,因为我们之前将引脚配置为输出模式,所以我们这里还得配置输出的形式,一共有两个,分别是推挽输出PP和开漏输出OD,关于推挽输出和开漏输出的区别可以点击这里 http://www.51hei.com/mcu/3988.html 我们这里选择推挽输出。

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    

    5、GPIO_PuPd

    typedef enum
    { 
      GPIO_PuPd_NOPULL = 0x00,
      GPIO_PuPd_UP     = 0x01,
      GPIO_PuPd_DOWN   = 0x02
    }GPIOPuPd_TypeDef;
    

    第五个是关于引脚有无上下拉的选择,这个不用多做介绍,如果有不了解的可以了解下上拉和下拉的作用。这里我们选择没有上拉和下拉。

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    

    6、初始化

    STM32F407VET6将引脚分成了GPIO PORT A、B、C、D、E五组,每组有15个引脚,所以我们需要确定到底要选择的是那个PORT的引脚,这里我们选择PORT A,对应上面的引脚,既是PA1、PA2和PA3这三个引脚。最后我们还需要调用GPIO初始化函数,将结构体变量中的信息传递给芯片。

    GPIO_Init(GPIOA,&GPIO_InitStructure);
    

    总结

    至此关于GPIO的配置已经基本完成,这里只做了一个简单的介绍,GPIO有很多复杂的功能需要去查看相关手册去使用,同时网络上的许多博客也是我们学习的资源。以下是完整代码:

    void GPIO_Config(void)
    {
      GPIO_InitTypeDef GPIO_InitStructure;
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    
      // typedef struct
      // {
      //   uint32_t GPIO_Pin;              /*!< Specifies the GPIO pins to be configured.
      //                                        This parameter can be any value of @ref GPIO_pins_define */
      //
      //   GPIOMode_TypeDef GPIO_Mode;     /*!< Specifies the operating mode for the selected pins.
      //                                        This parameter can be a value of @ref GPIOMode_TypeDef */
      //
      //   GPIOSpeed_TypeDef GPIO_Speed;   /*!< Specifies the speed for the selected pins.
      //                                        This parameter can be a value of @ref GPIOSpeed_TypeDef */
      //
      //   GPIOOType_TypeDef GPIO_OType;   /*!< Specifies the operating output type for the selected pins.
      //                                        This parameter can be a value of @ref GPIOOType_TypeDef */
      //
      //   GPIOPuPd_TypeDef GPIO_PuPd;     /*!< Specifies the operating Pull-up/Pull down for the selected pins.
      //                                        This parameter can be a value of @ref GPIOPuPd_TypeDef */
      // }GPIO_InitTypeDef;
    
      GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3;
      // #define GPIO_Pin_0                 ((uint16_t)0x0001)  /* Pin 0 selected */
      // #define GPIO_Pin_1                 ((uint16_t)0x0002)  /* Pin 1 selected */
      // #define GPIO_Pin_2                 ((uint16_t)0x0004)  /* Pin 2 selected */
      // #define GPIO_Pin_3                 ((uint16_t)0x0008)  /* Pin 3 selected */
      // #define GPIO_Pin_4                 ((uint16_t)0x0010)  /* Pin 4 selected */
      // #define GPIO_Pin_5                 ((uint16_t)0x0020)  /* Pin 5 selected */
      // #define GPIO_Pin_6                 ((uint16_t)0x0040)  /* Pin 6 selected */
      // #define GPIO_Pin_7                 ((uint16_t)0x0080)  /* Pin 7 selected */
      // #define GPIO_Pin_8                 ((uint16_t)0x0100)  /* Pin 8 selected */
      // #define GPIO_Pin_9                 ((uint16_t)0x0200)  /* Pin 9 selected */
      // #define GPIO_Pin_10                ((uint16_t)0x0400)  /* Pin 10 selected */
      // #define GPIO_Pin_11                ((uint16_t)0x0800)  /* Pin 11 selected */
      // #define GPIO_Pin_12                ((uint16_t)0x1000)  /* Pin 12 selected */
      // #define GPIO_Pin_13                ((uint16_t)0x2000)  /* Pin 13 selected */
      // #define GPIO_Pin_14                ((uint16_t)0x4000)  /* Pin 14 selected */
      // #define GPIO_Pin_15                ((uint16_t)0x8000)  /* Pin 15 selected */
      // #define GPIO_Pin_All               ((uint16_t)0xFFFF)  /* All pins selected */
    
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
      // typedef enum
      // {
      //   GPIO_Mode_IN   = 0x00, /*!< GPIO Input Mode */
      //   GPIO_Mode_OUT  = 0x01, /*!< GPIO Output Mode */
      //   GPIO_Mode_AF   = 0x02, /*!< GPIO Alternate function Mode */
      //   GPIO_Mode_AN   = 0x03  /*!< GPIO Analog Mode */
      // }GPIOMode_TypeDef;
    
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
      // typedef enum
      // {
      //   GPIO_Low_Speed     = 0x00, /*!< Low speed    */
      //   GPIO_Medium_Speed  = 0x01, /*!< Medium speed */
      //   GPIO_Fast_Speed    = 0x02, /*!< Fast speed   */
      //   GPIO_High_Speed    = 0x03  /*!< High speed   */
      // }GPIOSpeed_TypeDef;
    
      /* Add legacy definition */
      // #define  GPIO_Speed_2MHz    GPIO_Low_Speed
      // #define  GPIO_Speed_25MHz   GPIO_Medium_Speed
      // #define  GPIO_Speed_50MHz   GPIO_Fast_Speed
      // #define  GPIO_Speed_100MHz  GPIO_High_Speed
    
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      // typedef enum
      // {
      //   GPIO_OType_PP = 0x00,
      //   GPIO_OType_OD = 0x01
      // }GPIOOType_TypeDef;
    
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
      // typedef enum
      // {
      //   GPIO_PuPd_NOPULL = 0x00,
      //   GPIO_PuPd_UP     = 0x01,
      //   GPIO_PuPd_DOWN   = 0x02
      // }GPIOPuPd_TypeDef;
    
      GPIO_Init(GPIOA,&GPIO_InitStructure);
      // void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
    }
    
    
  • 相关阅读:
    HTML基础(一)基本语法知识
    本地方法接口
    本地方法栈
    虚拟机栈相关的问题
    栈帧的内部结构--一些附加信息
    基于角色的权限控制设计
    SpringBoot普通消息队列线程池配置
    栈帧的内部结构--动态返回地址(Return Address)
    栈帧的内部结构--动态链接 (Dynamic Linking)
    栈帧的内部结构--操作数栈(Opreand Stack)
  • 原文地址:https://www.cnblogs.com/gaojun4ever/p/5011332.html
Copyright © 2020-2023  润新知