STMicroelectronics 系列:STM32G4 系列_(11).STM32G4系列编程基础

STM32G4系列编程基础

1. 开发环境搭建

1.1 安装STM32CubeIDE

STM32CubeIDE 是 STMicroelectronics 提供的集成开发环境(IDE),它不仅支持代码编辑,还集成了项目管理、调试工具和代码生成器。以下是安装 STM32CubeIDE 的步骤:

  1. 下载安装包

    访问 STMicroelectronics 官方网站,下载最新版本的 STM32CubeIDE 安装包。

  2. 运行安装程序

    双击下载的安装包,运行安装程序。按照提示选择安装路径和组件。

  3. 安装完成后启动

    安装完成后,启动 STM32CubeIDE。首次启动时,软件会提示你选择工作空间,选择一个合适的文件夹即可。

1.2 创建新项目

  1. 启动STM32CubeIDE

    打开 STM32CubeIDE,选择 File -> New -> STM32 Project

  2. 选择目标芯片

    在弹出的对话框中,选择你使用的 STM32G4 系列芯片。例如,选择 STM32G431KB

  3. 配置项目

    选择项目名称和保存路径,点击 Next。在下一个界面中,可以配置项目的生成选项,如选择 HAL 库或 LL 库。

  4. 配置外设

    进入 Pinout & Configuration 选项卡,配置所需的外设。例如,配置 GPIO、定时器、ADC 等。

  5. 生成代码

    配置完成后,点击 Generate Code。IDE 会自动生成初始化代码和必要的库文件。

1.3 项目结构

生成的项目结构如下:


STM32G4_Project

├── .cproject

├── .project

├── CMakeLists.txt

├── README.md

├── STM32G4xx_HAL_Driver

│   ├── Inc

│   └── Src

├── STM32G4xx_JC

├── STM32G4xx_Libraries

│   └── CMSIS

│       ├── Device

│       └── DSP

├── STM32G4xx_StdPeriph_Driver

├── core

│   └── src

├── inc

├── src

│   ├── main.c

│   ├── stm32g4xx_hal_msp.c

│   └── stm32g4xx_it.c

  • .cproject.project:Eclipse 项目文件。

  • CMakeLists.txt:CMake 项目配置文件。

  • STM32G4xx_HAL_DriverSTM32G4xx_StdPeriph_Driver:HAL 和标准外设库文件。

  • STM32G4xx_JCSTM32G4xx_Libraries:芯片相关的库文件。

  • core:包含核心文件。

  • inc:包含头文件。

  • src:包含源文件,如 main.cstm32g4xx_hal_msp.cstm32g4xx_it.c

  • 2. GPIO编程

    2.1 GPIO基础

    GPIO(General Purpose Input Output)是通用输入输出端口,用于控制外设或与外部设备进行通信。STM32G4 系列提供了多个 GPIO 端口,每个端口有 16 个引脚。

    2.2 配置GPIO

    1. 选择GPIO端口和引脚

      Pinout & Configuration 选项卡中,选择需要配置的 GPIO 端口和引脚。例如,选择 PA0 作为输出引脚。

    2. 设置GPIO模式

      右键点击 PA0,选择 GPIO,然后设置引脚模式为 Output

    3. 生成代码

      配置完成后,点击 Generate Code 生成初始化代码。

    2.3 代码示例

    以下是一个简单的 GPIO 输出示例,控制 PA0 引脚的高低电平:

    
    // main.c
    
    #include "main.h"
    
    #include "stm32g4xx_hal.h"
    
    
    
    // 定义 GPIO 引脚
    
    #define LED_PIN GPIO_PIN_0
    
    #define LED_GPIO_PORT GPIOA
    
    
    
    void SystemClock_Config(void);
    
    static void MX_GPIO_Init(void);
    
    
    
    int main(void)
    
    {
    
        // 初始化 HAL 库
    
        HAL_Init();
    
    
    
        // 配置系统时钟
    
        SystemClock_Config();
    
    
    
        // 初始化 GPIO
    
        MX_GPIO_Init();
    
    
    
        while (1)
    
        {
    
            // 设置 PA0 引脚为高电平
    
            HAL_GPIO_WritePin(LED_GPIO_PORT, LED_PIN, GPIO_PIN_SET);
    
            HAL_Delay(500); // 延时 500 毫秒
    
    
    
            // 设置 PA0 引脚为低电平
    
            HAL_GPIO_WritePin(LED_GPIO_PORT, LED_PIN, GPIO_PIN_RESET);
    
            HAL_Delay(500); // 延时 500 毫秒
    
        }
    
    }
    
    
    
    void SystemClock_Config(void)
    
    {
    
        // 配置系统时钟
    
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    
    
        // 初始化振荡器
    
        RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    
        RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    
        RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    
        HAL_RCC_OscConfig(&RCC_OscInitStruct);
    
    
    
        // 初始化时钟
    
        RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    
        RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    
        RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    
        RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
        HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
    
    }
    
    
    
    static void MX_GPIO_Init(void)
    
    {
    
        GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    
    
        // 使能 GPIOA 时钟
    
        __HAL_RCC_GPIOA_CLK_ENABLE();
    
    
    
        // 配置 PA0 为输出模式
    
        GPIO_InitStruct.Pin = LED_PIN;
    
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    
        GPIO_InitStruct.Pull = GPIO_NOPULL;
    
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    
        HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);
    
    }
    
    

    2.4 代码解释

  • HAL_GPIO_WritePin:用于设置 GPIO 引脚的高低电平。

  • HAL_Delay:用于延时,单位为毫秒。

  • SystemClock_Config:配置系统时钟,使用内部高速振荡器(HSI)。

  • MX_GPIO_Init:初始化 GPIO 引脚,设置为推挽输出模式。

  • 3. 定时器编程

    3.1 定时器基础

    定时器是单片机中常用的外设,用于生成时间间隔或周期性中断。STM32G4 系列提供了多种定时器,包括基本定时器、通用定时器和高级定时器。

    3.2 配置定时器

    1. 选择定时器

      Pinout & Configuration 选项卡中,选择需要配置的定时器。例如,选择 TIM2

    2. 设置定时器参数

      右键点击 TIM2,选择 Timer,然后设置定时器的时钟源、预分频值、自动重装载值等参数。

    3. 生成代码

      配置完成后,点击 Generate Code 生成初始化代码。

    3.3 代码示例

    以下是一个使用 TIM2 生成周期性中断的示例:

    
    // main.c
    
    #include "main.h"
    
    #include "stm32g4xx_hal.h"
    
    
    
    // 定义定时器句柄
    
    TIM_HandleTypeDef htim2;
    
    
    
    void SystemClock_Config(void);
    
    static void MX_GPIO_Init(void);
    
    static void MX_TIM2_Init(void);
    
    
    
    int main(void)
    
    {
    
        // 初始化 HAL 库
    
        HAL_Init();
    
    
    
        // 配置系统时钟
    
        SystemClock_Config();
    
    
    
        // 初始化 GPIO
    
        MX_GPIO_Init();
    
    
    
        // 初始化 TIM2
    
        MX_TIM2_Init();
    
    
    
        // 启动定时器
    
        HAL_TIM_Base_Start_IT(&htim2);
    
    
    
        while (1)
    
        {
    
            // 主循环
    
        }
    
    }
    
    
    
    void SystemClock_Config(void)
    
    {
    
        // 配置系统时钟
    
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    
    
        // 初始化振荡器
    
        RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    
        RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    
        RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    
        HAL_RCC_OscConfig(&RCC_OscInitStruct);
    
    
    
        // 初始化时钟
    
        RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    
        RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    
        RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    
        RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
        HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
    
    }
    
    
    
    static void MX_GPIO_Init(void)
    
    {
    
        GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    
    
        // 使能 GPIOA 时钟
    
        __HAL_RCC_GPIOA_CLK_ENABLE();
    
    
    
        // 配置 PA0 为输出模式
    
        GPIO_InitStruct.Pin = GPIO_PIN_0;
    
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    
        GPIO_InitStruct.Pull = GPIO_NOPULL;
    
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    }
    
    
    
    static void MX_TIM2_Init(void)
    
    {
    
        TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    
        TIM_MasterConfigTypeDef sMasterConfig = {0};
    
    
    
        // 使能 TIM2 时钟
    
        __HAL_RCC_TIM2_CLK_ENABLE();
    
    
    
        // 配置定时器
    
        htim2.Instance = TIM2;
    
        htim2.Init.Prescaler = 8000 - 1; // 预分频值,假设系统时钟为 80 MHz
    
        htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    
        htim2.Init.Period = 1000 - 1; // 自动重装载值,1 ms
    
        htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    
        htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    
        HAL_TIM_Base_Init(&htim2);
    
    
    
        // 配置时钟源
    
        sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    
        HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig);
    
    
    
        // 配置主模式
    
        sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    
        sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    
        HAL_TIM_MasterConfigSynchronization(&htim2, &sMasterConfig);
    
    }
    
    
    
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    
    {
    
        // 定时器中断处理函数
    
        if (htim == &htim2)
    
        {
    
            // 切换 PA0 引脚电平
    
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
    
        }
    
    }
    
    

    3.4 代码解释

  • htim2:定时器句柄,用于操作定时器。

  • HAL_TIM_Base_Init:初始化定时器基类。

  • HAL_TIM_ConfigClockSource:配置定时器时钟源。

  • HAL_TIM_MasterConfigSynchronization:配置定时器主模式同步。

  • HAL_TIM_Base_Start_IT:启动定时器并使能中断。

  • HAL_TIM_PeriodElapsedCallback:定时器周期中断处理函数,用于在每个周期结束时执行特定操作,如切换 LED 状态。

  • 4. ADC编程

    4.1 ADC基础

    ADC(Analog-to-Digital Converter)是模数转换器,用于将模拟信号转换为数字信号。STM32G4 系列提供了多通道 ADC,支持多种采样模式和数据处理方式。ADC 在嵌入式系统中非常有用,可以用于测量温度、电压、电流等模拟信号。

    4.2 配置ADC

    1. 选择ADC通道

      Pinout & Configuration 选项卡中,选择需要配置的 ADC 通道。例如,选择 PA0 作为 ADC 通道。

    2. 设置ADC参数

      右键点击 ADC1,选择 Analog-to-Digital,然后设置采样时间、分辨率等参数。例如,设置采样时间为 239.5 个周期,分辨率选择为 12 位。

    3. 生成代码

      配置完成后,点击 Generate Code 生成初始化代码。IDE 会自动生成必要的 ADC 初始化函数和配置。

    4.3 代码示例

    以下是一个使用 ADC1 读取 PA0 通道上的模拟值并显示在串口上的示例:

    
    // main.c
    
    #include "main.h"
    
    #include "stm32g4xx_hal.h"
    
    #include "usart.h"
    
    
    
    // 定义 ADC 句柄
    
    ADC_HandleTypeDef hadc1;
    
    
    
    // 定义 UART 句柄
    
    UART_HandleTypeDef huart1;
    
    
    
    void SystemClock_Config(void);
    
    static void MX_GPIO_Init(void);
    
    static void MX_ADC1_Init(void);
    
    static void MX_USART1_UART_Init(void);
    
    
    
    int main(void)
    
    {
    
        // 初始化 HAL 库
    
        HAL_Init();
    
    
    
        // 配置系统时钟
    
        SystemClock_Config();
    
    
    
        // 初始化 GPIO
    
        MX_GPIO_Init();
    
    
    
        // 初始化 ADC
    
        MX_ADC1_Init();
    
    
    
        // 初始化 UART
    
        MX_USART1_UART_Init();
    
    
    
        while (1)
    
        {
    
            // 读取 ADC 值
    
            HAL_ADC_Start(&hadc1); // 启动 ADC 转换
    
            uint32_t adc_value = 0;
    
            HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); // 等待转换完成
    
            adc_value = HAL_ADC_GetValue(&hadc1); // 获取转换结果
    
    
    
            // 显示 ADC 值到串口
    
            char buffer[50];
    
            sprintf(buffer, "ADC Value: %lu\r\n", adc_value);
    
            HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), HAL_MAXDELAY);
    
    
    
            // 延时 1 秒
    
            HAL_Delay(1000);
    
        }
    
    }
    
    
    
    void SystemClock_Config(void)
    
    {
    
        // 配置系统时钟
    
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    
    
        // 初始化振荡器
    
        RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    
        RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    
        RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    
        HAL_RCC_OscConfig(&RCC_OscInitStruct);
    
    
    
        // 初始化时钟
    
        RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    
        RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    
        RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    
        RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
        HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
    
    }
    
    
    
    static void MX_GPIO_Init(void)
    
    {
    
        GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    
    
        // 使能 GPIOA 时钟
    
        __HAL_RCC_GPIOA_CLK_ENABLE();
    
    
    
        // 配置 PA0 为模拟输入
    
        GPIO_InitStruct.Pin = GPIO_PIN_0;
    
        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    
        GPIO_InitStruct.Pull = GPIO_NOPULL;
    
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    }
    
    
    
    static void MX_ADC1_Init(void)
    
    {
    
        ADC_ChannelConfTypeDef sConfig = {0};
    
    
    
        // 使能 ADC1 时钟
    
        __HAL_RCC_ADC12_CLK_ENABLE();
    
    
    
        // 配置 ADC1
    
        hadc1.Instance = ADC1;
    
        hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; // 单通道模式
    
        hadc1.Init.ContinuousConvMode = DISABLE; // 单次转换模式
    
        hadc1.Init.DiscontinuousConvMode = DISABLE; // 连续转换模式
    
        hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发
    
        hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 右对齐
    
        hadc1.Init.NbrOfConversion = 1; // 转换次数
    
        hadc1.Init.NbrOfDiscConversion = 1; // 不连续转换次数
    
        hadc1.Init.AutoInjectionMode = DISABLE; // 禁用自动注入模式
    
        hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // 单次转换结束时中断
    
        hadc1.Init.LowPowerAutoWait = DISABLE; // 禁用低功耗自动等待
    
        hadc1.Init.LowPowerFrequencyMode = ENABLE; // 低功耗频率模式
    
        hadc1.Init.LowPowerAutoPowerOff = DISABLE; // 禁用低功耗自动关闭
    
        hadc1.Init.ConversionCtxt = 0x00000000; // 转换上下文
    
        hadc1.Init.OversamplingMode = DISABLE; // 禁用过采样模式
    
        hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH; // 高触发频率模式
    
        HAL_ADC_Init(&hadc1);
    
    
    
        // 配置 ADC 通道
    
        sConfig.Channel = ADC_CHANNEL_0; // 通道 0
    
        sConfig.Rank = ADC_REGULAR_RANK_1; // 正常序列 1
    
        sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; // 采样时间
    
        HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    }
    
    
    
    static void MX_USART1_UART_Init(void)
    
    {
    
        // 使能 USART1 时钟
    
        __HAL_RCC_USART1_CLK_ENABLE();
    
    
    
        // 配置 USART1
    
        huart1.Instance = USART1;
    
        huart1.Init.BaudRate = 115200;
    
        huart1.Init.WordLength = UART_WORDLENGTH_8B;
    
        huart1.Init.StopBits = UART_STOPBITS_1;
    
        huart1.Init.Parity = UART_PARITY_NONE;
    
        huart1.Init.Mode = UART_MODE_TX;
    
        huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    
        huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    
        HAL_UART_Init(&huart1);
    
    }
    
    

    4.4 代码解释

  • hadc1:ADC 句柄,用于操作 ADC。

  • huart1:UART 句柄,用于操作 UART。

  • HAL_ADC_Start:启动 ADC 转换。

  • HAL_ADC_PollForConversion:等待 ADC 转换完成。

  • HAL_ADC_GetValue:获取 ADC 转换结果。

  • HAL_UART_Transmit:通过 UART 发送数据。

  • SystemClock_Config:配置系统时钟,使用内部高速振荡器(HSI)。

  • MX_GPIO_Init:初始化 GPIO 引脚,设置为模拟输入模式。

  • MX_ADC1_Init:初始化 ADC1,配置单通道模式、单次转换模式、软件触发等参数。

  • MX_USART1_UART_Init:初始化 USART1,配置波特率、字长、停止位等参数。

  • 5. 中断编程

    5.1 中断基础

    中断是嵌入式系统中处理外部事件或内部定时器的重要机制。STM32G4 系列提供了丰富的中断资源,可以用于处理各种外设事件。中断处理函数通常在 stm32g4xx_it.c 文件中定义。

    5.2 配置中断

    1. 选择外设中断

      Pinout & Configuration 选项卡中,选择需要配置的外设。例如,选择 TIM2 的更新中断。

    2. 设置中断优先级

      NVIC Settings 选项卡中,设置中断优先级。例如,设置 TIM2 的更新中断优先级为 1

    3. 生成代码

      配置完成后,点击 Generate Code 生成初始化代码和中断处理函数。

    5.3 代码示例

    以下是一个使用 TIM2 的更新中断来切换 PA0 引脚电平的示例:

    
    // main.c
    
    #include "main.h"
    
    #include "stm32g4xx_hal.h"
    
    
    
    // 定义定时器句柄
    
    TIM_HandleTypeDef htim2;
    
    
    
    void SystemClock_Config(void);
    
    static void MX_GPIO_Init(void);
    
    static void MX_TIM2_Init(void);
    
    
    
    int main(void)
    
    {
    
        // 初始化 HAL 库
    
        HAL_Init();
    
    
    
        // 配置系统时钟
    
        SystemClock_Config();
    
    
    
        // 初始化 GPIO
    
        MX_GPIO_Init();
    
    
    
        // 初始化 TIM2
    
        MX_TIM2_Init();
    
    
    
        // 启动定时器并使能中断
    
        HAL_TIM_Base_Start_IT(&htim2);
    
    
    
        while (1)
    
        {
    
            // 主循环
    
        }
    
    }
    
    
    
    void SystemClock_Config(void)
    
    {
    
        // 配置系统时钟
    
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    
    
        // 初始化振荡器
    
        RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    
        RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    
        RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    
        HAL_RCC_OscConfig(&RCC_OscInitStruct);
    
    
    
        // 初始化时钟
    
        RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    
        RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    
        RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    
        RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
        HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
    
    }
    
    
    
    static void MX_GPIO_Init(void)
    
    {
    
        GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    
    
        // 使能 GPIOA 时钟
    
        __HAL_RCC_GPIOA_CLK_ENABLE();
    
    
    
        // 配置 PA0 为输出模式
    
        GPIO_InitStruct.Pin = GPIO_PIN_0;
    
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    
        GPIO_InitStruct.Pull = GPIO_NOPULL;
    
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    }
    
    
    
    static void MX_TIM2_Init(void)
    
    {
    
        TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    
        TIM_MasterConfigTypeDef sMasterConfig = {0};
    
    
    
        // 使能 TIM2 时钟
    
        __HAL_RCC_TIM2_CLK_ENABLE();
    
    
    
        // 配置定时器
    
        htim2.Instance = TIM2;
    
        htim2.Init.Prescaler = 8000 - 1; // 预分频值,假设系统时钟为 80 MHz
    
        htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    
        htim2.Init.Period = 1000 - 1; // 自动重装载值,1 ms
    
        htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    
        htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    
        HAL_TIM_Base_Init(&htim2);
    
    
    
        // 配置时钟源
    
        sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    
        HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig);
    
    
    
        // 配置主模式
    
        sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    
        sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    
        HAL_TIM_MasterConfigSynchronization(&htim2, &sMasterConfig);
    
    
    
        // 配置中断
    
        HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0);
    
        HAL_NVIC_EnableIRQ(TIM2_IRQn);
    
    }
    
    
    
    // 定时器中断处理函数
    
    void TIM2_IRQHandler(void)
    
    {
    
        HAL_TIM_IRQHandler(&htim2); // 调用 HAL 库的定时器中断处理函数
    
    }
    
    
    
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    
    {
    
        // 定时器周期中断处理函数
    
        if (htim == &htim2)
    
        {
    
            // 切换 PA0 引脚电平
    
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
    
        }
    
    }
    
    

    5.4 代码解释

  • htim2:定时器句柄,用于操作定时器。

  • HAL_TIM_Base_Init:初始化定时器基类。

  • HAL_TIM_ConfigClockSource:配置定时器时钟源。

  • HAL_TIM_MasterConfigSynchronization:配置定时器主模式同步。

  • HAL_TIM_Base_Start_IT:启动定时器并使能中断。

  • HAL_NVIC_SetPriority:设置中断优先级。

  • HAL_NVIC_EnableIRQ:使能定时器中断。

  • TIM2_IRQHandler:定时器中断服务函数,调用 HAL 库的中断处理函数。

  • HAL_TIM_PeriodElapsedCallback:定时器周期中断处理函数,用于在每个周期结束时执行特定操作,如切换 LED 状态。

  • 6. 总结

    通过本文,我们学习了如何在 STM32CubeIDE 中搭建开发环境,创建新项目,配置 GPIO、定时器和 ADC 外设,并编写相应的代码示例。这些基础知识将帮助你快速上手 STM32G4 系列的编程。希望本文对你有所帮助,祝你编程愉快!

    作者:kkchenkx

    物联沃分享整理
    物联沃-IOTWORD物联网 » STMicroelectronics 系列:STM32G4 系列_(11).STM32G4系列编程基础

    发表回复