首页 > 其他分享 >STM32——GPIO

STM32——GPIO

时间:2024-11-28 11:00:42浏览次数:8  
标签:HAL 引脚 gpioInitStruct STM32 TIM Init GPIO

目录

一、基础知识

           (一)基本特性

                        数字和模拟信号

                        IO端口基本结构

           (二)引脚配置

       多路复用——基于stm32f103

       引脚电气特性

二、工作原理

           (一)逻辑状态

           (二)输入模式与输出模式的区别

           (三)基于中断的GPIO输入

三、控制方法

           (一) 硬件端口的配置

                        寄存器配置(8种工作模式)

      端口初始化

           (二)使用编程语言控制GPIO

       C语言基础操作

       使用库函数(HAL库)

            (三)示例代码讲解

        点亮LED

四、应用实例(PWM)——基于stm32f407

           (一) LED闪烁

           (二)LED流水灯

           (三)控制电机和蜂鸣器

五、调试与故障排除


一、基础知识

(一)基本特性

  • 数字和模拟信号
    • 数字信号

           基本概念:两种逻辑状态:逻辑高(1,接近VDD)和逻辑低(0,接近GND)。

           处理机制:GPIO操作、通信接口、中断驱动

    • 模拟信号

           处理机制:ADC、DAC、Op-Amps

  • IO端口基本结构
    • 端口
    • 引脚:包括GPIO(通用输入/输出)和其他引脚。
    • 寄存器

(二)引脚配置

  • 多路复用——基于stm32f103
    • // 以配置USART1为例  
      __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟  
      __HAL_RCC_USART1_CLK_ENABLE(); // 使能USART1时钟
      //使用HAL库的GPIO初始化函数,设置GPIO引脚的模式、输出类型以及复用功能。
      
      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_NOPULL; // 无上拉或下拉  
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 设置为高速  
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);  
      
      // 配置PA10为USART1_RX,如果需要  
      GPIO_InitStruct.Pin = GPIO_PIN_10;  
      // 其余配置与USART1_TX相同  
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

      对STM32F1系列来说,复用功能由特定的引脚与外设映射定义,因此选择特定复用功能的步骤主要通过正确选择引脚和外设关联来实现,并不需要像STM32F4系列那样设置AFR寄存器。

  • 引脚电气特性
    • 引脚输出类型

      • 推挽(Push-Pull):可主动输出高/低电平,适合大多数输出场景。
      • 开漏(Open-Drain):只能输出低电平,高电平依赖外部上拉,适用于总线通信。
    • 驱动能力与速度

      • 低功耗:低电流驱动,适合功耗敏感应用。
      • 中速:平衡电流和速度,适用于通用目的。
      • 高速:高电流驱动,适用于高速信号或大负载。
    • 上拉/下拉配置

      • 上拉(Pull-up):高电平稳定,避免悬空。
      • 下拉(Pull-down):低电平稳定,避免悬空。
    • 模拟模式

      • ADC/DAC转换,减少数字噪音干扰。

二、工作原理

(一)逻辑状态

  • 低电平(逻辑0)

  • 高电平(逻辑1)

  • 中断触发(ISR)

(二)输入模式与输出模式的区别

  • 方向性

  • 电阻状态

  • 应用目的

(三)基于中断的GPIO输入

  1. 使能GPIO端口时钟:确保GPIO端口的时钟使能,以供后续配置。

  2. 配置GPIO引脚为输入模式:通过GPIO初始化结构体设置引脚为输入模式,并定义上拉、下拉等电气特性。

  3. 配置中断触发条件:根据需要选择适当的触发条件,如上升沿、下降沿或双边沿触发。

  4. 使能中断和设置优先级:在NVIC(Nested Vectored Interrupt Controller)中使能GPIO中断,并设置其优先级。

  5. 实现中断服务程序(ISR):编写ISR以处理当中断发生时需要执行的任务,例如读取传感器数据、更改系统状态等。

        

三、控制方法

(一) 硬件端口的配置

  • 寄存器配置(8种工作模式)
  • 端口初始化
    • 启用外设时钟
      • __HAL_RCC_GPIOA_CLK_ENABLE(); // 启用GPIOA时钟
        __HAL_RCC_TIM1_CLK_ENABLE();   // 启用定时器1时钟
        
    • 配置GPIO引脚
      • GPIO_InitTypeDef gpioInitStruct = {0};
        gpioInitStruct.Pin = GPIO_PIN_0; // 选择引脚PA0
        gpioInitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出模式
        gpioInitStruct.Pull = GPIO_NOPULL; // 无上下拉
        gpioInitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 低速
        
        HAL_GPIO_Init(GPIOA, &gpioInitStruct); // 初始化GPIO
        
    • 配置定时器和PWM
      • TIM_HandleTypeDef htim1;
        
        void MX_TIM1_Init(void) {
            TIM_OC_InitTypeDef ocInitStruct = {0};
            
            htim1.Instance = TIM1; // 选择定时器1
            htim1.Init.Prescaler = 84 - 1; // 设置预分频器
            htim1.Init.Period = 100 - 1; // 设置PWM周期
            htim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 向上计数
            htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
        
            HAL_TIM_PWM_Init(&htim1); // 初始化定时器
        
            // 配置PWM参数
            ocInitStruct.OCMode = TIM_OCMODE_PWM1;
            ocInitStruct.Pulse = 0; // 初始占空比为0
            ocInitStruct.OCPolarity = TIM_OCPOLARITY_HIGH;
            ocInitStruct.OCFastMode = TIM_OCFAST_DISABLE;
        
            HAL_TIM_PWM_ConfigChannel(&htim1, &ocInitStruct, TIM_CHANNEL_1); // 配置PWM通道
        }
        

(二)使用编程语言控制GPIO

  • C语言基础操作
  • 使用库函数(HAL库)
    1. 启用GPIO时钟

      __HAL_RCC_GPIOC_CLK_ENABLE(); // 启用GPIOC时钟
      
    2. 配置GPIOC引脚

      GPIO_InitTypeDef gpioInitStruct = {0};
      gpioInitStruct.Pin = GPIO_PIN_0; // 选择引脚PC0
      gpioInitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出模式
      gpioInitStruct.Pull = GPIO_NOPULL; // 无上下拉
      gpioInitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 低速
      
      HAL_GPIO_Init(GPIOC, &gpioInitStruct); // 初始化PC0
      
    3. 设置引脚状态

      HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); // 将PC0设置为高
      HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); // 将PC0设置为低
      
    4. 读取引脚状态

      GPIO_PinState pinState = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_0); // 读取PC0状态
      

(三)示例代码讲解

  • 点亮LED
    • //Arduino
      
      #define LED_PIN 13 // LED引脚
      
      void setup() {
          pinMode(LED_PIN, OUTPUT); // 设置引脚为输出
      }
      
      void loop() {
          digitalWrite(LED_PIN, HIGH); // 点亮LED
          delay(1000);                  // 延时1秒
          digitalWrite(LED_PIN, LOW);  // 熄灭LED
          delay(1000);                  // 延时1秒
      }
      

四、应用实例(PWM)——基于stm32f407

(一)LED闪烁

  • #include "main.h"
    
    // 定义LED引脚
    const uint16_t ledPin = GPIO_PIN_0; // 选择PA0作为LED引脚
    
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    
    int main(void) {
        HAL_Init();
        SystemClock_Config();
        MX_GPIO_Init();
    
        while (1) {
            HAL_GPIO_WritePin(GPIOA, ledPin, GPIO_PIN_SET);   // 点亮LED
            HAL_Delay(500);                                    // 延时500毫秒
            HAL_GPIO_WritePin(GPIOA, ledPin, GPIO_PIN_RESET); // 熄灭LED
            HAL_Delay(500);                                    // 延时500毫秒
        }
    }
    
    static void MX_GPIO_Init(void) {
        __HAL_RCC_GPIOA_CLK_ENABLE();
    
        GPIO_InitTypeDef gpioInitStruct = {0};
        gpioInitStruct.Pin = ledPin;                          // 设置引脚
        gpioInitStruct.Mode = GPIO_MODE_OUTPUT_PP;            // 推挽输出模式
        gpioInitStruct.Pull = GPIO_NOPULL;                    // 不使用上拉或下拉
        gpioInitStruct.Speed = GPIO_SPEED_FREQ_LOW;           // 低速
    
        HAL_GPIO_Init(GPIOA, &gpioInitStruct);               // 初始化GPIO引脚
    }
    

(二)LED流水灯

  • #include "main.h"
    
    // 定义LED引脚数组
    const uint16_t ledPins[] = { GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3 };
    const uint8_t ledCount = sizeof(ledPins) / sizeof(ledPins[0]);
    
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    
    int main(void) {
        HAL_Init();
        SystemClock_Config();
        MX_GPIO_Init();
    
        while (1) {
            for (uint8_t i = 0; i < ledCount; i++) {
                HAL_GPIO_WritePin(GPIOA, ledPins[i], GPIO_PIN_SET);   // 点亮LED
                HAL_Delay(250);                                       // 延时
                HAL_GPIO_WritePin(GPIOA, ledPins[i], GPIO_PIN_RESET); // 熄灭LED
            }
        }
    }
    
    static void MX_GPIO_Init(void) {
        __HAL_RCC_GPIOA_CLK_ENABLE();
    
        GPIO_InitTypeDef gpioInitStruct = {0};
        gpioInitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        gpioInitStruct.Pull = GPIO_NOPULL;
        gpioInitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    
        // 为所有LED引脚初始化
        for (uint8_t i = 0; i < ledCount; i++) {
            gpioInitStruct.Pin = ledPins[i];
            HAL_GPIO_Init(GPIOA, &gpioInitStruct);
        }
    }
    

(三)控制电机和蜂鸣器

  • //PWM初始化与配置
    
    static void MX_TIM_Init(void) {
        __HAL_RCC_TIM1_CLK_ENABLE(); // 启用定时器1时钟
    
        TIM_OC_InitTypeDef ocInitStruct = {0};
        htim1.Instance = TIM1; // 选择定时器1
        htim1.Init.Prescaler = 84 - 1; // 设置预分频器(假设时钟频率为84MHz,分频到1MHz)
        htim1.Init.Period = 100 - 1; // 设置PWM周期(100us)
        htim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 向上计数
        htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
        
        HAL_TIM_PWM_Init(&htim1); // 初始化定时器
        
        // 设置PWM参数
        ocInitStruct.OCMode = TIM_OCMODE_PWM1;
        ocInitStruct.Pulse = 0; // 初始占空比为0
        ocInitStruct.OCPolarity = TIM_OCPOLARITY_HIGH;
        ocInitStruct.OCFastMode = TIM_OCFAST_DISABLE;
    
        HAL_TIM_PWM_ConfigChannel(&htim1, &ocInitStruct, TIM_CHANNEL_1); // 配置PWM通道
    }
    
    //控制电机和蜂鸣器
    
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // 启动PWM
    
    // 控制电机转动
    for (uint32_t dutyCycle = 0; dutyCycle <= 100; dutyCycle += 10) {
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, dutyCycle); // 设置PWM占空比
        HAL_Delay(500); // 延时500毫秒
    }
    
    // 控制蜂鸣器发声
    for (uint32_t freq = 500; freq <= 2000; freq += 500) {
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 50); // 设置占空比
        HAL_TIM_Base_Start(&htim1); // 启动定时器
        HAL_Delay(500); // 延时500毫秒
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 0); // 关闭蜂鸣器
        HAL_Delay(500); // 延时500毫秒
    }
    

五、调试与故障排除

  • USB Type-C接口自身并不直接支持传统的硬件级串口通信

标签:HAL,引脚,gpioInitStruct,STM32,TIM,Init,GPIO
From: https://blog.csdn.net/Proton17/article/details/144037408

相关文章

  • 26 基于STM32的智能门禁系统(指纹、蓝牙、刷卡、OLED、电机)
    目录一、主要功能二、硬件资源三、程序编程四、实现现象一、主要功能基于STM32单片机,六个按键,分别代表指纹、蓝牙、刷卡的正确进门与错误进门;比如第一个按键按下,表示指纹正确,OLED显示指纹正确,开门,第二个按键按下的话,则指纹错误,OLED显示指纹错误,请重试,第二个按键连......
  • STM32和STM8开发工具、常用软件和开发环境汇总
    文章目录一、前言二、KeilC51软件三、KeilMDK-ARM四、STM32CubeMX及HAL库五、STM32CubeIDE六、STM8CubeMX七、STM32ST-LINKUtility一、前言整理一些常见的STM32/STM8开发所需要的安装包和工具。可以分别去官网下载最新的安装包。也可以通过关注【小康师兄】......
  • STM32 cubeIDE 可执行文件 *.elf 的烧录
    1.准备工具:ST_LINKST-Link/V2 JTAG/SWD标准的接口排列:2.用杜邦线连接单片机3.开始烧录方法1:Ctrl+B编译项目成功后,右键项目名-Runas- STM32 C/C++Application方法2:Ctrl+B编译项目成功后,点击RunDebug按钮,直接烧录。当有多个程序时,默认烧写最近烧录过的程序,点击......
  • 除Keil和IAR之外的STM32开发环境
    3.STM32CubeIDESTM32CubeIDE是ST公司针对STM32推出的一款集成开发环境。 官网地址:https://www.st.com/stm32cubeide1.优点ST官方软件,对STM32开发很友好。基于Eclipse工具链,界面更现代化。免费、免费、免费。2.缺点仅限STM32,不支持其他厂家单片机。推出时间不长,存在一......
  • stm32 CRC32实现代码及软硬方式测试
    一、概叙:1、本文主要是针对常用的crc32的实现方式进行说明2、crc32的软件方式和硬件方式时间上的差异二、实现:1、软件实现代码1/***@brief软件crc32计算*@paramptr输入的32位数组*@paramlen32位数组的长度*@returnu32......
  • 关于STM32存储、内存分析(为何从0x8000起始)
    关于图上的几个问题(图从左往右看)1.为什么STM32的理论地址范围(寻址范围)为4G?STM32的地址总线为32位,32位可以理解为物理的引脚,32只引脚通过拉高拉低,也就是选择0或者1,32位2进制=2的32次方=4294967296组地址,一个地址对应一个字节,即:4294967296字节=4194304KB=4096MB=4GB地址总线......
  • 成为点灯大师的日志一——STM32之按键控制LED
    1、接线图展示注:图片来源江科大,此处3口也要接一个LED注:OLED用于检测说明按键按下2、原理说明利用按键按下过程检测到的电平变化来判断按键是否按下,通过改变Num的值来改变LED的状态利用Num的变化来实现LED多模式转换。3、代码实现Key.h#ifndef__KEY_H#define__KE......
  • STM32定时器中断原理及模板代码
    ———————————————————————————————————————————主要关注预分频器和中断重装载寄存器和计数器,这三个寄存器合称为时基单元基本定时器只能使用内部时钟(频率为72MHz)预分频器:        可以用预分频器将72MHz分频    ......
  • STM32 CAN的HAL库简单使用
    一、CAN的基本知识1.物理层差分信号ISO11898标准:高速、短距离“闭环网络”,它的总线最大长度为40m,通信速度最高为1Mbps,总线的两端各要求有一个“120欧”的电阻。ISO11519-2标准:低速、远距离“开环网络”它的最大传输距离为1km,最高通讯速率为125kbps,两根总线是独立的、不形......
  • STM32 通过按键方式触发中断的处理流程
    需求:通过按键方式触发中断中断处理流程整体流程图片首先中断处理源有三个方向方向:1:内核其他控件(灰色的图2)有可以配置的,配置优先级也有固定的,优先级最高,数越小优先级越高2:片上外设:位于CPU外部,STM32芯片内部(白色的图3)3:片上外设,EXTI专门管理外部中断  通过需求......