文章目录
-
- 一、方案背景与整体架构
-
- [1.1 核心硬件组成](#1.1 核心硬件组成)
- [1.2 整体工作流程](#1.2 整体工作流程)
- 二、开发环境搭建
-
- [2.1 软件环境](#2.1 软件环境)
- [2.2 硬件连接](#2.2 硬件连接)
- 三、代码开发步骤(详细版)
-
- [3.1 工程创建](#3.1 工程创建)
- [3.2 外设配置(STM32CubeMX)](#3.2 外设配置(STM32CubeMX))
-
- [3.2.1 时钟配置](#3.2.1 时钟配置)
- [3.2.2 低功耗配置](#3.2.2 低功耗配置)
- [3.2.3 ADC配置](#3.2.3 ADC配置)
- [3.2.4 GPIO配置](#3.2.4 GPIO配置)
- [3.3 核心代码编写](#3.3 核心代码编写)
-
- [3.3.1 代码文件1:main.c(主程序)](#3.3.1 代码文件1:main.c(主程序))
- [3.3.2 代码文件2:low_power.c(低功耗管理)](#3.3.2 代码文件2:low_power.c(低功耗管理))
- [3.3.3 代码文件3:low_power.h(低功耗头文件)](#3.3.3 代码文件3:low_power.h(低功耗头文件))
- [3.3.4 代码文件4:adc.c(ADC配置,由STM32CubeMX生成并修改)](#3.3.4 代码文件4:adc.c(ADC配置,由STM32CubeMX生成并修改))
- [3.3.5 代码文件5:gpio.c(GPIO配置,由STM32CubeMX生成并修改)](#3.3.5 代码文件5:gpio.c(GPIO配置,由STM32CubeMX生成并修改))
- [3.4 代码编译与烧录](#3.4 代码编译与烧录)
-
- [3.4.1 编译代码](#3.4.1 编译代码)
- [3.4.2 烧录代码](#3.4.2 烧录代码)
- 四、系统调试与验证
-
- [4.1 硬件调试](#4.1 硬件调试)
- [4.2 软件调试](#4.2 软件调试)
- [4.3 性能指标验证](#4.3 性能指标验证)
- 五、方案优化与扩展
-
- [5.1 硬件优化](#5.1 硬件优化)
- [5.2 软件优化](#5.2 软件优化)
- [5.3 功能扩展](#5.3 功能扩展)
- 总结
一、方案背景与整体架构
振动能量采集是一种将环境中的机械能(振动)转化为电能的技术,STM32U5系列MCU凭借超低功耗特性,成为这类能量采集系统的核心控制单元。本方案实现从振动触发启动、能量收集、储能管理到负载供电的完整闭环,适用于无线传感器节点、工业监测等无外接电源的场景。
1.1 核心硬件组成
- 核心控制器:STM32U585AIQ6Q(超低功耗,支持多种低功耗模式)
- 振动能量采集器:压电陶瓷片(PZT)+ 整流桥 + 储能电容(1000μF/10V)
- 能量管理芯片:BQ25570(支持能量收集、电池充电、低功耗管理)
- 辅助元件:LDO(AMS1117-3.3)、电压检测电阻、LED指示灯、按键(调试用)
1.2 整体工作流程
以下是系统完整工作流程的Mermaid流程图:
否
是
否
是
是
否
振动触发
电压检测
BQ25570输出≥3.0V?
STM32U5进入STOP2模式
功耗<1μA
STM32U5从STOP2唤醒
初始化核心外设
读取储能电容电压
监测能量状态
能量充足?
≥3.3V
优先补充能量
关闭非核心负载
执行采集数据处理
无线传输(可选)
能量消耗监测
判断是否进入低功耗
剩余能量≥2.8V?
二、开发环境搭建
2.1 软件环境
- 下载并安装STM32CubeIDE(版本:1.15.0):https://www.st.com/en/development-tools/stm32cubeide.html
- 安装STM32U5系列固件库(STM32CubeU5,版本:1.3.0)
- 配置编译器:GCC ARM Embedded(版本:10.3-2021.10)
- 安装ST-Link驱动(用于烧录和调试)
2.2 硬件连接
| STM32U5引脚 | 外部元件 | 连接说明 |
|---|---|---|
| PA0 | BQ25570 INT引脚 | 振动唤醒中断输入(上拉) |
| PA1 | BQ25570 VBAT引脚 | 储能电压检测(ADC输入) |
| PB0 | LED指示灯 | 系统工作状态指示 |
| PB1 | BQ25570 EN引脚 | 能量管理芯片使能 |
| VDD | AMS1117-3.3输出 | 3.3V供电 |
| GND | 所有元件地 | 共地 |
三、代码开发步骤(详细版)
3.1 工程创建
- 打开STM32CubeIDE,新建STM32 Project,选择STM32U585AIQ6Q芯片
- 配置工程参数:
- Project Name:Vibration_Energy_Harvesting
- Toolchain/IDE:STM32CubeIDE
- 勾选"Initialize all peripherals with their default mode"
- 保存工程到本地路径(如:D:\STM32_Projects\Vibration_Energy_Harvesting)
3.2 外设配置(STM32CubeMX)
3.2.1 时钟配置
- 外部晶振:8MHz
- 系统时钟:160MHz(STM32U5最大主频)
- LSE(低速外部晶振):32.768kHz(用于RTC和低功耗计时)
3.2.2 低功耗配置
- 启用STOP2模式(最低功耗模式,支持中断唤醒)
- 启用WKUP引脚(PA0)作为唤醒源
- 配置RTC时钟源为LSE,用于低功耗计时
3.2.3 ADC配置
- 启用ADC1,通道PA1(IN1)
- 采样率:12位分辨率,采样时间20.5个周期
- 低功耗模式:单次采样,采样完成后关闭ADC
3.2.4 GPIO配置
- PA0:输入模式,上拉,EXTI中断(下降沿触发)
- PA1:模拟输入(ADC)
- PB0:推挽输出,初始电平低(LED)
- PB1:推挽输出,初始电平高(BQ25570使能)
3.3 核心代码编写
3.3.1 代码文件1:main.c(主程序)
c
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "gpio.h"
#include "rtc.h"
#include "low_power.h"
/* Private define ------------------------------------------------------------*/
#define VBAT_THRESHOLD_LOW 2800 // 低电压阈值:2.8V(mV)
#define VBAT_THRESHOLD_HIGH 3300 // 高电压阈值:3.3V(mV)
#define VBAT_THRESHOLD_START 3000 // 启动阈值:3.0V(mV)
#define LED_BLINK_DELAY 500 // LED闪烁延时(ms)
/* Private variables ---------------------------------------------------------*/
uint16_t vbat_voltage = 0; // 电池/电容电压(mV)
/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static uint16_t ADC_Read_VBAT(void);
static void Energy_Management_Task(void);
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_RTC_Init();
/* 初始化低功耗管理模块 */
LowPower_Init();
/* 开启BQ25570能量管理芯片 */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
/* 启动LED指示系统初始化完成 */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
/* 主循环 */
while (1)
{
/* 读取储能电容电压 */
vbat_voltage = ADC_Read_VBAT();
/* 执行能量管理核心任务 */
Energy_Management_Task();
/* 低功耗优化:若无任务执行,进入睡眠模式 */
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
}
}
/**
* @brief 读取VBAT电压(ADC采样并转换为mV)
* @param 无
* @retval 电压值(mV)
*/
static uint16_t ADC_Read_VBAT(void)
{
uint32_t adc_value = 0;
uint16_t voltage_mv = 0;
/* 启动ADC单次转换 */
HAL_ADC_Start(&hadc1);
/* 等待转换完成 */
if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)
{
/* 读取ADC原始值 */
adc_value = HAL_ADC_GetValue(&hadc1);
/* 转换为电压值:ADC参考电压3.3V,12位分辨率(4096)
公式:电压(mV) = (ADC值 * 3300) / 4096 */
voltage_mv = (adc_value * 3300) / 4096;
}
/* 停止ADC */
HAL_ADC_Stop(&hadc1);
return voltage_mv;
}
/**
* @brief 能量管理核心任务
* @param 无
* @retval 无
*/
static void Energy_Management_Task(void)
{
/* 1. 电压低于启动阈值,进入STOP2模式 */
if (vbat_voltage < VBAT_THRESHOLD_START)
{
/* 关闭LED和非必要外设 */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
/* 进入STOP2模式,等待PA0中断唤醒(振动触发) */
LowPower_EnterSTOP2Mode();
/* 唤醒后重新初始化时钟 */
SystemClock_Config();
return;
}
/* 2. 电压在启动阈值和高阈值之间,补充能量 */
if (vbat_voltage >= VBAT_THRESHOLD_START && vbat_voltage < VBAT_THRESHOLD_HIGH)
{
/* LED慢闪:补充能量中 */
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
HAL_Delay(LED_BLINK_DELAY * 2);
/* 关闭无线传输等高功耗模块 */
// Power_Off_Wireless_Module();
return;
}
/* 3. 电压高于高阈值,执行正常任务 */
if (vbat_voltage >= VBAT_THRESHOLD_HIGH)
{
/* LED快闪:正常工作中 */
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
HAL_Delay(LED_BLINK_DELAY);
/* 执行振动数据采集、处理、传输等任务 */
// Vibration_Data_Collection();
// Data_Processing();
// Wireless_Transmission();
/* 监测能量消耗,低于低阈值则停止任务 */
if (vbat_voltage < VBAT_THRESHOLD_LOW)
{
/* 紧急进入低功耗 */
LowPower_EnterSTOP2Mode();
SystemClock_Config();
}
}
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
Error_Handler();
}
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 40;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_PCLK3;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
/** Initializes the peripherals clocks
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_ADC;
PeriphClkInit.RtcClockSelection = RCC_RTCCLKSOURCE_LSE;
PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
PeriphClkInit.PLL2.PLL2M = 4;
PeriphClkInit.PLL2.PLL2N = 20;
PeriphClkInit.PLL2.PLL2P = 2;
PeriphClkInit.PLL2.PLL2Q = 2;
PeriphClkInit.PLL2.PLL2R = 2;
PeriphClkInit.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
PeriphClkInit.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
PeriphClkInit.PLL2.PLL2FRACN = 0;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* 用户可以添加自定义错误处理代码 */
__disable_irq();
while (1)
{
/* LED常亮表示错误 */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
}
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* 用户可以添加自定义打印信息 */
}
#endif /* USE_FULL_ASSERT */
3.3.2 代码文件2:low_power.c(低功耗管理)
c
/* Includes ------------------------------------------------------------------*/
#include "low_power.h"
#include "main.h"
/* Private define ------------------------------------------------------------*/
#define STOP2_WAKEUP_PIN GPIO_PIN_0
#define STOP2_WAKEUP_PORT GPIOA
/* Private function prototypes -----------------------------------------------*/
static void LowPower_ConfigGPIO(void);
static void LowPower_ConfigEXTI(void);
/**
* @brief 低功耗模块初始化
* @param 无
* @retval 无
*/
void LowPower_Init(void)
{
/* 配置唤醒引脚 */
LowPower_ConfigGPIO();
/* 配置EXTI中断 */
LowPower_ConfigEXTI();
/* 使能PWR时钟 */
__HAL_RCC_PWR_CLK_ENABLE();
/* 解锁PWR寄存器 */
HAL_PWR_EnableBkUpAccess();
}
/**
* @brief 配置低功耗模式下的GPIO
* @param 无
* @retval 无
*/
static void LowPower_ConfigGPIO(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* 关闭所有非必要GPIO的时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/* 配置唤醒引脚为上拉输入 */
GPIO_InitStruct.Pin = STOP2_WAKEUP_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(STOP2_WAKEUP_PORT, &GPIO_InitStruct);
/* 配置其他GPIO为模拟输入(降低漏电流) */
// PB0(LED)
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// PB1(BQ25570 EN)
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// PA1(ADC)
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/**
* @brief 配置EXTI中断(用于STOP2唤醒)
* @param 无
* @retval 无
*/
static void LowPower_ConfigEXTI(void)
{
/* 使能SYSCFG时钟 */
__HAL_RCC_SYSCFG_CLK_ENABLE();
/* 配置EXTI中断优先级 */
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}
/**
* @brief 进入STOP2模式
* @param 无
* @retval 无
*/
void LowPower_EnterSTOP2Mode(void)
{
/* 1. 停止TIM、ADC等外设 */
HAL_ADC_DeInit(&hadc1);
/* 2. 配置PWR进入STOP2模式 */
HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_OFF, PWR_STOPENTRY_WFI);
/* 3. 唤醒后恢复外设时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_ADC1_CLK_ENABLE();
}
/**
* @brief EXTI0中断服务函数(PA0唤醒)
* @param 无
* @retval 无
*/
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(STOP2_WAKEUP_PIN);
}
/**
* @brief EXTI中断回调函数
* @param GPIO_Pin: 触发中断的引脚
* @retval 无
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == STOP2_WAKEUP_PIN)
{
/* 清除中断标志 */
__HAL_GPIO_EXTI_CLEAR_IT(STOP2_WAKEUP_PIN);
/* 唤醒后可添加自定义处理逻辑 */
}
}
3.3.3 代码文件3:low_power.h(低功耗头文件)
c
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LOW_POWER_H
#define __LOW_POWER_H
/* Includes ------------------------------------------------------------------*/
#include "stm32u5xx_hal.h"
/* Exported functions prototypes ---------------------------------------------*/
void LowPower_Init(void);
void LowPower_EnterSTOP2Mode(void);
/* External variables --------------------------------------------------------*/
extern ADC_HandleTypeDef hadc1;
#endif /* __LOW_POWER_H */
3.3.4 代码文件4:adc.c(ADC配置,由STM32CubeMX生成并修改)
c
/* Includes ------------------------------------------------------------------*/
#include "adc.h"
/* ADC1 init function */
void MX_ADC1_Init(void)
{
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/* Common config */
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
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_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_20CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(adcHandle->Instance==ADC1)
{
/* ADC1 clock enable */
__HAL_RCC_ADC12_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**ADC1 GPIO Configuration
PA1 ------> ADC1_IN1
*/
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
if(adcHandle->Instance==ADC1)
{
/* Peripheral clock disable */
__HAL_RCC_ADC12_CLK_DISABLE();
/**ADC1 GPIO Configuration
PA1 ------> ADC1_IN1
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1);
}
}
3.3.5 代码文件5:gpio.c(GPIO配置,由STM32CubeMX生成并修改)
c
/* Includes ------------------------------------------------------------------*/
#include "gpio.h"
/* GPIO Ports Clock Enable */
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1, GPIO_PIN_RESET);
/*Configure GPIO pin : PA0 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PB0 PB1 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}
3.4 代码编译与烧录
3.4.1 编译代码
- 在STM32CubeIDE中,点击菜单栏"Project" -> "Build Project"
- 检查编译日志,确保无错误(0 errors)、无警告(0 warnings)
- 编译完成后,在工程目录下的"Debug"文件夹中生成
.elf和.hex文件
3.4.2 烧录代码
- 连接ST-Link调试器到STM32U5开发板
- 点击STM32CubeIDE菜单栏"Run" -> "Debug Configurations"
- 选择"STM32 Cortex-M C/C++ Application",新建配置
- 选择生成的
.elf文件,点击"Debug"开始烧录 - 烧录完成后,点击"Resume"按钮运行程序
四、系统调试与验证
4.1 硬件调试
- 使用示波器测量PA0引脚,当有振动时,BQ25570的INT引脚会产生下降沿,触发STM32U5唤醒
- 测量PA1引脚的ADC采样值,验证电压转换是否准确(可通过电源模块模拟不同电压)
- 观察PB0的LED指示灯:
- 慢闪:能量补充中(电压3.0V~3.3V)
- 快闪:正常工作(电压≥3.3V)
- 熄灭:低功耗模式(电压<3.0V)
4.2 软件调试
- 使用STM32CubeIDE的Debug功能,设置断点在
Energy_Management_Task函数,观察电压值变化 - 调试低功耗模式:通过
LowPower_EnterSTOP2Mode函数,查看MCU功耗(可通过电流表测量,STOP2模式功耗应<1μA) - 验证唤醒功能:在低功耗模式下,触发PA0引脚的下降沿,观察MCU是否能正常唤醒并恢复时钟
4.3 性能指标验证
| 指标 | 目标值 | 验证方法 |
|---|---|---|
| 唤醒响应时间 | <10ms | 示波器测量PA0到PB0的延迟 |
| STOP2模式功耗 | <1μA | 电流表测量MCU供电电流 |
| ADC电压测量精度 | ±50mV | 对比万用表和ADC采样值 |
| 能量采集效率 | ≥60% | 测量输入振动能量和输出电能 |
五、方案优化与扩展
5.1 硬件优化
- 更换更高容量的储能电容(如2200μF),延长续航时间
- 添加锂电池(如3.7V锂聚合物电池),实现能量存储和不间断供电
- 使用高效LDO(如TPS7333),降低电压转换损耗
5.2 软件优化
- 实现动态电压阈值调整,根据环境振动强度自动调整阈值
- 添加RTC计时功能,定期唤醒MCU进行状态检测
- 集成无线传输模块(如BLE5.0),实现数据远程传输(需添加
Wireless_Transmission函数)
5.3 功能扩展
- 添加温度、湿度传感器(如DHT11),实现多参数监测
- 集成边缘计算算法,在MCU端完成数据预处理,减少传输功耗
- 实现多节点组网,通过无线通信实现能量均衡管理
总结
- 本方案基于STM32U5和BQ25570实现了振动能量采集的完整闭环,核心流程为:振动触发唤醒→电压检测→能量管理→低功耗休眠,通过Mermaid流程图清晰展示了系统逻辑。
- 核心代码分为主程序(main.c)、低功耗管理(low_power.c/h)、外设配置(adc.c/gpio.c),代码包含详细注释,零基础用户可直接编译烧录。
- 系统调试需重点验证低功耗模式功耗、电压检测精度和唤醒响应时间,可通过示波器、电流表等工具完成,优化方向包括硬件储能和软件算法两方面。