STM32H743之GPIO输⼊输出实验
GPIO基础知识
GPIO配置是所有外设驱动的基础。
STM32H7 的 GPIO 特性如下:
下联① 输出状态:开漏/推挽 + 上拉/下拉电阻。
② 通过输出数据寄存器(GPIOx_ODR)或者外设(GPIO 设置为复⽤模式时)输出数据。
③ GPIO 速度等级设置。
④ 输⼊状态:浮空,上拉/下拉,模拟。
⑤ 通过输⼊数据寄存器(GPIOx_IDR)或者外设(GPIO 设置为复⽤模式)输⼊数据。
⑥ 通过寄存器 GPIOx_BSRR 实现对寄存器 GPIOx_ODR 的位操作。
⑦ 通过配置寄存器 GPIOx_LCKR 的锁机制,实现冻结 IO ⼝配置。
⑧ 每两个时钟周期就可以翻转⼀次 IO。
⑨ ⾼度灵活的引脚复⽤功能,允许 IO 引脚既可以做 GPIO 也可以做功能复⽤。
STM32H7 的 GPIO 端⼝可以配置为如下的 8 种模式: ① 输⼊浮空
② 输⼊上拉
生生世世情③ 输⼊下拉
④ 模拟功能
⑤ 具有上拉或下拉功能的开漏输出
⑥ 具有上拉或下拉功能的推挽输出
⑦ 具有上拉或下拉功能的复⽤功能推挽
⑧ 具有上拉或下拉功能的复⽤功能开漏
由于上拉和下拉是可选配置,对应的 HAL 库配置使⽤下⾯ 6 种就可以表⽰:
① GPIO_MODE_INPUT 输⼊模式
② GPIO_MODE_OUTPUT_PP 推挽输出
③ GPIO_MODE_OUTPUT_OD 开漏输出
④ GPIO_MODE_AF_PP 复⽤推挽
⑤ GPIO_MODE_AF_OD 复⽤开漏
⑥ GPIO_MODE_ANALOG 模拟模式
开漏输出模式输出⾼电平的驱动能⼒完全由外接上拉电阻决定,但是其输出低电平的驱动能⼒很强。
相对于开漏输出模式,推挽输出最⼤优势是输出⾼电平时,上升时间快,电压驱动能⼒强。
IO 补偿单元⽤于控制 I/O 通信压摆率(tfall / tri)以此来降低 I/O 噪声。当前 STM32H7 的速度等级可以配置为以下四种:
#define GPIO_SPEED_FREQ_LOW ((uint32_t)0x00000000U) /*!< Low speed */
#define GPIO_SPEED_FREQ_MEDIUM ((uint32_t)0x00000001U) /*!< Medium speed */
#define GPIO_SPEED_FREQ_HIGH ((uint32_t)0x00000002U) /*!< Fast speed */
#define GPIO_SPEED_FREQ_VERY_HIGH ((uint32_t)0x00000003U) /*!< High speed */
使⽤后两种速度等级的话,最好使能 IO 补偿单元。
从功耗和防⼲扰考虑,不使⽤的引脚设置为模拟模式,悬空即可。
硬件连接
将 LED,独⽴按键五项摇杆按键的跳线(KEY JMP)接好。(其实已经默认⽤跳帽连接好了,如图所⽰)
我们使⽤的是LED1,其对应的IO端⼝是PB6;使⽤CTR(五项摇杆中间)按键,其对应的IO端⼝是PI11。
本实验的操作与现象是:按下 CTR(五项摇杆中间)按键 LED1会熄灭,松开 LED1会亮。
实验步骤与代码详解
本实验是⽤MDK-ARM调试,基于HAL库的,开发板为STM32H743ⅡT6。
需要包括的头⽂件
main.c main.h、gpio.h
main.h stm32h7xx_hal.h
gpio.c gpio.h
gpio.h main.h
① GPIO初始化
gpio.h中定义GPIO初始化函数:
void MX_GPIO_Init(void);
main.h中对所要⽤的引脚与端⼝进⾏宏定义:
#define KEY_Pin GPIO_PIN_11
#define KEY_GPIO_Port GPIOI
#define LED_Pin GPIO_PIN_6
#define LED_GPIO_Port GPIOB
GPIO_PIN_11、GPIOI、GPIO_PIN_6、GPIOB已在stm32h7xx_hal.h中定义过,故main.h要包括该头⽂件,⽽在main.h中进⾏宏定义,是为了⽅便移植,其作⽤相当于别名。
gpio.c中实现GPIO初始化函数:
(1)定义GPIO_InitTypeDef类型的结构体GPIO_InitStruct
GPIO_InitTypeDef GPIO_InitStruct ={0};
具体查看GPIO_InitTypeDef的结构体,在stm32h7xx_hal_gpio.h中进⾏了定义,其结构体元素包括Pin、Mode、Pull、Speed、Alternate
typedef struct
{
uint32_t Pin;//指定要配置的GPIO引脚
uint32_t Mode;//指定选定接点的⼯作模式
uint32_t Pull;//指定选定接点的上拉或下拉激活
uint32_t Speed;//指定选定接点的速度
uint32_t Alternate;//要连接到所选引脚的外围设备
}GPIO_InitTypeDef;
(2)使能GPIOI、GPIOH、GPIOB的时钟
/* GPIO Ports Clock Enable 使能GPIO端⼝时钟 */
__HAL_RCC_GPIOI_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
(3)配置GPIO引脚输出电平
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
(4)选择结构体GPIO_InitStruct的元素参数,并调⽤HAL库函数HAL_GPIO.Init初始化
/*配置CTR即PI11 */
GPIO_InitStruct.Pin = KEY_Pin;//选择引脚KEY
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;//输⼊模式
GPIO_InitStruct.Pull = GPIO_PULLUP;//上拉
HAL_GPIO_Init(KEY_GPIO_Port,&GPIO_InitStruct);
/*配置LED1即PB6 */
GPIO_InitStruct.Pin = LED_Pin;//选择引脚LED
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//推挽输出
GPIO_InitStruct.Pull = GPIO_PULLUP;//上拉
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;//⾼速
HAL_GPIO_Init(LED_GPIO_Port,&GPIO_InitStruct);
其中,库函数HAL_GPIO_Init的定义(位于stm32h7xx_hal_gpio.h中)如下,⼊⼝参数为指针类型的GPIO端⼝与GPIO结构体void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
② main.c中实现实验现象
while(1)//死循环
{
/* 按下 CTR(五项摇杆中间)按键 LED1会亮,松开 LED1会熄灭 */
#if 0
if(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin)== GPIO_PIN_RESET){
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
}el{
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
}
HAL_Delay(100);
#endif
/* 按下 CTR(五项摇杆中间)按键 LED1会熄灭,松开 LED1会亮 */
#if 1
if(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin)== GPIO_PIN_SET){
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
}el{
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
}
健身励志语录HAL_Delay(100);
#endif
}
附上代码:
main.c
#include"main.h"
只要的英文#include"gpio.h"
void SystemClock_Config(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while(1)
1999年是什么年
while(1)
{
/* 按下 CTR(五项摇杆中间)按键 LED1会熄灭,松开 LED1会亮 */
#if 1
if(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin)== GPIO_PIN_SET){
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
}el{
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
}
HAL_Delay(100);
#endif
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct ={0};
RCC_ClkInitTypeDef RCC_ClkInitStruct ={0};
MODIFY_REG(PWR->CR3, PWR_CR3_SCUEN,0);
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); while((PWR->D3CR &(PWR_D3CR_VOSRDY))!= PWR_D3CR_VOSRDY)
{
被子发霉了怎么办}
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM =4;
RCC_OscInitStruct.PLL.PLLN =400;
RCC_OscInitStruct.PLL.PLLP =2;
RCC_OscInitStruct.PLL.PLLQ =2;
RCC_OscInitStruct.PLL.PLLR =2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN =0;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct)!= HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
槟榔芋RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2)!= HAL_OK)
{
Error_Handler();
}
}
void Error_Handler(void)
{
}
main.h
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus extern"C"{
#endif
#include"stm32h7xx_hal.h" void Error_Handler(void);
#define KEY_Pin GPIO_PIN_11 #define KEY_GPIO_Port GPIOI #define LED_Pin GPIO_PIN_6 #define LED_GPIO_Port GPIOB
#ifdef __cplusplus
}
#endif
#endif
gpio.h
#ifndef __gpio_H
#define __gpio_H
#ifdef __cplusplus extern"C"{
#endif
#include"main.h"
void MX_GPIO_Init(void);如何治疗白发
#ifdef __cplusplus
}
#endif
#endif
gpio.c