目录
1、建立.ioc工程
2、 MX_GPIO_Init()函数
(1)MX_GPIO_Init()函数的类型
(2)MX_GPIO_Init()函数中用到的结构体变量
(3)MX_GPIO_Init()函数使能时钟
(4)MX_GPIO_Init()函数配置GPIO
本文中使用ST的开发板NUCLEO-G474RE,板上MCU型号为STM32G474RET6。配套的扩展板:
实例中当开发板上的按键B1被按下时,PC13引脚被上拉至高电平VDD,不按下时,PC13下拉至低电平GND。用按键B1控制板上的LD2灯的亮灭,当PA5输出高电平时LD2亮,否则灯灭。
1、建立.ioc工程
根据上述信息,建立工程,具体操作,略。
2、 MX_GPIO_Init()函数
系统自动生成代码后,打开main.c。因为工程配置了2个GPIO,一个作为输入,另一个作为输出。MX_GPIO_Init()定义如下:
static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* USER CODE BEGIN MX_GPIO_Init_1 *//* USER CODE END MX_GPIO_Init_1 *//* GPIO Ports Clock Enable */__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOF_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_SET);/*Configure GPIO pin : KEY_Pin */GPIO_InitStruct.Pin = KEY_Pin;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLDOWN;HAL_GPIO_Init(KEY_GPIO_Port, &GPIO_InitStruct);/*Configure GPIO pin : LED0_Pin */GPIO_InitStruct.Pin = LED0_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(LED0_GPIO_Port, &GPIO_InitStruct);/* USER CODE BEGIN MX_GPIO_Init_2 *//* USER CODE END MX_GPIO_Init_2 */
}
(1)MX_GPIO_Init()函数的类型
从上面的定义可知,函数MX_GPIO_Init()的类型为void,不返回任何值。不过在void前加了一个static,表示该函数只能在定义它的文件中可见。对于MX_GPIO_Init()函数,只能在main.c中可见。实际上,该函数只置用于设置GPIO的参数,别的地方也用不到。
(2)MX_GPIO_Init()函数中用到的结构体变量
其中,第一句定义了一个结构体变量GPIO_InitStruct,结构体名称为GPIO_InitTypeDef。这个结构体的声明是在固件库的stm32g4xx_hal_gpio.h文件中:
typedef struct
{unint32_t Pin:unint32_t Mode;unint32_t Pull;unint32_t Speed;unint32_t Alternate;
}GPIO_IniyTypeDef;
GPIO_InitTypeDef在这里是结构体名称,并不是一个结构体变量,所以在使用该结构体类型时,还需要定义变量。结构体GPIO_InitTypeDef中有5个成员。
- 成员Pin
成员Pin实际就是引脚号,譬如GPIO_PIN_0~GPIO_PIN_15等。这些引脚号也是数值,在stm32g4xx_hal_gpio.h中有定义:
#define GPIO_PIN_0 ((uint16_t)0x0001) //第1个引脚
......
#define GPIO_PIN_15 ((uint16_t)0x8000) //第16个引脚
#define GPIO_PIN_All ((uint16_t)0xFFFF)//所有引脚
在这些define宏定义中,引脚号定义为uint16_t类型,而在结构体GPIO_InitTypeDef中,成员Pin定义为uint32_t。由此可见,在给32位的结构体变量赋值时,实际赋的是16位数。
实际上STM32G4系列MCU的GPIO寄存器,都是32位的,但有的寄存器只是低16位有效。
- 成员Mode
成员Mode是指输入、输出等模式。例如:
输入模式:GPIO_MODE_INPUT;
推挽输出模式:GPIO_MODE_OUTPUT_PP;
开漏输出模式:GPIO_MODE_OUTPUT_OD。
当然还有一些响应外部中断和外部事件的模式,此处暂时略过。
- 成员Pull
成员Pull是用于配置上拉、下拉功能的。例如:
不用上拉下拉:GPIO_NOPULL;
上拉:GPIO_PULLUP;
下拉:GPIO_PULLDOWN。
- 成员Speed
成员Speed用于配置GPIO速度,有4个挡位。例如:
低速:GPIO_GPIO_SPEED_FREQ_LOW,最高5MHz;
中速:GPIO_SPEED_FREQ_MEDIUM,5~25 MHz;
高速:GPIO_SPEED_FREQ_HIGH,25~50 MHz;
很高速:GPIO_SPEED_FREQ_VERY_HIGH,50~120 MHz。
- 成员Alternate
成员 Alternate涉及引脚复用功能。
继续,看MX_GPIO_Init()函数的定义,第一条语句是给变量GPIO_InitStruct赋值,等号右侧为{0},意思是将结构体中的所有成员都初始化为0。
(3)MX_GPIO_Init()函数使能时钟
接下来是三条时钟使能语句,分别使能GPIOC、GPIOF和GPIOA的时钟。使能GPIOF是因为外接晶体用到了GPIOF端口。
(4)MX_GPIO_Init()函数配置GPIO
因为配置了PA5作为输出,所以接下来的一条语句是初始化PA5的输出状态,用的是GPIO_PIN_RESET,即将其初始化为低电平输出。
随后,分别对PC13(KEY)和PA5(LED)进行配置。由于已经定义了一个结构体变量GPIO_InitStruct,所以这里需要先给其中的成员赋值:
GPIO_InitStruct.Pin =KEY_Pin;
GPIO_InitStruct.Mode =GPIO_MODE_INPUT;
GPIO_InitStruct.Pull =GPIO_PULLDOWN;
在这三条语句中,访问结构体成员变量用的是“.”。
至此,这只是通过结构体变量给成员赋值,还不会作用到硬件(GPIO寄存器)来,调用HAL_GPIO_Init函数,将结构体变量的信息传递过来并作用到相关GPIO寄存器中。所用语句如下:
HAL_GPIO_Init(KEY_GPIO_Port,&GPIO_InitStruct);
HAL_GPIO_Init函数有两个参数:一个是端口KEY_GPIO_Port,也就是GP个是已经给结构体成员赋值的结构体变量GPIO_InitStruct,注意在结构体变量前要后面的代码是用类似的方式初始化PA5。
关于HAL_GPIO_Init函数的解析,请看本文作者的其他文章。