首页 > 其他分享 >STM32微控制器GPIO库函数

STM32微控制器GPIO库函数

时间:2024-11-17 22:43:24浏览次数:3  
标签:HAL 引脚 LED STM32 Init InitStruct GPIO 库函数

STM32微控制器GPIO库函数

目录

  1. 概述

  2. GPIO库函数基础

  3. GPIO数学基础

  4. GPIO应用实例

  5. 常见问题与解决方法

  6. GPIO库函数基础

  7. GPIO初始化

  8. GPIO引脚操作

  9. GPIO高级功能

  10. 代码示例及解读


概述

通用输入/输出(GPIO)模块是STM32微控制器中最基本且最重要的外设之一。通过GPIO库函数,开发者可以方便地配置和操作GPIO引脚,实现与外部设备的数字信号交互,如控制LED、读取按钮状态、进行串行通信等。STM32提供了两种主要的外设库:HAL(硬件抽象层)库和标准外设库,每种库都有其独特的API和使用方法。

GPIO库函数基础

HAL库与标准外设库

STM32微控制器支持两种主要的外设库:

  • HAL库(Hardware Abstraction Layer):提供高级别的抽象,简化了外设的配置和操作,适合快速开发和跨系列移植。
  • 标准外设库:提供对底层寄存器的直接访问,适合需要精细控制和优化的应用。

本文主要介绍HAL库中的GPIO函数,并简要提及标准外设库的相关函数。

GPIO库函数分类

GPIO库函数主要分为以下几类:

  1. 初始化函数:用于配置GPIO引脚的模式、速度、输出类型和上拉/下拉电阻。
  2. 引脚操作函数:用于设置、重置和切换GPIO引脚的状态。
  3. 读取函数:用于读取GPIO引脚的当前状态。
  4. 中断配置函数:用于配置GPIO引脚的外部中断。
  5. 复用功能配置函数:用于配置GPIO引脚的复用功能,如USART、SPI等外设。

GPIO数学基础

理解GPIO(通用输入/输出)模块的数学基础对于有效配置和使用GPIO引脚至关重要。以下是一些关键的数学概念和公式,它们在GPIO应用中经常用到。

电阻分压公式

在配置上拉或下拉电阻时,电阻分压公式用于计算引脚电压。这对于确保引脚在不同状态下有正确的电压水平非常重要。

V p i n = V C C × R 2 R 1 + R 2 V_{pin} = V_{CC} \times \frac{R_2}{R_1 + R_2} Vpin​=VCC​×R1​+R2​R2​​

  • V p i n V_{pin} Vpin​:引脚电压
  • V C C V_{CC} VCC​:供电电压
  • R 1 R_1 R1​:上拉电阻
  • R 2 R_2 R2​:下拉电阻

应用实例:假设 V C C = 3.3 V V_{CC} = 3.3V VCC​=3.3V, R 1 = 10 k Ω R_1 = 10k\Omega R1​=10kΩ, R 2 = 10 k Ω R_2 = 10k\Omega R2​=10kΩ

V p i n = 3.3 V × 10 k Ω 10 k Ω + 10 k Ω = 1.65 V V_{pin} = 3.3V \times \frac{10k\Omega}{10k\Omega + 10k\Omega} = 1.65V Vpin​=3.3V×10kΩ+10kΩ10kΩ​=1.65V

输入电流计算

在输入模式下,引脚的输入电流可以通过电阻和电压计算。这有助于确保电流在安全范围内,避免损坏微控制器。

I i n = V C C R p u l l I_{in} = \frac{V_{CC}}{R_{pull}} Iin​=Rpull​VCC​​

  • I i n I_{in} Iin​:输入电流
  • R p u l l R_{pull} Rpull​:上拉或下拉电阻

示例: V C C = 3.3 V V_{CC} = 3.3V VCC​=3.3V, R p u l l = 10 k Ω R_{pull} = 10k\Omega Rpull​=10kΩ

I i n = 3.3 V 10 k Ω = 0.33 m A I_{in} = \frac{3.3V}{10k\Omega} = 0.33mA Iin​=10kΩ3.3V​=0.33mA

输出驱动能力

输出引脚的驱动能力决定了其能驱动的负载电流。确保不超过微控制器的规格限制,以防止损坏引脚。

I o u t = V O H − V O L R l o a d I_{out} = \frac{V_{OH} - V_{OL}}{R_{load}} Iout​=Rload​VOH​−VOL​​

  • V O H V_{OH} VOH​:高电平输出电压
  • V O L V_{OL} VOL​:低电平输出电压
  • R l o a d R_{load} Rload​:负载电阻

功率计算

GPIO引脚的功率消耗可以通过以下公式计算:

P G P I O = V G P I O × I G P I O P_{GPIO} = V_{GPIO} \times I_{GPIO} PGPIO​=VGPIO​×IGPIO​

  • P G P I O P_{GPIO} PGPIO​:GPIO引脚功率
  • V G P I O V_{GPIO} VGPIO​:GPIO引脚电压
  • I G P I O I_{GPIO} IGPIO​:GPIO引脚电流

RC时间常数

GPIO引脚连接电容性负载时,RC时间常数决定了信号的上升和下降时间。信号的稳定性和响应速度依赖于RC时间常数的合理配置。

τ = R × C \tau = R \times C τ=R×C

  • τ \tau τ:时间常数
  • R R R:电阻
  • C C C:电容

应用实例:若 R = 1 k Ω R = 1k\Omega R=1kΩ, C = 100 n F C = 100nF C=100nF

τ = 1 k Ω × 100 n F = 0.1 s \tau = 1k\Omega \times 100nF = 0.1s τ=1kΩ×100nF=0.1s


GPIO应用实例

实际应用中,GPIO库函数配合数学公式可以实现各种功能。以下是几个常见的GPIO应用实例,详细介绍了电路设计、数学计算和软件实现。

LED控制

通过GPIO引脚控制LED的开关,实现指示灯功能。

电路设计

  • 将LED通过限流电阻连接到GPIO输出引脚。
  • 负极连接到地。

数学计算

限流电阻的计算确保LED在安全电流下工作,防止烧毁LED或损坏微控制器引脚。

R = V C C − V L E D I L E D R = \frac{V_{CC} - V_{LED}}{I_{LED}} R=ILED​VCC​−VLED​​

  • V C C V_{CC} VCC​:供电电压(如3.3V)
  • V L E D V_{LED} VLED​:LED正向电压(如2V)
  • I L E D I_{LED} ILED​:LED工作电流(如20mA)

R = 3.3 V − 2 V 0.02 A = 65 Ω R = \frac{3.3V - 2V}{0.02A} = 65\Omega R=0.02A3.3V−2V​=65Ω

选择标准电阻值为68Ω,以确保安全。

按钮输入与中断

使用GPIO引脚读取按钮状态,并通过中断响应按钮按下事件,提高系统响应速度和效率。

电路设计

  • 按钮一端连接到GPIO输入引脚。
  • 另一端连接到地。
  • PUPDR寄存器中启用上拉电阻。

工作原理

  • 按钮未按下时,引脚通过上拉电阻维持高电平。
  • 按钮按下时,引脚被拉低,触发中断。

串行通信

通过GPIO引脚实现串行通信,如USART、SPI、I2C等,实现与其他设备的数据交换。

配置步骤

  1. 将相关引脚配置为复用功能模式。
  2. AFR寄存器中选择对应的复用功能。
  3. 使用相应的通信协议初始化和管理数据传输。

PWM信号生成

通过GPIO引脚生成PWM(脉宽调制)信号,用于控制电机速度、LED亮度等,实现模拟信号控制。

配置步骤

  1. 配置相关引脚为复用功能模式。
  2. 配置定时器以PWM模式工作。
  3. 设置PWM频率和占空比。

外部中断触发

通过GPIO引脚触发外部中断,实现对外部事件的快速响应,如传感器信号变化、紧急停止等。

配置步骤

  1. 配置GPIO引脚为输入模式,并启用上拉或下拉电阻。
  2. 配置EXTI寄存器以连接到特定的引脚。
  3. 配置中断触发类型(上升沿、下降沿、双边沿)。
  4. 使能中断并配置中断优先级。
  5. 编写中断服务程序(ISR)。

常见问题与解决方法

在使用STM32 GPIO库函数时,开发者可能会遇到各种问题。以下列出了一些常见问题及其解决方法,帮助您快速排除故障。

GPIO引脚无法正确读取输入状态

  • 原因

    • 未配置上拉/下拉电阻。
    • 外部电路连接问题,如按钮未正确接地。
    • 引脚损坏或未正确配置模式。
  • 解决方法

    • 检查并确保在GPIO_InitTypeDef结构体中正确配置Pull参数(GPIO_PULLUPGPIO_PULLDOWN)。
    • 确认外部电路连接是否正确,按钮连接到地或VCC。
    • 使用示波器或万用表检查引脚电压,确保信号稳定。
    • 重新初始化GPIO引脚,确保配置正确。

输出引脚无法驱动负载

  • 原因

    • 负载电流超过GPIO引脚的最大承载能力。
    • 连接电路错误,如短路或缺少限流电阻。
    • 引脚未正确配置为输出模式。
  • 解决方法

    • 检查负载电流是否在GPIO引脚规格范围内(通常不超过20mA)。
    • 确保在LED等负载前使用限流电阻。
    • 检查电路连接,避免短路。
    • 确认通过GPIO_InitTypeDef结构体正确配置引脚模式为输出。

复用功能引脚功能异常

  • 原因

    • 复用功能配置错误,未选择正确的复用功能编号。
    • AFR寄存器设置不当。
    • 相关外设未正确初始化。
  • 解决方法

    • 核对引脚的复用功能编号,确保选择正确的Alternate值。
    • 检查AFR寄存器配置,确保每个引脚的复用功能位正确设置。
    • 确保相关外设(如USART、SPI)的初始化代码正确无误。

中断无法触发

  • 原因

    • 中断未正确配置。
    • 中断未使能或优先级设置错误。
    • 外部信号变化未达到触发条件。
  • 解决方法

    • 检查中断配置步骤,确保EXTI寄存器正确配置。
    • 确认NVIC中断使能及优先级设置。
    • 使用调试工具验证外部信号是否达到中断触发条件。
    • 确保中断服务程序(ISR)正确实现。

信号抖动或不稳定

  • 原因

    • 输入信号未去抖动,尤其是机械按钮输入。
    • 电源噪声影响,引脚电压不稳定。
  • 解决方法

    • 在硬件电路中添加去抖电路,如RC滤波器或使用电容。
    • 在软件中实现去抖逻辑,通过延时和状态确认减少抖动影响。
    • 增加电源滤波电容,改善电源质量,减少噪声干扰。

功耗过高

  • 原因

    • 未使用的GPIO引脚未配置为低功耗模式。
    • 输出引脚持续高电流,导致微控制器功耗增加。
  • 解决方法

    • 配置未使用的GPIO引脚为模拟输入模式,以减少漏电流。
    • 检查输出引脚的负载,确保没有短路或过高电流。
    • 使用低功耗模式配置,减少GPIO引脚的电流消耗。

GPIO库函数基础

了解STM32的GPIO库函数是高效开发的关键。STM32提供了两种主要的外设库:HAL(硬件抽象层)库和标准外设库。本文将重点介绍HAL库中的GPIO函数,并简要提及标准外设库的相关函数。

HAL库与标准外设库

  • HAL库(Hardware Abstraction Layer)

    • 提供高级别的抽象,简化了外设的配置和操作。
    • 适合快速开发和跨系列移植。
    • 采用结构化编程风格,易于理解和使用。
  • 标准外设库

    • 提供对底层寄存器的直接访问。
    • 适合需要精细控制和优化的应用。
    • 编程风格更接近底层硬件,适合有一定经验的开发者。

GPIO库函数分类

GPIO库函数主要分为以下几类:

  1. 初始化函数:用于配置GPIO引脚的模式、速度、输出类型和上拉/下拉电阻。
  2. 引脚操作函数:用于设置、重置和切换GPIO引脚的状态。
  3. 读取函数:用于读取GPIO引脚的当前状态。
  4. 中断配置函数:用于配置GPIO引脚的外部中断。
  5. 复用功能配置函数:用于配置GPIO引脚的复用功能,如USART、SPI等外设。

GPIO初始化

GPIO初始化是使用GPIO库函数的第一步,涉及配置GPIO引脚的工作模式、速度、输出类型和上拉/下拉电阻等参数。

GPIO_InitTypeDef结构体

在HAL库中,GPIO的初始化依赖于GPIO_InitTypeDef结构体,该结构体包含了配置GPIO引脚所需的所有参数:

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;

HAL_GPIO_Init函数

HAL_GPIO_Init函数用于根据GPIO_InitTypeDef结构体的配置,初始化指定的GPIO端口:

HAL_StatusTypeDef HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init);
  • 参数:
    GPIOx:指向GPIO端口的指针(如GPIOA、GPIOB)。
    GPIO_Init:指向GPIO_InitTypeDef结构体的指针,包含引脚的配置参数。
  • 返回值:函数执行状态(成功或失败)。

标准外设库的GPIO初始化

在标准外设库中,GPIO初始化使用GPIO_Init函数和GPIO_InitTypeDef结构体:

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
  • 参数:
    GPIOx:指向GPIO端口的指针。
    GPIO_InitStruct:指向GPIO_InitTypeDef结构体的指针,包含引脚的配置参数。
  • 功能:根据结构体中的参数配置GPIO引脚。

GPIO引脚操作

在GPIO初始化完成后,可以使用GPIO库函数对引脚进行操作,包括设置引脚状态、切换引脚状态以及读取引脚状态。

设置引脚状态

HAL_GPIO_WritePin函数

HAL_GPIO_WritePin函数用于设置GPIO引脚的输出状态(高或低)。

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
  • 参数:
    GPIOx:指向GPIO端口的指针。
    GPIO_Pin:指定要设置的引脚(如GPIO_PIN_0)。
    PinState:引脚状态,GPIO_PIN_SET或GPIO_PIN_RESET。

使用示例:

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); // 设置PA5为高电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // 设置PA5为低电平

HAL_GPIO_TogglePin函数

HAL_GPIO_TogglePin函数用于切换GPIO引脚的当前状态。

void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
  • 参数:
    GPIOx:指向GPIO端口的指针。
    GPIO_Pin:指定要切换的引脚。

使用示例:

HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // 切换PA5的电平状态

读取引脚状态

HAL_GPIO_ReadPin函数

HAL_GPIO_ReadPin函数用于读取GPIO引脚的当前输入状态。

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
  • 参数:
    GPIOx:指向GPIO端口的指针。
    GPIO_Pin:指定要读取的引脚。
  • 返回值:引脚状态,GPIO_PIN_SET或GPIO_PIN_RESET。

使用示例:

GPIO_PinState pinState = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13);
if(pinState == GPIO_PIN_SET) {
    // 引脚为高电平
} else {
    // 引脚为低电平
}

GPIO高级功能

除了基本的引脚操作外,STM32 GPIO库函数还支持高级功能,如中断配置和复用功能配置,这些功能极大地扩展了GPIO的应用范围。

中断配置

GPIO引脚可以配置为外部中断源,响应外部信号的变化(上升沿、下降沿或双边沿),实现实时响应。

HAL_GPIO_EXTI_Callback函数

HAL_GPIO_EXTI_Callback是中断回调函数,当指定的GPIO引脚触发中断时会调用该函数。开发者需要在此函数中编写中断处理代码。

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
  • 参数:
    GPIO_Pin:触发中断的引脚编号。
    使用示例:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if(GPIO_Pin == GPIO_PIN_13) {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // 切换LED状态
    }
}

HAL_GPIO_EXTI_IRQHandler函数

HAL_GPIO_EXTI_IRQHandler用于处理中断事件,并调用回调函数。

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);
  • 参数:
    GPIO_Pin:触发中断的引脚编号。

使用示例:

在中断服务程序(ISR)中调用:

void EXTI15_10_IRQHandler(void) {
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
}

复用功能配置

复用功能允许GPIO引脚连接到其他外设,如USART、SPI、I2C等,实现多功能的引脚使用。

Alternate Function设置

在GPIO_InitTypeDef结构体中,通过设置Alternate成员来指定复用功能编号。

使用示例:配置PA9为USART1_TX,PA10为USART1_RX

GPIO_InitTypeDef GPIO_InitStruct = {0};

// 配置PA9为USART1_TX
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

// 配置PA10为USART1_RX
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

注意事项:

  • 每个引脚的复用功能编号(AF)需根据具体外设手册选择。
  • 确保相关外设(如USART)已经正确初始化。

代码示例及解读

以下是多个代码示例,展示如何使用STM32的GPIO库函数进行不同的操作,包括LED控制、按钮输入与中断、串行通信、PWM信号生成及外部中断触发。所有代码均使用HAL库实现,旨在帮助您理解和应用GPIO库函数。

示例代码1:LED控制

通过GPIO引脚控制LED的开关,实现指示灯功能。

#include "stm32f4xx_hal.h"

// LED引脚定义
#define LED_PIN GPIO_PIN_5
#define LED_GPIO_PORT GPIOA

// GPIO初始化函数
void GPIO_Init(void) {
    __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = LED_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出模式
    GPIO_InitStruct.Pull = GPIO_NOPULL;         // 无上拉/下拉
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
    HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);
}

// 延时函数
void delay(uint32_t time) {
    HAL_Delay(time);
}

int main(void) {
    HAL_Init();      // 初始化HAL库
    GPIO_Init();     // 初始化GPIO

    while (1) {
        HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_PIN); // 切换LED状态
        delay(500);                               // 延时500ms
    }
}

简要解读:

  1. GPIO初始化:
  • 启用GPIOA时钟。
  • 配置PA5为推挽输出模式,高速,无上拉/下拉电阻。
  1. 主循环:
  • 使用HAL_GPIO_TogglePin函数切换PA5引脚的电平,实现LED的闪烁。
  • 调用HAL_Delay函数实现500ms的延时控制闪烁频率。

示例代码2:按钮输入与中断

使用GPIO引脚读取按钮状态,并通过中断响应按钮按下事件,实现实时响应。

#include "stm32f4xx_hal.h"

// LED引脚定义
#define LED_PIN GPIO_PIN_5
#define LED_GPIO_PORT GPIOA

// 按钮引脚定义
#define BUTTON_PIN GPIO_PIN_13
#define BUTTON_GPIO_PORT GPIOC

// GPIO初始化函数
void GPIO_Init(void) {
    __HAL_RCC_GPIOA_CLK_ENABLE();  // 使能GPIOA时钟
    __HAL_RCC_GPIOC_CLK_ENABLE();  // 使能GPIOC时钟
    __HAL_RCC_SYSCFG_CLK_ENABLE(); // 使能SYSCFG时钟

    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // 配置PA5为输出模式
    GPIO_InitStruct.Pin = LED_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);

    // 配置PC13为输入模式,并设置为中断触发(下降沿)
    GPIO_InitStruct.Pin = BUTTON_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; // 下降沿触发中断
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(BUTTON_GPIO_PORT, &GPIO_InitStruct);
}

// 中断初始化函数
void EXTI_Init(void) {
    HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0); // 设置中断优先级
    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);         // 使能EXTI15_10中断
}

// 中断回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if(GPIO_Pin == BUTTON_PIN) {
        HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_PIN); // 切换LED状态
    }
}

int main(void) {
    HAL_Init();        // 初始化HAL库
    GPIO_Init();       // 初始化GPIO
    EXTI_Init();       // 初始化外部中断

    while (1) {
        // 主循环可以执行其他任务
    }
}

// 中断服务程序
void EXTI15_10_IRQHandler(void) {
    HAL_GPIO_EXTI_IRQHandler(BUTTON_PIN);
}

简要解读:

  1. GPIO初始化:
  • 配置PA5为输出模式,用于控制LED。
  • 配置PC13为输入模式,并设置为下降沿触发中断,启用上拉电阻。
  1. 中断初始化:
  • 设置EXTI15_10中断的优先级并使能中断。
  1. 中断回调:
  • 当按钮按下(PC13引脚检测到下降沿)时,回调函数HAL_GPIO_EXTI_Callback被调用,切换LED状态。
  1. 中断服务程序:
  • 调用HAL_GPIO_EXTI_IRQHandler处理中断,并触发回调函数。

示例代码3:串行通信(USART1)

通过GPIO引脚实现串行通信,实现与其他设备的数据交换。

#include "stm32f4xx_hal.h"

// USART1引脚定义
#define USART1_TX_PIN GPIO_PIN_9
#define USART1_RX_PIN GPIO_PIN_10
#define USART1_GPIO_PORT GPIOA
#define USART1_AF GPIO_AF7_USART1

// USART1句柄
UART_HandleTypeDef huart1;

// GPIO初始化函数
void GPIO_Init(void) {
    __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟

    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // 配置PA9为USART1_TX
    GPIO_InitStruct.Pin = USART1_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = USART1_AF;
    HAL_GPIO_Init(USART1_GPIO_PORT, &GPIO_InitStruct);

    // 配置PA10为USART1_RX
    GPIO_InitStruct.Pin = USART1_RX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Alternate = USART1_AF;
    HAL_GPIO_Init(USART1_GPIO_PORT, &GPIO_InitStruct);
}

// USART1初始化函数
void USART1_Init(void) {
    __HAL_RCC_USART1_CLK_ENABLE(); // 使能USART1时钟

    huart1.Instance = USART1;
    huart1.Init.BaudRate = 9600;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;

    HAL_UART_Init(&huart1);
}

// USART1发送字符函数
void USART1_SendChar(char c) {
    HAL_UART_Transmit(&huart1, (uint8_t*)&c, 1, HAL_MAX_DELAY);
}

// USART1接收字符函数
char USART1_ReceiveChar(void) {
    uint8_t c;
    HAL_UART_Receive(&huart1, &c, 1, HAL_MAX_DELAY);
    return c;
}

int main(void) {
    HAL_Init();        // 初始化HAL库
    GPIO_Init();       // 初始化GPIO
    USART1_Init();     // 初始化USART1

    while (1) {
        char received = USART1_ReceiveChar(); // 接收字符
        USART1_SendChar(received);             // 发送回显
    }
}

简要解读:

  1. GPIO初始化:
    配置PA9为USART1_TX,PA10为USART1_RX的复用功能模式。
  2. USART1初始化:
    设置波特率为9600,数据位为8位,无校验,1停止位,启用发送和接收功能。
  3. 发送与接收函数:
  • USART1_SendChar用于发送一个字符。
  • USART1_ReceiveChar用于接收一个字符。
  1. 主循环:
    实现简单的回显功能,接收到的字符将被发送回去。

示例代码4:PWM信号生成(TIM3_CH1在PA6上)

通过GPIO引脚生成PWM(脉宽调制)信号,用于控制电机速度、LED亮度等。

#include "stm32f4xx_hal.h"

// PWM引脚定义
#define PWM_PIN GPIO_PIN_6
#define PWM_GPIO_PORT GPIOA
#define PWM_AF GPIO_AF2_TIM3

// 定时器句柄
TIM_HandleTypeDef htim3;

// GPIO初始化函数
void GPIO_Init(void) {
    __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟

    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // 配置PA6为TIM3_CH1复用功能
    GPIO_InitStruct.Pin = PWM_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = PWM_AF;
    HAL_GPIO_Init(PWM_GPIO_PORT, &GPIO_InitStruct);
}

// TIM3初始化函数
void TIM3_PWM_Init(void) {
    __HAL_RCC_TIM3_CLK_ENABLE(); // 使能TIM3时钟

    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 1600 - 1;           // 预分频器
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim3.Init.Period = 10000 - 1;             // 自动重装载值
    htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_PWM_Init(&htim3);

    TIM_OC_InitTypeDef sConfigOC = {0};
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 2500;                    // 比较寄存器值,占空比25%
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);

    HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);   // 启动PWM
}

int main(void) {
    HAL_Init();        // 初始化HAL库
    GPIO_Init();       // 初始化GPIO
    TIM3_PWM_Init();   // 初始化TIM3 PWM

    while (1) {
        // 主循环可以进行占空比调整等操作
    }
}

简要解读:

  1. GPIO初始化:
    配置PA6为TIM3_CH1的复用功能模式。
  2. TIM3初始化:
  • 设置预分频器为1600,自动重装载值为10000,确定PWM频率。
  • 配置TIM3通道1为PWM模式1,占空比25%。
  • 启动TIM3的PWM输出。
  1. 主循环:
    主循环保持空闲,可用于动态调整PWM占空比,实现如LED亮度调节或电机速度控制。

示例代码5:外部中断触发(PC13)

通过GPIO引脚触发外部中断,实现对外部事件的快速响应。

#include "stm32f4xx_hal.h"

// LED引脚定义
#define LED_PIN GPIO_PIN_5
#define LED_GPIO_PORT GPIOA

// 按钮引脚定义
#define BUTTON_PIN GPIO_PIN_13
#define BUTTON_GPIO_PORT GPIOC

// GPIO初始化函数
void GPIO_Init(void) {
    __HAL_RCC_GPIOA_CLK_ENABLE();  // 使能GPIOA时钟
    __HAL_RCC_GPIOC_CLK_ENABLE();  // 使能GPIOC时钟
    __HAL_RCC_SYSCFG_CLK_ENABLE(); // 使能SYSCFG时钟

    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // 配置PA5为输出模式
    GPIO_InitStruct.Pin = LED_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);

    // 配置PC13为外部中断输入模式,启用上拉电阻
    GPIO_InitStruct.Pin = BUTTON_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; // 下降沿触发中断
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(BUTTON_GPIO_PORT, &GPIO_InitStruct);
}

// 中断初始化函数
void EXTI_Init(void) {
    HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0); // 设置中断优先级
    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);         // 使能EXTI15_10中断
}

// 中断回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if (GPIO_Pin == BUTTON_PIN) {
        HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_PIN); // 切换LED状态
    }
}

int main(void) {
    HAL_Init();        // 初始化HAL库
    GPIO_Init();       // 初始化GPIO
    EXTI_Init();       // 初始化外部中断

    while (1) {
        // 主循环可以执行其他任务
    }
}

// 中断服务程序
void EXTI15_10_IRQHandler(void) {
    HAL_GPIO_EXTI_IRQHandler(BUTTON_PIN);
}

简要解读:

  1. GPIO初始化:
  • 配置PA5为输出模式,用于控制LED。
  • 配置PC13为外部中断输入模式,启用上拉电阻。
  1. 中断初始化:
    设置EXTI15_10中断的优先级并使能中断。
  2. 中断回调:
    当按钮按下(PC13引脚检测到下降沿)时,回调函数HAL_GPIO_EXTI_Callback被调用,切换LED状态。
  3. 中断服务程序:
    调用HAL_GPIO_EXTI_IRQHandler处理中断,并触发回调函数。

标签:HAL,引脚,LED,STM32,Init,InitStruct,GPIO,库函数
From: https://blog.csdn.net/qq_44648285/article/details/143840337

相关文章

  • STM32移植u8g2图形库
    1.从GitHub上下载源代码,https://github.com/olikraus/u8g22.复制csrc文件夹(这是u8g2库在C语言环境下的源文件)到工程文件中,在所有的驱动文件(即u8x8_d_开头的文件)中只保留u8x8_d_ssd1306_128x64_noname.c(这是与以ssd1306为驱动芯片的0.96/1.3寸OLED屏幕进行通讯的实现函数),然后将......
  • STM32F103开发
    本节我们将会对STM32的硬件资源进行介绍,包括如下内容:点亮LED;检测按键按下和松开事件;串口;点亮128*128TFT_LCD液晶屏;一、点亮LED1.1电路原理图LED电路原理图如下图所示:其中:LED1连接到PA8`引脚,低电平点亮;LED2连接到PD2引脚,低电平点亮;1.2GPIO引脚介绍STM32F103RTC......
  • 【课程设计】单片机课程设计之基于STM32的LCD电子钟的设计(LVGL+TFT彩屏)
    零.前置说明 由于本项目使用了LVGL开源框架,建议至少了解一点LVGL,可看前置文章:【LVGL快速入门(一)】LVGL开源框架入门教程之框架移植_lvgl教程-CSDN博客【LVGL快速入门(二)】LVGL开源框架入门教程之框架使用(UI界面设计)_lvgl框架详解-CSDN博客【LVGL速成】LVGL修改标签文......
  • STM32F103简介
    自从大学毕业之后,已经很久没有接触STM32控制器了,最近打算学习一下LVGL,控制芯片计划使用STM32,因此这里我们会简单介绍有关STM32的知识。一、STM32F103RTC6介绍1.1命名规则我从网上买了一块STM32F103RTC6开发板,STM32F103RCT6各个字段的含义:STM32(芯片系列):STM32代表ARMCortex-......
  • GPIO通用输入输出端口
    GPIO概述GPIO的定义单片机的GPIO资源是实现单片机信号发生、接收或控制的一种资源STM8的通用输入输出端口用于芯片和外部设备或电路进行数据传输一组GPIO端口可以包含8个引脚,每个引脚可以被独立配置为数字输入或者输出口通过对单片机编程就可以控制相关的GPIO资源,实现......
  • 【OpenOCD 与 FT4232H 专栏 4 -- FT4232H 实现 USB 转 GPIO】
    文章目录FT4232H概述MPSSE功能应用示例GPIO控制通道C和D配置典型应用FT4232H概述FT4232H是一款由FTDI提供的多功能USB转串行接口芯片,广泛应用于各种电子和嵌入式系统中。它具有四个独立的通道,每个通道可以配置为不同的模式以支持多种通信协议。FT423......
  • STM32F407使用LVGL之字库IC
    LVGL使用字库IC-基于STM32F407在上一篇笔记中,记录了所以用STM32F407移植LVGL。其中提到了中文显示,使用的是字库IC。相比于大多数使用的数组字库方式,使用字库IC编译后占用更小的存储空间,可以解码并显示更多的汉字,能够支持更多的字体大小等。字库IC读取字形数据根据自己所使用......
  • JPQL与数据库函数的完美结合实例
    在Java持久化操作中,JPQL(JavaPersistenceQueryLanguage)是一种强大的查询语言,它允许开发者以面向对象的方式执行数据库查询。JPQL不仅支持对实体属性的查询,还支持调用内置和用户自定义的数据库函数。本文将通过一个具体实例,展示如何在JPQL中调用H2数据库的内置函数,以实现更......
  • 基于STM32通过TM1637驱动4位数码管详细解析(可直接移植使用)
    目录1. 单位数码管概述2. 对应编码2.1 共阳数码管2.2 共阴数码管3. TM1637驱动数码管3.1 工作原理3.1.1 读键扫数据3.1.2 显示器寄存器地址和显示模式3.2 时序3.2.1 指令数据传输过程(读案件数据时序)3.2.2 写SRAM数据地址自动加1模式3.2.3 ......
  • 【提高篇】3.3 GPIO(三,工作模式详解 上)
    目录一,工作模式介绍二,输入浮空三,输入上拉一,工作模式介绍GPIO有八种工作模式,参考下面列表,我们先有一个简单的认识。二,输入浮空在输入浮空模式下,上拉/下拉电阻为断开状态,施密特触发器打开,输出被禁止。输入浮空模式下,IO口的电平完全是由外部电路决定。如果IO引脚没有......