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内核的基本参数:
-
启动STM32CubeMX:
-
打开STM32CubeMX软件,选择STM32G4系列微控制器。
-
点击“Project”菜单,选择“Project Settings”进行项目设置。
-
配置内核参数:
-
在“Clock Configuration”页面,配置系统时钟频率。
-
在“Pinout & Configuration”页面,配置外部中断和GPIO等外设。
-
在“NVIC”页面,配置中断优先级。
-
生成代码:
-
配置完成后,点击“Project”菜单,选择“Generate Code”生成初始代码。
-
生成的代码包括内核初始化、时钟配置和中断配置等部分。
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系列的存储器映射如下:
闪存:地址范围为0x08000000
到0x0807FFFF
(512KB)。
SRAM1:地址范围为0x20000000
到0x2001FFFF
(128KB)。
SRAM2:地址范围为0x20020000
到0x2003FFFF
(128KB)。
系统存储器:地址范围为0x1FFF0000
到0x1FFF77FF
。
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的基本参数:
-
启动STM32CubeMX:
-
打开STM32CubeMX软件,选择STM32G4系列微控制器。
-
点击“Project”菜单,选择“Project Settings”进行项目设置。
-
配置DAC参数:
-
在“Pinout & Configuration”页面,配置DAC通道和引脚。
-
在“Clock Configuration”页面,确保DAC时钟已使能。
-
在“NVIC”页面,配置相关的中断(如果需要)。
-
生成代码:
-
配置完成后,点击“Project”菜单,选择“Generate Code”生成初始代码。
-
生成的代码包括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