STMicroelectronics 系列:STM32G4 系列_(2).STM32G4系列核心架构

STM32G4系列核心架构

1. 介绍

STM32G4系列是STMicroelectronics推出的一款高性能、低功耗的32位微控制器系列,基于Arm Cortex-M4内核。该系列微控制器集成了多种高级功能,如高精度ADC、高速DAC、低功耗定时器等,适用于各种工业和消费类应用。本节将详细介绍STM32G4系列的核心架构,包括其内核、存储器、外设和系统配置等方面。

2. Arm Cortex-M4内核

2.1 内核概述

STM32G4系列微控制器采用Arm Cortex-M4内核,这是一种高性能的32位RISC处理器,具有出色的能效比。Cortex-M4内核支持浮点运算单元(FPU),适用于需要高精度计算的应用场景。此外,它还支持DSP指令集,能够高效处理数字信号。

2.2 内核特性

  • 高性能:最高工作频率可达170MHz,提供高达216 DMIPS的处理能力。

  • 低功耗:支持多种低功耗模式,如睡眠、深度睡眠和待机模式。

  • 浮点运算单元(FPU):支持单精度浮点运算,适用于需要高精度数学计算的应用。

  • DSP指令集:集成DSP指令集,能够高效处理数字信号。

  • 内存保护单元(MPU):支持内存保护单元,提高系统的安全性。

  • 嵌套向量中断控制器(NVIC):支持多达80个中断线,具有灵活的中断优先级配置。

  • 2.3 内核配置

    Cortex-M4内核的配置可以通过STM32CubeMX等配置工具进行。以下是一个简单的配置示例,展示如何通过STM32CubeMX配置Cortex-M4内核的基本参数:

    1. 启动STM32CubeMX

    2. 打开STM32CubeMX软件,选择STM32G4系列微控制器。

    3. 点击“Project”菜单,选择“Project Settings”进行项目设置。

    4. 配置内核参数

    5. 在“Clock Configuration”页面,配置系统时钟频率。

    6. 在“Pinout & Configuration”页面,配置外部中断和GPIO等外设。

    7. 在“NVIC”页面,配置中断优先级。

    8. 生成代码

    9. 配置完成后,点击“Project”菜单,选择“Generate Code”生成初始代码。

    10. 生成的代码包括内核初始化、时钟配置和中断配置等部分。

    2.4 代码示例:内核初始化

    以下是一个简单的代码示例,展示如何在STM32G4系列微控制器上初始化Cortex-M4内核:

    
    #include "stm32g4xx_hal.h"
    
    
    
    void SystemClock_Config(void);
    
    void Error_Handler(void);
    
    
    
    int main(void)
    
    {
    
        HAL_Init(); // 初始化HAL库
    
    
    
        SystemClock_Config(); // 配置系统时钟
    
    
    
        // 配置GPIO
    
        GPIO_InitTypeDef GPIO_InitStruct = {0};
    
        __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
    
        GPIO_InitStruct.Pin = GPIO_PIN_5; // 选择PA5引脚
    
        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);
    
    
    
        while (1)
    
        {
    
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // 切换PA5引脚状态
    
            HAL_Delay(500); // 延时500ms
    
        }
    
    }
    
    
    
    void SystemClock_Config(void)
    
    {
    
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    
    
        // 配置HSE时钟
    
        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 = 85;
    
        RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    
        RCC_OscInitStruct.PLL.PLLQ = 7;
    
        RCC_OscInitStruct.PLL.PLLR = 2;
    
        if (HAL_RCC_OscInit(&RCC_OscInitStruct) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        // 配置系统时钟
    
        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_DIV2;
    
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
        if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    }
    
    
    
    void Error_Handler(void)
    
    {
    
        // 错误处理函数
    
        while (1)
    
        {
    
            // 无限循环,等待错误处理
    
        }
    
    }
    
    

    3. 存储器架构

    3.1 存储器类型

    STM32G4系列微控制器集成了多种存储器类型,包括闪存(Flash)、SRAM和系统存储器(System Memory)。以下是对这些存储器类型的详细描述:

  • 闪存(Flash):用于存储程序代码和常量数据。STM32G4系列提供高达512KB的闪存。

  • SRAM:用于存储运行时数据。STM32G4系列提供高达128KB的SRAM。

  • 系统存储器(System Memory):包含启动代码和一些预定义的系统配置。系统存储器通常用于引导加载程序。

  • 3.2 存储器映射

    STM32G4系列的存储器映射如下:

  • 闪存:地址范围为0x080000000x0807FFFF(512KB)。

  • SRAM1:地址范围为0x200000000x2001FFFF(128KB)。

  • SRAM2:地址范围为0x200200000x2003FFFF(128KB)。

  • 系统存储器:地址范围为0x1FFF00000x1FFF77FF

  • 3.3 存储器配置

    存储器的配置通常在系统初始化时完成。以下是一个简单的配置示例,展示如何在STM32G4系列微控制器上配置闪存和SRAM:

    
    #include "stm32g4xx_hal.h"
    
    
    
    void SystemClock_Config(void);
    
    void Error_Handler(void);
    
    
    
    int main(void)
    
    {
    
        HAL_Init(); // 初始化HAL库
    
    
    
        SystemClock_Config(); // 配置系统时钟
    
    
    
        // 配置闪存
    
        __HAL_FLASH_PREFETCH_BUFFER_ENABLE(); // 使能预取缓冲
    
        __HAL_FLASH_INSTR_CACHE_ENABLE(); // 使能指令缓存
    
        __HAL_FLASH_INSTR_CACHE_RESET(); // 重置指令缓存
    
        __HAL_FLASH_DATA_CACHE_ENABLE(); // 使能数据缓存
    
        __HAL_FLASH_DATA_CACHE_RESET(); // 重置数据缓存
    
    
    
        // 配置SRAM
    
        // 通常无需特殊配置,HAL库会自动管理
    
    
    
        while (1)
    
        {
    
            // 主循环
    
        }
    
    }
    
    
    
    void SystemClock_Config(void)
    
    {
    
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    
    
        // 配置HSE时钟
    
        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 = 85;
    
        RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    
        RCC_OscInitStruct.PLL.PLLQ = 7;
    
        RCC_OscInitStruct.PLL.PLLR = 2;
    
        if (HAL_RCC_OscInit(&RCC_OscInitStruct) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        // 配置系统时钟
    
        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_DIV2;
    
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
        if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    }
    
    
    
    void Error_Handler(void)
    
    {
    
        // 错误处理函数
    
        while (1)
    
        {
    
            // 无限循环,等待错误处理
    
        }
    
    }
    
    

    4. 外设架构

    4.1 外设概述

    STM32G4系列微控制器集成了丰富的外设,包括定时器、ADC、DAC、SPI、I2C、USART等。这些外设通过外设访问控制器(APB)和高级外设总线(AHB)连接到内核。

    4.2 定时器

    定时器是STM32G4系列微控制器的重要外设之一,用于生成定时中断和PWM信号等。STM32G4系列提供了多种类型的定时器,包括通用定时器(TIM)、高级定时器(TIM1和TIM8)和低功耗定时器(LPTIM)。

    4.2.1 通用定时器(TIM)

    通用定时器可以用于生成定时中断和PWM信号。以下是一个简单的代码示例,展示如何配置和使用TIM2生成定时中断:

    
    #include "stm32g4xx_hal.h"
    
    
    
    uint32_t tick_value;
    
    
    
    void SystemClock_Config(void);
    
    void Error_Handler(void);
    
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
    
    
    
    int main(void)
    
    {
    
        HAL_Init(); // 初始化HAL库
    
    
    
        SystemClock_Config(); // 配置系统时钟
    
    
    
        // 配置TIM2
    
        TIM_HandleTypeDef htim2;
    
        __HAL_RCC_TIM2_CLK_ENABLE(); // 使能TIM2时钟
    
        htim2.Instance = TIM2;
    
        htim2.Init.Prescaler = 8499; // 设置预分频器,8500-1 = 8499
    
        htim2.Init.CounterMode = TIM_COUNTERMODE_UP; // 设置计数模式
    
        htim2.Init.Period = 9999; // 设置计数周期
    
        htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 设置时钟分割
    
        htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; // 禁用自动重装载预加载
    
        if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        // 配置TIM2中断
    
        HAL_NVIC_SetPriority(TIM2_IRQn, 0, 1);
    
        HAL_NVIC_EnableIRQ(TIM2_IRQn);
    
    
    
        // 开始TIM2
    
        if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        while (1)
    
        {
    
            // 主循环
    
        }
    
    }
    
    
    
    void SystemClock_Config(void)
    
    {
    
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    
    
        // 配置HSE时钟
    
        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 = 85;
    
        RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    
        RCC_OscInitStruct.PLL.PLLQ = 7;
    
        RCC_OscInitStruct.PLL.PLLR = 2;
    
        if (HAL_RCC_OscInit(&RCC_OscInitStruct) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        // 配置系统时钟
    
        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_DIV2;
    
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
        if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    }
    
    
    
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    
    {
    
        if (htim->Instance == TIM2)
    
        {
    
            tick_value++;
    
            // 在这里处理定时器中断
    
        }
    
    }
    
    
    
    void Error_Handler(void)
    
    {
    
        // 错误处理函数
    
        while (1)
    
        {
    
            // 无限循环,等待错误处理
    
        }
    
    }
    
    

    4.3 ADC

    STM32G4系列集成了高精度ADC,适用于需要精确模拟信号采集的应用场景。以下是一个简单的代码示例,展示如何配置和使用ADC1进行模拟信号采集:

    
    #include "stm32g4xx_hal.h"
    
    
    
    uint32_t adc_value;
    
    
    
    void SystemClock_Config(void);
    
    void Error_Handler(void);
    
    void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);
    
    
    
    int main(void)
    
    {
    
        HAL_Init(); // 初始化HAL库
    
    
    
        SystemClock_Config(); // 配置系统时钟
    
    
    
        // 配置ADC1
    
        ADC_HandleTypeDef hadc1;
    
        __HAL_RCC_ADC12_CLK_ENABLE(); // 使能ADC1时钟
    
        hadc1.Instance = ADC1;
    
        hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; // 设置时钟预分频器
    
        hadc1.Init.Resolution = ADC_RESOLUTION_12B; // 设置分辨率
    
        hadc1.Init.ScanConvMode = 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.DMAContinuousRequests = DISABLE; // 禁用DMA连续请求
    
        hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // 设置EOC选择
    
        if (HAL_ADC_Init(&hadc1) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        // 配置ADC通道
    
        ADC_ChannelConfTypeDef sConfig = {0};
    
        sConfig.Channel = ADC_CHANNEL_4; // 选择ADC通道4
    
        sConfig.Rank = ADC_REGULAR_RANK_1; // 设置通道在常规序列中的位置
    
        sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; // 设置采样时间
    
        if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        while (1)
    
        {
    
            // 启动ADC转换
    
            if (HAL_ADC_Start(&hadc1) != HAL_OK)
    
            {
    
                Error_Handler();
    
            }
    
    
    
            // 等待ADC转换完成
    
            if (HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY) != HAL_OK)
    
            {
    
                Error_Handler();
    
            }
    
    
    
            // 读取ADC转换结果
    
            adc_value = HAL_ADC_GetValue(&hadc1);
    
    
    
            // 在这里处理ADC值
    
        }
    
    }
    
    
    
    void SystemClock_Config(void)
    
    {
    
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    
    
        // 配置HSE时钟
    
        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 = 85;
    
        RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    
        RCC_OscInitStruct.PLL.PLLQ = 7;
    
        RCC_OscInitStruct.PLL.PLLR = 2;
    
        if (HAL_RCC_OscInit(&RCC_OscInitStruct) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        // 配置系统时钟
    
        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_DIV2;
    
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
        if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    }
    
    
    
    void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
    
    {
    
        // ADC转换完成回调函数
    
        if (hadc->Instance == ADC1)
    
        {
    
            adc_value = HAL_ADC_GetValue(hadc); // 读取ADC值
    
            // 在这里处理ADC值
    
        }
    
    }
    
    
    
    void Error_Handler(void)
    
    {
    
        // 错误处理函数
    
        while (1)
    
        {
    
            // 无限循环,等待错误处理
    
        }
    
    }
    
    

    4.4 DAC

    STM32G4系列集成了高速DAC,适用于需要生成精确模拟信号的应用场景。DAC(数模转换器)可以将数字信号转换为模拟信号,广泛应用于音频处理、传感器校准和信号生成等领域。STM32G4系列提供了两个12位DAC通道,分别为DAC1和DAC2。

    4.4.1 DAC特性
  • 12位分辨率:提供12位的数模转换精度。

  • 双通道:支持两个独立的DAC通道,可以同时生成两个不同的模拟信号。

  • 多种触发模式:支持软件触发、定时器触发和外部触发等多种触发模式。

  • 波形生成:可以通过DMA(直接存储器访问)实现波形生成,适用于需要连续输出波形的应用。

  • 4.4.2 DAC配置

    DAC的配置可以通过STM32CubeMX等配置工具进行。以下是一个简单的配置示例,展示如何通过STM32CubeMX配置DAC的基本参数:

    1. 启动STM32CubeMX

    2. 打开STM32CubeMX软件,选择STM32G4系列微控制器。

    3. 点击“Project”菜单,选择“Project Settings”进行项目设置。

    4. 配置DAC参数

    5. 在“Pinout & Configuration”页面,配置DAC通道和引脚。

    6. 在“Clock Configuration”页面,确保DAC时钟已使能。

    7. 在“NVIC”页面,配置相关的中断(如果需要)。

    8. 生成代码

    9. 配置完成后,点击“Project”菜单,选择“Generate Code”生成初始代码。

    10. 生成的代码包括DAC初始化、时钟配置和中断配置等部分。

    4.4.3 代码示例:DAC初始化和输出

    以下是一个简单的代码示例,展示如何在STM32G4系列微控制器上初始化DAC并输出一个模拟信号:

    
    #include "stm32g4xx_hal.h"
    
    
    
    void SystemClock_Config(void);
    
    void Error_Handler(void);
    
    
    
    int main(void)
    
    {
    
        HAL_Init(); // 初始化HAL库
    
    
    
        SystemClock_Config(); // 配置系统时钟
    
    
    
        // 配置DAC1
    
        DAC_HandleTypeDef hdac1;
    
        __HAL_RCC_DAC12_CLK_ENABLE(); // 使能DAC1时钟
    
        hdac1.Instance = DAC1;
    
        hdac1.Initresolution = DAC_RESOLUTION_12B; // 设置分辨率
    
        hdac1.Init.DataAlignment = DAC_DATAALIGN_RIGHT; // 设置数据对齐方式
    
        hdac1.Init.OutPutBuffer = DAC_OUTPUTBUFFER_ENABLE; // 使能输出缓冲
    
        if (HAL_DAC_Init(&hdac1) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        // 配置DAC通道
    
        DAC_ChannelConfTypeDef sConfig = {0};
    
        sConfig.DAC_Trigger = DAC_TRIGGER_NONE; // 设置触发模式为软件触发
    
        sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; // 使能输出缓冲
    
        if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        while (1)
    
        {
    
            // 生成一个模拟信号
    
            uint32_t dac_value = 2048; // 12位中间值
    
            if (HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, dac_value) != HAL_OK)
    
            {
    
                Error_Handler();
    
            }
    
    
    
            HAL_Delay(1000); // 延时1秒
    
        }
    
    }
    
    
    
    void SystemClock_Config(void)
    
    {
    
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    
    
        // 配置HSE时钟
    
        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 = 85;
    
        RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    
        RCC_OscInitStruct.PLL.PLLQ = 7;
    
        RCC_OscInitStruct.PLL.PLLR = 2;
    
        if (HAL_RCC_OscInit(&RCC_OscInitStruct) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        // 配置系统时钟
    
        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_DIV2;
    
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
        if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    }
    
    
    
    void Error_Handler(void)
    
    {
    
        // 错误处理函数
    
        while (1)
    
        {
    
            // 无限循环,等待错误处理
    
        }
    
    }
    
    

    4.5 其他外设

    除了定时器、ADC和DAC,STM32G4系列微控制器还集成了其他多种外设,如SPI、I2C、USART等。这些外设提供了丰富的通信接口,适用于各种复杂的应用场景。

    4.5.1 SPI

    SPI(串行外设接口)是一种高速、全双工的通信协议,适用于连接闪存、传感器和其他微控制器。以下是一个简单的代码示例,展示如何配置和使用SPI1进行通信:

    
    #include "stm32g4xx_hal.h"
    
    
    
    void SystemClock_Config(void);
    
    void Error_Handler(void);
    
    void SPI1_Init(void);
    
    
    
    int main(void)
    
    {
    
        HAL_Init(); // 初始化HAL库
    
    
    
        SystemClock_Config(); // 配置系统时钟
    
    
    
        SPI1_Init(); // 初始化SPI1
    
    
    
        while (1)
    
        {
    
            // 主循环
    
        }
    
    }
    
    
    
    void SystemClock_Config(void)
    
    {
    
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    
    
        // 配置HSE时钟
    
        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 = 85;
    
        RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    
        RCC_OscInitStruct.PLL.PLLQ = 7;
    
        RCC_OscInitStruct.PLL.PLLR = 2;
    
        if (HAL_RCC_OscInit(&RCC_OscInitStruct) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        // 配置系统时钟
    
        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_DIV2;
    
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
        if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    }
    
    
    
    void SPI1_Init(void)
    
    {
    
        // 配置SPI1
    
        SPI_HandleTypeDef hspi1;
    
        __HAL_RCC_SPI1_CLK_ENABLE(); // 使能SPI1时钟
    
        hspi1.Instance = SPI1;
    
        hspi1.Init.Mode = SPI_MODE_MASTER; // 设置为主模式
    
        hspi1.Init.Direction = SPI_DIRECTION_2LINES; // 设置为全双工模式
    
        hspi1.Init.DataSize = SPI_DATASIZE_8BIT; // 设置数据大小为8位
    
        hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; // 设置时钟极性
    
        hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; // 设置时钟相位
    
        hspi1.Init.NSS = SPI_NSS_SOFT; // 设置NSS引脚为软件管理
    
        hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; // 设置波特率分频器
    
        hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; // 设置先传输最高位
    
        hspi1.Init.TIMode = SPI_TIMODE_DISABLE; // 禁用TI模式
    
        hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; // 禁用CRC校验
    
        hspi1.Init.CRCPolynomial = 10; // 设置CRC多项式
    
        if (HAL_SPI_Init(&hspi1) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        // 配置GPIO
    
        GPIO_InitTypeDef GPIO_InitStruct = {0};
    
        __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
    
        GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; // 选择PA5(SCK)、PA6(MISO)、PA7(MOSI)引脚
    
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 设置为复用推挽输出模式
    
        GPIO_InitStruct.Pull = GPIO_NOPULL; // 无上拉下拉
    
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; // 设置输出速度
    
        GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; // 选择SPI1复用功能
    
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    }
    
    
    
    void Error_Handler(void)
    
    {
    
        // 错误处理函数
    
        while (1)
    
        {
    
            // 无限循环,等待错误处理
    
        }
    
    }
    
    

    5. 系统配置

    5.1 时钟配置

    STM32G4系列微控制器的时钟配置是系统初始化的重要部分。通过配置系统时钟,可以优化系统的性能和功耗。以下是一个详细的时钟配置示例:

    
    #include "stm32g4xx_hal.h"
    
    
    
    void SystemClock_Config(void);
    
    void Error_Handler(void);
    
    
    
    int main(void)
    
    {
    
        HAL_Init(); // 初始化HAL库
    
    
    
        SystemClock_Config(); // 配置系统时钟
    
    
    
        while (1)
    
        {
    
            // 主循环
    
        }
    
    }
    
    
    
    void SystemClock_Config(void)
    
    {
    
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    
    
        // 配置HSE时钟
    
        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 = 85;
    
        RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    
        RCC_OscInitStruct.PLL.PLLQ = 7;
    
        RCC_OscInitStruct.PLL.PLLR = 2;
    
        if (HAL_RCC_OscInit(&RCC_OscInitStruct) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        // 配置系统时钟
    
        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_DIV2;
    
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
        if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    }
    
    
    
    void Error_Handler(void)
    
    {
    
        // 错误处理函数
    
        while (1)
    
        {
    
            // 无限循环,等待错误处理
    
        }
    
    }
    
    
    5.2 电源管理

    STM32G4系列微控制器支持多种低功耗模式,如睡眠模式、深度睡眠模式和待机模式。通过合理配置电源管理,可以显著降低系统的功耗。

    
    #include "stm32g4xx_hal.h"
    
    
    
    void SystemClock_Config(void);
    
    void Error_Handler(void);
    
    void EnterSleepMode(void);
    
    
    
    int main(void)
    
    {
    
        HAL_Init(); // 初始化HAL库
    
    
    
        SystemClock_Config(); // 配置系统时钟
    
    
    
        while (1)
    
        {
    
            EnterSleepMode(); // 进入睡眠模式
    
        }
    
    }
    
    
    
    void SystemClock_Config(void)
    
    {
    
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    
    
        // 配置HSE时钟
    
        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 = 85;
    
        RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    
        RCC_OscInitStruct.PLL.PLLQ = 7;
    
        RCC_OscInitStruct.PLL.PLLR = 2;
    
        if (HAL_RCC_OscInit(&RCC_OscInitStruct) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    
    
        // 配置系统时钟
    
        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_DIV2;
    
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
        if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    
        {
    
            Error_Handler();
    
        }
    
    }
    
    
    
    void EnterSleepMode(void)
    
    {
    
        HAL_PWRErrorAction HAL_Power_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
    
    }
    
    
    
    void Error_Handler(void)
    
    {
    
        // 错误处理函数
    
        while (1)
    
        {
    
            // 无限循环,等待错误处理
    
        }
    
    }
    
    

    6. 总结

    STM32G4系列微控制器基于Arm Cortex-M4内核,提供了高性能、低功耗的特性,并集成了多种高级外设。通过合理配置内核、存储器和外设,可以实现复杂而高效的应用。本节详细介绍了STM32G4系列的核心架构,包括内核、存储器、外设和系统配置等方面,希望对读者有所帮助。

    7. 参考资料

  • STM32G4系列参考手册:详细描述了STM32G4系列微控制器的架构和外设。

  • STM32CubeMX用户手册:介绍了如何使用STM32CubeMX进行微控制器配置。

  • HAL库用户手册:提供了HAL库的详细使用方法和示例代码。

  • 通过以上内容,读者可以对STM32G4系列微控制器的核心架构有一个全面的了解,并能够开始进行具体的应用开发。

    作者:kkchenkx

    物联沃分享整理
    物联沃-IOTWORD物联网 » STMicroelectronics 系列:STM32G4 系列_(2).STM32G4系列核心架构

    发表回复