IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32-GPIO输入输出 -> 正文阅读

[嵌入式]STM32-GPIO输入输出

1、GPIO功能概述

(1)概述

STM32F407ZG有8个16引脚的GPIO端口。还有一个12引脚的PI端口。

GPIO端口都连接在AHB1总线上,自高时钟频率168MHz。

GPIO引脚能承受5V电压.

每个GPIO端口有4个32位寄存器,用于配置GPIO引脚的工作模式;1个32位输入数据寄存器和1个32位输出数据寄存器,还有复用功能选择寄存器等。

(2)GPIO引脚可以配置多种工作模式:

输入浮空(input floating):作为GPIO输入引脚,不使用上拉或下拉电阻。

输入上拉(input pull-up),作为GPIO输入引脚,使用内部上拉电阻。当没有外部输入时,引脚输入电平为高电平。

输入下拉(input pull-down):作为GPIO输入引脚,使用内部下拉电阻。当没有外部输入时,引脚输入电平为低电平。

模拟(analog):作为GPIO模拟引脚,用于ADC输入引脚或DAC输出引脚。

具有上拉或下拉的开漏输出(output open-drain):如果不使用上拉或下拉电阻,开漏输出1时引脚为高阻态,输出0时引脚是低电平。这种模式可用于共用总线的信号。

具有上拉或下拉的推挽输出(output push-pull):如果不使用上拉或下拉电阻,推挽输出1时引脚是高电平,输出0时引脚为低电平。若需要增强引脚输出驱动能力,就可以使用上拉。例如需要GPIO引脚输出高电平点亮LED时。

具有上拉或下拉的复用功能推挽(afternate function push-pull)。

具有上拉或下拉的复用功能开漏(afternate function open-drain)。

2、GPIO的HAL驱动程序

HAL_GPIO_Init() GPIO引脚初始化

void HAL_GPIO_Init(GPIO_TypeDef *GPIOx,GPIO_InitTypeDef *GPIO_Init);

参数1 GPIO_TypeDef *GPIOx,定义了各个端口的各个寄存器的偏移地址,实际调用HAL_GPIO_Init()时使用端口的基地址作为参数GPIOx的值。在stm32f407xx.h中定义了各个端口的基地址。

#define GPIOA ? ? ? ? ? ? ? ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOB ? ? ? ? ? ? ? ((GPIO_TypeDef *) GPIOB_BASE)
#define GPIOC ? ? ? ? ? ? ? ((GPIO_TypeDef *) GPIOC_BASE)
#define GPIOD ? ? ? ? ? ? ? ((GPIO_TypeDef *) GPIOD_BASE)
#define GPIOE ? ? ? ? ? ? ? ((GPIO_TypeDef *) GPIOE_BASE)
#define GPIOF ? ? ? ? ? ? ? ((GPIO_TypeDef *) GPIOF_BASE)
#define GPIOG ? ? ? ? ? ? ? ((GPIO_TypeDef *) GPIOG_BASE)
#define GPIOH ? ? ? ? ? ? ? ((GPIO_TypeDef *) GPIOH_BASE)
#define GPIOI ? ? ? ? ? ? ? ((GPIO_TypeDef *) GPIOI_BASE)

参数2GPIO_InitTypeDef *GPIO_Init,定义了GPIO引脚的属性。

//定义GPIO属性的结构体
typedef struct
{
 ?uint32_t Pin;
 ?uint32_t Mode;
 ?uint32_t Pull;
 ?uint32_t Speed;
 ?uint32_t Alternate;
}GPIO_InitTypeDef;
//Pin定义GPIO的引脚
#define GPIO_PIN_0 ? ? ? ? ? ? ? ? ((uint16_t)0x0001)
#define GPIO_PIN_1 ? ? ? ? ? ? ? ? ((uint16_t)0x0002)
#define GPIO_PIN_2 ? ? ? ? ? ? ? ? ((uint16_t)0x0004)
#define GPIO_PIN_3 ? ? ? ? ? ? ? ? ((uint16_t)0x0008)
#define GPIO_PIN_4 ? ? ? ? ? ? ? ? ((uint16_t)0x0010)
#define GPIO_PIN_5 ? ? ? ? ? ? ? ? ((uint16_t)0x0020)
#define GPIO_PIN_6 ? ? ? ? ? ? ? ? ((uint16_t)0x0040)
#define GPIO_PIN_7 ? ? ? ? ? ? ? ? ((uint16_t)0x0080)
#define GPIO_PIN_8 ? ? ? ? ? ? ? ? ((uint16_t)0x0100)
#define GPIO_PIN_9 ? ? ? ? ? ? ? ? ((uint16_t)0x0200)
#define GPIO_PIN_10 ? ? ? ? ? ? ?  ((uint16_t)0x0400)
#define GPIO_PIN_11 ? ? ? ? ? ? ?  ((uint16_t)0x0800)
#define GPIO_PIN_12 ? ? ? ? ? ? ?  ((uint16_t)0x1000)
#define GPIO_PIN_13 ? ? ? ? ? ? ?  ((uint16_t)0x2000)
#define GPIO_PIN_14 ? ? ? ? ? ? ?  ((uint16_t)0x4000)
#define GPIO_PIN_15 ? ? ? ? ? ? ?  ((uint16_t)0x8000)
#define GPIO_PIN_All ? ? ? ? ? ? ? ((uint16_t)0xFFFF)
?
#define GPIO_PIN_MASK ? ? ? ? ? ?  0x0000FFFFU
//Mode定义引脚功能模式设置
#define  GPIO_MODE_INPUT ? ? MODE_INPUT 
    /*!<输入浮空模式*/
#define  GPIO_MODE_OUTPUT_PP ?  (MODE_OUTPUT | OUTPUT_PP)
    /*!<推挽输出模式*/
#define  GPIO_MODE_OUTPUT_OD ?  (MODE_OUTPUT | OUTPUT_OD)
    /*!<开漏输出模式*/
#define  GPIO_MODE_AF_PP ? (MODE_AF | OUTPUT_PP) ? ? ? ? ? ? 
    /*!<复用功能推挽模式*/
#define  GPIO_MODE_AF_OD ? (MODE_AF | OUTPUT_OD) 
    /*!<复用功能开漏模式*/
#define  GPIO_MODE_ANALOG   MODE_ANALOG 
    /*!<带上升沿触发检测的外部中断模式*/
#define GPIO_MODE_IT_RISING 0x10110000U 
    /*!<带上升沿触发检测的外部中断模式*/
#define GPIO_MODE_IT_FALLING 0x10210000U 
    /*!<带下降沿触发检测的外部中断模式*/
#define GPIO_MODE_IT_RISING_FALLING 0x10310000U 
    /*!<带上升沿/下降沿触发检测的外部中断模式*/
?
#define  GPIO_MODE_EVT_RISING 0x10120000u ? 
    /*!<具有上升沿触发器检测的外部事件模式*/
#define  GPIO_MODE_EVT_FALLING 0x10220000u ? 
    /*!< 具有下降沿触发器检测的外部事件模式*/
#define  GPIO_MODE_EVT_RISING_FALLING 0x10320000u ? 
    /*!< 具有下降沿/下降沿触发器检测的外部事件模式*/
?
//pull定义是否使用内部上拉或下拉电阻
#define  GPIO_NOPULL ? ? ?  0x00000000U /*!< 无上拉或下拉*/
#define  GPIO_PULLUP ? ? ?  0x00000001U /*!< 上拉*/
#define  GPIO_PULLDOWN ? ?  0x00000002U /*!< 下拉*/
//Speed定义输出模式引脚的最高输出频率
#define  GPIO_SPEED_FREQ_LOW ? ? ? 0x00000000U //2MHz
#define  GPIO_SPEED_FREQ_MEDIUM ?  0x00000001U //12.5-50MHz
#define  GPIO_SPEED_FREQ_HIGH ? ?  0x00000002U //25-100MHz
#define  GPIO_SPEED_FREQ_VERY_HIGH 0x00000003U //50-200MHz
//Alternate定义引脚复用功能
#define GPIO_AF1_TIM1 ? ? ? ?  ((uint8_t)0x01) 
#define GPIO_AF1_TIM2 ? ? ? ?  ((uint8_t)0x01)
#define GPIO_AF4_I2C1 ? ? ? ?  ((uint8_t)0x04)
#define GPIO_AF4_I2C2 ? ? ? ?  ((uint8_t)0x04)
#define GPIO_AF4_I2C3 ? ? ? ?  ((uint8_t)0x04) 
#define GPIO_AF5_SPI1 ? ? ? ?  ((uint8_t)0x05) 
#define GPIO_AF5_SPI2 ? ? ? ?  ((uint8_t)0x05) 
#define GPIO_AF5_SPI3 ? ? ? ?  ((uint8_t)0x05) 
#define GPIO_AF7_USART1 ? ? ?  ((uint8_t)0x07) ?
#define GPIO_AF7_USART2 ? ? ?  ((uint8_t)0x07) 
#define GPIO_AF7_USART3 ? ? ?  ((uint8_t)0x07)

HAL_GPIO_DeInit() GPIO引脚反初始化,恢复为复位后的状态。

HAL_GPIO_WritePin() 使引脚输出0或1

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin,GPIO_PinState PinState);

PinState是引脚输出电平,是枚举类型GPIO_PinState,.

typedef enum
{
 ? ?GPIO_PIN_RESET = 0,
 ? ?GPIO_PIN_SET
}GPIO_PinState;

例如,要使PF9和PF10输出低电平,使用下面代码:

HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9|GPIO_PIN_10,GPIO_PIN_RESET);

如果要输出高电平,使用下面代码:

HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9|GPIO_PIN_10,GPIO_PIN_SET);

HAL_GPIO_ReadPin() 读取引脚输入电平

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx,uint16_t GPIO_PIN);

HAL_GPIO_TogglePin() 反转引脚的输出

void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx,uint16_t,GPIO_PIN);

HAL_GPIO_LockPin() 锁定引脚配置,而不是锁定引脚的输入或输出状态

3、GPIO使用示例

(1)电路资源

资源:

2个LED灯:由+3.3V电源驱动,当GPIO引脚输出为0时,LED点亮。当GPIO引脚输出为1时,LED熄灭。与LED连接的引脚PF9和PF10要设置为推挽输出。

4个按键:KeyUp键,外端接+3.3V,在按键按下时,输入PA0的是高电平,所以引脚PA0应该被设置为输入下拉。在按键未按下时,输入0;

另外3个按键,连接在PE2/PE3/PE4上,外端接地。按键按下时,输入低电平,所以使用输入上拉。

1个有源蜂鸣器:控制端在PF8,应设置为推挽输出。当PF8输出0时,蜂鸣器响,输出为1时,蜂鸣器不响。

原理图:

?

(2)功能要求

按下KeyLeft键时,使LED1的输出翻转。

按下KeyRight键时,使LED2的输出翻转。

按下KeyUp键时,使LED1和LED2的输出都翻转。

按下KeyDown键时,使蜂鸣器的输出翻转。

(3)软件配置

SYS组件中,设置Debug接口为Serial Wire。

RCC组件中,设置HSE为Crystal/Ceramic Resonator。

在时钟树上,设置HSE频率8MHz,实际开发板就是8MHz,主锁相环选择HSE作为时钟源,设置HCLK频率168MHz,软件自动配置时钟树。

根据3.3.2配置GPIO引脚。

用户标签引脚名称引脚功能GPIO模式上拉或下拉
LED1PF9GPIO_Output推挽输出
LED2PF10GPIO_Output推挽输出
KeyRightPE2GPIO_Input输入上拉
KeyDownPE3GPIO_Input输入上拉
KeyLeft4PE4GPIO_Input输入上拉
KeyUpPA0GPIO_Input输入下拉
buzzerPF8GPIO_Output推挽输出

4、代码

(1)GPIO初始化

void MX_GPIO_Init(void)
{
?
 ?GPIO_InitTypeDef GPIO_InitStruct = {0};
?
 ?/* GPIO Ports Clock Enable */
 ?__HAL_RCC_GPIOE_CLK_ENABLE();
 ?__HAL_RCC_GPIOF_CLK_ENABLE();
 ?__HAL_RCC_GPIOH_CLK_ENABLE();
 ?__HAL_RCC_GPIOA_CLK_ENABLE();
?
 ?/*Configure GPIO pin Output Level */
 ?HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_SET);
?
 ?/*Configure GPIO pin Output Level */
 ?HAL_GPIO_WritePin(GPIOF, LED1_Pin|LED2_Pin, GPIO_PIN_RESET);
?
 ?/*Configure GPIO pins : PEPin PEPin PEPin */
 ?GPIO_InitStruct.Pin = KeyRight_Pin|KeyDown_Pin|KeyLeft_Pin;
 ?GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
 ?GPIO_InitStruct.Pull = GPIO_PULLUP;
 ?HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
?
 ?/*Configure GPIO pins : PFPin PFPin PFPin */
 ?GPIO_InitStruct.Pin = Buzzer_Pin|LED1_Pin|LED2_Pin;
 ?GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 ?GPIO_InitStruct.Pull = GPIO_NOPULL;
 ?GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
 ?HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
?
 ?/*Configure GPIO pin : PtPin */
 ?GPIO_InitStruct.Pin = KeyUp_Pin;
 ?GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
 ?GPIO_InitStruct.Pull = GPIO_PULLDOWN;
 ?HAL_GPIO_Init(KeyUp_GPIO_Port, &GPIO_InitStruct);
?
}

(2)时钟初始化

void SystemClock_Config(void)
{
 ?RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 ?RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
?
 ?/** Configure the main internal regulator output voltage
 ?*/
 ?__HAL_RCC_PWR_CLK_ENABLE();
 ?__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
?
 ?/** Initializes the RCC Oscillators according to the specified parameters
 ?* in the RCC_OscInitTypeDef structure.
 ?*/
 ?RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
 ?RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 ?RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
 ?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();
  }
?
 ?/** Initializes the CPU, AHB and APB buses 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();
  }
}

(3)按键处理函数

typedef enum{
    Key_NONE = 0,   //没有那件按键被按下
    Key_LEFT,       //KeyLeft
    Key_RIGHT,      //KeyRight
    Key_UP,         //KeyUp
    Key_DOWN        //KeyDown
}KEYS;
?
KEYS ScanPressedKey(uint32_t timeout)
{
    KEYS key = Key_NONE;
    uint32_t tickstart = HAL_GetTick();     //当前技术值
    const uint32_t btnDelay = 20;           //按下按键的抖动,延时在采样时间
    GPIO_PinState keyState;                 //引脚输入状态
    while(1)
    {
        keyState = HAL_GPIO_ReadPin(KeyLeft_GPIO_Port,KeyLeft_Pin);
        if(keyState == GPIO_PIN_RESET)
        {
            HAL_Delay(btnDelay);            //延时跳过前抖动期
            keyState = HAL_GPIO_ReadPin(KeyLeft_GPIO_Port,KeyLeft_Pin);     //再采样
            if(keyState == GPIO_PIN_RESET)
                return Key_LEFT;
        }
?
        keyState = HAL_GPIO_ReadPin(KeyRight_GPIO_Port,KeyRight_Pin);
        if(keyState == GPIO_PIN_RESET)
        {
            HAL_Delay(btnDelay);            //延时跳过前抖动期
            keyState = HAL_GPIO_ReadPin(KeyRight_GPIO_Port,KeyRight_Pin);       //再采样
            if(keyState == GPIO_PIN_RESET)
                return Key_RIGHT;
        }
?
        keyState = HAL_GPIO_ReadPin(KeyDown_GPIO_Port,KeyDown_Pin);
        if(keyState == GPIO_PIN_RESET)
        {
            HAL_Delay(btnDelay);            //延时跳过前抖动期
            keyState = HAL_GPIO_ReadPin(KeyDown_GPIO_Port,KeyDown_Pin);     //再采样
            if(keyState == GPIO_PIN_RESET)
                return Key_DOWN;
        }
?
        keyState = HAL_GPIO_ReadPin(KeyUp_GPIO_Port,KeyUp_Pin);
        if(keyState == GPIO_PIN_SET)
        {
            HAL_Delay(btnDelay);            //延时跳过前抖动期
            keyState = HAL_GPIO_ReadPin(KeyUp_GPIO_Port,KeyUp_Pin);     //再采样
            if(keyState == GPIO_PIN_SET)
                return Key_UP;
        }
?
        if(timeout != KEY_WAIT_ALWAYS)
        {
            if((HAL_GetTick() == tickstart) > timeout)
                break;
        }
    }
    return key;
}
?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:41:35  更:2022-03-30 18:44:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:51:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码