STM32使用HAL库操作GPIO

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

一 初始化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);
复制代码

相关文章
|
4月前
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
715 0
|
5月前
|
存储 数据采集 数据安全/隐私保护
使用STM32F103读取TF卡并模拟U盘:使用标准库实现
通过以上步骤,你可以实现用STM32F103将TF卡内容变成U盘进行读取。这种功能在数据采集、便携式存储设备等应用中非常有用。如果你有更多的需求,可以进一步扩展此项目,例如添加文件管理功能、加密存储等。希望这篇博客能帮到你,如果有任何问题,欢迎在评论区留言讨论!
238 1
|
4月前
stm32f407探索者开发板(八)——按键输入实验--GPIO做输入
stm32f407探索者开发板(八)——按键输入实验--GPIO做输入
|
4月前
|
传感器 编解码 API
【STM32开发入门】温湿度监测系统实战:SPI LCD显示、HAL库应用、GPIO配置、UART中断接收、ADC采集与串口通信全解析
SPI(Serial Peripheral Interface)是一种同步串行通信接口,常用于微控制器与外围设备间的数据传输。SPI LCD是指使用SPI接口与微控制器通信的液晶显示屏。这类LCD通常具有较少的引脚(通常4个:MISO、MOSI、SCK和SS),因此在引脚资源有限的系统中非常有用。通过SPI协议,微控制器可以向LCD发送命令和数据,控制显示内容和模式。
164 0
|
5月前
经验大分享:STM32F4寄存器初始化系列:GPIO
经验大分享:STM32F4寄存器初始化系列:GPIO
31 0
|
5月前
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
447 2
|
6月前
|
传感器
STM32标准库ADC和DMA知识点总结-1
STM32标准库ADC和DMA知识点总结
|
5月前
|
IDE 开发工具
使用STM32F103标准库实现自定义键盘
通过本文,我们学习了如何使用STM32F103标准库实现一个简单的自定义键盘。我们首先初始化了GPIO引脚,然后实现了一个扫描函数来检测按键状态。这个项目不仅能够帮助我们理解STM32的GPIO配置和按键扫描原理,还可以作为进一步学习中断处理和低功耗设计的基础。希望本文对你有所帮助,祝你在嵌入式开发的道路上不断进步!
509 4