故障预测与健康管理:STM32G4监控自身参数,早期预警

文章目录

一、技术背景与实现目标

故障预测与健康管理(PHM, Prognostics and Health Management)是通过实时采集设备运行状态参数,结合算法分析实现故障早期预警的技术体系。本文以STM32G4系列单片机为核心,实现对芯片自身核心健康参数的实时监控,包括:

  1. 芯片内核温度(内置温度传感器)
  2. 供电电压(VDD/VREFINT参考电压校准)
  3. Flash读写次数(模拟存储寿命计数)
  4. 系统运行时长与异常复位次数
    通过阈值判断实现早期故障预警,最终输出可视化的健康状态报告,为嵌入式设备的预防性维护提供依据。

二、硬件准备与开发环境搭建

2.1 硬件清单(零基础适配)

硬件名称 型号/规格 数量 用途
开发板 STM32G431RBT6-Nucleo 1块 核心控制单元
USB数据线 Type-C 1根 烧录程序+串口通信
杜邦线 公对公/公对母 若干 可选扩展外设
电源 5V/1A 1个 开发板供电(可选)

2.2 开发环境搭建步骤

步骤1:安装STM32CubeIDE
  1. 下载地址:https://www.st.com/en/development-tools/stm32cubeide.html
  2. 安装流程:
    • 运行安装包,选择安装路径(建议非中文路径,如D:\STM32CubeIDE_1.15.0
    • 勾选"STM32CubeMX Integration",完成安装
    • 首次启动需配置编译器路径,默认路径无需修改
步骤2:安装STM32G4固件库
  1. 打开STM32CubeIDE,点击菜单栏Help->STM32Cube MCU Package Installer
  2. 在搜索框输入STM32G4,勾选STM32Cube FW_G4 V1.6.0(最新稳定版)
  3. 点击Install Now,等待固件库下载安装完成
步骤3:配置串口终端(用于查看监控数据)
  1. 下载串口工具:SSCOM5.13(免费开源)
  2. 配置参数:波特率115200、数据位8、停止位1、无校验、无流控

三、整体实现流程(Mermaid流程图)





系统初始化
参数采集模块初始化
采集周期到?
采集内核温度
采集供电电压
读取Flash寿命计数
统计系统运行状态
阈值判断与异常标记
是否触发预警?
输出预警信息到串口
输出正常健康状态
存储历史数据到Flash

四、详细代码实现

4.1 代码文件结构

复制代码
PHM_Project/
├── Core/
│   ├── Inc/
│   │   ├── main.h          // 主函数头文件
│   │   ├── phm_monitor.h   // PHM监控模块头文件
│   │   ├── stm32g4xx_hal_conf.h // HAL配置文件
│   │   └── stm32g4xx_it.h  // 中断服务函数头文件
│   └── Src/
│       ├── main.c          // 主函数(核心逻辑)
│       ├── phm_monitor.c   // PHM监控模块实现
│       ├── stm32g4xx_hal_msp.c // MSP初始化
│       └── sysmem.c        // 系统内存配置
└── STM32G431RBTx_FLASH.ld  // 链接脚本

4.2 头文件定义(phm_monitor.h)

文件名:phm_monitor.h

c 复制代码
#ifndef __PHM_MONITOR_H
#define __PHM_MONITOR_H

#include "stm32g4xx_hal.h"
#include <stdint.h>
#include <stdbool.h>

// 健康参数阈值配置(可根据实际需求调整)
#define TEMP_WARNING_THRESHOLD    60.0f   // 温度预警阈值(℃)
#define TEMP_ERROR_THRESHOLD      85.0f   // 温度故障阈值(℃)
#define VDD_WARNING_LOW_THRESHOLD 2.9f    // 电压低预警阈值(V)
#define VDD_WARNING_HIGH_THRESHOLD 3.4f   // 电压高预警阈值(V)
#define FLASH_CYCLE_WARNING       10000   // Flash读写次数预警阈值
#define RESET_ERROR_THRESHOLD     5       // 异常复位次数阈值

// 健康状态枚举
typedef enum {
    PHM_STATUS_NORMAL = 0,    // 正常
    PHM_STATUS_WARNING,       // 预警
    PHM_STATUS_ERROR          // 故障
} PHM_StatusTypeDef;

// 设备健康数据结构体
typedef struct {
    float core_temperature;   // 内核温度(℃)
    float vdd_voltage;        // VDD供电电压(V)
    uint32_t flash_write_count; // Flash写入次数
    uint32_t system_run_time; // 系统运行时间(秒)
    uint8_t reset_count;      // 异常复位次数
    PHM_StatusTypeDef overall_status; // 整体健康状态
} PHM_DataStruct;

// 函数声明
void PHM_Monitor_Init(void);                  // 监控模块初始化
void PHM_Collect_All_Parameters(void);        // 采集所有参数
void PHM_Check_Health_Status(void);           // 检查健康状态
void PHM_Print_Health_Info(void);             // 打印健康信息
void PHM_Save_History_Data(void);             // 保存历史数据
float PHM_Get_Core_Temperature(void);         // 获取内核温度
float PHM_Get_VDD_Voltage(void);              // 获取VDD电压
uint32_t PHM_Get_Flash_Write_Count(void);     // 获取Flash写入次数
void PHM_Increment_Flash_Write_Count(void);   // 增加Flash写入次数
void PHM_Increment_Reset_Count(void);         // 增加复位次数

#endif /* __PHM_MONITOR_H */

4.3 核心实现代码(phm_monitor.c)

文件名:phm_monitor.c

c 复制代码
#include "phm_monitor.h"
#include "stm32g4xx_hal_adc.h"
#include "stm32g4xx_hal_flash.h"

// 全局变量定义
static PHM_DataStruct phm_data = {0};
static ADC_HandleTypeDef hadc1;               // ADC句柄(用于温度/电压采集)
static TIM_HandleTypeDef htim6;               // 定时器句柄(用于定时采集)

// Flash存储地址定义(选择未使用的Flash区域,需匹配芯片容量)
#define FLASH_DATA_ADDR    0x0801FC00         // STM32G431RBT6 Flash末尾区域
#define FLASH_PAGE_SIZE    2048               // STM32G4 Flash页大小

/**
 * @brief  ADC初始化(用于温度传感器和VREFINT采集)
 * @note   零基础适配:ADC1通道16=温度传感器,通道17=VREFINT
 */
static void MX_ADC1_Init(void)
{
  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  // ADC基础配置
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;  // 扫描模式(多通道)
  hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;    // 单次转换模式
  hadc1.Init.NbrOfConversion = 2;             // 2个通道(温度+VREFINT)
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.NbrOfDiscConversion = 1;
  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();
  }

  // 多模式配置(单ADC模式)
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }

  // 通道16配置(温度传感器)
  sConfig.Channel = ADC_CHANNEL_16;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5; // 长采样时间保证精度
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  // 通道17配置(VREFINT参考电压)
  sConfig.Channel = ADC_CHANNEL_17;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  // 启用温度传感器和VREFINT
  HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
  __HAL_ADC_ENABLE(&hadc1);
}

/**
 * @brief  定时器6初始化(1秒定时,用于参数采集周期)
 */
static void MX_TIM6_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 8399;                // 84MHz/8400=10kHz
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim6.Init.Period = 9999;                   // 10kHz/10000=1Hz(1秒)
  htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  {
    Error_Handler();
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }

  // 启动定时器中断
  HAL_TIM_Base_Start_IT(&htim6);
}

/**
 * @brief  获取内核温度
 * @retval 温度值(℃)
 */
float PHM_Get_Core_Temperature(void)
{
  uint32_t adc_temp_value = 0;
  float temperature = 0.0f;

  // 启动ADC转换
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1, 100);    // 等待转换完成(超时100ms)
  
  // 读取温度传感器ADC值
  adc_temp_value = HAL_ADC_GetValue(&hadc1);
  
  // STM32G4温度计算公式:Temp(℃) = (Vtemp - V25)/Avg_Slope + 25
  // V25=0.76V, Avg_Slope=2.5mV/℃, Vtemp=ADC值*3.3/4095
  temperature = ((adc_temp_value * 3.3f / 4095.0f) - 0.76f) / 0.0025f + 25.0f;
  
  HAL_ADC_Stop(&hadc1);
  return temperature;
}

/**
 * @brief  获取VDD供电电压
 * @retval 电压值(V)
 */
float PHM_Get_VDD_Voltage(void)
{
  uint32_t adc_vrefint_value = 0;
  float vdd_voltage = 0.0f;

  // 切换到VREFINT通道并启动转换
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1, 100);
  HAL_ADC_GetValue(&hadc1); // 跳过第一个通道(温度)
  adc_vrefint_value = HAL_ADC_GetValue(&hadc1); // 读取VREFINT值
  
  // VREFINT校准值(从芯片内部读取)
  uint16_t vrefint_cal = *(__IO uint16_t *)(0x1FFF75AA);
  
  // VDD计算公式:VDD = 3.3f * (VREFINT_CAL / ADC_VREFINT_VALUE)
  vdd_voltage = 3.3f * ((float)vrefint_cal / (float)adc_vrefint_value);
  
  HAL_ADC_Stop(&hadc1);
  return vdd_voltage;
}

/**
 * @brief  读取Flash写入次数
 * @retval 写入次数
 */
uint32_t PHM_Get_Flash_Write_Count(void)
{
  uint32_t write_count = 0;
  
  // 从指定Flash地址读取计数
  write_count = *(__IO uint32_t *)(FLASH_DATA_ADDR);
  
  // 首次读取时初始化计数
  if (write_count == 0xFFFFFFFF)
  {
    write_count = 0;
    PHM_Increment_Flash_Write_Count();
  }
  
  return write_count;
}

/**
 * @brief  增加Flash写入次数
 */
void PHM_Increment_Flash_Write_Count(void)
{
  uint32_t write_count = PHM_Get_Flash_Write_Count() + 1;
  FLASH_EraseInitTypeDef erase_init = {0};
  uint32_t page_error = 0;
  
  // 解锁Flash
  HAL_FLASH_Unlock();
  
  // 擦除Flash页
  erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
  erase_init.Page = (FLASH_DATA_ADDR - FLASH_BASE) / FLASH_PAGE_SIZE;
  erase_init.NbPages = 1;
  if (HAL_FLASHEx_Erase(&erase_init, &page_error) != HAL_OK)
  {
    Error_Handler();
  }
  
  // 写入新的计数
  HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_DATA_ADDR, write_count);
  
  // 锁定Flash
  HAL_FLASH_Lock();
}

/**
 * @brief  增加异常复位次数
 */
void PHM_Increment_Reset_Count(void)
{
  uint32_t reset_count = phm_data.reset_count + 1;
  FLASH_EraseInitTypeDef erase_init = {0};
  uint32_t page_error = 0;
  
  HAL_FLASH_Unlock();
  erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
  erase_init.Page = (FLASH_DATA_ADDR + 4) / FLASH_PAGE_SIZE;
  erase_init.NbPages = 1;
  HAL_FLASHEx_Erase(&erase_init, &page_error);
  HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_DATA_ADDR + 4, reset_count);
  HAL_FLASH_Lock();
  
  phm_data.reset_count = reset_count;
}

/**
 * @brief  采集所有参数
 */
void PHM_Collect_All_Parameters(void)
{
  // 采集温度
  phm_data.core_temperature = PHM_Get_Core_Temperature();
  
  // 采集电压
  phm_data.vdd_voltage = PHM_Get_VDD_Voltage();
  
  // 读取Flash计数
  phm_data.flash_write_count = PHM_Get_Flash_Write_Count();
  
  // 更新运行时间
  phm_data.system_run_time++;
  
  // 打印调试信息(可选)
  HAL_Delay(10);
}

/**
 * @brief  检查健康状态
 */
void PHM_Check_Health_Status(void)
{
  phm_data.overall_status = PHM_STATUS_NORMAL;
  
  // 温度判断
  if (phm_data.core_temperature >= TEMP_ERROR_THRESHOLD)
  {
    phm_data.overall_status = PHM_STATUS_ERROR;
  }
  else if (phm_data.core_temperature >= TEMP_WARNING_THRESHOLD)
  {
    phm_data.overall_status = PHM_STATUS_WARNING;
  }
  
  // 电压判断
  if (phm_data.vdd_voltage < VDD_WARNING_LOW_THRESHOLD || phm_data.vdd_voltage > VDD_WARNING_HIGH_THRESHOLD)
  {
    phm_data.overall_status = PHM_STATUS_WARNING;
  }
  
  // Flash计数判断
  if (phm_data.flash_write_count >= FLASH_CYCLE_WARNING)
  {
    phm_data.overall_status = PHM_STATUS_WARNING;
  }
  
  // 复位次数判断
  if (phm_data.reset_count >= RESET_ERROR_THRESHOLD)
  {
    phm_data.overall_status = PHM_STATUS_ERROR;
  }
}

/**
 * @brief  打印健康信息到串口
 */
void PHM_Print_Health_Info(void)
{
  char info_buf[256] = {0};
  
  // 拼接健康信息
  sprintf(info_buf, "=== STM32G4 PHM Status ===\r\n");
  sprintf(info_buf + strlen(info_buf), "System Run Time: %d s\r\n", phm_data.system_run_time);
  sprintf(info_buf + strlen(info_buf), "Core Temperature: %.2f ℃\r\n", phm_data.core_temperature);
  sprintf(info_buf + strlen(info_buf), "VDD Voltage: %.2f V\r\n", phm_data.vdd_voltage);
  sprintf(info_buf + strlen(info_buf), "Flash Write Count: %d\r\n", phm_data.flash_write_count);
  sprintf(info_buf + strlen(info_buf), "Reset Count: %d\r\n", phm_data.reset_count);
  
  // 状态描述
  switch (phm_data.overall_status)
  {
    case PHM_STATUS_NORMAL:
      sprintf(info_buf + strlen(info_buf), "Overall Status: NORMAL\r\n");
      break;
    case PHM_STATUS_WARNING:
      sprintf(info_buf + strlen(info_buf), "Overall Status: WARNING (Early Alert)\r\n");
      break;
    case PHM_STATUS_ERROR:
      sprintf(info_buf + strlen(info_buf), "Overall Status: ERROR (Fault Detected)\r\n");
      break;
    default:
      break;
  }
  sprintf(info_buf + strlen(info_buf), "==========================\r\n\r\n");
  
  // 串口输出
  HAL_UART_Transmit(&huart2, (uint8_t *)info_buf, strlen(info_buf), 1000);
}

/**
 * @brief  保存历史数据到Flash
 */
void PHM_Save_History_Data(void)
{
  // 简化实现:仅保存最新状态(可扩展为历史日志)
  FLASH_EraseInitTypeDef erase_init = {0};
  uint32_t page_error = 0;
  
  HAL_FLASH_Unlock();
  erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
  erase_init.Page = (FLASH_DATA_ADDR + 8) / FLASH_PAGE_SIZE;
  erase_init.NbPages = 1;
  HAL_FLASHEx_Erase(&erase_init, &page_error);
  
  // 保存温度和电压
  HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, FLASH_DATA_ADDR + 8, (uint16_t)(phm_data.core_temperature * 100));
  HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, FLASH_DATA_ADDR + 10, (uint16_t)(phm_data.vdd_voltage * 100));
  
  HAL_FLASH_Lock();
}

/**
 * @brief  PHM监控模块初始化
 */
void PHM_Monitor_Init(void)
{
  // 初始化ADC(温度/电压采集)
  MX_ADC1_Init();
  
  // 初始化定时器(1秒采集周期)
  MX_TIM6_Init();
  
  // 初始化Flash计数
  phm_data.flash_write_count = PHM_Get_Flash_Write_Count();
  
  // 读取复位次数
  phm_data.reset_count = *(__IO uint32_t *)(FLASH_DATA_ADDR + 4);
  if (phm_data.reset_count == 0xFFFFFFFF)
  {
    phm_data.reset_count = 0;
    PHM_Increment_Reset_Count();
  }
  
  // 串口打印初始化完成信息
  char init_info[] = "PHM Monitor Initialized Successfully!\r\n";
  HAL_UART_Transmit(&huart2, (uint8_t *)init_info, strlen(init_info), 1000);
}

/**
 * @brief  定时器6中断服务函数(1秒触发一次参数采集)
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == TIM6)
  {
    // 采集参数
    PHM_Collect_All_Parameters();
    
    // 检查健康状态
    PHM_Check_Health_Status();
    
    // 打印信息
    PHM_Print_Health_Info();
    
    // 保存数据
    PHM_Save_History_Data();
  }
}

/**
 * @brief  错误处理函数
 */
void Error_Handler(void)
{
  // 点亮LED(可选)+ 串口输出错误信息
  char error_info[] = "PHM Monitor Error Occurred!\r\n";
  HAL_UART_Transmit(&huart2, (uint8_t *)error_info, strlen(error_info), 1000);
  while(1)
  {
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Nucleo板LED引脚
    HAL_Delay(500);
  }
}

4.4 主函数实现(main.c)

文件名:main.c

c 复制代码
#include "main.h"
#include "phm_monitor.h"

UART_HandleTypeDef huart2;

/**
 * @brief  主函数
 * @retval int
 */
int main(void)
{
  // 1. 初始化HAL库
  HAL_Init();

  // 2. 配置系统时钟(84MHz)
  SystemClock_Config();

  // 3. 初始化GPIO(LED、串口等)
  MX_GPIO_Init();

  // 4. 初始化串口(USART2,用于输出监控信息)
  MX_USART2_UART_Init();

  // 5. 初始化PHM监控模块
  PHM_Monitor_Init();

  // 6. 主循环(空循环,所有逻辑在定时器中断中执行)
  while (1)
  {
    // 可添加其他业务逻辑
    HAL_Delay(100);
  }
}

/**
 * @brief  系统时钟配置函数
 * @note   STM32G431RBT6 - 84MHz
 */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  // 配置电源电压缩放
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  // 配置HSE振荡器
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  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 = RCC_PLLM_DIV1;
  RCC_OscInitStruct.PLL.PLLN = 42;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&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_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
 * @brief  USART2初始化(串口输出)
 */
void MX_USART2_UART_Init(void)
{
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
 * @brief  GPIO初始化(LED等)
 */
void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  // 启用GPIO时钟
  __HAL_RCC_GPIOA_CLK_ENABLE();

  // 配置LED引脚(Nucleo板PA5)
  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);

  // 默认关闭LED
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
}

五、代码烧录与测试步骤

5.1 代码烧录

  1. 打开STM32CubeIDE,导入上述代码工程
  2. 连接STM32G4 Nucleo开发板到电脑USB口
  3. 点击IDE右上角Run->Debug Configurations
  4. 选择STM32 Debugging,点击New创建新配置
  5. 配置Target ConfigurationSTM32G431RBTx,调试器选择ST-LINK
  6. 点击Debug开始烧录代码,烧录完成后自动进入调试模式

5.2 测试步骤

  1. 打开串口工具SSCOM5.13,选择对应串口(设备管理器查看COM口)
  2. 配置串口参数:波特率115200、8N1、无流控,点击打开串口
  3. 复位开发板(按Nucleo板上的RESET按钮)
  4. 串口终端会输出初始化信息,随后每秒输出一次健康状态数据
  5. 测试验证:
    • 用手触摸芯片表面,观察温度值上升,超过60℃时触发预警
    • 调整供电电压(可选),观察电压预警逻辑
    • 多次复位开发板,观察复位次数增加,超过5次触发故障

六、功能扩展建议

  1. 数据存储扩展:增加Flash历史日志存储,保存最近100条健康数据
  2. 无线传输:添加ESP8266/ESP32模块,将健康数据上传到云端
  3. 阈值动态调整:通过串口指令远程修改预警阈值
  4. 多参数扩展:增加GPIO状态、外设通信状态等监控项
  5. LCD显示:外接LCD屏幕,本地可视化显示健康状态

七、常见问题与解决方法

  1. 串口无输出
    • 检查串口COM口是否正确
    • 确认串口参数配置为115200 8N1
    • 检查USART2引脚映射(Nucleo板PA2/PA3)
  2. 温度值异常
    • 确认ADC初始化中启用了温度传感器
    • 检查采样时间是否足够(建议≥640个ADC周期)
  3. Flash写入失败
    • 确认Flash地址未被程序占用
    • 检查Flash解锁/锁定流程是否正确

总结

  1. 本教程基于STM32G4实现了故障预测与健康管理的核心功能,通过采集芯片温度、电压、Flash寿命、复位次数等参数,结合阈值判断实现早期预警,代码可直接落地使用。
  2. 核心实现流程包括:系统初始化→定时参数采集→健康状态判断→预警输出→数据存储,所有步骤均提供了零基础适配的详细代码和操作指南。
  3. 代码采用模块化设计,可通过扩展Flash日志、无线传输、LCD显示等功能,满足不同场景的PHM需求。
相关推荐
ipod7412 小时前
STM32 GPIO控制器及其应用
stm32·单片机·嵌入式硬件
逐步前行2 小时前
STM32_USART_串口通信
stm32·单片机·嵌入式硬件
我不是程序猿儿2 小时前
【嵌入式】趣味理解“volatile”
stm32·单片机·嵌入式硬件·学习
謓泽2 小时前
【51单片机】DS18B20温度传感器(1-Wire)
单片机·嵌入式硬件·51单片机
F137298015572 小时前
220V降5V,100MA非隔离离线恒压稳压器WD5202A
stm32·单片机·嵌入式硬件·51单片机
电子工程师成长日记-C512 小时前
51单片机PM2.5监测系统
单片机·嵌入式硬件·51单片机
恶魔泡泡糖2 小时前
51单片机带字库LCD12864液晶屏显示
单片机·嵌入式硬件·51单片机
项目題供诗2 小时前
51单片机入门-AT24C02(十二)
单片机·嵌入式硬件·51单片机
是大强3 小时前
DSP 和 MCU 的区别
单片机·嵌入式硬件