振动能量采集:STM32U5从振动启动,能量管理完整方案

文章目录

    • 一、方案背景与整体架构
      • [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 软件环境

  1. 下载并安装STM32CubeIDE(版本:1.15.0):https://www.st.com/en/development-tools/stm32cubeide.html
  2. 安装STM32U5系列固件库(STM32CubeU5,版本:1.3.0)
  3. 配置编译器:GCC ARM Embedded(版本:10.3-2021.10)
  4. 安装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 工程创建

  1. 打开STM32CubeIDE,新建STM32 Project,选择STM32U585AIQ6Q芯片
  2. 配置工程参数:
    • Project Name:Vibration_Energy_Harvesting
    • Toolchain/IDE:STM32CubeIDE
    • 勾选"Initialize all peripherals with their default mode"
  3. 保存工程到本地路径(如: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 编译代码
  1. 在STM32CubeIDE中,点击菜单栏"Project" -> "Build Project"
  2. 检查编译日志,确保无错误(0 errors)、无警告(0 warnings)
  3. 编译完成后,在工程目录下的"Debug"文件夹中生成.elf.hex文件
3.4.2 烧录代码
  1. 连接ST-Link调试器到STM32U5开发板
  2. 点击STM32CubeIDE菜单栏"Run" -> "Debug Configurations"
  3. 选择"STM32 Cortex-M C/C++ Application",新建配置
  4. 选择生成的.elf文件,点击"Debug"开始烧录
  5. 烧录完成后,点击"Resume"按钮运行程序

四、系统调试与验证

4.1 硬件调试

  1. 使用示波器测量PA0引脚,当有振动时,BQ25570的INT引脚会产生下降沿,触发STM32U5唤醒
  2. 测量PA1引脚的ADC采样值,验证电压转换是否准确(可通过电源模块模拟不同电压)
  3. 观察PB0的LED指示灯:
    • 慢闪:能量补充中(电压3.0V~3.3V)
    • 快闪:正常工作(电压≥3.3V)
    • 熄灭:低功耗模式(电压<3.0V)

4.2 软件调试

  1. 使用STM32CubeIDE的Debug功能,设置断点在Energy_Management_Task函数,观察电压值变化
  2. 调试低功耗模式:通过LowPower_EnterSTOP2Mode函数,查看MCU功耗(可通过电流表测量,STOP2模式功耗应<1μA)
  3. 验证唤醒功能:在低功耗模式下,触发PA0引脚的下降沿,观察MCU是否能正常唤醒并恢复时钟

4.3 性能指标验证

指标 目标值 验证方法
唤醒响应时间 <10ms 示波器测量PA0到PB0的延迟
STOP2模式功耗 <1μA 电流表测量MCU供电电流
ADC电压测量精度 ±50mV 对比万用表和ADC采样值
能量采集效率 ≥60% 测量输入振动能量和输出电能

五、方案优化与扩展

5.1 硬件优化

  1. 更换更高容量的储能电容(如2200μF),延长续航时间
  2. 添加锂电池(如3.7V锂聚合物电池),实现能量存储和不间断供电
  3. 使用高效LDO(如TPS7333),降低电压转换损耗

5.2 软件优化

  1. 实现动态电压阈值调整,根据环境振动强度自动调整阈值
  2. 添加RTC计时功能,定期唤醒MCU进行状态检测
  3. 集成无线传输模块(如BLE5.0),实现数据远程传输(需添加Wireless_Transmission函数)

5.3 功能扩展

  1. 添加温度、湿度传感器(如DHT11),实现多参数监测
  2. 集成边缘计算算法,在MCU端完成数据预处理,减少传输功耗
  3. 实现多节点组网,通过无线通信实现能量均衡管理

总结

  1. 本方案基于STM32U5和BQ25570实现了振动能量采集的完整闭环,核心流程为:振动触发唤醒→电压检测→能量管理→低功耗休眠,通过Mermaid流程图清晰展示了系统逻辑。
  2. 核心代码分为主程序(main.c)、低功耗管理(low_power.c/h)、外设配置(adc.c/gpio.c),代码包含详细注释,零基础用户可直接编译烧录。
  3. 系统调试需重点验证低功耗模式功耗、电压检测精度和唤醒响应时间,可通过示波器、电流表等工具完成,优化方向包括硬件储能和软件算法两方面。
相关推荐
浩子智控2 小时前
zynq嵌入式开发(1)—开发准备和流程
linux·嵌入式硬件·硬件架构
VALENIAN瓦伦尼安教学设备2 小时前
便携式蒸汽阀门漏气检测仪作用
人工智能·嵌入式硬件·算法
_探索_11 小时前
STM32U5F7VJT6Q (Cortex-M33, 160MHz) TouchGFX统计MCU占用率和FPS
stm32·单片机·嵌入式硬件
浩子智控11 小时前
zynq嵌入式开发(2)—基本开发测试实例
linux·嵌入式硬件·硬件架构
猫猫的小茶馆11 小时前
【Linux 驱动开发】Linux 内核启动过程详解
linux·c语言·arm开发·驱动开发·stm32·单片机·mcu
辰哥单片机设计11 小时前
STM32太阳能光伏板
stm32·单片机·嵌入式硬件
mftang11 小时前
MCU上应用的主流NVM技术: 嵌入式相变存储器(PCM) 和嵌入式磁阻随机存取存储器(MRAM)
单片机·嵌入式硬件·pcm
炸膛坦客11 小时前
Cortex-M3-STM32F1 开发:(五十四)CAN(车企会用),难但很重要
stm32·单片机·嵌入式硬件
willhuo11 小时前
RS485回响程序设计方案
单片机·lua