STMicroelectronics 系列:STM32L4 系列_(7).STM32L4系列的编程模型

STM32L4系列的编程模型

在上一节中,我们介绍了STM32L4系列的基本架构和特点。接下来,我们将深入探讨STM32L4系列的编程模型,包括其内存模型、中断系统、外设控制和低功耗特性等方面。

内存模型

STM32L4系列微控制器提供了丰富的内存资源,包括闪存(Flash)、静态随机存取存储器(SRAM)和系统存储器(System Memory)。了解这些内存资源的组织方式和访问方式对于高效编程至关重要。

闪存(Flash)

闪存主要用于存储程序代码和常量数据。STM32L4系列通常具有128KB到1MB的闪存容量,具体取决于不同的型号。闪存的访问速度较快,但写入和擦除速度较慢,且有写入次数的限制。

闪存操作示例

以下是一个简单的示例,展示如何在STM32L4上编写和读取闪存数据。我们将使用STM32CubeMX生成的代码框架,并通过HAL库进行操作。


#include "stm32l4xx_hal.h"



// 定义闪存地址

#define FLASH_USER_START_ADDR   ADDR_FLASH_PAGE_10    /* Start @ of user Flash area */

#define FLASH_USER_END_ADDR     (ADDR_FLASH_PAGE_10 + 0x400)  /* End @ of user Flash area */

#define FLASH_USER_DATA_OFFSET  0x400  /* Data start address in user Flash area */

#define DATA_LENGTH             4  /* Length of data to program */



void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_FLASH_Init(void);



int main(void)

{

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();

    MX_FLASH_Init();



    uint32_t data_to_program[DATA_LENGTH] = {0x11223344, 0x55667788, 0x99AABBCC, 0xDDEEFF00};

    uint32_t data_read[DATA_LENGTH];



    // 编程闪存

    if (HAL_FLASH_Unlock() != HAL_OK) {

        Error_Handler();

    }



    for (uint32_t i = 0; i < DATA_LENGTH; i++) {

        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_USER_START_ADDR + (i * 4), data_to_program[i]) != HAL_OK) {

            Error_Handler();

        }

    }



    HAL_FLASH_Lock();



    // 读取闪存

    for (uint32_t i = 0; i < DATA_LENGTH; i++) {

        data_read[i] = *(__IO uint32_t*)(FLASH_USER_START_ADDR + (i * 4));

    }



    // 检查读取的数据是否与编程的数据一致

    for (uint32_t i = 0; i < DATA_LENGTH; i++) {

        if (data_read[i] != data_to_program[i]) {

            Error_Handler();

        }

    }



    // 成功读取数据

    while (1) {

        // 空循环

    }

}



void SystemClock_Config(void)

{

    // 系统时钟配置

    // 例如:设置系统时钟为80MHz

}



static void MX_GPIO_Init(void)

{

    // GPIO初始化

    // 例如:配置LED引脚

}



static void MX_FLASH_Init(void)

{

    // 闪存初始化

    // 例如:设置闪存访问参数

}



void Error_Handler(void)

{

    // 错误处理函数

    // 例如:点亮错误指示灯

}

SRAM

SRAM用于存储变量和堆栈等动态数据。STM32L4系列通常具有64KB到320KB的SRAM容量,具体取决于不同的型号。SRAM的访问速度非常快,且没有写入次数的限制。

SRAM操作示例

以下是一个简单的示例,展示如何在STM32L4上使用SRAM。


#include "stm32l4xx_hal.h"



// 定义SRAM变量

uint32_t sram_data[DATA_LENGTH];



void SystemClock_Config(void);

static void MX_GPIO_Init(void);



int main(void)

{

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();



    // 写入SRAM数据

    for (uint32_t i = 0; i < DATA_LENGTH; i++) {

        sram_data[i] = 0x11223344 + i;

    }



    // 读取SRAM数据

    for (uint32_t i = 0; i < DATA_LENGTH; i++) {

        if (sram_data[i] != (0x11223344 + i)) {

            Error_Handler();

        }

    }



    // 成功读取数据

    while (1) {

        // 空循环

    }

}



void SystemClock_Config(void)

{

    // 系统时钟配置

    // 例如:设置系统时钟为80MHz

}



static void MX_GPIO_Init(void)

{

    // GPIO初始化

    // 例如:配置LED引脚

}



void Error_Handler(void)

{

    // 错误处理函数

    // 例如:点亮错误指示灯

}

系统存储器(System Memory)

系统存储器主要用于存储启动代码和一些重要的系统参数。系统存储器的容量较小,但访问速度较快。系统存储器通常用于存储引导加载程序(Bootloader)和一些固件更新相关的数据。

系统存储器操作示例

以下是一个简单的示例,展示如何在STM32L4上使用系统存储器。


#include "stm32l4xx_hal.h"



// 定义系统存储器地址

#define SYSTEM_MEMORY_ADDR   0x1FFF0000

#define DATA_LENGTH          4



void SystemClock_Config(void);

static void MX_GPIO_Init(void);



int main(void)

{

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();



    uint32_t system_memory_data[DATA_LENGTH];



    // 读取系统存储器数据

    for (uint32_t i = 0; i < DATA_LENGTH; i++) {

        system_memory_data[i] = *(__IO uint32_t*)(SYSTEM_MEMORY_ADDR + (i * 4));

    }



    // 检查读取的数据

    for (uint32_t i = 0; i < DATA_LENGTH; i++) {

        if (system_memory_data[i] != (0x11223344 + i)) {

            Error_Handler();

        }

    }



    // 成功读取数据

    while (1) {

        // 空循环

    }

}



void SystemClock_Config(void)

{

    // 系统时钟配置

    // 例如:设置系统时钟为80MHz

}



static void MX_GPIO_Init(void)

{

    // GPIO初始化

    // 例如:配置LED引脚

}



void Error_Handler(void)

{

    // 错误处理函数

    // 例如:点亮错误指示灯

}

中断系统

STM32L4系列微控制器具有强大的中断处理能力,可以处理各种外设和内部事件的中断。了解中断系统的工作原理和配置方法对于编写高效、可靠的嵌入式程序非常重要。

中断向量表

中断向量表(Vector Table)位于闪存的起始地址,包含所有中断和异常的处理函数地址。可以通过配置寄存器改变中断向量表的位置,以便在不同的启动模式下使用不同的中断处理函数。

中断向量表配置示例

以下是一个简单的示例,展示如何配置中断向量表。


#include "stm32l4xx_hal.h"



// 定义中断向量表地址

#define CUSTOM_VECTOR_TABLE_ADDR  0x08000800



void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_NVIC_Init(void);



int main(void)

{

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();

    MX_NVIC_Init();



    // 设置中断向量表地址

    SCB->VTOR = CUSTOM_VECTOR_TABLE_ADDR;



    while (1) {

        // 空循环

    }

}



void SystemClock_Config(void)

{

    // 系统时钟配置

    // 例如:设置系统时钟为80MHz

}



static void MX_GPIO_Init(void)

{

    // GPIO初始化

    // 例如:配置LED引脚

}



static void MX_NVIC_Init(void)

{

    // NVIC初始化

    // 例如:配置外部中断

    HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);

    HAL_NVIC_EnableIRQ(EXTI0_IRQn);

}



void EXTI0_IRQHandler(void)

{

    // 外部中断0处理函数

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

}



void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

    // GPIO中断回调函数

    if (GPIO_Pin == GPIO_PIN_0) {

        // 处理GPIO_PIN_0的中断

        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);  // 切换LED状态

    }

}



void Error_Handler(void)

{

    // 错误处理函数

    // 例如:点亮错误指示灯

}

中断优先级

STM32L4系列的中断系统支持可配置的中断优先级。每个中断向量可以设置两个优先级:抢占优先级(Preemption Priority)和子优先级(Subpriority)。抢占优先级决定了中断是否可以打断其他正在处理的中断,子优先级用于在相同抢占优先级的中断之间进行调度。

中断优先级配置示例

以下是一个简单的示例,展示如何配置中断优先级。


#include "stm32l4xx_hal.h"



void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_NVIC_Init(void);



int main(void)

{

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();

    MX_NVIC_Init();



    while (1) {

        // 空循环

    }

}



void SystemClock_Config(void)

{

    // 系统时钟配置

    // 例如:设置系统时钟为80MHz

}



static void MX_GPIO_Init(void)

{

    // GPIO初始化

    // 例如:配置LED引脚

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};

    GPIO_InitStruct.Pin = GPIO_PIN_0;

    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);



    GPIO_InitStruct.Pin = GPIO_PIN_5;

    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_NVIC_Init(void)

{

    // NVIC初始化

    // 例如:配置外部中断

    HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0);  // 设置抢占优先级为1,子优先级为0

    HAL_NVIC_EnableIRQ(EXTI0_IRQn);



    HAL_NVIC_SetPriority(EXTI1_IRQn, 2, 0);  // 设置抢占优先级为2,子优先级为0

    HAL_NVIC_EnableIRQ(EXTI1_IRQn);

}



void EXTI0_IRQHandler(void)

{

    // 外部中断0处理函数

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

}



void EXTI1_IRQHandler(void)

{

    // 外部中断1处理函数

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);

}



void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

    // GPIO中断回调函数

    if (GPIO_Pin == GPIO_PIN_0) {

        // 处理GPIO_PIN_0的中断

        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);  // 切换LED状态

    } else if (GPIO_Pin == GPIO_PIN_1) {

        // 处理GPIO_PIN_1的中断

        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);  // 切换LED状态

    }

}



void Error_Handler(void)

{

    // 错误处理函数

    // 例如:点亮错误指示灯

}

外设控制

STM32L4系列微控制器集成了丰富的外设,如GPIO、定时器、ADC、DAC、USART、SPI、I2C等。了解如何配置和使用这些外设是编写嵌入式应用程序的基础。

GPIO配置

GPIO(General Purpose Input/Output)是STM32L4系列中最基本的外设之一。可以通过配置寄存器设置GPIO的模式、速度和上拉/下拉电阻。

GPIO配置示例

以下是一个简单的示例,展示如何配置GPIO。


#include "stm32l4xx_hal.h"



void SystemClock_Config(void);

static void MX_GPIO_Init(void);



int main(void)

{

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();



    while (1) {

        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);  // 切换LED状态

        HAL_Delay(500);  // 延时500ms

    }

}



void SystemClock_Config(void)

{

    // 系统时钟配置

    // 例如:设置系统时钟为80MHz

}



static void MX_GPIO_Init(void)

{

    // GPIO初始化

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};



    // 配置LED引脚

    GPIO_InitStruct.Pin = GPIO_PIN_5;

    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);



    // 配置外部中断引脚

    GPIO_InitStruct.Pin = GPIO_PIN_0;

    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);



    // 配置NVIC

    HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0);

    HAL_NVIC_EnableIRQ(EXTI0_IRQn);

}



void EXTI0_IRQHandler(void)

{

    // 外部中断0处理函数

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

}



void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

    // GPIO中断回调函数

    if (GPIO_Pin == GPIO_PIN_0) {

        // 处理GPIO_PIN_0的中断

        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);  // 切换LED状态

    }

}



void Error_Handler(void)

{

    // 错误处理函数

    // 例如:点亮错误指示灯

}

定时器配置

定时器是STM32L4系列中常用的外设之一,可以用于产生周期性中断、测量时间间隔、生成PWM信号等。

定时器配置示例

以下是一个简单的示例,展示如何配置和使用定时器。


#include "stm32l4xx_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_Init();

    SystemClock_Config();

    MX_GPIO_Init();

    MX_TIM2_Init();



    HAL_TIM_Base_Start_IT(&htim2);  // 启动定时器并使能中断



    while (1) {

        // 空循环

    }

}



void SystemClock_Config(void)

{

    // 系统时钟配置

    // 例如:设置系统时钟为80MHz

}



static void MX_GPIO_Init(void)

{

    // GPIO初始化

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};



    // 配置LED引脚

    GPIO_InitStruct.Pin = GPIO_PIN_5;

    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)

{

    // 定时器初始化

    __HAL_RCC_TIM2_CLK_ENABLE();



    htim2.Instance = TIM2;

    htim2.Init.Prescaler = 8000 - 1;  // 预分频器,80MHz / 8000 = 10kHz

    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;

    htim2.Init.Period = 10000 - 1;  // 计数器周期,10000 * 10us = 100ms

    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

    if (HAL_TIM_Base_Init(&htim2) != HAL_OK) {

        Error_Handler();

    }



    // 配置NVIC

    HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0);

    HAL_NVIC_EnableIRQ(TIM2_IRQn);

}



void TIM2_IRQHandler(void)

{

    // 定时器2中断处理函数

    HAL_TIM_IRQHandler(&htim2);

}



void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

    // 定时器周期中断回调函数

    if (htim->Instance == TIM2) {

        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);  // 切换LED状态

    }

}



void Error_Handler(void)

{

    // 错误处理函数

    // 例如:点亮错误指示灯

}

ADC配置

ADC(Analog-to-Digital Converter)用于将模拟信号转换为数字信号。STM32L4系列通常具有多个ADC通道,可以配置不同的采样率和分辨率。了解如何配置和使用ADC对于处理模拟输入信号至关重要。

ADC配置示例

以下是一个简单的示例,展示如何配置和使用ADC。


#include "stm32l4xx_hal.h"



ADC_HandleTypeDef hadc1;



void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_ADC1_Init(void);



int main(void)

{

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();

    MX_ADC1_Init();



    while (1) {

        uint32_t adc_value = 0;



        // 启动ADC转换

        if (HAL_ADC_Start(&hadc1) == HAL_OK) {

            // 等待ADC转换完成

            if (HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY) == HAL_OK) {

                // 获取ADC转换值

                adc_value = HAL_ADC_GetValue(&hadc1);

            }

            // 停止ADC转换

            HAL_ADC_Stop(&hadc1);

        }



        // 处理ADC值

        if (adc_value > 2048) {

            // 如果ADC值大于2048,点亮LED

            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

        } else {

            // 如果ADC值小于或等于2048,熄灭LED

            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

        }



        HAL_Delay(500);  // 延时500ms

    }

}



void SystemClock_Config(void)

{

    // 系统时钟配置

    // 例如:设置系统时钟为80MHz

}



static void MX_GPIO_Init(void)

{

    // GPIO初始化

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};



    // 配置LED引脚

    GPIO_InitStruct.Pin = GPIO_PIN_5;

    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);



    // 配置ADC输入引脚

    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)

{

    // ADC1初始化

    __HAL_RCC_ADC12_CLK_ENABLE();



    hadc1.Instance = ADC1;

    hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;

    hadc1.Init.Resolution = ADC_RESOLUTION_12B;

    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

    hadc1.Init.ScanConvMode = DISABLE;  // 单通道模式

    hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;

    hadc1.Init.LowPowerAutoWait = DISABLE;

    hadc1.Init.LowPowerAutoPowerOff = DISABLE;

    hadc1.Init.ContinuousConvMode = DISABLE;  // 单次转换模式

    hadc1.Init.DiscontinuousConvMode = DISABLE;

    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;

    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

    hadc1.Init.DMAContinuousRequests = DISABLE;

    hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;

    if (HAL_ADC_Init(&hadc1) != HAL_OK) {

        Error_Handler();

    }



    // 配置ADC通道

    ADC_ChannelConfTypeDef sConfig = {0};

    sConfig.Channel = ADC_CHANNEL_0;

    sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

    sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;

    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {

        Error_Handler();

    }

}



void Error_Handler(void)

{

    // 错误处理函数

    // 例如:点亮错误指示灯

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

    while (1) {

        // 空循环

    }

}

DAC配置

DAC(Digital-to-Analog Converter)用于将数字信号转换为模拟信号。STM32L4系列通常具有多个DAC通道,可以配置不同的输出模式和分辨率。

DAC配置示例

以下是一个简单的示例,展示如何配置和使用DAC。


#include "stm32l4xx_hal.h"



DAC_HandleTypeDef hdac1;



void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_DAC1_Init(void);



int main(void)

{

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();

    MX_DAC1_Init();



    while (1) {

        // 设置DAC输出值

        HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 2048);



        HAL_Delay(1000);  // 延时1000ms



        // 设置DAC输出值

        HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 1024);



        HAL_Delay(1000);  // 延时1000ms

    }

}



void SystemClock_Config(void)

{

    // 系统时钟配置

    // 例如:设置系统时钟为80MHz

}



static void MX_GPIO_Init(void)

{

    // GPIO初始化

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};



    // 配置LED引脚

    GPIO_InitStruct.Pin = GPIO_PIN_5;

    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);



    // 配置DAC输出引脚

    GPIO_InitStruct.Pin = GPIO_PIN_4;

    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}



static void MX_DAC1_Init(void)

{

    // DAC1初始化

    __HAL_RCC_DAC1_CLK_ENABLE();



    hdac1.Instance = DAC1;

    hdac1.Initresolution = DAC_RESOLUTION_12B;

    hdac1.Init.DataAlignment = DAC_DATAALIGN_12B_R;

    hdac1.InitTro = DISABLE;

    hdac1.Init.Trigger = DAC_TRIGGER_NONE;

    hdac1.Init.WaveGeneration = DAC_WAVE_NONE;

    if (HAL_DAC_Init(&hdac1) != HAL_OK) {

        Error_Handler();

    }



    // 配置DAC通道

    if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK) {

        Error_Handler();

    }

}



void Error_Handler(void)

{

    // 错误处理函数

    // 例如:点亮错误指示灯

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

    while (1) {

        // 空循环

    }

}

低功耗特性

STM32L4系列微控制器具有多种低功耗模式,如睡眠模式(Sleep Mode)、停止模式(Stop Mode)和待机模式(Standby Mode)。这些模式可以显著减少功耗,延长电池寿命。理解如何配置和使用这些低功耗模式对于开发低功耗应用非常重要。

睡眠模式

在睡眠模式下,CPU停止工作,但系统时钟和外设继续运行。可以通过不同的触发源(如中断、事件等)唤醒CPU。

睡眠模式配置示例

以下是一个简单的示例,展示如何配置和使用睡眠模式。


#include "stm32l4xx_hal.h"



void SystemClock_Config(void);

static void MX_GPIO_Init(void);



int main(void)

{

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();



    while (1) {

        // 切换LED状态

        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);



        // 进入睡眠模式

        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

        HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);



        // 延时500ms

        HAL_Delay(500);

    }

}



void SystemClock_Config(void)

{

    // 系统时钟配置

    // 例如:设置系统时钟为80MHz

}



static void MX_GPIO_Init(void)

{

    // GPIO初始化

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};



    // 配置LED引脚

    GPIO_InitStruct.Pin = GPIO_PIN_5;

    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);



    // 配置外部中断引脚

    GPIO_InitStruct.Pin = GPIO_PIN_0;

    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);



    // 配置NVIC

    HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0);

    HAL_NVIC_EnableIRQ(EXTI0_IRQn);

}



void EXTI0_IRQHandler(void)

{

    // 外部中断0处理函数

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

}



void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

    // GPIO中断回调函数

    if (GPIO_Pin == GPIO_PIN_0) {

        // 处理GPIO_PIN_0的中断

        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);  // 切换LED状态

    }

}



void Error_Handler(void)

{

    // 错误处理函数

    // 例如:点亮错误指示灯

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

    while (1) {

        // 空循环

    }

}

停止模式

在停止模式下,CPU和大部分外设停止工作,只有某些低功耗外设(如RTC、I2C等)继续运行。可以通过外部中断或复位唤醒CPU。

停止模式配置示例

以下是一个简单的示例,展示如何配置和使用停止模式。


#include "stm32l4xx_hal.h"



void SystemClock_Config(void);

static void MX_GPIO_Init(void);



int main(void)

{

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();



    while (1) {

        // 切换LED状态

        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);



        // 进入停止模式

        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

        HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);



        // 延时500ms

        HAL_Delay(500);

    }

}



void SystemClock_Config(void)

{

    // 系统时钟配置

    // 例如:设置系统时钟为80MHz

}



static void MX_GPIO_Init(void)

{

    // GPIO初始化

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};



    // 配置LED引脚

    GPIO_InitStruct.Pin = GPIO_PIN_5;

    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);



    // 配置外部中断引脚

    GPIO_InitStruct.Pin = GPIO_PIN_0;

    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);



    // 配置NVIC

    HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0);

    HAL_NVIC_EnableIRQ(EXTI0_IRQn);

}



void EXTI0_IRQHandler(void)

{

    // 外部中断0处理函数

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

}



void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

    // GPIO中断回调函数

    if (GPIO_Pin == GPIO_PIN_0) {

        // 处理GPIO_PIN_0的中断

        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);  // 切换LED状态

    }

}



void Error_Handler(void)

{

    // 错误处理函数

    // 例如:点亮错误指示灯

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

    while (1) {

        // 空循环

    }

}

待机模式

在待机模式下,CPU和所有外设停止工作,只有RTC和某些低功耗外设可以继续运行。可以通过外部唤醒引脚或复位唤醒CPU。

待机模式配置示例

以下是一个简单的示例,展示如何配置和使用待机模式。


#include "stm32l4xx_hal.h"



void SystemClock_Config(void);

static void MX_GPIO_Init(void);



int main(void)

{

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();



    while (1) {

        // 切换LED状态

        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);



        // 进入待机模式

        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

        HAL_PWR_EnterSTANDBYMode();



        // 延时500ms

        HAL_Delay(500);

    }

}



void SystemClock_Config(void)

{

    // 系统时钟配置

    // 例如:设置系统时钟为80MHz

}



static void MX_GPIO_Init(void)

{

    // GPIO初始化

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};



    // 配置LED引脚

    GPIO_InitStruct.Pin = GPIO_PIN_5;

    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);



    // 配置外部唤醒引脚

    GPIO_InitStruct.Pin = GPIO_PIN_0;

    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);



    // 配置NVIC

    HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0);

    HAL_NVIC_EnableIRQ(EXTI0_IRQn);

}



void EXTI0_IRQHandler(void)

{

    // 外部中断0处理函数

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

}



void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

    // GPIO中断回调函数

    if (GPIO_Pin == GPIO_PIN_0) {

        // 处理GPIO_PIN_0的中断

        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);  // 切换LED状态

    }

}



void Error_Handler(void)

{

    // 错误处理函数

    // 例如:点亮错误指示灯

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

    while (1) {

        // 空循环

    }

}

通过以上示例,我们可以看到STM32L4系列微控制器在内存模型、中断系统、外设控制和低功耗特性方面的强大功能和灵活性。这些功能使得STM32L4系列非常适合各种嵌入式应用,从简单的控制任务到复杂的低功耗应用。希望这些示例能帮助你更好地理解和使用STM32L4系列微控制器。

作者:kkchenkx

物联沃分享整理
物联沃-IOTWORD物联网 » STMicroelectronics 系列:STM32L4 系列_(7).STM32L4系列的编程模型

发表回复