zoukankan      html  css  js  c++  java
  • (1)STM32使用HAL库操作GPIO

    一  初始化GPIO

    使用HAL库的优点在于不用手动添加初始化的代码了,CubeMX会根据软件设置自动生成。

    自动生成的HAL库GPIO初始化代码:

    复制代码
    static void MX_GPIO_Init(void)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct;
    
      /* GPIO Ports Clock Enable */
      __HAL_RCC_GPIOH_CLK_ENABLE();
      __HAL_RCC_GPIOD_CLK_ENABLE();
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET);
    
      /*Configure GPIO pin : PD11 */
      GPIO_InitStruct.Pin = GPIO_PIN_11;
      GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
      GPIO_InitStruct.Pull = GPIO_PULLUP;
      HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
      /*Configure GPIO pins : PD12 PD13 PD14 PD15 */
      GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
      HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
    }
    复制代码

    顺序:(1)定义结构体变量。(2)使能时钟。(3)配置初始化电平。(4)通过结构体变量初始化GPIO。

    1.首先定义一个结构体变量GPIO_InitStruct,该变量类型是GPIO_InitTypeDef。

    GPIO_InitTypeDef 定义如下:

    复制代码
    /** 
      * @brief GPIO Init structure definition  
      */ 
    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 */
    
      uint32_t Alternate;  /*!< Peripheral to be connected to the selected pins. 
                                This parameter can be a value of @ref GPIO_Alternate_function_selection */
    }GPIO_InitTypeDef;
    复制代码

    作用是:设置要用的是哪个引脚、引脚工作模式、上拉还是下拉、速度、XX这个还不知道是干嘛的XX。

    2.使能时钟。

      /* GPIO Ports Clock Enable */
      __HAL_RCC_GPIOH_CLK_ENABLE();
      __HAL_RCC_GPIOD_CLK_ENABLE();

    这里使能时钟的方法与标准库不一样,HAL库其实是宏定义,标准库则是函数。

    宏定义(使能H口的宏定义):

    复制代码
    #define __HAL_RCC_GPIOH_CLK_ENABLE()  do { \
                                            __IO uint32_t tmpreg = 0x00U; \
                                            SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOHEN);\
                                            /* Delay after an RCC peripheral clock enabling */ \
                                            tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOHEN);\
                                            UNUSED(tmpreg); \
                                             } while(0U)
    复制代码

    这里使能H口是因为H口接的外部晶振。

    3.配置引脚的初始化电平。

      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET);

    这里设置D口的pin12、pin13、pin14、pin15为高电平。如果最后一个参数是GPIO_PIN_RESET则为低电平。

    4.通过结构体变量配置具体的引脚。

    复制代码
      /*Configure GPIO pin : PD11 */
      GPIO_InitStruct.Pin = GPIO_PIN_11;
      GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
      GPIO_InitStruct.Pull = GPIO_PULLUP;
      HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
      /*Configure GPIO pins : PD12 PD13 PD14 PD15 */
      GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
      HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    复制代码

    PD11为输入,上拉。PD12-15为推挽输出。所以分开配置。

    总结一下:(1)定义结构体变量。(2)使能时钟。(3)配置初始化电平。(4)通过结构体变量初始化GPIO。

    其中,(3)和(4)可调换顺序

    二  功能解释

    1.系统分析。

    STM32F4Discovery的PD12-15的四个引脚是LED。

    我们要做的功能是按键一次点亮一个LED(顺时针PIN12-15,从PIN12开始)并关闭上一个LED。

    首先我们需要一个标志变量来代表当前正在亮的LED:

    int LEDNUM_Flag = 12;

    流程:按键扫描  ->  读到Pin11按下  ->  关闭当前LEDNUM_Flag代表的LED(正在亮的)  ->  LEDNUM_Flag+1  ->  点亮当前LEDNUM_Flag代表的LED;

    2.按键输入。

    复制代码
    _Bool GetPress(void)
    {
        if(HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11)==0)
        {
            HAL_Delay(10);//防抖
            if(HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11)==0)
                {
                    while(HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11)==0)//等待按键抬起。
                    {;}
                    return 1;
                }
                else return 0;
        }
        else    return 0;
    }
    复制代码

    3.点亮LED。

    复制代码
    void TurnOnLED(int flag)
    {
        switch(flag)
        {
            case 12 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
                break;
            case 13 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET);
                break;
            case 14 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
                break;
            case 15 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET);
                break;
        }
    }
    复制代码

    4.关闭LED。

    复制代码
    void TurnOffLED(int flag)
    {
        switch(flag)
        {
            case 12 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
                break;
            case 13 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_RESET);
                break;
            case 14 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
                break;
            case 15 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
                break;
        }
    }
    复制代码

    5.标志变量自加。

    复制代码
    void FlagPlus(int *flag)
    {
        (*flag)++;
        if((*flag)==16)
        {
            (*flag)=12;
        }
    }
    复制代码

    这里一定要用指针,因为函数参数是值传递所以只能用指针来改变LEDNUM_Flag。

    6.整合代码。

    复制代码
    #include "main.h"
    #include "stm32f4xx_hal.h"
    
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    
    int LEDNUM_Flag = 12;
        
    _Bool GetPress(void);
    
    void TurnOnLED(int flag);
    
    void TurnOffLED(int flag);
    
    void FlagPlus(int *flag);
    
    int main(void)
    {
    
      HAL_Init();
      SystemClock_Config();
      MX_GPIO_Init();
      //最开始先点亮PD12的LED
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); 
      while (1)
      {
        //有按键按下
        if(GetPress()==1)
            {
                TurnOffLED(LEDNUM_Flag);
                FlagPlus(&LEDNUM_Flag);
                TurnOnLED(LEDNUM_Flag);
            }
      }
    }
    
    /** System Clock Configuration
    */
    void SystemClock_Config(void)
    {
    
      RCC_OscInitTypeDef RCC_OscInitStruct;
      RCC_ClkInitTypeDef RCC_ClkInitStruct;
    
        /**Configure the main internal regulator output voltage 
        */
      __HAL_RCC_PWR_CLK_ENABLE();
    
      __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    
        /**Initializes the CPU, AHB and APB busses clocks 
        */
      RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
      RCC_OscInitStruct.HSIState = RCC_HSI_ON;
      RCC_OscInitStruct.HSICalibrationValue = 16;
      RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
      RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
      RCC_OscInitStruct.PLL.PLLM = 8;
      RCC_OscInitStruct.PLL.PLLN = 168;
      RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
      RCC_OscInitStruct.PLL.PLLQ = 4;
      if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
      {
        _Error_Handler(__FILE__, __LINE__);
      }
    
        /**Initializes the CPU, AHB and APB busses clocks 
        */
      RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                  |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
      RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
      RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
      RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
      RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
    
      if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
      {
        _Error_Handler(__FILE__, __LINE__);
      }
    
        /**Configure the Systick interrupt time 
        */
      HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
    
        /**Configure the Systick 
        */
      HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
    
      /* SysTick_IRQn interrupt configuration */
      HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
    }
    
    /** Configure pins as 
            * Analog 
            * Input 
            * Output
            * EVENT_OUT
            * EXTI
    */
    static void MX_GPIO_Init(void)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct;
    
      /* GPIO Ports Clock Enable */
      __HAL_RCC_GPIOH_CLK_ENABLE();
      __HAL_RCC_GPIOD_CLK_ENABLE();
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
    
      /*Configure GPIO pin : PD11 */
      GPIO_InitStruct.Pin = GPIO_PIN_11;
      GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
      GPIO_InitStruct.Pull = GPIO_PULLUP;
      HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
      /*Configure GPIO pins : PD12 PD13 PD14 PD15 */
      GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
      HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
    }
    
    ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
    _Bool GetPress(void)
    {
        if(HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11)==0)
        {
            HAL_Delay(10);
            if(HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11)==0)
                {
                    while(HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11)==0)
                    {;}
                    return 1;
                }
                else return 0;
        }
        else    return 0;
    }
    
    void TurnOnLED(int flag)
    {
        switch(flag)
        {
            case 12 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
                break;
            case 13 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET);
                break;
            case 14 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
                break;
            case 15 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET);
                break;
        }
    }
    
    void TurnOffLED(int flag)
    {
        switch(flag)
        {
            case 12 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
                break;
            case 13 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_RESET);
                break;
            case 14 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
                break;
            case 15 :
                HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
                break;
        }
    }
    
    void FlagPlus(int *flag)
    {
        (*flag)++;
        if((*flag)==16)
        {
            (*flag)=12;
        }
    }
    ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// /**
      * @brief  This function is executed in case of error occurrence.
      * @param  None
      * @retval None
      */
    void _Error_Handler(char * file, int line)
    {
      /* USER CODE BEGIN Error_Handler_Debug */
      /* User can add his own implementation to report the HAL error return state */
      while(1) 
      {
      }
      /* USER CODE END Error_Handler_Debug */ 
    }
    
    #ifdef USE_FULL_ASSERT
    
    /**
       * @brief Reports the name of the source file and the source line number
       * where the assert_param error has occurred.
       * @param file: pointer to the source file name
       * @param line: assert_param error line source number
       * @retval None
       */
    void assert_failed(uint8_t* file, uint32_t line)
    {
      /* USER CODE BEGIN 6 */
      /* User can add his own implementation to report the file name and line number,
        ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
      /* USER CODE END 6 */
    
    }
    
    #endif
    复制代码

    三  重要的API。

    复制代码
    //IO口使能,  注意这里是D口
    __HAL_RCC_GPIOD_CLK_ENABLE();
    
    //设置推挽输出的IO口输出电平为低
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
    
    //设置推挽输出的IO口输出电平为高
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
    
    //初始化一个IO口为输入
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
    //初始化IO为推挽输出
    GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
    //读取一个输入IO口的电平
    HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11);
  • 相关阅读:
    Wannafly挑战赛14 F.细胞
    D 勤奋的杨老师(二)(最小割)
    三分算法求最值
    初识最大流
    初识数据结构
    决策型DP
    哈希表
    【BZOJ】1878: [SDOI2009]HH的项链 (主席树)
    【HDU】1520 Anniversary party(树形dp)
    【UVa】1606 Amphiphilic Carbon Molecules(计算几何)
  • 原文地址:https://www.cnblogs.com/wt88/p/9624082.html
Copyright © 2011-2022 走看看